装载与汇编
RIP - 存放下一条指令的偏移地址 RSP - 存放当前栈帧的栈顶偏移地址 RBP - 存放当前栈帧的栈底偏移地址 静态链接的程序的执行过程$ ./binary -> fork() -> execve("./binary", \*argv[], \*envp[]) <user mode> -> sys_execve() -> do_execve() -> search_binary_handler() -> load_elf_binary() <kernal mode> -> _start -> main() <user mode> [!note]fork()将当前进程复制一份,然后execve()用新的可执行二进制文件代码替换新进程的代码,以此创建新进程 动态链接的程序的执行过程$ ./binary -> fork() -> execve("./binary", \*argv[], \*envp[]) <user mode>...
CPU与进程执行
进程虚拟地址空间段视图用于进程的内存区域的 rwx权限划分节视图用于 ELF文件 编译链接时 与 在磁盘上存储时 的文件结构的组织 .bss段 可以存储未初始化的全局变量(其不占用磁盘空间,但仍需占用内存空间).rodata节 专门用于储存程序中的只读(r–)数据 (rodata -> read only data) //局部变量会存放在stack中,malloc从Heap段申请字节空间(可以在任意时刻归还给系统,并让它可以被任意其他部分重新分配使用) 程序的编译与链接大端序与小端序 小端序 低地址存放数据低位、高地址存放数据高位 我们所需要关注的主要格式 大端序 低地址存放数据高位、高地址存放数据低位 //内存分布上,大小端序仅影响多字节元素内部的字节排列;数组内元素固定从低地址到高地址存入;而不同的元素按先后顺序固定从高地址向低地址存入
程序装载与虚拟内存
Linux下的可执行文件格式ELF磁盘中的ELF(可执行文件)与内存中的ELF(进程内存映像)磁盘中可读写(RW)的.data、.bss、.got .pit对应内存中的Data段磁盘中可读执行(RX)的.rodata、.text、init、ELF Header对应内存中的Code(Text)段 不同的section由于读写执行权限相同被合并成segment,这个操作由Linker完成而磁盘中的静态文件变为内存中的进程映像,是由os来完成映射的 进程虚拟地址空间地址以字节编码,常以16进制表示 虚拟内存用户空间每个进程一份虚拟内存内核空间所有进程共享一份虚拟内存 mmap 段中的动态链接库仅在物理内存中装载一份,例:glibc(虽然在虚拟内存中被多次载入) 每个进程都会分到4GB的虚拟内存(因为32位的寻址限制),而其中1GB是共享的内核空间(Kernel),剩下的3GB为用户空间 拥有相同读写执行权限的不同section由Linker合并成为一个segment,接着从磁盘中的静态文件由os完成映射成为一个进程映像 //硬件读取物理内存,而程序员看的是由os转化...
基本ROP
原理随着NX保护的开启,传统的向栈上直接注入代码的方式难以执行,因此目前被广泛使用的攻击手法是返回导向编程(Return Oriented Programming),即ROP。其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段(gadgets)来改变某些寄存器或者变量的值,从而控制程序的执行流程。gadgets 通常是以 ret 结尾的指令序列,通过这样的指令序列,我们可以多次劫持程序控制流,从而运行特定的指令序列,以完成攻击的目的。返回导向编程这一名称的由来是因为其核心在于利用了指令集中的 ret 指令,从而改变了指令流的执行顺序,并通过数条 gadget “执行” 了一个新的程序。 使用 ROP 攻击一般得满足如下条件: 程序漏洞允许我们劫持控制流,并控制后续的返回地址 可以找到满足条件的 gadgets 以及相应 gadgets 的地址 //作为一项基本的攻击手段,ROP 攻击并不局限于栈溢出漏洞,也被广泛应用在堆溢出等各类漏洞的利用当中。 [!info] 注意点现代操作系统通常会开启地址随机化保护(ASLR),这意味着 gadgets 在...
栈溢出原理
介绍栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。这种问题是一种特定的缓冲区溢出漏洞,类似的还有堆溢出,bss 段溢出等溢出方式。栈溢出漏洞轻则可以使程序崩溃,重则可以使攻击者控制程序执行流程。此外,我们也不难发现,发生栈溢出的基本前提是: 程序必须向栈上写入数据。 写入的数据大小没有被良好地控制。 [!info]编译时的 PIE 保护,Linux 平台下还有地址空间分布随机化(ASLR)的机制。简单来说即使可执行文件开启了 PIE 保护,还需要系统开启 ASLR 才会真正打乱基址,否则程序运行时依旧会在加载一个固定的基址上(不过和 No PIE 时基址不同)。我们可以通过修改 /proc/sys/kernel/randomize_va_space 来控制 ASLR 启动与否 0,关闭 ASLR,没有随机化。栈、堆、.so 的基地址每次都相同。 1,普通的 ASLR。栈基地址、mmap 基地址、.so 加载基地址都将被随机化,但是堆基地址没有随机化。 2,增强的 ASLR,在 1 的基础上,增加了堆基...
栈介绍
基本栈介绍栈是一种后进先出的数据结构,其主要的操作主要有压栈(push)与出栈(pop)两种操作。程序操作栈时,是操作当前sp指向的位置 压栈时,sp由高地址向低地址移动,后将数据存入sp指向的位置 出栈时,先将sp指向的数据弹出,然后sp由低地址向高地址移动 函数调用栈C语言函数调用栈程序的执行可以看作是连续的函数调用。当一个函数执行完毕时,程序要回到调用指令的下一条指令处继续执行。而这个函数调用的过程常使用堆栈实现,每个用户态进程对应一个调用栈结构。编译器使用堆栈传递函数参数、保存返回地址、临时保存寄存器原有值(即函数调用的上下文)以备恢复以及存储本地局部变量。 1 寄存器分配寄存器是处理器加工数据或运行程序的重要载体,用于存放程序执行中用到的数据和指令Intel 32位体系结构(IA32)处理器包含了8个四字节寄存器。对于寄存器%eax、%ebx、%ecx、%edx,各自又可作为两个独立的16位寄存器使用,而其中,低16位寄存器还可以继续分为两个独立的8位寄存器使用 在x86处理器中: EIP是指令寄存器,指向处理器下条等待执行的指令地址(代码段内的偏移量),...
ELF文件概述
0. PWN概述什么是PWN? 破解、利用成功(程序的二进制漏洞) 攻破(设备、服务器) 控制(设备、服务器) 几个简单名词: exploit 用于攻击的脚本与方案 payload 攻击载荷,是对目标程序被劫持控制流的数据 shellcode 调用攻击目标的shell代码 CTF中PWN题常见模式: 根据提供的IP及其端口,连接至目标漏洞服务器 然后根据漏洞,编写exp脚本发送payload给漏洞服务器进行攻击操作 攻击操作一般目的为调取一个shell 通过shell控制远程服务器 通常为读取远程服务器上的flag文件 [!info] 什么是Shell?Shell 俗称壳(用来区别于核),是指为使用者提供操作界面的软件(命令解析器)。它接收用户命令,然后调用相应的应用程序。 核指的是计算机操作系统内核(Kernel),内核是管理 CPU、内存等硬件的核心软件。 Shell 是一个命令语言的同时,它也是一种程序设计语言。 作为命令语言时,它可以使用一个操作界面,交互式地解释和执行用户输入的命令。 交互式是指用户输入一个指令时,Shell 能马上...
滴水-PE
1. PE文件结构1.1 可执行文件可执行文件指的是可以由操作系统进行加载执行的文件 可执行文件结构: Windows平台:PE(Portable Executable)文件结构 Linux平台:ELF(Executable and Linking Format)文件结构 PE文件结构使用场景: 病毒与反病毒 外挂与反外挂 加壳与脱壳(保护与破解) 无源码修改功能、软件汉化等 1.2 如何识别PE文件 PE文件的特征(PE指纹)分别打开.exe、.dll、.sys等文件,观察特征前2个字节 不能仅仅通过文件的后缀名来认定PE文件 1.3 PE文件的整体结构 2. PE文件的两种状态2.1 主要结构体 DOS部分: IMAGE_DOS_HEADER结构:DOS MZ文件头,64 Byte DOS Stub:DOS块(IMAGE_DOS_HEADER结构的最后一个成员指向了PE头开始的位置,由此可以判断DOS块的大小) PE文件头: “PE”,0,0:PE文件头标志,4 Byte IMAGE_FILE_HEADER结构:PE文件表头,标准PE头,20 Byte IMA...
Z3-Solver
创建声明12345x = Int('x') #声明整数x = Real('x') #声明实数x = Bool('x') #声明布尔类型x = BitVec('x', 8) #声明位向量类型a, b, c = Reals('a b c') #批量声明 //Int类型无法使用& | ~计算 常用API1. 创建约束求解器1solver = Solver() 2. 添加约束条件1solver.add() 3. 判断解是否存在1if(solver.check() == sat) 4. 求解1print(solver.model())
Python
1. 字面量1.1 定义字面量:在代码中,被写下来的固定的值,称之为字面量 1.2 常用的值类型Python中常见的有6种值(数据)类型 类型 描述 说明 数字(Number) 整数(int) 10、-10 浮点数(float) 10.1、-10.1 复数(complex) 4+3j,以j结尾表示复数 布尔(bool) 表示逻辑,真(True–1)和假(False–0) 字符串(String) 描述文本的一种数据类型 字符串由任意数量的字符组成 列表(List) 有序的可变序列 Python中最常用的数据类型,可有序记录一堆数据 元组(Tuple) 有序的不可变序列 可有序记录一堆不可变的Python数据集合 集合(Set) 无序不重复集合 可无序记录一堆不重复的Python数据集合 字典(Dictionary) 无序Key-Value集合 可无序记录一堆Key-Value型的Python数据集合 12345print(10)print(10.1)print("字符串")# 这里括号内的内容也是字面量 1...
