Search code examples
c++delete-operatorheap-corruptionreadprocessmemory

C++ heap corruption when delete is called on char array


hello I cannot understand why this is leading to when I delete this char buffer that the program is returning heap corruption. I made sure I am calling delete correctly for the correct type. I can only think that maybe ReadProcessMemory is causing problem. Furthermore, I am not sure though why this is happening .

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

Solution

  •         if (ReadProcessMemory(hprocess, (LPCVOID)(StartAddress), &Buffer, MemBlockSize, nullptr))
    

    The third parameter to ReadProcessMemory is supposed to be a pointer to the buffer, not a pointer to the address of the buffer.