1. 核心原理:glibc 的堆块管理机制在 glibc 中,空闲堆块通过双向链表组织(fd 和 bk 指针)
123456struct malloc_chunk { size_t prev_size; // 前一块大小 size_t size; // 当前块大小 + 标志位 struct malloc_chunk *fd; // 前向指针(指向链表中前一个空闲块) struct malloc_chunk *bk; // 后向指针(指向链表中后一个空闲块)};
当释放堆块时,glibc 会执行 unlink 操作将其从空闲链表移除:
1234567// 简化版 unlink 宏#define unlink(P, BK, FD) { FD = P->fd; BK = P->bk; FD->bk = BK; // 关键操作:任意地址写 BK->fd = FD; // 关键操作:任意地址写}
2. 攻击条件
堆溢出漏洞:可覆盖相邻堆块的 ...
signal机制signal机制是类unix系统中进程之间相互传递信息的一种方法。一般,我们也称之为软中断信号,或者软中断。比如说进程之间可以通过系统调用kill来发送软中断信号。一般分为三大步
1.内核会向某个进程发送signal机制,改进程会被暂时挂起,进入内核态
2.内核会为该进程保存相应的上下文,跳转到之前注册好的signal handler中处理signal
3.signal返回
4.内核为进程恢复之前保留的上下文,恢复进程的执行
内核会为进程保存相应的上下文,主要是将所有寄存器压入栈中,以及压入signal信息 以及指向sigreturn的系统调用地址。此时栈的结构如下图所示,我们称ucontext以及siginfo这一段为Signal Frame。需要注意的是,这一部分是在用户进程的地址空间的。之后会跳转到注册过的signal handler中处理相应的signal。因此,当signal handler执行完之后,就会执行sigreturn代码
1234567#unix signals+++++++++++++| stack || uncontext || si ...
ida分析首先来看题目
123456789101112int __cdecl main(int argc, const char **argv, const char **envp){ char format[68]; // [esp+0h] [ebp-48h] BYREF setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); puts("Welcome to my ctf! What's your name?"); __isoc99_scanf("%64s", format); printf("Hello "); printf(format); return 0;}
可以看到题目里有明显的格式化字符串漏洞
再来看一下函数表
123456789101112131415161718192021222324252627_init_procsub_80483A0_printf_puts_system___libc_start_main_s ...
UAF 即 Use After Free (释放后使用)当一个指针所指向的指针块被释放掉之后可以再次被使用, 但是这是有要求的,不妨将所有的情况列举出来
12345chunk被释放之后,其对应的指针被设置为NULL,如果再次使用它,程序就会崩溃。chunk被释放之后,其对应的指针未被设置为NULL,如果在下一次使用之前没有代码对这块内存进行修改,那么再次使用这个指针时**程序很有可能正常运转**内存块被释放后,其对应的指针没有被设置为NULL,但是在它下一次使用之前,有代码对这块内存进行了修改,那么当程序再次使用这块内存时,**就很有可能会出现奇怪的问题**
在堆中 Use After Free 一般指的是后两种漏洞, 我们一般称被释放后没有被设置为NULL的内存指针为dangling pointer(悬空指针)
来看一道题
[HNCTF 2022 WEEK4]ez_uafida静态分析
123456789101112131415161718192021222324252627282930313233343536373839404142int __fastcall __noret ...
漏洞利用的必要条件chunk extend 是堆漏洞的一种常见利用手法, 通过extend可以实现chunk overlapping(块重叠)的效果。这种利用手法需要以下的时机和条件:
1.程序中存在基于堆的漏洞
2.漏洞可以控制chunk header 中的数据
基本示例 1: 对inuse 的 fastbin 进行 extend
源码如下:
123#include<stdio.h>int main(void)
基本概念字典是另一种可变容器模型,且可存储任意类型对象。
字典的每个键值 key=>value 对用冒号 : 分割,每个对之间用逗号(,)分割,整个字典包括在花括号 {} 中 ,格式如下所示:
1d = {key1 : value1, key2 : value2, key3 : value3 }
注意:dict 作为 Python 的关键字和内置函数,变量名不建议命名为 dict。
键必须是唯一的,但值则不必。
值可以取任何数据类型,但键必须是不可变的,如字符串,数字。
创建字典12#一个简单的字典实例:tinydict = {'name': 'xxx', 'likes': 123, 'url': 'www.baidu.com'}
也可以如此创建字典
12tinydict1 = { 'abc': 456 }tinydict2 = { 'abc': 123, 9 ...
[HNCTF 2022 WEEK4]ezheapNSS
来看题目
123456789101112131415161718192021222324252627282930313233343536373839404142int __fastcall __noreturn main(int argc, const char **argv, const char **envp){ int v3; // [rsp+Ch] [rbp-4h] init_env(argc, argv, envp); puts("Easy Note."); while ( 1 ) { while ( 1 ) { menu(); v3 = getnum(); if ( v3 != 4 ) break; edit(); } if ( v3 > 4 ) {LABEL_13: puts("Invalid!"); } ...
变量在什么情况共用一块内存区域1. 不可变对象的引用复用Python 为了提高内存使用效率,对于一些不可变对象(如整数、字符串、元组等)会进行引用复用。当多个变量被赋值为相同的不可变对象时,它们通常会引用内存中的同一个对象。
整数在 Python 中,对于小整数(通常范围是 -5 到 256),Python 会缓存这些整数对象,多个变量赋值为相同的小整数时会共用内存。
字符串对于一些短字符串和符合标识符规则的字符串,Python 也会复用内存。
2. 直接赋值当使用直接赋值语句将一个变量赋值给另一个变量时,两个变量会引用同一个对象,即共用内存区域。这种情况对于可变对象(如列表、字典、集合等)和不可变对象都适用。
3. 函数参数传递在 Python 中,函数参数传递是通过对象引用进行的。当将一个对象作为参数传递给函数时,函数内部的参数变量和外部的变量会引用同一个对象。
4. 浅拷贝的部分情况对于包含可变对象的嵌套结构,浅拷贝只会复制最外层对象,而内部的可变对象仍然是引用关系,即共用内存区域。
shellcraft 模块功能:生成特定架构的汇编代码(如执行 /bin/sh、反弹 Shell 等)。
语法:shellcraft.<架构>.<功能>()
架构:amd64、i386、arm、mips 等。
功能:sh()(获取 shell)、cat(“flag.txt”)(读取文件)、connect(“IP”, PORT)(反弹 Shell)等。
close(1)关闭标准输出流解决方法 exec 1 > &0在Linux中
一切都可以作为文件,文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。 如果此时去打开一个新的文件,它的文件描述符会是3。
而标准输入输出的指向是默认的,我们也可以去修改他的指向,也就是重定位文件描述符。 例如,可以用exec 1>myoutput把标准输出重定向到myoutput文件中, ...
堆1.堆是由操作系统内核或者堆管理器动态分配的
2.只有在程序中需要时才会分配
3.在CTF的pwn程序中,栈是程序加载进内存后就会出现,而堆需要malloc,alloc,realoc函数分配内存后才会出现。
Windows和Linux下的堆分配,管理方式都不同,
堆在虚拟内存中的位置
128M
123456789101112131415161718*用户空间*(独立).reserve(预留) //0x00000000 ----- 0x0848000.text(代码段).data //数据段.bss(默认为0) //数据段heap(堆)libc.so(共享库)stack(栈)argv|----命令行参数envp|---->环境变量*内核空间*(共享)ZONE_DMA(16M)ZONE_NORMAL(892M)ZONE_HIGHMEN(128M)
堆的生长方向是从低地址向高地址生长的,而栈是从高地址向低地址生长的
生长方向不同的原因
内存利用效率:堆和栈的生长方向不同可以让空闲的内存最大程度地被使用。如果栈的生长方向也是向上增长,那么栈空 ...