将内存从地址复制到缓冲区而不是复制

时间:2015-02-17 19:21:24

标签: c memory

我正在编写内存扫描程序,我希望能够将特定地址的内存内容复制到我创建的内存块结构中的缓冲区中。到目前为止,这是我的代码:

#include <windows.h>
#include <stdio.h>

typedef struct _MEMBLOCK
{
    HANDLE hProc;
    unsigned char *addr;
    int size;
    unsigned char *buffer;

    unsigned char *searchmask;
    int matches;

    struct _MEMBLOCK *next;
} MEMBLOCK;


MEMBLOCK* createMemblock(HANDLE hProc, MEMORY_BASIC_INFORMATION *meminfo)
{
    MEMBLOCK *mb = malloc(sizeof(MEMBLOCK));

    if (mb)
    {
        mb->hProc = hProc;
        mb->addr = meminfo->BaseAddress;
        mb->size = meminfo->RegionSize;
        mb->buffer = malloc(meminfo->RegionSize);
        mb->searchmask = malloc(meminfo->RegionSize / 8);
        memset(mb->searchmask, 0xff, meminfo->RegionSize / 8);
        mb->matches = meminfo->RegionSize;
        mb->next = NULL;
    }

    return mb;
}

void dumpScanInfo(MEMBLOCK *mbList)
{
    MEMBLOCK *mb = mbList;

    while (mb)
    {
        int i;
        printf("0x%08X - 0x%08X (0x%08X)", mb->addr, (mb->addr + mb->size), mb->size);

        for (i = 0; i < mb->size; i++)
        {
            printf("%02x", mb->buffer[i]);
        }
        printf("\n");

        mb = mb->next;
    }
}

void freeMemblock(MEMBLOCK *mb)
{
    if (mb)
    {
        if (mb->buffer)
        {
            free(mb->buffer);
        }

        if (mb->searchmask)
        {
            free(mb->searchmask);
        }

        free(mb);
    }
}

void updateMemblock(MEMBLOCK *mb)
{
    static unsigned char tempbuf[128 * 1024];
    unsigned int bytesLeft;
    unsigned int totalRead;
    unsigned int bytesToRead;
    unsigned int bytesRead;

    bytesLeft = mb->size;
    totalRead = 0;
    while (bytesLeft)
    {
        bytesToRead = (bytesLeft > sizeof(tempbuf)) ? sizeof(tempbuf) : bytesLeft;
        ReadProcessMemory(mb->hProc, mb->addr + totalRead, tempbuf, (DWORD)bytesToRead,(PDWORD)&bytesRead);
        if (bytesRead != bytesToRead) break;
        memcpy(mb->buffer + totalRead, tempbuf, bytesRead);

        bytesLeft -= bytesRead;
        totalRead += bytesRead;
    }

    mb->size = totalRead;
}

BOOL DoRtlAdjustPrivilege()
{
#define SE_DEBUG_PRIVILEGE  20L
#define AdjustCurrentProcess    0
    BOOL bPrev = FALSE;
    LONG(WINAPI *RtlAdjustPrivilege)(DWORD, BOOL, INT, PBOOL);
    *(FARPROC *)&RtlAdjustPrivilege = GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAdjustPrivilege");
    if (!RtlAdjustPrivilege) return FALSE;
    RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, AdjustCurrentProcess, &bPrev);
    return TRUE;
}

typedef BOOL(CALLBACK *LPENUMADDRESSES)(LPBYTE lpAddress, DWORD dwSize, DWORD dwState, DWORD dwType, DWORD dwProtect);
BOOL EnumProcessAddresses(HANDLE hProcess, LPENUMADDRESSES lpCallback)
{
    MEMORY_BASIC_INFORMATION mbi;
    MEMBLOCK *mbList = NULL;
    SYSTEM_INFO msi;
    ZeroMemory(&mbi, sizeof(mbi));
    GetSystemInfo(&msi);
    for (LPBYTE lpAddress = (LPBYTE)msi.lpMinimumApplicationAddress;
        lpAddress <= (LPBYTE)msi.lpMaximumApplicationAddress;
        lpAddress += mbi.RegionSize)
    {
        if (VirtualQueryEx(hProcess, lpAddress, &mbi, sizeof(mbi)))
        {
            MEMBLOCK *mb = createMemblock(hProcess, &mbi);
            if (mb)
            {
                mb->next = mbList;
                mbList = mb;
                updateMemblock(mb);

            }
            if (lpCallback && !lpCallback((LPBYTE)mbi.BaseAddress, mbi.RegionSize,
                mbi.State, mbi.Type, mbi.Protect))
            {
                return FALSE;
            }

        }
        else break;
    }
    printf("\nAfter updating the buffers\n");
    dumpScanInfo(mbList);
    return TRUE;
}

BOOL CALLBACK PrintAddressSpace(LPBYTE lpAddress, DWORD dwSize, DWORD dwState, DWORD dwType, DWORD dwProtect)
{
    printf("0x%08X - 0x%08X (0x%08X) : ", lpAddress, (lpAddress + dwSize), dwSize);
    if (dwState   & MEM_COMMIT)      printf("COMMITTED ");
    if (dwState   & MEM_FREE)        printf("FREE ");
    if (dwState   & MEM_RESERVE)     printf("RESERVED ");
    if (dwType    & MEM_IMAGE)       printf("IMAGE ");
    if (dwType    & MEM_MAPPED)      printf("MAPPED ");
    if (dwType    & MEM_PRIVATE)     printf("PRIVATE ");
    if (dwProtect & PAGE_EXECUTE)        printf("EXECUTE ");
    if (dwProtect & PAGE_EXECUTE_READ)   printf("EXECUTE_READ ");
    if (dwProtect & PAGE_EXECUTE_READWRITE)  printf("EXECUTE_READWRITE ");
    if (dwProtect & PAGE_EXECUTE_WRITECOPY)  printf("EXECUTE_WRITECOPY ");
    if (dwProtect & PAGE_NOACCESS)       printf("NOACCESS ");
    if (dwProtect & PAGE_READONLY)       printf("READONLY ");
    if (dwProtect & PAGE_READWRITE)      printf("READWRITE ");
    if (dwProtect & PAGE_WRITECOPY)      printf("WRITECOPY ");
    if (dwProtect & PAGE_GUARD)      printf("GUARD ");
    if (dwProtect & PAGE_NOCACHE)        printf("NOCACHE ");
    if (dwProtect & PAGE_WRITECOMBINE)   printf("WRITECOMBINE ");
    printf("\n");
    return TRUE;
}

int main(int argc, char **argv)
{
    if (!DoRtlAdjustPrivilege()) 
        return 1;
    if (argc < 2) 
        return 1;
    DWORD dwPID = atoi(argv[1]);
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID);
    if (hProcess == NULL) 
        return 1;

    EnumProcessAddresses(hProcess, PrintAddressSpace);
    CloseHandle(hProcess);
    printf("Press Enter to Continue");
    while (getchar() != '\n');
    return 0;
}

现在,我遇到的问题是,我知道内存内容不为空的事实,如下所示:

0x00010000 - 0x00020000 (0x00010000) : COMMITTED MAPPED READWRITE
0x00020000 - 0x00027000 (0x00007000) : COMMITTED MAPPED READONLY
0x00027000 - 0x00030000 (0x00009000) : FREE NOACCESS
0x00030000 - 0x00034000 (0x00004000) : COMMITTED MAPPED READONLY
0x00034000 - 0x00040000 (0x0000C000) : FREE NOACCESS
0x00040000 - 0x00042000 (0x00002000) : COMMITTED MAPPED READONLY
0x00042000 - 0x00050000 (0x0000E000) : FREE NOACCESS
0x00050000 - 0x00051000 (0x00001000) : COMMITTED PRIVATE READWRITE
0x00051000 - 0x00060000 (0x0000F000) : FREE NOACCESS
0x00060000 - 0x000C7000 (0x00067000) : COMMITTED MAPPED READONLY
0x000C7000 - 0x000D0000 (0x00009000) : FREE NOACCESS
0x000D0000 - 0x000D2000 (0x00002000) : COMMITTED MAPPED READWRITE
0x000D2000 - 0x000E0000 (0x0000E000) : FREE NOACCESS
0x000E0000 - 0x000E3000 (0x00003000) : COMMITTED MAPPED WRITECOPY
0x000E3000 - 0x000F0000 (0x0000D000) : FREE NOACCESS
0x000F0000 - 0x000F1000 (0x00001000) : COMMITTED PRIVATE READWRITE
0x000F1000 - 0x00100000 (0x0000F000) : FREE NOACCESS
0x00100000 - 0x00101000 (0x00001000) : COMMITTED PRIVATE READWRITE
0x00101000 - 0x00110000 (0x0000F000) : FREE NOACCESS
0x00110000 - 0x0011D000 (0x0000D000) : COMMITTED MAPPED WRITECOPY
0x0011D000 - 0x00120000 (0x00003000) : FREE NOACCESS
0x00120000 - 0x00121000 (0x00001000) : COMMITTED MAPPED READONLY
0x00121000 - 0x00130000 (0x0000F000) : FREE NOACCESS
0x00130000 - 0x00132000 (0x00002000) : COMMITTED MAPPED READONLY
0x00132000 - 0x00140000 (0x0000E000) : FREE NOACCESS
0x00140000 - 0x001AC000 (0x0006C000) : RESERVED PRIVATE
0x001AC000 - 0x001AF000 (0x00003000) : COMMITTED PRIVATE READWRITE GUARD
0x001AF000 - 0x001C0000 (0x00011000) : COMMITTED PRIVATE READWRITE
0x001C0000 - 0x001C1000 (0x00001000) : COMMITTED MAPPED READONLY
0x001C1000 - 0x00240000 (0x0007F000) : FREE NOACCESS
0x00240000 - 0x00248000 (0x00008000) : COMMITTED PRIVATE READWRITE
0x00248000 - 0x00250000 (0x00008000) : RESERVED PRIVATE
0x00250000 - 0x00260000 (0x00010000) : FREE NOACCESS
0x00260000 - 0x002FB000 (0x0009B000) : COMMITTED PRIVATE READWRITE
0x002FB000 - 0x00360000 (0x00065000) : RESERVED PRIVATE
0x00360000 - 0x003C8000 (0x00068000) : COMMITTED PRIVATE READWRITE
0x003C8000 - 0x00460000 (0x00098000) : RESERVED PRIVATE
0x00460000 - 0x00470000 (0x00010000) : COMMITTED MAPPED READONLY
0x00470000 - 0x005E0000 (0x00170000) : RESERVED MAPPED
0x005E0000 - 0x005E3000 (0x00003000) : COMMITTED MAPPED READONLY
0x005E3000 - 0x005E8000 (0x00005000) : RESERVED MAPPED
0x005E8000 - 0x005F0000 (0x00008000) : FREE NOACCESS
0x005F0000 - 0x00771000 (0x00181000) : COMMITTED MAPPED READONLY
0x00771000 - 0x00780000 (0x0000F000) : FREE NOACCESS
0x00780000 - 0x008C9000 (0x00149000) : COMMITTED MAPPED READONLY
0x008C9000 - 0x01B80000 (0x012B7000) : RESERVED MAPPED
0x01B80000 - 0x01C00000 (0x00080000) : FREE NOACCESS
0x01C00000 - 0x01C10000 (0x00010000) : COMMITTED PRIVATE READWRITE
0x01C10000 - 0x01C20000 (0x00010000) : COMMITTED PRIVATE READWRITE
0x01C20000 - 0x01C30000 (0x00010000) : COMMITTED PRIVATE READWRITE
0x01C30000 - 0x01C98000 (0x00068000) : COMMITTED PRIVATE READWRITE
0x01C98000 - 0x01D30000 (0x00098000) : RESERVED PRIVATE
0x01D30000 - 0x01D98000 (0x00068000) : COMMITTED PRIVATE READWRITE
0x01D98000 - 0x01E30000 (0x00098000) : RESERVED PRIVATE
0x01E30000 - 0x01E98000 (0x00068000) : COMMITTED PRIVATE READWRITE
0x01E98000 - 0x01F30000 (0x00098000) : RESERVED PRIVATE
0x01F30000 - 0x01FC0000 (0x00090000) : FREE NOACCESS
0x01FC0000 - 0x01FCA000 (0x0000A000) : COMMITTED PRIVATE READWRITE
0x01FCA000 - 0x01FD0000 (0x00006000) : RESERVED PRIVATE
0x01FD0000 - 0x01FE0000 (0x00010000) : FREE NOACCESS
0x01FE0000 - 0x01FE2000 (0x00002000) : COMMITTED PRIVATE READWRITE
0x01FE2000 - 0x01FF0000 (0x0000E000) : RESERVED PRIVATE
0x01FF0000 - 0x020E0000 (0x000F0000) : FREE NOACCESS
0x020E0000 - 0x020F0000 (0x00010000) : COMMITTED PRIVATE READWRITE
0x020F0000 - 0x0215F000 (0x0006F000) : COMMITTED PRIVATE READWRITE
0x0215F000 - 0x021F0000 (0x00091000) : RESERVED PRIVATE
0x021F0000 - 0x021F1000 (0x00001000) : COMMITTED PRIVATE READWRITE
0x021F1000 - 0x022F0000 (0x000FF000) : RESERVED PRIVATE
0x022F0000 - 0x023C0000 (0x000D0000) : FREE NOACCESS
0x023C0000 - 0x023DF000 (0x0001F000) : COMMITTED PRIVATE READWRITE
0x023DF000 - 0x02440000 (0x00061000) : RESERVED PRIVATE
0x02440000 - 0x0270F000 (0x002CF000) : COMMITTED MAPPED READONLY
0x0270F000 - 0x02710000 (0x00001000) : FREE NOACCESS
0x02710000 - 0x02778000 (0x00068000) : COMMITTED PRIVATE READWRITE
0x02778000 - 0x02810000 (0x00098000) : RESERVED PRIVATE
0x02810000 - 0x028C0000 (0x000B0000) : FREE NOACCESS
0x028C0000 - 0x028C2000 (0x00002000) : COMMITTED PRIVATE READWRITE
0x028C2000 - 0x02940000 (0x0007E000) : RESERVED PRIVATE
0x02940000 - 0x03290000 (0x00950000) : COMMITTED MAPPED READONLY
0x03290000 - 0x777D0000 (0x74540000) : FREE NOACCESS
0x777D0000 - 0x777D1000 (0x00001000) : COMMITTED IMAGE READONLY
0x777D1000 - 0x7786C000 (0x0009B000) : COMMITTED IMAGE EXECUTE_READ
0x7786C000 - 0x778DA000 (0x0006E000) : COMMITTED IMAGE READONLY
0x778DA000 - 0x778DC000 (0x00002000) : COMMITTED IMAGE READWRITE
0x778DC000 - 0x778EF000 (0x00013000) : COMMITTED IMAGE READONLY
0x778EF000 - 0x778F0000 (0x00001000) : FREE NOACCESS
0x778F0000 - 0x778F1000 (0x00001000) : COMMITTED IMAGE READONLY
0x778F1000 - 0x77972000 (0x00081000) : COMMITTED IMAGE EXECUTE_READ
0x77972000 - 0x77982000 (0x00010000) : COMMITTED IMAGE READONLY
0x77982000 - 0x77984000 (0x00002000) : COMMITTED IMAGE READWRITE
0x77984000 - 0x779EA000 (0x00066000) : COMMITTED IMAGE READONLY
0x779EA000 - 0x779F0000 (0x00006000) : FREE NOACCESS
0x779F0000 - 0x779F1000 (0x00001000) : COMMITTED IMAGE READONLY
0x779F1000 - 0x77AF3000 (0x00102000) : COMMITTED IMAGE EXECUTE_READ
0x77AF3000 - 0x77B22000 (0x0002F000) : COMMITTED IMAGE READONLY
0x77B22000 - 0x77B23000 (0x00001000) : COMMITTED IMAGE READWRITE
0x77B23000 - 0x77B24000 (0x00001000) : COMMITTED IMAGE READONLY
0x77B24000 - 0x77B25000 (0x00001000) : COMMITTED IMAGE READWRITE
0x77B25000 - 0x77B27000 (0x00002000) : COMMITTED IMAGE WRITECOPY
0x77B27000 - 0x77B28000 (0x00001000) : COMMITTED IMAGE READWRITE
0x77B28000 - 0x77B29000 (0x00001000) : COMMITTED IMAGE WRITECOPY
0x77B29000 - 0x77B2B000 (0x00002000) : COMMITTED IMAGE READWRITE
0x77B2B000 - 0x77B2E000 (0x00003000) : COMMITTED IMAGE WRITECOPY
0x77B2E000 - 0x77B99000 (0x0006B000) : COMMITTED IMAGE READONLY
0x77B99000 - 0x7EFE0000 (0x07447000) : FREE NOACCESS
0x7EFE0000 - 0x7EFE5000 (0x00005000) : COMMITTED MAPPED READONLY
0x7EFE5000 - 0x7F0E0000 (0x000FB000) : RESERVED MAPPED
0x7F0E0000 - 0x7FFE0000 (0x00F00000) : RESERVED PRIVATE
0x7FFE0000 - 0x7FFE1000 (0x00001000) : COMMITTED PRIVATE READONLY
0x7FFE1000 - 0x7FFF0000 (0x0000F000) : RESERVED PRIVATE

我们看到大小不为零,但是在更新函数上运行内存块以将内存复制到缓冲区后,会发生以下情况:

After updating the buffers
0x7FFE1000 - 0x7FFE1000 (0x00000000)
0x7FFE0000 - 0x7FFE0000 (0x00000000)
0x7F0E0000 - 0x7F0E0000 (0x00000000)
0x7EFE5000 - 0x7EFE5000 (0x00000000)
0x7EFE0000 - 0x7EFE0000 (0x00000000)
0x77B99000 - 0x77B99000 (0x00000000)
0x77B2E000 - 0x77B2E000 (0x00000000)
0x77B2B000 - 0x77B2B000 (0x00000000)
0x77B29000 - 0x77B29000 (0x00000000)
0x77B28000 - 0x77B28000 (0x00000000)
0x77B27000 - 0x77B27000 (0x00000000)
0x77B25000 - 0x77B25000 (0x00000000)
0x77B24000 - 0x77B24000 (0x00000000)
0x77B23000 - 0x77B23000 (0x00000000)
0x77B22000 - 0x77B22000 (0x00000000)
0x77AF3000 - 0x77AF3000 (0x00000000)
0x779F1000 - 0x779F1000 (0x00000000)
0x779F0000 - 0x779F0000 (0x00000000)
0x779EA000 - 0x779EA000 (0x00000000)
0x77984000 - 0x77984000 (0x00000000)
0x77982000 - 0x77982000 (0x00000000)
0x77972000 - 0x77972000 (0x00000000)
0x778F1000 - 0x778F1000 (0x00000000)
0x778F0000 - 0x778F0000 (0x00000000)
0x778EF000 - 0x778EF000 (0x00000000)
0x778DC000 - 0x778DC000 (0x00000000)
0x778DA000 - 0x778DA000 (0x00000000)
0x7786C000 - 0x7786C000 (0x00000000)
0x777D1000 - 0x777D1000 (0x00000000)
0x777D0000 - 0x777D0000 (0x00000000)
0x03290000 - 0x03290000 (0x00000000)
0x02940000 - 0x02940000 (0x00000000)
0x028C2000 - 0x028C2000 (0x00000000)
0x028C0000 - 0x028C0000 (0x00000000)
0x02810000 - 0x02810000 (0x00000000)
0x02778000 - 0x02778000 (0x00000000)
0x02710000 - 0x02710000 (0x00000000)
0x0270F000 - 0x0270F000 (0x00000000)
0x02440000 - 0x02440000 (0x00000000)
0x023DF000 - 0x023DF000 (0x00000000)
0x023C0000 - 0x023C0000 (0x00000000)
0x022F0000 - 0x022F0000 (0x00000000)
0x021F1000 - 0x021F1000 (0x00000000)
0x021F0000 - 0x021F0000 (0x00000000)
0x0215F000 - 0x0215F000 (0x00000000)
0x020F0000 - 0x020F0000 (0x00000000)
0x020E0000 - 0x020E0000 (0x00000000)
0x01FF0000 - 0x01FF0000 (0x00000000)
0x01FE2000 - 0x01FE2000 (0x00000000)
0x01FE0000 - 0x01FE0000 (0x00000000)
0x01FD0000 - 0x01FD0000 (0x00000000)
0x01FCA000 - 0x01FCA000 (0x00000000)
0x01FC0000 - 0x01FC0000 (0x00000000)
0x01F30000 - 0x01F30000 (0x00000000)
0x01E98000 - 0x01E98000 (0x00000000)
0x01E30000 - 0x01E30000 (0x00000000)
0x01D98000 - 0x01D98000 (0x00000000)
0x01D30000 - 0x01D30000 (0x00000000)
0x01C98000 - 0x01C98000 (0x00000000)
0x01C30000 - 0x01C30000 (0x00000000)
0x01C20000 - 0x01C20000 (0x00000000)
0x01C10000 - 0x01C10000 (0x00000000)
0x01C00000 - 0x01C00000 (0x00000000)
0x01B80000 - 0x01B80000 (0x00000000)
0x008C9000 - 0x008C9000 (0x00000000)
0x00780000 - 0x00780000 (0x00000000)
0x00771000 - 0x00771000 (0x00000000)
0x005F0000 - 0x005F0000 (0x00000000)
0x005E8000 - 0x005E8000 (0x00000000)
0x005E3000 - 0x005E3000 (0x00000000)
0x005E0000 - 0x005E0000 (0x00000000)
0x00470000 - 0x00470000 (0x00000000)
0x00460000 - 0x00460000 (0x00000000)
0x003C8000 - 0x003C8000 (0x00000000)
0x00360000 - 0x00360000 (0x00000000)
0x002FB000 - 0x002FB000 (0x00000000)
0x00260000 - 0x00260000 (0x00000000)
0x00250000 - 0x00250000 (0x00000000)
0x00248000 - 0x00248000 (0x00000000)
0x00240000 - 0x00240000 (0x00000000)
0x001C1000 - 0x001C1000 (0x00000000)
0x001C0000 - 0x001C0000 (0x00000000)
0x001AF000 - 0x001AF000 (0x00000000)
0x001AC000 - 0x001AC000 (0x00000000)
0x00140000 - 0x00140000 (0x00000000)
0x00132000 - 0x00132000 (0x00000000)
0x00130000 - 0x00130000 (0x00000000)
0x00121000 - 0x00121000 (0x00000000)
0x00120000 - 0x00120000 (0x00000000)
0x0011D000 - 0x0011D000 (0x00000000)
0x00110000 - 0x00110000 (0x00000000)
0x00101000 - 0x00101000 (0x00000000)
0x00100000 - 0x00100000 (0x00000000)
0x000F1000 - 0x000F1000 (0x00000000)
0x000F0000 - 0x000F0000 (0x00000000)
0x000E3000 - 0x000E3000 (0x00000000)
0x000E0000 - 0x000E0000 (0x00000000)
0x000D2000 - 0x000D2000 (0x00000000)
0x000D0000 - 0x000D0000 (0x00000000)
0x000C7000 - 0x000C7000 (0x00000000)
0x00060000 - 0x00060000 (0x00000000)
0x00051000 - 0x00051000 (0x00000000)
0x00050000 - 0x00050000 (0x00000000)
0x00042000 - 0x00042000 (0x00000000)
0x00040000 - 0x00040000 (0x00000000)
0x00034000 - 0x00034000 (0x00000000)
0x00030000 - 0x00030000 (0x00000000)
0x00027000 - 0x00027000 (0x00000000)
0x00020000 - 0x00020000 (0x00000000)
0x00010000 - 0x00010000 (0x00000000)
Press Enter to Continue

我的猜测是我的updateMemblock功能是导致整个崩溃的原因,但不确定是什么错...

编辑:

稍微调查一下,似乎问题出在我的ReadProcessMemory调用中。通过一些谷歌搜索,我了解到有些进程设置了Page_Guard标志,这会阻止使用ReadProcessMemory读取该进程的内存,我还了解到可以通过使用VirtualProtectEx临时禁用此标志,这是我如何使用它(而且你可以想象,它还不适合我)

DOWRD OLDPROTECT;
VirtualProtectEx(mb->hProc, mb->addr+totalRead, 1, PAGE_READONLY, &OLDPROTECT))

编辑:

所以我对它进行了修改,这就是我所拥有的:

#include <windows.h>
#include <stdio.h>
#include <iostream>


BOOL DoRtlAdjustPrivilege()
{
#define SE_DEBUG_PRIVILEGE  20L
#define AdjustCurrentProcess    0
    BOOL bPrev = FALSE;
    LONG(WINAPI *RtlAdjustPrivilege)(DWORD, BOOL, INT, PBOOL);
    *(FARPROC *)&RtlAdjustPrivilege = GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAdjustPrivilege");
    if (!RtlAdjustPrivilege) return FALSE;
    RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, AdjustCurrentProcess, &bPrev);
    return TRUE;
}


typedef BOOL(CALLBACK *LPENUMADDRESSES)(LPBYTE lpAddress, DWORD dwSize, DWORD dwState, DWORD dwType, DWORD dwProtect);
BOOL EnumProcessAddresses(HANDLE hProcess, LPENUMADDRESSES lpCallback)
{
    MEMORY_BASIC_INFORMATION mbi;
    SYSTEM_INFO msi;
    ZeroMemory(&mbi, sizeof(mbi));
    GetSystemInfo(&msi);
    for (LPBYTE lpAddress = (LPBYTE)msi.lpMinimumApplicationAddress;
        lpAddress <= (LPBYTE)msi.lpMaximumApplicationAddress;
        lpAddress += mbi.RegionSize)
    {
        if (VirtualQueryEx(hProcess, lpAddress, &mbi, sizeof(mbi)))
        {

            //Read memory here
            static unsigned char tempbuf[128 * 1024];
            unsigned int bytesLeft;
            unsigned int totalRead;
            unsigned int bytesToRead;
            SIZE_T bytesRead;
            DWORD OLDPROTECT;
            bytesLeft = sizeof(mbi);
            totalRead = 0;

            while (bytesLeft)
            {
                bytesToRead = (bytesLeft > sizeof(tempbuf)) ? sizeof(tempbuf) : bytesLeft;
                //VirtualProtectEx(hProcess, (LPVOID)(lpAddress + totalRead), 1, PAGE_READONLY, &OLDPROTECT);
                if (ReadProcessMemory(hProcess, (LPVOID)(lpAddress + totalRead), (LPVOID)&tempbuf, bytesToRead, &bytesRead))
                {

                    if (bytesRead != bytesToRead) break;
                    bytesLeft -= bytesRead;
                    totalRead += bytesRead;
                    std::cout << tempbuf << std::endl;
                }
                else
                {
                    break;
                }
            }

            //End reading memory here
            if (lpCallback && !lpCallback((LPBYTE)mbi.BaseAddress, mbi.RegionSize,
                mbi.State, mbi.Type, mbi.Protect))
            {
                return FALSE;
            }

        }
        else break;
    }

    /*DWORD lastError = GetLastError();
    std::cout << "General failure. GetLastError returned " << std::hex
    << lastError << ".";*/

    return TRUE;
}

BOOL CALLBACK PrintAddressSpace(LPBYTE lpAddress, DWORD dwSize, DWORD dwState, DWORD dwType, DWORD dwProtect)
{
    printf("0x%08X - 0x%08X (0x%08X) : ", lpAddress, (lpAddress + dwSize), dwSize);
    if (dwState   & MEM_COMMIT)      printf("COMMITTED ");
    if (dwState   & MEM_FREE)        printf("FREE ");
    if (dwState   & MEM_RESERVE)     printf("RESERVED ");
    if (dwType    & MEM_IMAGE)       printf("IMAGE ");
    if (dwType    & MEM_MAPPED)      printf("MAPPED ");
    if (dwType    & MEM_PRIVATE)     printf("PRIVATE ");
    if (dwProtect & PAGE_EXECUTE)        printf("EXECUTE ");
    if (dwProtect & PAGE_EXECUTE_READ)   printf("EXECUTE_READ ");
    if (dwProtect & PAGE_EXECUTE_READWRITE)  printf("EXECUTE_READWRITE ");
    if (dwProtect & PAGE_EXECUTE_WRITECOPY)  printf("EXECUTE_WRITECOPY ");
    if (dwProtect & PAGE_NOACCESS)       printf("NOACCESS ");
    if (dwProtect & PAGE_READONLY)       printf("READONLY ");
    if (dwProtect & PAGE_READWRITE)      printf("READWRITE ");
    if (dwProtect & PAGE_WRITECOPY)      printf("WRITECOPY ");
    if (dwProtect & PAGE_GUARD)      printf("GUARD ");
    if (dwProtect & PAGE_NOCACHE)        printf("NOCACHE ");
    if (dwProtect & PAGE_WRITECOMBINE)   printf("WRITECOMBINE ");
    printf("\n");
    return TRUE;
}


int main(int argc, char **argv)
{
    printf("Starting\n");
    if (!DoRtlAdjustPrivilege())
        return 1;
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 8748);
    if (hProcess == NULL)
        return 1;

    EnumProcessAddresses(hProcess, PrintAddressSpace);
    CloseHandle(hProcess);
    printf("Press Enter to Continue");
    while (getchar() != '\n');
    return 0;
}

好消息是正在读取一些内存内容,VirtualQueryEx有时会返回正确的内容,问题是,它无法从内存中获取所有内容,如输出中所示(也已删除)它从存储读存储器到MEMBLOCK,不再需要500mb内存来读取记事本)。一些调试显示我收到12b错误(部分复制错误)。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

    ReadProcessMemory(mb->hProc, ...);

这是您的问题开始的地方,这是使用Winapi时的常见错误。您必须添加错误检查,它不是可选的。不这样做会产生不可诊断的失败。纠正这个:

    BOOL ok = ReadProcessMemory(mb->hProc, mb->addr + totalRead, tempbuf, (DWORD)bytesToRead, (PDWORD)&bytesRead);
    if (!ok) {
        int err = GetLastError();
        printf("Read error %d\n", err);
        break;
    }

您现在会看到每次读取失败,错误5,&#34;访问被拒绝&#34;。因此,您没有足够的权限来访问其他进程的虚拟内存。请注意OpenProcess(),dwDesiredAccess参数的MSDN article。您使用PROCESS_QUERY_INFORMATION是不够的,想要访问该进程的VM。修正:

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);

您不再需要RtlAdjustPrivilege()黑客,只需将其删除即可。

现在您已经完成了解决程序中其他错误的问题。您仍然会收到读取失败,错误代码299,因为您没有注意内存块的dwState。您不想读取未映射或保留的内存。有些人不可避免地会失败,因为你不被允许在堆栈保护页面中捅,这对于这个过程来说是非常致命的。并且您仍然缺少足够的错误检查,malloc()很可能在此程序中失败并将返回NULL。你可以轻松解决的事情。

答案 1 :(得分:1)

请注意,此答案基于您发布的代码的最新版本。

好吧,首先,手动加载和使用笨重的RTLAdjustPriveliges或多或少都是毫无意义的工作,而AdjustTokenPrivileges可以轻松地获得调试功能:

HANDLE hToken;
LUID seDebugPrivilege;
TOKEN_PRIVILEGES tp;

OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &seDebugPrivilege);

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = seDebugPrivilege;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);

第二件事,这个:

bytesLeft = sizeof(mbi);

while (bytesLeft)
{
   //ReadProcessMemory...
   bytesLeft -= bytesRead;
}
嗯,你想要完成什么 sizeof(mbi)不会让你获得正在阅读的内存的区域大小。它只是struct的大小,而且总是一样的!您可能想要使用mbi.RegionSize

所以,因为在这一行:bytesToRead = (bytesLeft > sizeof(tempbuf)) ? sizeof(tempbuf) : bytesLeft;你将结构的小sizeof与你的巨大阵列的sizeof进行比较,bytesToRead总是等于到bytesLeftReadProcessMemory抓住这个小尺寸的记忆,几乎总是占用所有这些记忆,因此bytesRead几乎总是等于bytesToRead,它总是等于bytesLeft。因此bytesLeft -= bytesReadbytesLeft提供值0。这意味着你的while循环总是在一次迭代后结束。

我想这就是为什么你错过了大量的记忆。你只是没有全部阅读。

如果您在此之后仍然遇到问题,我建议您以管理员身份运行此程序。这有助于阅读某些过程的记忆。