VirtualProtect and kernel32.dll - attempt to access invalid address
c++, dll, kernel32, winapi, windows
Solution
Pretty hard to verify that you got the address correct, it is unusually low. I just wrote another program to test this. It enumerates the regions in kernel32.dll and calls VirtualProtect() on them:
#include <Windows.h>
#include <assert.h>
#include <iostream>
int main()
{
HMODULE hmod = GetModuleHandle(L"kernel32.dll");
MEMORY_BASIC_INFORMATION info;
// Start at PE32 header
SIZE_T len = VirtualQuery(hmod, &info, sizeof(info));
assert(len > 0);
BYTE* dllBase = (BYTE*)info.AllocationBase;
BYTE* address = dllBase;
for (;;) {
len = VirtualQuery(address, &info, sizeof(info));
assert(len > 0);
if (info.AllocationBase != dllBase) break;
std::cout << "Address: " << std::hex << info.BaseAddress;
std::cout << " (" << std::hex << info.RegionSize << ") ";
std::cout << " protect = " << std::hex << info.Protect;
DWORD oldprotect;
if (info.Protect == 0) std::cout << ", VirtualProtect skipped" << std::endl;
else {
BOOL ok = VirtualProtect(info.BaseAddress, info.RegionSize, PAGE_EXECUTE_READWRITE, &oldprotect);
std::cout << ", VirtualProtect = " << (ok ? "okay" : "Failed!") << std::endl;
}
address = (BYTE*)info.BaseAddress + info.RegionSize;
}
return 0;
}
Output of this program on my machine, running Windows 8.1 x64:
Address: 77470000 (1000) protect = 2, VirtualProtect = okay
Address: 77471000 (f000) protect = 0, VirtualProtect skipped
Address: 77480000 (62000) protect = 20, VirtualProtect = okay
Address: 774E2000 (e000) protect = 0, VirtualProtect skipped
Address: 774F0000 (7e000) protect = 2, VirtualProtect = okay
Address: 7756E000 (2000) protect = 0, VirtualProtect skipped
Address: 77570000 (1000) protect = 4, VirtualProtect = okay
Address: 77571000 (f000) protect = 0, VirtualProtect skipped
Address: 77580000 (1000) protect = 2, VirtualProtect = okay
Address: 77581000 (f000) protect = 0, VirtualProtect skipped
Address: 77590000 (1a000) protect = 2, VirtualProtect = okay
Address: 775AA000 (6000) protect = 0, VirtualProtect skipped
Running it in 64-bit mode:
Address: 00007FFC4F870000 (1000) protect = 2, VirtualProtect = okay
Address: 00007FFC4F871000 (112000) protect = 20, VirtualProtect = okay
Address: 00007FFC4F983000 (1000) protect = 4, VirtualProtect = okay
Address: 00007FFC4F984000 (1000) protect = 8, VirtualProtect = okay
Address: 00007FFC4F985000 (24000) protect = 2, VirtualProtect = okay
Clearly you have a different Windows version so be sure to run this program on your machine to get comparable results.
The conclusion I draw is there is no fundamental reason for this kind of code to fail. And if it does on your machine then that's likely to be environmental. With a very obvious candidate to be your anti-malware software, which of course has a great stake in preventing code from messing with kernel32.dll. I'm running minimal protection on my machine.
Problem
I'm analyzing various modules loaded by the process. Unfortunately I'm not able to create the `kernel32.dll` memory snapshot although the function works properly with other modules (e.g. `ntddl.dll`). The problem is with the following code: ``` /* Copy code from memory */ if (VirtualProtect((BYTE*)virtualAddress, sizeOfCode, PAGE_EXECUTE_READWRITE, &flags) == 0) { std::cout << "VirtualProtect failed!" << std::endl; std::cout << "Virtual address: " << virtualAddress << std::endl; std::cout << "Size of code: " << sizeOfCode << std::endl; std::cout << "Error code: " << GetLastError() << std::endl; } ``` The result of calling this code for `kernel32.dll` is: ``` Virtual address: 747d0000 Size of code: 6a000 Error code: 0x1e7 ``` The error description says that: ``` ERROR_INVALID_ADDRESS 487 (0x1E7) Attempt to access invalid address. ``` I checked the process' memory map and kernel32.dll address is correct. What's the cause?