Reputation: 1
simple asm for ptint the string "/bin/sh" and then exit
global _start:
_start:
jmp what
are:
mov rbx,0x68732f6e69622fff
shr rbx,0x8
push rbx
mov rsi,rsp
mov dl,0x8
xor rax,rax
mov al,1
syscall
xor rax,rax
mov al,0x3c
syscall
what:
call are
nasm -f elf64 test.asm
ld -o test test.o
Run as expected .
but use in shellcode :
const char shellcode[] = "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe6\xb2\x08\x48\x31\xc0\xb0\x01\x0f\x05\x48\x31\xc0\xb0\x3c\x0f\x05";
int main(){
( (void (*)(void))&shellcode )();
return 0;
}
gcc -fno-stack-protector -z execstack -o test2 test.c
it prints nothing.
Upvotes: 0
Views: 107
Reputation: 39306
Your code assumes rdi
== 0, 1, or 2, and that 56 high bits of rdx
are zero. This happens to be true at the start of the process. It just isn't true at the point where you call your shellcode.
To fix, you need to set rdi
to 1 (if you want the output to be to standard output) or 2 (for output to go to standard error), and set rdx
8.
The syscall ABI in Linux on x86-64 is
syscall number in rax
char
, short
, int
, long
, and pointer parameters in rdi
, rsi
, rdx
, r10
, r8
, and r9
registers, respectively
return value will be in rax
; most syscalls return -errno
if an error occurs
(the actual errno
variable is a C library construct, and the kernel does not know anything about it)
rcx
and r11
are clobbered (may be modified by the syscall); all other registers are preserved
Thus, for write
(SYS_write
== __NR_write
== 1) you set rax
== 1; rdi
== descriptor number (STDOUT_FILENO
== 1 for standard output, STDERR_FILENO
== 2 for standard error); rsi
== pointer to the data to be written, and rdx
== the number of chars to be written.
Upvotes: 2