There are other questions about the same message, but I specifically seem to run into this when I try to execute a string of machine code that invokes certain functions. In my case I make a call to exit(0) which works fine when called as typical in C in the same program. If, however, as an exercise I set the EIP to the address of some machine code (you might call it “shellcode”), e.g.
const char code[] =
"\x6A\x00" // push 0"
"\xFF\x15\x00\x00\x00\x00" //system call, 'read access violation': call dword ptr [__imp__exit]
"\x5D" //pop ebp
"\xC3"; //ret
I will get the message “Access violation reading location 0x00000000.”. The “\x6A\x00” instruction will run, but the call to exit(0) will throw this exception.
This is C compiled in VS2010 with /GS-, and also running the “shellcode” with execute rights, but is there still some sort of nonexecutable memory or stack protection going on? Why is this instruction causing an error?
int main()
{
void *exec = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, code, sizeof(code));
//EIP = exec in debug->immediate
exit(0);
}
If you disassemble your shellcode, you’ll get something like this (AT&T syntax):
The
callinstruction is doing a memory-indirect jump through address 0: it’s loading the target from memory address 0 and jumping to that location. Since memory address 0 is invalid (in rare exceptions it can be valid, but this is no exception), an access violation results.Ordinarily, when you compile C code, the jumps to external functions get replaced by placeholders, and those placeholders get filled in by the linker at link time. When you’re generating shellcode at runtime, you don’t have the assistance of the linker, so you have to do it yourself. You need to figure out what your desired target address is and fill that in directly in the shellcode, possibly using some position-independent tricks if you don’t know exactly what address the shellcode is going to execute at.