-
-
[原创][分享]Pwn从入门到放弃(五)
-
发表于:
2020-1-19 15:11
12298
-
题目为HCTF2016的一道PWN题,名为fheap,题目下载:
fheap
也可以直接使用c源代码自行编译生成:
话不多说,开始尝试解题:
程序为64位小端,除了stack canary外,保护全开,似乎有些棘手啊。
是一个典型的Create、Delete菜单类题目:
第三步,将程序丢到IDA中看一下:
通过F5,可以在create函数中查看到,当create时,程序会先申请0x20字节的堆块存储空间,如果输入的字符串长度小于0xf,则直接存储于0x20字节的前16个字节处,如果输入的字符串长度大于0xf,则申请相对应长度的空间存储字符串。

而在delete函数中,可以看到,由于程序只是未将指针置空,因此存在Double Free漏洞:



Double Free内存布局:

知识点1-Fastbin:Fast bins用于提高小内存的分配效率,不大于max_fast的chunk被释放后,首先会被缓存到Fast bins中。当分配的chunk小于或等于max_fast时,首先会在fast bins中查找相应的空闲块,用于加速分配。(在32bit的系统中,max_fast的值为64;在64bit的系统中,max_fast的值为128)。
因此只要我们能够将新申请块中的Free函数指针修改为我们想要的函数地址,就可以达到劫持的目的,但是这里有个难点,因为程序开启了PIE保护,导致内存地址随机化的问题。虽然地址随机变化,但由于内存页的载入机制,PIE的随机化只能对单个内存页进行随机化,因此它的低12bit并不会改变,正是因为如此,为我们绕过PIE提供了帮助,具体的方法是将free函数指针的最低位修应该为我们想要改变的函数指针(比如puts),从而去泄露我们想要的函数地址,通过计算偏移可以得到程序的加载基址等信息。


动态调试一下看看,下面是申请了两次小于0xf的堆结构:

释放后重新申请大于0xf的堆结构:

可以看到2260的地方指向的是存放字符串的地址,而free指针已被我们修改为了puts的指针。
完整EXP代码:

参考资料:
c6cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2S2L8Y4q4#2j5h3&6C8k6g2)9J5k6h3y4G2L8g2)9J5c8Y4m8G2M7%4c8Q4x3V1k6A6k6q4)9J5c8U0R3#2x3U0R3I4
c85K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8V1y4Z5j5i4u0D9k6i4y4s2L8$3c8j5i4K6u0r3j5i4u0@1K9h3y4D9k6g2)9J5c8X3c8W2N6r3q4A6L8s2y4Q4x3V1j5^5z5o6V1I4x3e0b7I4y4H3`.`.
044K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4u0S2K9e0c8G2N6X3g2J5i4K6u0W2j5$3&6Q4x3V1j5J5x3o6p5&6i4K6u0r3x3e0q4Q4x3V1j5H3x3#2)9J5c8W2g2K6k6g2)9J5k6p5q4X3N6r3g2J5i4K6u0V1c8Y4u0W2k6g2)9J5y4f1f1$3i4K6t1#2b7V1y4Q4x3U0f1^5c8W2)9J5y4f1f1$3i4K6t1#2b7U0c8Q4x3U0f1&6c8g2)9J5k6o6t1H3x3e0k6Q4x3X3c8t1b7#2c8r3i4K6u0V1k6X3S2W2j5i4m8Q4x3X3c8i4M7X3W2@1k6g2g2H3i4K6u0r3K9h3&6V1k6i4S2Q4x3X3g2Z5N6r3#2D9
1bdK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8X3u0D9L8$3N6K6i4K6u0W2j5$3!0E0i4K6u0r3M7$3S2S2L8X3N6&6k6g2)9J5c8Y4m8Q4x3V1j5$3x3e0f1$3x3K6V1I4i4K6u0W2K9s2c8E0L8l9`.`.
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2020-1-19 15:43
被bugchong编辑
,原因: