I'm writing a memory scanner and I want to be able to copy the memory content of a particular address to the buffer inside a memory block structure that I created. Here's my code so far:
#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;
}
Now, the problem that I'm encountering is, that I know for a fact that the memory content is not empty, as shown below:
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
we see that the size is non zero, but after running the memory block on the update function to copy the memory to a buffer, this is what happens:
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
My guess is that my updateMemblock function is the cause of this whole debacle, but not sure what's wrong...
EDIT:
After investigating a bit, it seems like the problem lies in my ReadProcessMemory call. With some googling I learned that there are processes that have a Page_Guard flag set, which prevents the memory for that process from being read using ReadProcessMemory, I also learned that it's possible to temporarily disable this flag by using VirtualProtectEx, this is how I'm using it (and as you can imagine, it's not working for me yet)
DOWRD OLDPROTECT;
VirtualProtectEx(mb->hProc, mb->addr+totalRead, 1, PAGE_READONLY, &OLDPROTECT))
EDIT:
So I tinkered with it for a bit, and this is what I have:
#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;
}
The good news is that some of the memory content is being read, and VirtualQueryEx is returning proper content sometimes, the issue is, it's not getting everything from the memory as you can see in the output (also removed it from storing the read memory to a MEMBLOCK, no longer takes 500mb memory to just read notepad). Some debugging shows that I'm getting a 12b error (Partial Copy error). Any ideas?
ReadProcessMemory(mb->hProc, ...);
This is where your problem started, a common mistake when using the Winapi. You must add error checking, it is not optional. Failure to do so produces undiagnosable failure. Correct this to:
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;
}
You'll now see that every read fails with error 5, "access denied". So you don't have enough privilege to access the virtual memory of the other process. Turn your attention to the MSDN article for OpenProcess(), dwDesiredAccess argument. Your use of PROCESS_QUERY_INFORMATION is not enough, you also want to access the VM of the process. Fix:
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);
You no longer need the RtlAdjustPrivilege() hack, just delete it.
You are now well ahead to fix the other bugs in your program. You still get read failures, error code 299, that's because you don't pay attention to dwState of the memory block. You don't want to read unmapped or reserved memory. And some are inevitably going to fail because you are not allowed to poke in the stack guard pages, that would be pretty fatal to the process. And you are still missing enough error checking, malloc() is pretty likely to fail in this program and is going to return NULL. Things you can easily fix yourself.
Please note that this answer is based on the last version of the code you posted.
All right, so, first thing, manually loading and using the clunky RTLAdjustPriveliges
is more or less lots of pointless work, while AdjustTokenPrivileges
can get you the debug privelige just as easily:
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);
Second thing, this:
bytesLeft = sizeof(mbi);
while (bytesLeft)
{
//ReadProcessMemory...
bytesLeft -= bytesRead;
}
Um, what exactly are you trying to accomplish? sizeof(mbi)
isn't going to get you the region size of the memory you're reading. It's just the size of the struct
, and it's always the same! You probably wanted to use mbi.RegionSize
.
So, because in this line: bytesToRead = (bytesLeft > sizeof(tempbuf)) ? sizeof(tempbuf) : bytesLeft;
you're comparing the small sizeof
of the struct with the sizeof
of your humongous array, bytesToRead
always ends up equal to bytesLeft
. ReadProcessMemory
grabs some memory of this small size, and nearly always takes all of it, so bytesRead
is nearly always equal to bytesToRead
, which is always equal to bytesLeft
. So bytesLeft -= bytesRead
gives bytesLeft
the value 0
. This means your while
loop invariably ends after one iteration.
I guess this is why you're missing out on lots of memory. You're just not reading all of it.
If you'll still encounter problems after this, I recommend you run this program as administrator. This could help with reading the memory of some processes.
User contributions licensed under CC BY-SA 3.0