Use After Free

  • use after free

    free之后的变量,该变量的堆内存处的内存指针还在指向该内存处,所以当我们下一次申请同样大小的变量时,可以申请到上一个变量的位置

    使用gdb可视化观察堆

  • free()

  • 观察堆

    set disassembly-flavor intel

    set pagination off

    disassembly main

    info proc mapping 查看内存映射

    deine hook-stop

    x/56wx 0x804c000

    x/3i $eip

    end

    查看第一次malloc(32),该快已被标记not free

    查看strcpy之后

    每个地址4字节,每行16字节,即0x10大小

    free(c)

    现在就有个了新的块叫fastbins,这个c作为头

    free(b)

    链表fastbins:c←b

    free(a)

    链表fastbins:c←b←a

    unlink (): 如果刚释放的堆块要与前面或者后面的堆块进行合并操作,那么需要把前面或者后面的堆块从双向链表中摘取下来,合成更大的堆块插入到别的bin之中,将空闲堆块从bin里面摘取下来的操作就是unlink

    /* consolidate backward 往前合并*/ 
     //先检查要free chunk的上一个chunk是不是 in_use,不是的话就往下操作 
    if (!prev_inuse(p)) {
    		//取p的前一个chunk的size
    		prevsize = prev_size(p);
    		//free_chunk的size + 上一个chunk的size 
    		size += prevsize; 
    		//p指向上一个chunk的开始处 
    		p = chunk_at_offset(p, -((long)prevsize)); 
    		if (__glibc_unlikely(chunksize(p) != prevsize)) 
    //检查前后改变的chunk的size大小跟prev_size是不是相等 
    malloc_printerr("corrupted size vs. prev_size while consolidating"); 
    unlink(av, p, bck, fwd); //这个就是我们要利用的地方了,下面有详解 
    }
    

    P是从block we want to free的prevsize找到的previous block

    FD是通过P的fd找到的,BK是通过P的bk找到的

    用gdb模拟攻击

    set {int}0x804c054=100,使得size这里的最尾位为0(freed)

    再把prevsize设成0x10因为我们想要创造一个fake chunk,然后往前数0x10大小的chunk的size改成0x11代表in use.

    然后把GOT表的put函数地址搞来,放在前面那个假装in use块的fd处

    bk放heap里放shellcode的地址

    注意一下,chunk空闲的时候FD和BK才发挥作用,如果非空闲那么从FD开始就是usedata了

  • free的时候会检查能否向前和向后合并

    来自 :https://wooyun.js.org/drops/堆溢出的unlink利用方法.html

    1)检查是否可以向后合并

    首先需要检查previous chunk是否是空闲的(通过当前chunk size部分中的flag最低位去判断),当然在这个例子中,前一个chunk是正在使用的,不满足向后合并的条件。

    2)检查是否可以向前合并

    在这里需要检查next chunk是否是空闲的(通过下下个chunk的flag的最低位去判断) ,

    在找下下个chunk(这里的下、包括下下都是相对于chunk first而言的)的过程中,

    首先当前chunk+当前size可以引导到下个chunk

    然后从下个chunk的开头+下个chunk的size就可以引导到下下个chunk

    但是我们已经把下个chunk的size覆盖为了-4,

    那么它会认为下个chunkprev_size开始就是下下个chunk了,

    既然已经找到了下下个chunk,那就就要去看看size的最低位以确定下个chunk是否在使用,当然这个size-4,所以它指示下个chunk是空闲的。

    在这个时候,就要发生向前合并了。即first chunk会和 first chunk下个chunk(即second chunk)发生合并。在此时会触发unlink(second)宏,想将second从它所在的bin list中解引用。

    具体如下

  • how computer handle negative values

    cale in 32 bit : 0xFFFF FFFC + 0x64 = 0x60

    the same to :-0x4 + 0x64 = 0x60

    Null-Bytes :0xFFFF FFFC = -4

    所以现在有两个要求:

    1.因为要用双链表merge所以得size>80(因为要避免单链表fastbin < 80)

    2.set prev not in use,last bit of the block we going to free is set to 0.

    所以我们需要两个fake chunk,第一个用来伪造FD和BK来覆盖上GOT函数地址,第二个用来把size的最低位设为0.

    而在查找size时候是用加offset来做的,不关心我们用了多大的size

    然后我们把offset/size设成0xFFFF FFFC导致最后的结果为-4

    这时候查找nextchunk的时候会找到我们仍set的ffff fffc的地方

    然后就向后合并unlink了

  • 利用unlink把shellcode写进put函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 堆使用后释放错误(heap use after free)是指在程序中使用了已经被释放的堆内存。这种错误通常会导致程序崩溃或者出现不可预测的行为。为了避免这种错误,程序员需要在使用完堆内存后及时释放它,并且在释放后不再使用该内存。 ### 回答2: heap use after free是一种常见的内存使用错误,它指的是在使用堆内存时,释放了某个内存块,但后续又继续使用了该内存块。这种错误可以导致程序崩溃、数据损坏,甚至是安全漏洞。 通常,堆内存的分配和释放是由程序员负责的。在程序中,当需要动态分配一块内存时,通常使用malloc()函数,在使用完该内存块之后,需要通过free()函数来释放该内存块。但是,如果程序员在释放内存块之后,依然在程序中继续使用该内存块,则会发生heap use after free错误。 具体来说,当程序释放内存块时,操作系统会将该内存块标记为可用的状态,但是并不会真正销毁该内存块,这意味着该内存块中原有的数据可能还存在,但已经不再属于该内存块。如果程序员在已经释放了内存块的情况下,继续使用该内存块,则可能会覆盖该内存块原有的数据,导致数据损坏。此外,由于已经释放的内存块可能会被操作系统重复利用,这也可能会导致堆内存中存在未预期的数据。 为了避免heap use after free错误,程序员可以采取一些措施。首先,应该在使用内存块之前检查该内存块是否已经被释放,以确保不会继续使用已经释放的内存块。其次,在释放内存块之后,可以将指向该内存块的指针设置为NULL,以避免意外地继续使用该内存块。此外,可以使用一些内存检测工具,如Valgrind等,来帮助检测和排除heap use after free错误。 ### 回答3: Heap use after free(堆溢出)是一种常见的内存管理错误,它会导致程序崩溃或者安全漏洞。 当程序中使用malloc()、realloc()、calloc()等动态分配内存的函数后,程序会在堆区域内分配内存,同时也会记录该块内存的大小和地址等信息。而当程序中释放该块内存时,通过free()函数将其返回给操作系统并将相关记录清空,但是在程序中,如果继续使用已经释放的内存,就会导致Heap use after free错误。 通常,程序员在使用free()函数释放内存后,应该将指向该内存的指针设置为NULL,以避免后续误用该指针。否则,指针会指向之前释放的内存地址,后续再次访问该指针就会导致程序崩溃或者执行错误的操作。 堆溢出还可能是一些恶意程序攻击的手段。攻击者在程序中制造类似的堆溢出漏洞,以便在运行时利用该漏洞来执行恶意代码。这种攻击被称为堆溢出攻击(Heap Overflow Attack)。 对于企业和个人开发者来说,避免Heap use after free错误可以通过以下几个方面来做到。 1. 了解内存分配释放的细节,在编写程序时注意不要出现内存泄露、重复释放等问题。 2. 使用内存分配和释放函数时,必须正确地管理内存指针,不要造成内存泄露或者重复释放的问题。 3. 使用编译器的内存检查工具进行内存检查,如Valgrind、Clang、GCC等。 4. 在编写程序时,可以使用一些内存管理工具和库,如Boost库、STL库等。这些工具和库可以帮助程序员进行内存管理和错误检测,减少代码错误的可能性。 总之,了解和避免Heap use after free错误是编写高质量、可靠和安全的程序的必要条件之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值