0

The reading works fine until it reaches base+27.058.176(bytes) address. At this address VirtualProtect() failes with error 487 (Attempt to access invalid address).

Why does it return this error? Btw the process uses over 300 MB of memory.

if (vInTokens.size() == 3 && !vInTokens.at(0).compare("scan")) {   // vInTokens holds the command and parameters
        int valueToScan = std::stoi(vInTokens.at(1));   // param 1
        Uint offset = std::stoi(vInTokens.at(2));       // param 2
        hits.clear();   // hits is a global variable of type std::vector. in this vector all addresses with valueToScan should get stored.
        Uint scans = 0; // tracks the number of integers (4 bytes) read
        Uint pages = 0; // tracks the number of process pages read

        Uint addr = base;   // base is a global variable that holds the process base address. retrieved with (Uint)GetModuleHandle(NULL)
        Uint addr_max = base + offset; // 0x7FFFFFFF;
        MEMORY_BASIC_INFORMATION mbi{};

        while (addr < addr_max) {

            // get page
            if (VirtualQuery((LPCVOID)addr, &mbi, sizeof(mbi)) == 0) {
                std::cout << "Error: VirtualQuery failed with error " << GetLastError() << std::endl;
                break;
            }

            // update page protection (enable read and write)
            DWORD oldProtect;
            if(VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &oldProtect) == 0) {
                std::cout << "Error: VirtualProtect(1) failed with error " << GetLastError() << " at " << std::hex << addr << std::endl;
                break;
            }

            // read page memory
            Uint start = addr;
            Uint end = start + mbi.RegionSize;
            while (start < end) {
                int value = *((int*)start);
                if(value == valueToScan)
                    hits.push_back(start);
                scans++;
                start += 4;
            }

            // restore old page protection
            if (VirtualProtect(mbi.BaseAddress, mbi.RegionSize, oldProtect, &oldProtect) == 0) {
                std::cout << "Error: VirtualProtect(2) failed with error " << " with code " << GetLastError() << " at " << std::hex << addr << std::endl;
                break;
            }

            // set values for next page
            pages++;
            addr += mbi.RegionSize;
            mbi = {};
        }

        std::cout << "Scanned " << std::dec << scans << std::endl;
        std::cout << "Pages   " << std::dec << pages << std::endl;
        std::cout << "Found   " << std::dec << hits.size() << std::endl;
    }
0

MEMORY_BASIC_INFORMATION struct holds a "State" property that is one of the following:

MEM_RESERVE, MEM_COMMIT, MEM_FREE

You can only use VirtualProtect on pages that are actually allocated for use, i.e. the MEM_COMMIT type.

Reserved and free memory pages cannot be read or written to and so you cannot change their protection flags.

A process may take memory of size x, split over many pages that are not continguous.

| improve this answer | |
  • Now I added a additional check for state == MEM_COMMIT. But it still returns an error a couple addresses later (base+27.394.048(bytes)). But the error code changed, now it's 87 (The parameter is incorrect.) ?? – Created Mar 30 at 22:44
  • You should add sanity checks before the call to VirtualProtect to better understand what is going on, breakpoints/assertions/prints etc. Make sure that the page address and sizes are aligned to the size of a full page. Also, check the type property of the area, if is it a MAPPED_* type region then you cannot change its protection to a different one than the one it was initially mapped with. – Yotamz Mar 31 at 8:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.