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

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

最佳答案

    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,“访问被拒绝”。所以你没有足够的权限访问其他进程的虚拟内存。将注意力转移到 MSDN article对于 OpenProcess(),dwDesiredAccess 参数。您对 PROCESS_QUERY_INFORMATION 的使用还不够,您想要访问进程的 VM。修复:

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

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

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

关于将内存从地址复制到缓冲区而不是复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28569437/

相关文章:

c - 结构的字段是否算作变量?数组的元素算作变量吗?

无法在 VS2012 中的 for 循环后声明变量

c - C中的UDP客户端源端口?

c - 有哪些重构方法可以减少编译代码的大小?

c - 在 Linux 中使用 c 私有(private)内存使用量不断增加

c - 程序的执行停止 - C(内存分配)

c - 在c中将文本文件读入字符数组

c++ - CIELab 色彩空间转换

java - 我的 JUnit 测试在 Eclipse 中运行时有效,但有时会通过 Ant 随机失败

memory - 如何分析堆转储