堆的初始化
堆的初始化–源码分析堆的初始化堆的初始化是用户在第一次申请内存执行malloc_consolidate 再执行malloc_init_state实现的。
malloc_init_state1234567891011121314151617181920212223242526272829#define INTERNAL_SIZE_T size_t#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))//就是size_t的长度typedef struct malloc_state *mstate; //mstate就是malloc_sate 指针static struct malloc_state main_arena; //main_arena在这里声明的typedef struct malloc_chunk* mbinptr;#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - (SIZE_SZ<<1))) /* 寻址 ...
堆的Tcache机制
堆的Tcache机制tcache是glibc 2.26(ubuntu 17.10)之后引入的一种技术 ,目的是提升堆管理的性能。但提升性能的同时舍弃了很多安全检查,也因此有利很多新的利用方式。
相关结构体tcache 引入了两个新的结构体,tcache_entry和tcache_perthread_struct。
这其实和fastbin很像,但又不一样。
tcache_entry123456/* We overlay this structure on the user-data portion of a chunk when the chunk is stored in the per-thread cache. */typedef struct tcache_entry{ struct tcache_entry *next;} tcache_entry;
tcache_entry用于链接空闲的chunk结构体,其中的 next指针指向下一个大小相同的chunk。需要注意的是这里的next指向chunk的user data,而fastbin的fd指向ch ...
堆溢出
堆溢出介绍堆溢出是指程序向某个堆块中写入的字节数超过了堆块本身可以使用的字节数(之所以是可以使用而不是用户申请的字节数,是因为堆管理器会对用户所申请的字节数进行调整,这也导致可利用的字节数都不小于用户申请的字节数)因而导致了数据溢出,并覆盖到了物理相邻的高地址的下一个堆块。
不难发现,堆溢出漏洞发生的基本前提是
程序向堆上写入数据。
写入的数据大小没有被良好地控制。
对于攻击者来说,堆溢出漏洞轻则可以使得程序崩溃,重则可以使得攻击者控制程序执行流程。
堆溢出是一种特定的缓冲区溢出(还有栈溢出,bss段溢出等)。但是其与栈溢出有所不同的是,堆上并不存在返回地址可以让攻击者直接控制执行流程的数据,因此我们一般无法直接通过堆溢出来控制EIP。一般来说,我们利用堆溢出的策略是
覆盖与其 物理相邻的下一个chunk的内容
pre_size
size,主要有三个比特位,以及该堆块真正的大小。
NON_MAIN_ARENA
IS_MAPPED
PREV_INUSE
the True chunk size
chunk content ,从而改变程序固有的执行流。
利用堆中的机制(如 un ...
堆学习---fastbin二次释放
堆学习—fastbin二次释放
由于fastbin采用单链表结构(通过fd指针进行链接),且当chunk释放时,不会清空next_chunk的prev_inuse,再加上一些检查机制上的不完善,使得fastbin比较脆弱。针对它的攻击方法包括二次释放,修改fd指针并申请(或释放)任意位置的chunk(或fake chunk)等,条件是存在堆溢出或者其他漏洞能够控制chunk的内容。
fastbin dup一般而言,不同大小的free chuk会被分类到不同的bin中,而bin的类型可以被分为fast bin ,small bin,large bin 以及unsorted bin 。其中,fast bin的操作效率最高,为单向链表,其他的都是双向链表。较高的操作效率意味着较低的安全性(传统艺能—牺牲安全换效率),所以fastbin机制产生的漏洞也是堆区漏洞最重要的组成部分之一。
默认情况下,对于size_t为4B的平台, 小于64B的chunk分配请求;对于size_t为8B的平台,小于128B的chunk分配请求,程序会根据所需的size首先到fastbin中去寻找对应大小的bin中 ...
堆利用
堆利用1.1 glibc 堆概述1.1.1 内存管理与堆内存管理是对计算机的内存资源进行管理,这要求在程序请求时能够动态分配内存的一部分,并在程序不需要时释放分配的内存。CTF中常见的ptmalloc2就是glibc实现内存管理机制,它继承自dlmalloc,并提供了对多线程的支持。
其他常见的堆管理机制还有 dlmalloc, tcmalloc ,jemalloc等,一般这些机制由用户显示的调用malloc())函数申请内存,调用free()函数释放内存。除此之外,还有由编程语言实现的自动内存管理机制,也就是垃圾回收。
堆是程序虚拟内存中由低地址向高地址增长的线性区域。一般只有当用户向操作系统申请内存时,这片区域才会被内核分配出来,并且由于页对齐和效率的问题,一般分配的空间很大。堆的位置一般在BSS段的高地址处。
brk()和sbrk()堆的属性是可读可写的,大小通过brk()和sbrk()函数进行控制。如下图,在堆未初始化时,program_break 指向BSS段的末尾,通过调用brk()和sbrk()函数来移动progam_break使得堆增长。在堆初始化时,如果开启了ASLR ...
堆中的Off-By-One
堆中的Off-By-One介绍严格来说off-by-onr漏洞是一种特殊的溢出漏洞,off-by-one指程序向缓冲区写入时,写入的字节数超过了这个缓冲区本身所申请的字节数并且只越界了一个字节。这种漏洞往往是在字符串操作时边界检查不严谨所导致的,例如
循环语句中的循环次数设置有误。
字符串操作不合适
一般来说,单字节溢出被认为是难以利用的,但是因为Linux的堆管理机制ptmalloc验证的松散性,基于Linux堆的off-by-one漏洞利用起来并不复杂,并且威力强大。
off-by-one利用思路发生在堆上的off-by-one,根据其是否涉及堆块头的修改可以分为两类,第一类是普通的off-by-one,通常用于修改堆上的指针;第二类则是通过溢出修改堆块头,制造堆块重叠,达到泄露或改写其他数据的目的,通常情况下溢出后修改的是下一个堆块的size域。由于glibc采用了空间复用技术,即将下一个堆块的prev_size域提供给当前chunk使用,所以堆块实际可用的大小(可以由malloc_usable_size()获得)不是固定的,如果堆块是通过mmap分配的,实际可用大小是siz ...
WEBPWN-初探
WEBPWN-初探前言在好几次接触到webpwn的一直没去复现,打完熊猫杯就准备以这个为基础开始复现
0x00 2024年熊猫杯这道题给了一个docker环境
检查一下保护发现只有简单的保护
前置知识CGICGI,全称是Common Gateway Interface(通用网关接口),是一种标准,用于定义Web服务器与外部应用程序(通常称为CGI脚本)之间的交互方式。CGI脚本可以用多种编程语言编写,如C、C++、Perl、Python、PHP等。组成CGI通信系统的是两部分:一部分是html页面,就是在用户端浏览器上显示的页面。另一部分则是运行在服务器上的Cgi程序。它们之间的通讯方式如下图:
服务器和客户端之间的通信,是客户端的浏览器和服务器端的http服务器之间的HTTP通信,我们只需要知道浏览器请求执行服务器上哪个CGI程序就可以了,其他不必深究细节,因为这些过程不需要程序员去操作。
服务器和CGI程序之间的通讯才是我们关注的。一般情况下,服务器和CGI程序之间是通过标准输入输出来进行数据传递的,而这个过程需要环境变量的协作方可实现。
1. 服务器将URL指向一个应用程序 ...
ret2dlsolve漏洞的复现
ret2dlsolve漏洞的复现前言为了学到更多的关于ROP利用的知识开始复现这个漏洞,也为了能够更加深刻的了解程序动态链接的过程,学习更加底层的知识。
原理在Linux中,程序使用_dl_runtime_resolve(link_map_obj,reloc_offset)来对动态链接的函数进行重定位。那么如果我们可以控制相应的参数及其对应地址的内容是不是就可以控制解析函数了呢?答案是肯定的。这也就是ret2dlresolve攻击的核心所在。
具体的,动态链接器在解析符号地址时所使用的重定位表项,动态符号表,动态字符串表都是从目标文件中的动态节.dynamic索引得到的。如果我们能够修改其中的某些内容使得动态链接器解析的符号是我们想要解析的符号,那么攻击就达成了。
思路一 – 直接控制重定位表项的相关内容由于动态链接器最后在解析符号的地址时,是依据符号的名字进行解析的。因此,一个很自然的想法是直接修改动态字符串表.dynstr,比如把某个函数在字符串表中对应的字符串修改为目标函数对应的字符串表。但是动态字符串表和代码映射在一起,是只读的,此外,类似地,我们可以发现动态符号表,重定位表项 ...
ret2csu原理与利用
ret2csu原理与利用原理
在 64 位程序中,函数的前 6 个参数是通过寄存器传递的,但是大多数时候,我们很难找到每一个寄存器对应的 gadgets。 这时候,我们可以利用 x64 下的 __libc_csu_init 中的 gadgets。这个函数是用来对 libc 进行初始化操作的,而一般的程序都会调用 libc 函数,所以这个函数一定会存在。我们先来看一下这个函数 (当然,不同版本的这个函数有一定的区别)
123456789101112131415161718192021222324252627282930313233343536373839404142.text:00000000004005C0 ; void _libc_csu_init(void).text:00000000004005C0 public __libc_csu_init.text:00000000004005C0 __libc_csu_init proc near ; DATA XREF: _start+16o.text:0000000000 ...
RELRO保护原理
RELRO保护原理简介由于 GOT和PLT以及延迟绑定的原因,在启用延迟绑定时,符号解析只发生在第一次使用的时候,该过程是通过PLT表进行的,解析完成后,相应的GOT条目会被修改为正确的函数地址。因此,在延迟绑定的情况下。.got.plt必须可写,这就给了攻击者篡改地址劫持程序的执行的可能。
RELRO(ReLocation Read-Only)机制的提出就是为了解决延迟绑定的安全问题,它最初于2004年由Redhat的工程师Jakub jelnek实现,他将符号重定位表设置为只读,或者在程序启动时就解析并绑定所有的动态符号,从而避免GOT上的地址被篡改。RELRO有两种形式:
partial PELRO:一些段(包括.dynamic,.got等)在初始化后会被标记为只读。在unbuntu16.04(GCC-5.4.0)上,默认开启Partial RELRO。
**Full RELRO **:除了Partial RELRO,延迟绑定将被禁止,所有的导入符号将在开始时被解析,.got.plt段会被完全初始化为目标函数的最终地址,并被mprotect标记为只读,但其实.got.plt会被 ...