PWN系列堆利用之off

访客4年前关于黑客接单1048

我们按照学习原理,然后找一道例题学习,最后复盘总结的方式来学习这个知识点。

off-by-one原理

off-by-one 指程序向缓冲区中写入时,写入的字节数超过了这个缓冲区本身所申请的字节数并且只越界了一个字节。

Asis CTF 2016 b00ks

配置搭建环境

环境:pwndocker配置:

# 配置libc的版本
cp /glibc/2.23/64/lib/ld-2.23.so /tmp/ld-2.23.so
patchelf --set-interpreter /tmp/ld-2.23.so https://www.freebuf.com/articles/web/b00ks
LD_PRELOAD=/glibc/2.23/64/lib/libc.so.6
# 转发输入输出流到 10001 端口
socat tcp-listen:10001,reuseaddr,fork EXEC:https://www.freebuf.com/articles/web/b00ks,pty,raw,echo=0

题目分析

按照惯例,我们先大概浏览一下题目,题目是一个图书管理系统:

1. Create a book 2. Delete a book 3. Edit a book 4. Print book detail 5. Change current author name 6. Exit

简单分析下Create

book 结构中存在 name 和 description , name 和 description 在堆上分配。首先分配 name buffer ,使用 malloc ,大小自定但小于 32 。

printf("
Enter book name size: ", *(_QWORD *)&size);
__isoc99_scanf("%d", &size);
printf("Enter book name (Max 32 chars): ", &size);
ptr=malloc(size);

之后分配 description ,同样大小自定但无限制。

printf("
Enter book description size: ", *(_QWORD *)&size);
      __isoc99_scanf("%d", &size);
v5=malloc(size);

之后分配 book 结构的内存

book=malloc(0x20uLL);
if ( book )
{
  *((_DWORD *)book + 6)=size;
  *((_QWORD *)off_202010 + v2)=book;
  *((_QWORD *)book + 2)=description;
  *((_QWORD *)book + 1)=name;
  *(_DWORD *)book=++unk_202024;
  return 0LL;
}

综合调试,我们得出book的结构体如下:

struct book{
   int id;
   char *name;
   char *description;
   int size;
}

漏洞点

程序编写的 read 函数存在 null byte off-by-one 漏洞,仔细观察这个 read 函数可以发现对于边界的考虑是不当的。

signed __int64 __fastcall MyRead(char *a_string, int str_size)
{
int i; // [rsp+14h] [rbp-Ch]
char *buf; // [rsp+18h] [rbp-8h]
if ( str_size <=0 )
  return 0LL;
buf=a_string;
for ( i=0; ; ++i )
{
  if ( (unsigned int)read(0, buf, 1uLL) !=1 )
    return 1LL;
  if ( *buf==10 )
    break;
  ++buf;
  if ( i==str_size )
    break;
}
*buf=0;
return 0LL;
}

利用思路

攻击过程

1.填充满 author

2.创建堆块1,覆盖author结尾的\x00,这样我们输出的时候就可以泄露堆块1的地址

3.创建堆块2,为后续做准备,堆块2要申请得比较大,因为mmap申请出来的堆块地址与libc有固定的偏移

4.泄露堆块1地址,记为first_heap

5.在调试中我们知道,创建的book结构体的地址是存储在全局变量中的,该全局变量正好与author相临,更改 author,利用多写的一个\x00字节,可以覆盖到堆块1的地址的最后一位,如果我们提前将堆块1的description内容编辑并伪造一个book的结构体,然后多次调试构造好位置,让覆盖过后的地址刚好是book1的description部分的话,我们相当于获得了一个任意地址读写

6.任意读:获得libc地址

7.任意写:将__free_hook函数的地址改写成one_gadget地址

__free_hook若没有则不调用,若有将先于free函数调用

调试

OK现在我们用IDA远程调试的方式按照上边的利用思路来调试一下:

填充 author

我们创建一个32字节大小的名字A

createname(b"A"*32)

然后我们看到填充的内存,除了32个A之外,还额外增加了一个\x00。

1612836740_6021ef847e23dc1475f27.jpg!small

创建堆块1、创建堆块2

创建堆块1后,我们看到0x55C38D8C7530覆盖了author的\x00字节。创建的堆块2的地址也紧接着堆块1。

1612836764_6021ef9c00f9cd5222c45.jpg!small

我们看看堆块1和堆块2的结构体如下:

1612836786_6021efb24f36c0f3f67e2.jpg!small

泄露堆块1地址

我们通过上一步覆盖了末尾的\x00后,就可以打印出堆块1的地址,如下图:

1612836807_6021efc74d8f95e7014ea.jpg!small

编辑堆块1的description字段,伪造堆块1

Payload代码如下,我们注意到我们构造这个假堆块1,它的name指针0x55C38D8C7568指向的是堆块2的name,它的description指针0x55C38D8C7570指向的是堆块2的description。

payload=b'A'*0x50+p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p64(0xffff)
editbook(book_id_1,payload)

让伪造的堆块1恰巧在地址0x55C38D8C7500处,有人或许会问为什么你构造的堆块1是恰巧在这个位置的,因为这是经过多次尝试和调试出来的,适当的将堆块1的description大小分配的大一些,然后增加Payload的偏移。

1612836828_6021efdccd89b97d1a2e1.jpg!small

接下来,最关键的时候到了,如下图,我们再次修改author,使得author填充完32个A之后,还是将\x00覆盖了原始堆块1的地址,导致现在的地址变为了0x55C38D8C7500,恰好指向了我们构造的假的堆块1的地址,这样以来,我们就可以实现任意地址的读写。

1612836848_6021eff09986d8eb774a9.jpg!small

获取libc地址

接下来,我们利用打印功能,打印出堆块1的相关值,因为mmap申请出来的堆块地址与libc有固定的偏移,所以我们利用前边多次调试得到的偏移,计算出libc。

1612836864_6021f00068ecd60e7d605.jpg!small

将__free_hook函数的地址改写成one_gadget地址

首先使用editbook(1,p64(free_hook))将free_hook的指针写到堆块2的description变量中去,然后使用editbook(2,p64(one_gadget)),将one_gadget地址写入到free_hook中去。

1612836881_6021f0119bfd94340ffac.jpg!small

最后我们再调用free获得shell

1612836902_6021f0267fc886d0cb704.jpg!small

小结

在刚开始调试的时候以为是使用pwntools+GDB的调试方式效率比较高一些,但最终发现,图形界面的IDA使得调试时候的视野更加广泛一些,而且还有强大的反编译功能,特别适合初学,也增加了学习的效率。此外针对off-by-one,我们更多的是与其他的技巧结合的方式,做题之前得多次调试理解题目的逻辑和内存的构造,这样做题目才能够得心应手。

相关文章

有泪沟怎么去除小方法(去除泪沟的小方法)

有泪沟怎么去除小方法(去除泪沟的小方法)生活当中因为各种各样的原因,很多人都有泪沟,而泪沟的出现对于我们的形象影响是十分大的,所以我们就要想方法去除泪沟了,那么去除泪沟的方法有哪些呢?如何去除泪沟比较...

动物之森星星碎片怎么获得 集合啦动物森友会星星碎片获取攻略

动物之森星星碎片怎么获得 集合啦动物森友会星星碎片获取攻略

集合啦动物森友会中,玩具啊可以收集很多资源,然后利用资源制作一些东西,比如说,收集星星碎片就可以制作对应的道具。而在游戏中,星星碎片是很稀有的,也不容易获取,那么星星碎片怎么获取?想来很多朋友都还不是...

黑客配音秀视频(黑客配音秀视频下载)

黑客配音秀视频(黑客配音秀视频下载)

本文目录一览: 1、抖音黑客的声音怎么弄 2、感觉被黑客、病毒录屏了怎么办? 3、配音秀下载视频不能用Wi-Fi吗? 4、蒋昌建主持的黑客节目叫什么 抖音黑客的声音怎么弄 1、首先在打开...

支付宝APP扫码得余额宝体验金收益3天,最高100万,亲测2万收益3天白得5元,新增鲤鱼跳龙门流动

使用支付宝APP扫码领取余额宝体验金,最高100万,亲测获得2万体验金。 其实是个送钱的流动,可享受体验金3天的受益, 每个人获得的体验金差别,估量之前余额宝买的少的,体验金领的多。 好比:20...

金砖国家媒体高端论坛双福新区主席团“云聚首” 承诺合

  金砖国家媒体高端论坛主席团“云聚首” 承诺合力推动后疫情时代交流合作   新华社北京11月30日电 金砖国家媒体高端论坛第五次主席团会议30日晚以视频方式举行,各主席团成员一致承诺携手努力,进一...

扎头发的技巧?最实用的扎发教程

步骤一、将头发梳理通顺,预留出刘海的位置,用手抓取图中所示的区域的头发。 步骤二、向右侧将抓取出的发束松松的扎起来。 步骤三、然后在橡皮筋上方的位置将发束掏出一个空隙。 步骤四、将发束的尾部向上...