.global main
main:
call func
.string "/bin/sh"
func:
push %rsp
pop %rsi
pop %rdi
mov $0x00, %edx
mov $0x3b, %eax
syscall
I wrote assembly lagunage like above for execute /bin/sh
I compiled it but when I try to execute program, /bin/sh: 0: Can't open ????
this error is occur.
It doesn't execute /bin/sh. I want to know why I can't execute /bin/sh
I'm using Ubuntu 16.04 and x64 Architectures
Your code is needlessly hard to follow because of using push/pop in a weird way, but running your program under
strace -f ./a.out
to trace the system calls shows:So on my system,
execve
returns with an error, but the program exits successfully. IDK how you're getting/bin/sh: 0: Can't open ????
. Your question doesn't contain enough information to reproduce your results. But maybe when you tried, the stack happened to contain different garbage. I built it withgcc -g foo.S
.After
main
fails to return, execution falls through into whatever CRT function followsmain
, which does end with a RET instruction. It must also zero eax, since it will be-EFAULT
after the SYSCALL.Anyway, your asm is equivalent to this non-useful code:
note that
push %rsp; pop %rsi
is equivalent tomov %rsp, %rsi
. So RSI holds a pointer to the stack memory where CALL wrote the "return address".One more POP after that dereferences the stack pointer and loads the pointer to the string into RDI.
Using CALL to push the address of a string is really nasty. IDK why you'd do that. Just use MOV like a normal person.
How to do this correctly
This works, and doesn't do anything weird.
Or, in a way that works as a position-independent flat binary, and doesn't use main()'s argv, since you added that request:
Your RSI=RSP idea is not bad, but you forgot to add a terminating NULL pointer to the end of the
argv[]
array.Outside of
main
which getsenvp[]
as an arg, we don't have an already-constructedenvp[]
accessible anywhere convenient, so just pass NULL. On Linux, that's equivalent to passing a valid pointer to an empty NULL-terminated array, i.e. a pointer to an 8-byte0
in memory.C code:
64 bit X86 assembly code:
you can invoke the shell as:
or
With this code all parameters of the command "shell" will be passed to /bin/bash unchanged.
Also the process name will change and become "bash" (in ps -ef)
And what is more important (which I didn't see anywhere else)
is that with this code the environment is preserved. (no pun intended)
If you don't need the args and you don't want the env preserved, uncomment the comments and comment the previous lines.