Reputation: 23
i am succesfully build up my shellcode.
[BITS 64]
segment .text
global _start
_start: jmp call
back: lea rsi, [rsp]
mov rdi, [rsi]
xor rax, rax
push rax
lea rdx, [rsp]
mov al, 0x3b
syscall
call: call back
db "/bin/sh",0
But there is something mysterious about the code execution. I still can not figure it out whats the issue and maybe someone is able to help.
When i am debugging the code with radare2 the whole process of setting the arguments and syscalling is executed twice. I have no idea whats wrong with it. The registers, rip and so on looks good. In the end, the shell pops after the second loop. But for execution on stack it is a pain in the ass, because my /bin/sh screwed up in the second loop.
The first syscall returns -14 (BAD ADRESS)
I tried already some code variations and RTFM. Help
Thank you in advance :)
Upvotes: 1
Views: 135
Reputation: 44046
Well, the argv
array is malformed.
You set that parameter to an address on the stack but you didn't put a null pointer to terminate it.
This is the (lower portion of) stack when the first instruction of _start
is executed:
...
0
argN
...
arg0
argc <-- rsp
Note that these are the arguments of your program. Also note that <--
means "points to" (or: contains the address of).
When back
is called the stack is:
...
0
argN
...
arg0
count
ptr to shell path <-- rsp
After the lea
s (by the way, lea
with such a trivial addressing mode is just a mov
) and the xor
, the stack is:
...
0
argN
...
arg0
count
ptr to shell path <-- rsp, rsi
rdi = ptr to shell path
Then just before the syscall
we have:
...
0
argN
...
arg0
count
ptr to shell path <-- rsi
rdi = ptr to shell path
0 <-- rsp, rdx
Then execve
will read the executable path from rdi
(which checks), the envp
from rdx
(which checks), and the argv
from rsi
(which fails).
The last one fails because execve
will read up the stack from the path of the shell to the first 0, but count
is not a valid pointer (it is probably 1).
Having the system call failed, the execution falls through to call back
, the steps are repeated but this time the 0 from the previous iteration will correctly terminate argv
:
...
0
argN
...
arg0
count
ptr to shell path
0
ptr to shell path <-- rsi
rdi = ptr to shell path
0 <-- rsp, rdx
You can:
count
could be interpreted as a valid pointer, giving the shell an argument).count
into a zero. You can move xor eax, eax
up and use mov [rsp+8], rax
. This works in other contexts as long as you can write at [rsp+8]
.xchg
or similar.argv
and envp
as NULL
(i.e. zero out rsi
and rdx
). On Linux this has the same effect as what you are already doing (passing an array with a single null pointer).mov
to overwrite count
.Upvotes: 4