2017-12-18 7 views
0

Ich versuche, alle Heapspeicherbereiche von einem Prozess zu scannen und ein Muster darin zu scannen.Suchen eines Musters in einem Prozess-Heap-Speicher

Ich benutze x64 und Windows 10. Ich bin im Zielprozess nur zu Testzwecken.

Mein Code ist:

std::vector<__int64> matches; // Holds all pattern matches 

int FindPattern(__int64 patternAddress, char * mask) { 

SYSTEM_INFO sysInfo; // Holds System Information 
GetSystemInfo(&sysInfo); 

__int64 procMin = (__int64)sysInfo.lpMinimumApplicationAddress; // Minimum memory address of process 
__int64 procMax = (__int64)sysInfo.lpMaximumApplicationAddress; // Maximum memory address of process 

MEMORY_BASIC_INFORMATION mBI, mBINext; 
DWORD firstOldProtect = NULL; 
DWORD secondOldProtect = NULL; 
HMODULE hdll; 

DWORD patternSize = (DWORD)strlen(mask); 

while (procMin < procMax) { // While still scanning memory 

    VirtualQueryEx(GetCurrentProcess(), (LPVOID)procMin, &mBI, sizeof(MEMORY_BASIC_INFORMATION)); // Get memory page details 

    if (mBI.State == MEM_COMMIT) { 

     VirtualProtect((LPVOID)procMin, mBI.RegionSize, PAGE_EXECUTE_READWRITE, &firstOldProtect); // Set page to read/write/execute 

     for (auto n = (__int64)mBI.BaseAddress; n < (__int64)mBI.BaseAddress + mBI.RegionSize; n += 0x01) { // For each byte in this page 

      if (n + patternSize > procMax) { // If our pattern will extend past the maximum memory address, break 
       break; 
      } 

      if (*(char*)n == (*(char*)patternAddress)) { // If first byte of pattern matches current byte 

       if (n + patternSize < (UINT)mBI.BaseAddress + mBI.RegionSize) { // If entire length of pattern is within this page 

        if (ComparePattern((__int64)n, patternAddress, mask)) { // Test if full pattern matches 
         matches.push_back((__int64)n); // If it does, add it to the vector 
        } 
       } 
       else { // If it isn't within the same page 
        VirtualQueryEx(GetCurrentProcess(), (LPVOID)(procMin + mBI.RegionSize), &mBINext, sizeof(MEMORY_BASIC_INFORMATION)); // Same memory page stuff with next page 

        if (mBINext.State == MEM_COMMIT) { 
         VirtualProtect((LPVOID)(procMin + mBI.RegionSize), mBINext.RegionSize, PAGE_EXECUTE_READWRITE, &secondOldProtect); 

         if (ComparePattern((__int64)n, patternAddress, mask)) { 
          matches.push_back((__int64)n); 
         } 
        } 
       } 
      } 
     } 

     VirtualProtect((LPVOID)procMin, mBI.RegionSize, firstOldProtect, NULL); // Reset memory page state of first page 

     if (secondOldProtect) { // If we scanned into the second page 
      VirtualProtect((LPVOID)procMin, mBINext.RegionSize, secondOldProtect, NULL); // Reset memory page state of second page 
      secondOldProtect = NULL; 
     } 
    } 
    procMin = procMin + (__int64) mBI.RegionSize; // Start scanning next page 
    } 
return 0; 
} 

Dann wird die ComparePattern Funktion:

bool ComparePattern(__int64 address, __int64 patternAddress, char * mask) { 
int patternLen = strlen(mask); 

for (auto i = 1; i < patternLen; i++) { 
    if (mask[i] != *"?" && *(char*)(address + i) != *(char*)(patternAddress + i)) { // Compare each byte of the pattern with each byte after the current scanning address 
     return false; 
    } 
} 
if (address != patternAddress) { // Make sure we aren't returning a match for the pattern defined within your DLLMain 
    return true; 
} 
return false; 
} 

ich mehrere Speicherblöcke abrufen, aber ich bin nicht der spezifischen Speicherbereich/Block, in dem die in der Lage abrufen Muster wird mit diesem VirtualQueryEx-Code gefunden.

Um dies zu testen, und das seltsame Teil ist, dass, wenn ich die Heap-APIs verwenden, ich bin in der Lage, den Speicher zu identifizieren, zugeordnet und mit dem angegebenen Muster:

__int64 ReturnMachHeapAPI(__int64 patternAddress, char * mask) { 

HANDLE hHeaps[250]; 

DWORD numHeaps = GetProcessHeaps(250, hHeaps); 
unsigned long i; 

if (numHeaps <= 250) 
{ 
    for (i = 0; i < numHeaps; i++) { 

     HeapLock(hHeaps[i]); 

     PROCESS_HEAP_ENTRY entry; 
     memset(&entry, '\0', sizeof entry); 

     bool found = false; 

     while (!found && HeapWalk(hHeaps[i], &entry) != FALSE) 
     { 
       for (auto ii = (__int64)entry.lpData; ii < (__int64)entry.lpData + entry.cbData; ii += 0x01) { 

        if (ComparePattern((__int64)ii, patternAddress, mask)) { 

         return ii; 
        } 
       } 
     } 
    HeapUnlock(hHeaps[i]); 
    } 
} 
return 0; 
} 

ich auf irgendwelche Hinweise zu schätzen wissen, warum der VirtualQueryEx Code nicht Arbeiten wie erwartet. Ein erwähnenswerter Punkt ist, dass mein Prozess mehrere Module (DLLs) zusammen mit der Hauptdatei enthält.

Vielen Dank.

EDIT: Ich schrieb die VirtualQueryEx-Schleife mit ReadProcessMemory jetzt neu. Es funktioniert jetzt perfekt.

Der Arbeitscode lautet:

char* InScan(char* pattern, char* mask, char* begin, unsigned int size) 
{ 
//strlen the mask, not the pattern if you use the pattern 
//you will get short length because null terminator 
unsigned int patternLength = strlen(mask); 

for (unsigned int i = 0; i < size - patternLength; i++) 
{ 
    bool found = true; 
    for (unsigned int j = 0; j < patternLength; j++) 
    { 
     if (mask[j] != '?' && pattern[j] != *(begin + i + j)) 
     { 
      found = false; 
      break; 
     } 
    } 
    if (found) 
    { 
     return (begin + i); 
    } 
} 
return 0; 
} 

char * PatternScan(char* pattern, char* mask) 
{ 

SYSTEM_INFO sysInfo; 
GetSystemInfo(&sysInfo); 

__int64 end = (__int64)sysInfo.lpMaximumApplicationAddress; 

char* currentChunk = 0; 
char* match = nullptr; 
SIZE_T bytesRead; 

while (currentChunk < (char *) end) 
{ 
    MEMORY_BASIC_INFORMATION mbi; 

    HANDLE process = GetCurrentProcess(); 
    int hr = GetLastError(); 

    if (!VirtualQueryEx(process, currentChunk, &mbi, sizeof(mbi))) 
    { 
     return 0; 
    } 

    char* buffer = 0; 

    if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS) 
    { 
     buffer = new char[mbi.RegionSize]; 
     DWORD oldprotect; 
     if (VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &oldprotect)) 
     { 
      ReadProcessMemory(process, mbi.BaseAddress, buffer, mbi.RegionSize, &bytesRead); 
      VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, oldprotect, &oldprotect); 

      char* internalAddress = InScan(pattern, mask, buffer, bytesRead); 

      if (internalAddress != 0) 
      { 
       //calculate from internal to external 

       __int64 offsetFromBuffer = internalAddress - buffer; 
       match = currentChunk + offsetFromBuffer; 
       delete[] buffer; 
       break; 
      } 
     } 
    } 

    currentChunk = currentChunk + mbi.RegionSize; 
    if (buffer) delete[] buffer; 
    buffer = 0; 
} 
return match; 
} 

Antwort

1

ich die VirtualQueryEx Schleife neu geschrieben, einschließlich der Verwendung von Readprocessmemory und funktioniert perfekt.

char* InScan(char* pattern, char* mask, char* begin, unsigned int size) 
{ 

unsigned int patternLength = strlen(mask); 

for (unsigned int i = 0; i < size - patternLength; i++) 

{ 

bool found = true; 
for (unsigned int j = 0; j < patternLength; j++) 
{ 
    if (mask[j] != '?' && pattern[j] != *(begin + i + j)) 
    { 
     found = false; 
     break; 
    } 
} 
if (found) 
{ 
    return (begin + i); 
} 
} 

return 0; 

} 



char * PatternScan(char* pattern, char* mask) 
{ 

SYSTEM_INFO sysInfo; 

GetSystemInfo(&sysInfo); 

__int64 end = (__int64)sysInfo.lpMaximumApplicationAddress; 

char* currentChunk = 0; 
char* match = nullptr; 
SIZE_T bytesRead; 

while (currentChunk < (char *) end) 

{ 

MEMORY_BASIC_INFORMATION mbi; 

HANDLE process = GetCurrentProcess(); 
int hr = GetLastError(); 

if (!VirtualQueryEx(process, currentChunk, &mbi, sizeof(mbi))) 
{ 
    return 0; 
} 

char* buffer = 0; 


if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS) 
{ 
    buffer = new char[mbi.RegionSize]; 
    DWORD oldprotect; 
    if (VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &oldprotect)) 
    { 
     ReadProcessMemory(process, mbi.BaseAddress, buffer, mbi.RegionSize, &bytesRead); 
     VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, oldprotect, &oldprotect); 

     char* internalAddress = InScan(pattern, mask, buffer, bytesRead); 

     if (internalAddress != 0) 
     { 
      //calculate from internal to external 

      __int64 offsetFromBuffer = internalAddress - buffer; 
      match = currentChunk + offsetFromBuffer; 
      delete[] buffer; 
      break; 
     } 
    } 
} 

currentChunk = currentChunk + mbi.RegionSize; 

if (buffer) delete[] buffer; 
buffer = 0; 
} 

return match; 

} 
Verwandte Themen