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

Copying memory from address to buffer not copying

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

#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 错误(部分复制错误)。有什么想法吗?

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

好吧,所以,首先,手动加载和使用笨重的 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 和你的巨大数组的 sizeofbytesToRead 总是结束最多等于 bytesLeftReadProcessMemory 占用这么小的一些内存,几乎总是占用所有内存,因此 bytesRead 几乎总是等于 bytesToRead,它总是等于 bytesLeft。所以 bytesLeft -= bytesReadbytesLeft0。这意味着您的 while 循环总是在一次迭代后结束。

我想这就是您丢失大量内存的原因。你只是没有读完所有内容。

如果在此之后您仍然遇到问题,我建议您运行以管理员身份使用此程序。这可能有助于读取某些进程的内存。

    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,"access denied"。所以你没有足够的权限访问其他进程的虚拟内存。请注意 OpenProcess(), dwDesiredAccess 参数的 MSDN article。你用PROCESS_QUERY_INFORMATION还不够,你想访问进程的VM。修复:

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

您不再需要 RtlAdjustPrivilege() hack,只需将其删除。

您现在可以很好地修复程序中的其他错误。您仍然会遇到读取失败,错误代码 299,那是因为您没有注意内存块的 dwState。您不想读取未映射或保留的内存。有些不可避免地会失败,因为您不允许戳入堆栈保护页面,这对进程来说是非常致命的。而且您仍然缺少足够的错误检查,malloc() 很可能在此程序中失败并且将 return NULL。您自己可以轻松解决的问题。