So after changing the entry point via the e_entry field I managed to execute my shellcode before returning control to the original entry point. Here's how I did it:
// write string and jump to OEP, patch address at 23
unsigned char shellcode[] = "\x48\x31\xc0\x48\x31\xff\x48\x31\xf6\xeb"
"\x16\x5e\xb0\x01\x40\xb7\x01\xb2\x09\x0f"
"\x05\x48\xb8\x41\x41\x41\x41\x41\x41\x41"
"\xff\xe0\xe8\xe5\xff\xff\xff\x68\x69\x6a"
"\x61\x63\x6b\x65\x64\x0a";
So as soon as I parse the ELF header I patch the shellcode:
uint64_t oep = ehdr->e_entry;
memcpy(&opcode[23], &oep, 8);
Everything works, the shellcode executes and then execution resumes where it should. The problem is that after the target's main function finishes it segfaults(To make things simple I just made a program that prints a string).
So I used gdb and IDA to see what's going on. Just to make things clear the flow of excution is as follows:
- execution starts at the shellcode
- shellcode jumps to _start
- _start calls libc_start_main
- main executes and returns to libc_start_main
Now, after main returns IDA shows the following:
libc_start_main:
ext:000000000040244B lea rax, [rsp+108h+var_98]
.text:0000000000402450 mov fs:300h, rax
.text:0000000000402459 mov rdx, cs:environ
.text:0000000000402460 mov edi, [rsp+108h+var_FC]
.text:0000000000402464 mov rsi, [rsp+108h+var_F8]
.text:0000000000402469 mov rax, [rsp+108h+mainaddr]
.text:000000000040246E call rax ; jump to main
.text:0000000000402470 mov edi, eax
.text:0000000000402472
.text:0000000000402472 loc_402472: ; CODE XREF: __libc_start_main+4AF↓j
.text:0000000000402472 call exit
.text:0000000000402477 ; -----------------------------------------------------------
The exit function ends up calling run_exit_handlers which appears to be the real culprit, as it faults with the following instruction:
mov rdx, [rax+18h]
mov rdi, [rax+20h]
mov qword ptr [rax+10h], 0
mov esi, ebp
ror rdx, 11h
xor rdx, fs:30h
call rdx ; faults
jmp loc_40823A
For some reason rdx has the value of 9, which is not allowed and hence causes the segmentation fault.
I searched for information on run_exit_handlers but didn't find anything meaningful.
So my question is: Why is this happening? All my shellcode does is write a string and jump to the OEP, it shouldn't really affect anything else.
e0 e8
seems OK, but the rest disassembles to something strange likein eax, 0xff
. By the way, I think you meantmemcpy(&shellcode...
instead ofopcode
.