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