소스코드
스케치:
Step 1) ebp와 box 사이의 offset을 안다면 case 'P'의 print_box 함수를 이용하여 canary를 1byte씩 Leak 시킬 수 있을 것이다.
Step 2) 그 후 case 'E'에서 얻어낸 Canary를 이용하여 Canary 보호기법을 우회한 뒤 Return Address를 get_shell()로 옮겨, get_shell()이 실행되게 하면 shell을 획득할 수 있을 것이다.
Step 1. main함수의 Stack Frame 구조 파악
1) 함수 프롤로그가 일어난 후 <main+3>에서 4byte 크기의 dummy(edi)가 푸쉬된 것을 확인할 수 있다.
2) 그리고, main Stack Frame의 크기가 0x94(148byte) 크기인 것 또한 <main+4>에서 확인할 수 있다.
3) gs:[0x14]에 있는 canary값이 eax에 저장되고, 이 eax값이 ebp-8에 푸시(==Canary)된다.
4) ebp<->select의 offset은 0x8a(138)임을 확인할 수 있다
5) ebp와 box 사이의 offset을 알아내기 위해 case 'F'로 진입한다. 이를 위해 <main+135>에 break point를 설정하고 run 해준다. <main+138>에서 eax의 값과 0x48('F')이 같으면 <main+155>(==case 'F')로 jump되는 것을 확인할 수 있다.
그리고 case 'F'에서 read를 통해 box에 값을 넣어줄 때 ebp-0x88에 넣어주는 것을 확인할 수 있다. 이를 통해 ebp<->box offset이 0x88(136)임을 확인할 수 있다.
6) 5에서와 같은 방법으로 case 'P'로 진입한 뒤 <main+205>에서 ebp<->idx의 offset을 구해보면 offset이 0x94(148)임을 확인할 수 있다.
7) 위와 같은 방법으로 case 'E'에 진입한다. scanf 함수가 실행되는 것을 통해 <main+262>에서 ebp<->name_len의 offset이 0x90(144)임을 확인할 수 있다.
8) 그리고 case 'E' 안에서 printf 이후 read 함수가 실행되는 것을 통해 ebp<->name의 offset을 구할 수 있다. <main+302>를 통해 ebp<->name의 offset이 0x48(72)임을 확인할 수 있다.
1~8까지의 정보를 종합하여 main()의 Stack Frame 구조를 정리해보면 다음과 같다.
Step 2. Canary Leak & get_shell()의 주소 구하기
1) case 'P' 에서는 box[idx]를 출력해주므로 오버플로우를 이용하여 idx값에 128, 129, 130, 131을 넣어주면 Canary 값을 획들할 수 있을 것이다.
2) 이제 pwndbg를 이용하여 우리의 목표인 get_shell()의 주소는 '0x080486b9'임을 확인할 수 있다.
Step 3. 익스플로잇 구현
case 'P'를 이용하여 Canary를 획득한 후 이를 이용하여 case 'E'에서 name_len에 충분히 큰 값을 주고 name에 값을 입력하는 것을 통해 Buffer Overflow를 이용하여 Return Address를 get_shell()로 옮겨주면 성공적으로 shell을 획득할 수 있을 것이다
pwntools를 이용하여 짠 익스플로잇 코드는 다음과 같다
########## ssp_001.py ##########
그리고 이를 실행시켜보면 성공적으로 shell을 획득했음을 확인할 수 있다.
'DreamHack: System Hacking > F Stage 6' 카테고리의 다른 글
Exploit Tech: Return to Shellcode (0) | 2023.05.05 |
---|---|
Mitigation: Stack Canary (0) | 2023.05.05 |