
开启了canary保护
所以用printf泄露canary的数值
之后用ret2libc的方法解决
脚本
1 | from pwn import * |
1 | canary = u64(p.recv(7).rjust(8, b'\00')) |
此时读取的还是小端序。所以在左侧补位\x00
收获
canary接收
假设我们现在要泄露的 Canary 值是 0x1122334455667700。
步骤一:内存中的原始状态
在程序运行的内存中,这个 Canary 值以小端序存储。这意味着它的字节顺序是反过来的。
内存地址 (低) -> Canary 字节序 (高) \x00\x77\x66\x55\x44\x33\x22\x11 ,Canary 的最低字节是 \x00,存储在最低地址。
步骤二:构造并发送第一个 Payload (泄露)
我们构造 Payload:b’a’ * 0x48 + b’b’。
程序接收后,缓冲区被填满,b’b’ 覆盖了 Canary 的最低字节 \x00。
现在,内存中的 Canary 变成了: \x62\x77\x66\x55\x44\x33\x22\x11,\x62 是字符 ‘b’ 的十六进制值。
步骤三:程序输出泄露的数据
程序使用 printf(“%s”, buf) 这样的方式将栈上的数据当成字符串输出。它会从 buf 开始向后打印,直到遇到第一个空字节 \x00。
由于我们用 b 覆盖了 Canary 的最低字节,printf 不会在这里停止,而是继续向后打印。
它会打印出 b 加上 Canary 剩下的 7 个字节:\x62\x77\x66\x55\x44\x33\x22\x11
步骤四:脚本接收并处理泄露数据
我们的 Python 脚本执行 p.recvuntil(b’b’),先接收到 b,然后执行 p.recv(7),接收剩下的 7 个字节\x77\x66\x55\x44\x33\x22\x11
接下来,我们用 rjust(8, b’\x00’) 来恢复 Canary,就canary的小端序情况来看,在数据左侧添一个”\x00”,所以要用rjust(把现有数据放右边)
最后,我们用 u64() 将这个完整的 8 字节小端序数据转换回一个整数:
canary = u64(b’\x00\x77\x66\x55\x44\x33\x22\x11’)结果就是:0x1122334455667700
至此,Canary 泄露完成。
小端序
1 | leaked = p.recv(8) # 收到 8 字节:b'\x00\x12\x34\x56\x78\x9a\xbc\xde' |
1 | target_addr = 0x401123 |
| 从内存读整数(canary、地址) | ✅ 是 | 用u32/u64 |
| 向内存写整数(ROP、溢出) | ✅ 是 | 用p32/p64 |
| 字符串(”hello”) | ❌ 否 | 按正常顺序 |
| 网络协议 | ❌ 否(用大端) | 用>I,>Q |
| 文件格式(ELF、PNG) | ❌ 否 | 按字节流顺序 |
| 格式化字符串输出(%p) | ❌ 否 | 直接转整数 |
| 泄露的 hex 字符串(如 “aabbccdd”) | ❌ 否 | 先bytes.fromhex()再看是否要反转 |
