【发布时间】:2021-11-02 18:13:34
【问题描述】:
你好,我不明白为什么当我删除这个 char 缓冲区时,程序返回堆损坏。我确保我为正确的类型正确调用了删除。我只能认为可能是 ReadProcessMemory 引起了问题。此外,我不确定为什么会这样。
#include "includes.h"
HANDLE pHandle;
//F2 ?? 0F 38 F1 ??
// { 0xF2, 0x48, 0x49, 0x0F, 0x38, 0xF1, 0x1C, 0xC2 }
struct crc32Values {
byte first;
byte skip;
byte skip2;
byte third1;
byte third2;
byte third3;
byte lastskip;
byte lastskip2;
};
HANDLE Cr32Scanner::LaunchSuspendedProcess(char* cmd, PHANDLE ptr_thread) // cleaned up a bit, but no RAII
{
if (ptr_thread == nullptr) return nullptr;
PROCESS_INFORMATION pi;
STARTUPINFOA si{}; // initialize with zeroes.
si.cb = sizeof(STARTUPINFOA);
if (!CreateProcessA(nullptr, cmd, nullptr, nullptr, false, CREATE_SUSPENDED,
nullptr, nullptr, std::addressof(si), std::addressof(pi)))
{
std::cerr << "CreateProcess failed, " << GetLastError() << '\n';
*ptr_thread = nullptr;
return nullptr;
}
*ptr_thread = pi.hThread;
return pi.hProcess;
}
void PrintAddress(unsigned char* value)
{
std::cout << std::hex << value << std::dec;
}
void Cr32Scanner::EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);
CloseHandle(hToken);
}
void Cr32Scanner::GetVirtuInfo(HANDLE hprocess)
{
MEMORY_BASIC_INFORMATION mbi;
unsigned char* addr = 0;
while (VirtualQueryEx(hprocess, addr, &mbi, sizeof(mbi)))
{
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && mbi.Protect != PAGE_GUARD)
{
//std::cout << "base : 0x" << std::hex << mbi.BaseAddress << " end : 0x" << std::hex << (uintptr_t)mbi.BaseAddress + mbi.RegionSize << "\n";
this->InsertNodeAtLastPosition(&this->s_vmap, (uintptr_t)mbi.BaseAddress, (uintptr_t)mbi.BaseAddress + mbi.RegionSize, mbi.RegionSize);
}
addr += mbi.RegionSize;
}
//this->printList(this->s_vmap);
}
//F2 ?? 0F38F1 ?? ??
//F2 48 0F38F1 1C C2
//F2 49 0F38F1 04 C8
//F2 49 0F38F1 0C C0
//F2 48 0F38F1 3C C6
//F2 48 0F38F1 34 C7
//F2 48 0F38F1 3C C3
//F2 48 0F38F1 1C C7
bool found = false;
int main()
{
std::shared_ptr <Cr32Scanner> p_cr32scanner(new Cr32Scanner());
MEMORY_BASIC_INFORMATION MemInfo;
crc32Values s_crc32values = { 0xF2, 0x48, 0x49, 0x0F, 0x38, 0xF1, 0x1C, 0xC2 };
bool Is64Bit = false;
// set current process with admin token
p_cr32scanner->EnableDebugPriv();
char cmd[] = "C:\\Users\\Scd\\Desktop\\Testremmy_patched.exe"; // #notepad.exe"; // note: non-const (writeable array)
HANDLE thread = nullptr;
unsigned char* addr = 0;
std::cout << "Creating Process for " << cmd << std::endl;
HANDLE hprocess = p_cr32scanner->LaunchSuspendedProcess(cmd, std::addressof(thread));
p_cr32scanner->GetVirtuInfo(hprocess);
if (hprocess)
{
//GET NEXT blocks
VirtualAddressMap::vmap *currentNode = p_cr32scanner->s_vmap;
while(currentNode != nullptr){
long long StartAddress = currentNode->StartAddress;
long long EndAddress = currentNode->EndAddress;
size_t MemBlockSize = currentNode->RegionSize;
// CHECK BLOCK SIZES
std::cout << "Start Addr: " << std::hex << currentNode->StartAddress << " EndAddress " << std::hex << currentNode->EndAddress << " BlockSize " << currentNode->RegionSize << std::endl;
char* Buffer = new char[MemBlockSize + 1];
memset(&Buffer[0], 0, MemBlockSize + 1);
if (ReadProcessMemory(hprocess, (LPCVOID)(StartAddress), &Buffer, MemBlockSize, nullptr))
{
printf("[-] Error Occured - Failed to Read Memory. At Address -- 0x%llx 0x%08X \n", StartAddress, GetLastError());
break;
}
for (unsigned int i = 0; i < MemBlockSize; i++) {
if (Buffer[i] == s_crc32values.first) {
if (Buffer[i + 1] == s_crc32values.skip || Buffer[i + 1] == s_crc32values.skip2) {
if (Buffer[i + 2] == s_crc32values.third1) {
if (Buffer[i + 3] == s_crc32values.third2) {
if (Buffer[i + 4] == s_crc32values.third3) {
printf("CRC32 Found! at 0x%llx\n", StartAddress + i);
//found = true;
//break;
}
}
}
}
}
}
currentNode = currentNode->Next;
// crash here.
// delete[] Buffer;
}
std::cout << "press enter to resume process... " && std::cin.get();
ResumeThread(thread);
CloseHandle(thread);
CloseHandle(hprocess);
}
}
【问题讨论】:
-
它看起来几乎没有错误检查 - 将错误检查添加到您调用的 所有 API 函数中,您会发现问题。
-
我对@987654322@ 并不完全熟悉,但我认为您想通过
Buffer而不是&Buffer。看起来它会覆盖 pointer 而不是指向的缓冲区。 -
此外,您似乎正在阅读
Buffer的结尾和Buffer[i + 1]、Buffer[i + 2]等。 -
考虑改用
std::vector<char> Buffer(MemBlockSize + 1, 0);。它进行零初始化并为您管理内存。您可以删除memset和delete[],您不必再担心任何内存管理。 -
@FrançoisAndrieux 看起来缓冲区应该是 LPVOID,我应该如何将其转换为将缓冲区接收到向量中?
标签: c++ delete-operator heap-corruption readprocessmemory