我正在尝试从进程扫描所有堆内存区域并扫描其中的模式。
我正在使用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代码检索模式所在的特定内存区域/块。
要测试这一点,奇怪的是如果我使用Heap API,我能够识别分配的内存和指定的模式:
__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;
}
我很欣赏VirtualQueryEx代码无法按预期工作的任何提示。值得一提的是,我的Process有几个模块(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;
}
答案 0 :(得分:1)
我重新编写了VirtualQueryEx循环,包括使用ReadProcessMemory并且工作完美。
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;
}