I am learning x86-64 assembly. I am trying to write some "shellcode".
In the beginning I backup all the registers (I put 123 into rdi
so that I know I am doing everything right in the end)
mov rdi, 123
push rdi
push rsi
push rdx
push rcx
Then I prepare an array of arguments for the syscall execve
on the stack. I just push
pointers (all as qword
) to 0x00
, /usr/bin/touch AAA
, -c
and /bin/sh
and then I call execve
with address of rsp
in rsi
. The program works as expected.
But then I pop
the register values I pushed earlier and call sys_exit
with the value 123 that should now be in rdi
where I put it in the beginning.
; pop 4 times - the pointers for execve
pop rax
pop rax
pop rax
pop rax
; pop the backed up registers
pop rcx
pop rdx
pop rsi
pop rdi
; call EXIT with exit code in rdi
mov rax, 60
syscall
When I execute the code, it works as expected, but after executing echo $?
the output is 0
.
However if I comment out the syscall
command from where I call execve
, the output of echo $?
is 123
as it should be.
When I try to see what is happening in gdb
, it is complaining that I am running another process from my program (breakpoint 1 was at the beginning of the program, breakpoint 2 on mov rax, 60
at the end):
process 10140 is executing new program: /bin/dash
Error in re-setting breakpoint 1: No source file named /home/...
Error in re-setting breakpoint 2: No source file named /home/...
[Inferior 1 (process 10140) exited normally]
Why is the code behaving like this? Why does the system call to execve /bin/sh -c /usr/bin/touch AAA
change the stack of my program and how do I restore the registers properly?
Thank you for your answers.