1. 풀이
- level17의 권한을 부여하고 /bin/sh를 실행하는 shell() 함수와 문자를 출력하는 printit() 함수가 존재
- (*call) 함수 포인터를 printit() 함수 시작주소로 초기화 및 fgets()로 사용자 입력을 받은 후 call() 호출
- 즉, (*call)를 shell() 함수의 주소를 가리키게 한다면 문제를 풀 수 있을 것임
① Procedure Prelude
0x08048518 <main+0>: push %ebp
0x08048519 <main+1>: mov %esp,%ebp
0x0804851b <main+3>: sub $0x38,%esp
- 지역변수에 56byte(0x38) 할당
② void (*call)()=printit;
0x0804851e <main+6>: movl $0x8048500,0xfffffff0(%ebp) // printit() 함수 주소
- (*call) 함수 포인터에 $0x8048500 값 즉, printit() 함수의 주소를 저장
- printit() 함수를 disassembly 하면 시작 주소를 알 수 있으며, (*call) 함수 포인터는 0xfffffff0에 저장되어 있는것을 알 수 있음.
- 또한,같은 방법으로 shell() 함수의 시작 주소(0x080484d0)를 알 수 있음
③ fgets(배열, 문자 길이, STDIN)
0x08048528 <main+16>: pushl 0x80496e8 // STDIN
0x0804852e <main+22>: push $0x30 // 문자길이 (0x30 = 48)
0x08048530 <main+24>: lea 0xffffffc8(%ebp),%eax // 0xffffffc8 (buf의 주소)
0x08048533 <main+27>: push %eax // buf 주소
0x08048534 <main+28>: call 0x8048384 <fgets>
- 즉, fgets()를 통해 0xffffffc8 (buf의 주소)에 사용자 입력값을 받음
- ②와 ③을 통해 buf와 (*call) 사이에 20byte 만큼의 dummy가 있으며, 나머지 12 byte 공간에 crap(4byte)+dummy(8byte)가 저장되어 있음
- fgets() 실행 후인 main+33 지점에 bp 설정 및 level16 실행 후 esp 메모리 값을 확인
④ call()
0x0804853c <main+36>: mov 0xfffffff0(%ebp),%eax
0x0804853f <main+39>: call *%eax
- printit() 호출
- 메모리 구조는 위 그림과 같으며, 아래 그림 처럼 (*call) 함수 포인터를 shell() 함수의 주소로 설정할 경우 쉘을 획득할 수 있음
- buf와 dummy의 40byte 만큼의 NOP 슬라이드와 shell() 함수의 시작주소를 Littel Endian 방식으로 페이로드 작성
'문제풀이 > FTZ' 카테고리의 다른 글
FTZ Level18 풀이 (0) | 2022.11.07 |
---|---|
FTZ Level17 풀이 (0) | 2022.11.07 |
FTZ Level15 풀이 (0) | 2022.11.05 |
FTZ Level14 풀이 (0) | 2022.11.05 |
FTZ Level13 풀이 (0) | 2022.11.04 |