在metasploit中,我们任意选定一个payload时,metasploit都会加上generate,pry,reload等命令~
我们来看一下
在help输出的最后我们可以看到之前提到的命令
我们看下generate命令,首先-h查看帮助
我们当然也可以不用加上任何选项来生成shellcode
这么简单生成的shellcode基本上是不能用的。为了确保我们的shellcode有效,我们还需要结合靶机的具体情况,来过滤坏字符、选择特定类型的编码器等
上面的shellcode中我们看到一个很常见的坏字符,即null(\x00),我们可以通过添加参数来告诉metasploit删除这个字节
这次生成的shellcode中null字符已经被移除了。这个shellcode就是有效的了。由于我们指定了参数,所以两次生成的结果中我们发现了其他的差异。
一个很明显的区别就是之前的总字节大小是328字节,现在是355字节。
这是因为在第二次shellcode生成过程中,空字节的原始作用需要被替换,或者编码。来保证两次shellcode的功能的一致
仔细看看第二张截图,我们注意到相比第一张它还使用了encoder,我们称之为编码器。我们并没有显式指定,默认情况下,metasploit会选择最好的编码器来完成生成shellcode的任务。在这里,编码器负责删除-b后面指定的字符。
这里使用的是”x86/shikata_ga_nai”编码器,这个编码器只在我们需要溢出null字符时使用。我们如果需要删除的坏字符不是null而是其他的,就会有不同的编码器来生成shellcode
我们看到这次又换了一个编码器来移除我们指定的字符。
移除null字符用的shikata_ga_nai可能无法用来移除我们这次指定的字符,而fnstenv_mov可以做到。
如果我们想要在shellcode中移除太多字节,那是不可能的。比如你要说hello world,但是我不让你使用26个英文字母,那你怎么说呢。
我们来试试,一次性指定移除很多字节。
接下来我们来学习使用特定的编码器生成shellcode。比如说只有在包含非字母数字字符的情况下才能执行漏洞攻击利用。这种情况下,’shikata_ga_nai’编码器由于使用几乎全部的字符来编码,所以在我们假设的情况下是不适合的,我们应该选择其他编码器。
我们在选择特定的编码器之前,先来看看有哪些编码器
我们找到了一个’/x86/nonalpha’编码器
那我们使用这个编码器来生成shellcode看看。使用-e 来指定编码器
当我们使用自己指定编码器时,我们注意到生成的shellcode比之前的大得多,有470字节。
我们接下来学习如何把shellcode保存在文件中。使用-f选项。
注意到,我们使用-f选项后,shellcode不在终端输出了,直接保存在了指定的文件中
我们使用cat命令查看一下:
接下来我们学习下如何简单地进行bypass处理。我们通过重复编码的方式进行。使用”-I”参数。-i用于执行在执行多少次数的编码才生成最终的有效载荷。
上图的示例就是编码了2次生成的shellcde
将上图比最开始的第一张图对比,这次生成的shellcode的代码与仅有1次编码的shellcode有很大的不同
我们这此的示例是以一个绑定shell进行示范的。它默认是在4444端口进行监听。通过我们都会自己指定端口,我们可以在生成shellcode时使用-o指定我们想要修改的参数和值。我们首先来看看我们有哪些可以修改的选项。
可以看到默认的EXITFUNC是process,LPORT是4444.我们改为she,1234.
我们生成payload时默认的输出的是ruby的个格式。我们当然也可以选择其他的格式,比如Perl,C,Java等。
比如生成C的:
生成Java的
我们可以看到各种语言的输出都是符合相应的语法的。作为buffer的数组也都按照相应语言的格式声明了。这样我们可以很方便地复制粘贴。
比如说在ruby里#是注释,但是在C中/*是注释。
我们知道在写payloads的时候我们会用到NOP填充
NOP的意思就是当前没有操作或者邻接的指令没有操作。我们可以使用-s选项来执行我们想要填充的NOP的数量,当然,填充的越多,shllcode的体量也越大。
我们来比较下填充NOP前后
填充之前
填充之后
342-328=14就是我们填充的NOP数目。我们比较一下就会发现,填充之后的第一行就是我们的14字节的NOP,第二行开始才和没有填充生成的字符完全相同,说明填充的NOP会被放置在payload的起始位置。