PWN illustration

发布于 2019-09-19  34 次阅读


进程虚拟内存布局

cat /proc/pid/maps

  • Linux_x86 (ASLR-2、no-PIE)
  • Linux_amd64
    • mmap段向高地址增长,其余部分与Linux_x86类似

寄存器结构

函数调用栈

栈帧结构

Linux_x86、_stdcall

32位的程序,所以canary有4个字节,最低位一定是\x00,所以只需要爆破三个字节即可

参数传递

  • Linux_x86
    • 函数参数自右向左依次压栈
  • Linux_x64
    • 6个以内的参数自左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9
    • 第7个以后的参数依次自右向左放入栈中

相关指令

  • push
  • pop
  • call
    • push EIP & jmp addr
  • leave
    • mov ESP, EBP & pop EBP
  • ret
    • pop EIP

动态链接

相关文件

  • ld-2.xx.so
    • 动态链接器
  • libc.so.6
    • C语言动态链接库的软链接
  • libc-2.xx.so
    • C语言动态链接库

相关节

  • .dynamic
    • 保存动态链接相关结构信息
  • .dynsym (DYNamic SYMbol)
  • .dynstr (DYNamic STRing)
  • .got (Global Offset Table)
    • 保存外部变量的GOT表
  • .got.plt
    • 保存外部函数的GOT表
  • .plt (Procedure Linkage Table)
    • 包含函数链接表(function link table)
  • .rel.plt (RELocate Procedure Linkage Table)

一次首次调用外部函数的过程

以 printf 为例的延迟绑定

  • .text: call printf
  • .plt: printf@plt -> jmp printf@got.plt
  • .plt: printf@plt + 1 -> jmp .plt[0]
  • .plt: call _dl_runtime_resolve(link_map_obj, reloc_index)
    • link_map_obj
    • reloc_index
  • call *printf@got.plt

系统调用

ptmalloc2堆内存管理

内存申请方式

  • sys_mmap()
    • main_arena 与 tread_arena 采用
  • sys_brk()
    • 仅 main_arena 采用

堆数据结构

arena、heap、chunk 宏观关系图

以多 heap 的 tread_arena 为例

  • libc2.26后加入的 "super_fast_bin" ——>tcache

栈利用姿势

  • ROP
    • ret2text
    • ret2shellcode
    • ret2libc
    • ret2syscall
    • ret2csu
    • ret2reg
    • ret2_dl_runtime_resolve
    • ret2VSDO
    • BROP
    • SROP
  • JOP
  • COP
  • 栈迁移

堆利用姿势

  • Double Free
  • Forging chunks
  • Use After Free
  • Off By One
  • Unlink Exploit
  • Shrinking Free Chunks
  • House of Spirit
  • House of Lore
  • House of Force
  • House of Einherjar
  • House of Orange

其他漏洞利用姿势

  • 格式化字符串漏洞
  • 整数溢出
  • 数组越界
  • 条件竞争
  • IO_FILE利用

防护措施

  • ASLR (Address Space Layout Randomization,地址空间布局随机化)
    • 系统的防护措施,程序装载时生效
    • /proc/sys/kernel/randomize_va_space = 0:没有随机化。即关闭 ASLR
    • /proc/sys/kernel/randomize_va_space = 1:保留的随机化。共享库、栈、mmap() 以及 VDSO 将被随机化
    • /proc/sys/kernel/randomize_va_space = 2:完全的随机化。在randomize_va_space = 1的基础上,通过 brk() 分配的内存空间也将被随机化
  • PIE (Position-Independent Executable,地址无关可执行文件)
    • 程序的防护措施,编译时生效
    • 随机化代码段和数据段的映射地址
    • 开启 ASLR 之后,PIE 才会生效
  • the NX bits (the No-eXecute bits,不可执行位)
    • 程序的防护措施,编译时生效
    • 通过在内存页的标识中增加“执行”位, 可以表示该内存页是否可以执行, 若程序代码的 EIP 执行至不可运行的内存页, 则 CPU 将直接拒绝执行“指令”造成程序崩溃
  • Canary
    • 程序的防护措施,编译时生效
    • 在刚进入函数时,在栈上放置一个标志canary,在函数返回时检测其是否被改变。以达到防护栈溢出的目的
    • canary长度为1字长,其位置不一定与ebp/rbp存储的位置相邻,具体得看程序的汇编操作
  • RELRO (RELocate Read-Only)
    • 程序的防护措施,编译时生效
    • 部分 RELRO: 在程序装入后, 将其中一些段(如.dynamic)标记为只读, 防止程序的一些重定位信息被修改
    • 完全 RELRO: 在部分 RELRO 的基础上, 在程序装入时, 直接解析完所有符号并填入对应的值, 此时所有的 GOT 表项都已初始化, 且不装入link_map与_dl_runtime_resolve的地址

GCC编译参数

  • 关闭Cannary:-fno-stack-protector
  • 开启栈的可执行权限:-z execstack
  • 在64系统环境下编译32位程序:-m32
  • 关闭PIE:-no-pie