I currently got interested in binary exploitation (even though I do not know if today is still useful).
I started studying shellcode and buffer overflow (stack-buffer overflow, specifically). I know that this vulnerability is nowadays rare, but I still want to lean how to perform it (I have to start somewhere). So I wrote this shellcode:
section .text
global _start
_start:
xor rdx, rdx
push rdx
mov rax, 0x68732f2f6e69622f
push rax
mov rdi, rsp
push rdx
push rdi
mov rsi, rsp
xor rax, rax
mov al, 0x3b
syscall
and a C program to execute it:
char shellcode[] = "\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x31\xc0\xb0\x3b\x0f\x05";
int main(){
void(*f)() = (void(*)())shellcode;
f();
return 0;
}
Though when I run it, I got SIGSEGV
error.
This is what I get when I use strace
:
execve("./exec", ["./exec"], 0x7ffe855b4e80 /* 57 vars */) = 0
brk(NULL) = 0x55f5dd4d6000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffcceb7b7b0) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f913a4c2000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=81189, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 81189, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f913a4ae000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P<\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2072888, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2117488, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f913a200000
mmap(0x7f913a222000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f913a222000
mmap(0x7f913a39a000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19a000) = 0x7f913a39a000
mmap(0x7f913a3f2000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1f1000) = 0x7f913a3f2000
mmap(0x7f913a3f8000, 53104, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f913a3f8000
close(3) = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f913a4ab000
arch_prctl(ARCH_SET_FS, 0x7f913a4ab740) = 0
set_tid_address(0x7f913a4aba10) = 5515
set_robust_list(0x7f913a4aba20, 24) = 0
rseq(0x7f913a4ac060, 0x20, 0, 0x53053053) = 0
mprotect(0x7f913a3f2000, 16384, PROT_READ) = 0
mprotect(0x55f5dc905000, 4096, PROT_READ) = 0
mprotect(0x7f913a4f7000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7f913a4ae000, 81189) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x55f5dc906010} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
This is what I get running the program using GBD (peda):
RAX: 0x0
RBX: 0x7fffffffde88 --> 0x7fffffffe1e7 ("/home/mastermind/Desktop/Hydrogen/shellcode/exec")
RCX: 0x555555557df8 --> 0x5555555550e0 (<__do_global_dtors_aux>: endbr64)
RDX: 0x555555558010 --> 0x622fb84852d23148
RSI: 0x7fffffffde88 --> 0x7fffffffe1e7 ("/home/mastermind/Desktop/Hydrogen/shellcode/exec")
RDI: 0x1
RBP: 0x7fffffffdd70 --> 0x1
RSP: 0x7fffffffdd58 --> 0x55555555514b (<main+34>: mov eax,0x0)
RIP: 0x555555558010 --> 0x622fb84852d23148
R8 : 0x0
R9 : 0x7ffff7fccfb0 (<_dl_fini>: endbr64)
R10: 0x7ffff7fc88e8 --> 0xb00120000000e
R11: 0x7ffff7fe1480 (<_dl_audit_preinit>: endbr64)
R12: 0x0
R13: 0x7fffffffde98 --> 0x7fffffffe217 ("SHELL=/bin/bash")
R14: 0x555555557df8 --> 0x5555555550e0 (<__do_global_dtors_aux>: endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x555555558009: adc BYTE PTR [rbp+0x55],0x55
0x55555555800d: push rbp
0x55555555800e: add BYTE PTR [rax],al
=> 0x555555558010 <shellcode>: xor rdx,rdx
0x555555558013 <shellcode+3>: push rdx
0x555555558014 <shellcode+4>: movabs rax,0x5068732f6e69622f
0x55555555801e <shellcode+14>: mov rdi,rsp
0x555555558021 <shellcode+17>: push rdx
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdd58 --> 0x55555555514b (<main+34>: mov eax,0x0)
0008| 0x7fffffffdd60 --> 0x0
0016| 0x7fffffffdd68 --> 0x555555558010 --> 0x622fb84852d23148
0024| 0x7fffffffdd70 --> 0x1
0032| 0x7fffffffdd78 --> 0x7ffff7c23a90 (<__libc_start_call_main+128>: mov edi,eax)
0040| 0x7fffffffdd80 --> 0x7fffffffde70 --> 0x7fffffffde78 --> 0x38 ('8')
0048| 0x7fffffffdd88 --> 0x555555555129 (<main>: endbr64)
0056| 0x7fffffffdd90 --> 0x155554040
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000555555558010 in shellcode ()
Can you please help me figure out what the problem is here? I have tried countless times, changing the shellcode, analysing the program using GDB, but still the memory segmentation error present itself. If I am not able to execute the shellcode, I am not even able to exploit the stack-overflow vulnerability.
Thanks in advance for any useful answer.
Just as a side note:
I compiled the program using:
gcc -m64 -fno-stack-protector -z execstack -o exec exec.c
Got the shellcode using
objdump
strace
?