I'm trying to figure out how to execute arbitrary code on Windows 10. I feel like this code should work, but it's giving me an Access violation writing location error.
#include <iostream>
#include <vector>
#include <Windows.h>
// x64 assembly
#define ret (uint8_t)(0xc3)
#define nop (uint8_t)(0x90)
int main() {
std::vector<uint8_t> raw_code = {
nop, ret
};
LPVOID exec = VirtualAlloc(NULL, raw_code.size(), MEM_RESERVE, PAGE_READWRITE);
memcpy(exec, raw_code.data(), raw_code.size());
DWORD old_protect;
VirtualProtect(exec, raw_code.size(), PAGE_EXECUTE, &old_protect); // Line where error occurs
((void(*)())exec)();
VirtualProtect(exec, raw_code.size(), old_protect, &old_protect);
VirtualFree(exec, raw_code.size(), MEM_RELEASE);
return 0;
}
Well, for one thing MEM_RESERVE
means the memory isn't allocated, so trying to dereference the pointer will cause an access violation (as you saw for yourself). Don't be cute and just allocate your memory as normal, using MEM_COMMIT | MEM_RESERVE
.
You also aren't setting your memory to be executable, you need to use PAGE_EXECUTE_READWRITE
instead. Otherwise, with DEP enabled, your code will crash with access violation.
Actually, the error occurs on the following line (at least, it does when I run your code):
memcpy(exec, raw_code.data(), raw_code.size());
This is because your call to VirtualAlloc
only reserves memory, but does not actually commit it. From the documentation:
MEM_RESERVE (0x00002000)
Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk.
To commit the memory (i.e., make it usable), you need to add the MEM_COMMIT
flag:
LPVOID exec = VirtualAlloc(nullptr, raw_code.size(), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
With this flag added, you code runs on my Windows 10 (built with clang-cl/VS-2019) without error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With