2017-12-18 5 views
0

프로세스에서 모든 힙 메모리 영역을 스캔하고 패턴을 스캔하려고합니다.프로세스 힙에서 패턴 찾기 메모리

x64 및 Windows 10을 사용하고 있습니다. 테스트 목적으로 만 대상 프로세스 안에 있습니다.

내 코드는 다음과 같습니다

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; 
} 

그런 다음 ComparePattern 기능은 다음과 같습니다 나는 여러 메모리 블록을 검색

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; 
} 

,하지만 특정 메모리 영역/블록을 검색 할 수있는 아니에요 곳 패턴은이 VirtualQueryEx 코드를 사용하여 찾을 수 있습니다.

이를 테스트하고 이상한 부분은 내가 힙 API를 사용하는 경우 I는 할당 된 메모리와 지정된 패턴 식별 할 생각이다 : 나는 VirtualQueryEx 코드가없는 이유에 대한 어떤 힌트를 주셔서 감사합니다

__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; 
} 

을 예상대로 작동합니다. 한 가지 언급할만한 점은 내 프로세스에는 주요 실행 파일과 함께 여러 모듈 (DLL)이 있다는 것입니다.

고마워요.

편집 : 이제 ReadProcessMemory를 사용하여 VirtualQueryEx 루프를 다시 작성했습니다. 이제 완벽하게 작동합니다.

작업 코드는 다음과 같습니다

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; 
} 

답변

1

내가 ReadProcessMemory의 사용을 포함하여 VirtualQueryEx 루프를 다시 쓰고 완벽하게 작동합니다.

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; 

}