我就学学吧,开开眼界也好
# 重要芝士
PLT 表存放跳转相关指令,GOT 表存放外部函数(符号)地址
plt 在 ida 是蓝色的,got 在 ida 是粉色的,plt 可跳转 got 表
# 32 位调用约定
# 64 位调用约定
# 特殊调用约定
__stdcall:
Windows API 默认函数调用协议
函数参数从右到左入栈,调用结束被调者负责清理压入的参数,在 Windows 中出现的比较多
__cdecl:
C/C++ 默认函数调用协议
函数参数从右到左入栈,调用结束后调用者负责清理压入的参数,x86 平台大多都是这个
__fastcall:
对性能要求高的场合的调用方法
从左开始将不大于四个字节的参数放入 eax 到 edx 寄存器,其余参数从右向左入栈
__thiscall:
为类方法专门优化的调用约定
如果参数个数确定
this 指针会被放在 ecx 里,其余参数右向左压栈
# Canary 保护
Canary 保护是在栈中插入应该随机数据的操作。一旦程序跳转时检测到 canary 发生改变就说明栈发生了溢出,程序会直接终止
这段数据有下面的特点
绕过 Canary 方法
*** stack smashing detected ***:[./pwn] terminated |
./pwn
字符串的是在 main 函数的 argv [0] 处,我们可以溢出到此处修改指针,获取内存数据,但是这段错误信息在环境变量 LIBC_FATAL_STDERR_
不等于 1 的时候是不会输出在控制台的,我们这时还需要修改环境变量指针指向 scanf 输入字符串 LIBC_FATAL_STDERR_=1
(环境变量指针 envp 一遍在 argv 往下两个地址)
# FORTIFY
当编译时加上参数 - D_FORTIFY_SOURCE=2, 一些敏感函数如 read, fgets, memcpy, printf 等等可能导致漏洞出现的函数都会被替换成 read_chk, fgets_chk, memcpy_chk,printf_chk 等。这些带了 chk 的函数会检查读取 / 复制的字节长度是否超过缓冲区长度,通过检查诸如 % n 之类的字符串位置是否位于可能被用户修改的可写地址,避免了格式化字符串跳过某些参数(如直接 %7$x)等方式来避免漏洞出现。开启了 FORTIFY 保护的程序会被 checksec 检出,此外,在反汇编时直接查看 got 表也会发现 chk 函数的存在。
有些时候函数可能不被替换,这就会产生漏洞