CTF-特训营-Notes

第11章 PWN 基础

gcc 的 -z execstack 可开启栈可执行功能.

修改 /proc/sys/kernel/randomize_va_space 里的值用于控制系统级的 ASLR.

gcc 添加 -fno-stack-protector 可以关闭程序的 stack canary 栈保护.

11.3 PWN 类型

  • 栈漏洞
  • 堆漏洞
  • 格式化字符串漏洞
  • 整形漏洞
  • 逻辑漏洞

11.4 常见的利用方法

shellcode 指用于获取 shell 的代码.

查看 shellcode 的网址

11.5 程序内存布局

Data 段用来存放可执行文件中已经初始化的变量, 包括静态分配的变量和全局变量.

BSS 段主要包含程序中未初始化的全局变量, 在内存中 BSS 段全部置零.

栈 (stack) 存放程序临时创建的局部变量, 包括函数内部的临时变量和调用函数时压入的参数.


对于一些题, 需要找到 buffer 的大小, 以及读取 buffer 的长度.

第12章 栈相关漏洞

12.1 栈介绍

不同的函数栈之间是相互隔离的.

函数栈上存储的信息一般包括:

  • 临时变量 (包括栈保护哨 canary)
  • 函数的返回栈基址 (bp)
  • 函数的返回地址 (ip)

示意图如:

12.1.1 函数栈的调用机制

函数栈用于实现状态的隔离, 当前函数栈的边界就是:

  • 栈顶指针 (sp)
  • 栈底指针 (bp)

压入过程, 函数调用时:

  • 首先将参数入栈
  • 压入返回地址 (通过 call 实现)
  • 压入栈底指针寄存器 bp

函数结束时:

  • sp 重新指向 bp 的位置
  • 弹出 bp (通过 leavepop rbp)
  • 弹出返回地址 ip

函数栈示意图:

12.1.2 函数参数传递

函数的穿参规则受函数调用协议影响, 包括:

  • __stdcall
  • __cdecl
  • __fastcall

影响函数参数的入栈方式 (从左向右还是从右向左), 栈平衡的修复方式, 编译器函数名的修饰规则等.

Linux 程序通常采用 __cdecl 的调用方式.

规则如:

尝试后的输出:

注意这里 <main> 之下的第一条指令为什么就是 push %rbp (为什么不是先 push 参数和返回地址?):

这里就是先调用了 main 函数, 因此之前已经有了 call main, 也就是说, push 参数和返回地址的指令已经运行了

12.2 栈溢出

12.2.1 基本概念

栈溢出是指栈上的缓冲区被填入了过多的数据, 超出了边界, 从而导致栈上原有的数据被覆盖.

12.2.2 覆盖栈缓冲区的具体用途

一般覆盖的方面包括:

  • 数据不可执行及栈保护哨
  • 覆盖当前栈中函数的返回地址 (当前函数或之前的函数)
  • 覆盖栈中所存储的临时变量
  • 覆盖栈底寄存器 bp
  • 关注的敏感函数

利用 NX 保护

若开启了 NX 保护, 则:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
char shellcode[] = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05";

int main(void)
{
char stack_buff[0x40];
char *heap_buff = malloc(0x40);
memcpy(stack_buff, shellcode, sizeof(shellcode));
memcpy(heap_buff, shellcode, sizeof(shellcode));
((void (*)(void))stack_buff)();
}

会报错.

未开启, 则能 get shell.

关于 canary

canary 是程序在每次进入函数前会被赋予的值, 在函数返回前检查该值是否发生了改变, 若检测出改变则报异常并退出. (此时加大了覆盖 bpip 的难度)

虽然 canary 在程序中每次运行时都是随机的, 但是就程序的一次运行来说, 大部分情况下, 不同函数中的 canary 值是固定的.

只要泄漏出 canary, 就可以绕过 canary 保护机制.

容易发生栈覆盖的函数

常见有:

  • gets(buff)
  • scanf("%s", buff)

潜在的覆盖函数:

  • read
  • strcpy
  • memcpy

12.3 栈的特殊利用

  1. libc 信息泄漏

main 函数的栈底存放的是 __libc_start_main_ret

可以利用 libc.so 文件或使用 libc_database 来计算 libc 的基址以及 system 地址.

  1. 环境变量修改, 环境变量指针参数会压在栈上, 修改可以达到特殊目的

在进入程序主逻辑之前, 环境变量已经压入栈底, 如 LD_PRELOAD, LIBC_FATAL_STDERR_


CTF-特训营-Notes
http://example.com/2023/08/04/CTF-特训营-Notes/
作者
Jie
发布于
2023年8月4日
许可协议