手工shellcode注入

本人首发于先知社区

手工shellcode注入

0x01

  • 这篇文章将介绍如何添加我们的shellcode而不增加大小或更改功能的来对合法的可执行文件进行添加后门。
  • 我们可以使用自己的Shellcode注入到特定的可执行文件,而又不增加可执行文件的大小或更改其预期功能,并使其难以检测。

为了保证shellcode和程序的精简

  • shellcode不会经过任何编码器的混淆
  • 文件大小保持不变。
  • 后门程序的功能不受影响

0x02

ASLR

  • ASLR(Address space layout randomization)是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的。

所以我们需要先检查程序是否开启了ASLR

avatar

PS脚本地址:https://github.com/NetSPI/PESecurity

看来这是一个好靶子。

0x03

实现过程

  • 在代码区段中创建新的节头,或在内存中找到合适的位置植入我们的Shell代码,这两种方法均在下面演示。

  • 在程序执行开始时从堆栈中复制操作码。

  • 将这些指令替换为我们自己的操作码,以将应用程序的执行流劫持到内存中的所需位置。

  • 将shellcode添加到该内存位置。

  • 将寄存器设置回第一步中复制的堆栈,以正常执行流程。

添加新的区段

该方法背后的原理是在PE文件中创建一个新的区段,在新创建的区段中添加我们的shellcode,然后指向该部分的执行流程。可以使用诸如LordPE之类的工具来修改区段表。

  • 用Lord PE打开目标程序,并在区段表底部添加节标题(这里是.demo)
  • 将虚拟大小和原始大小相加1000字节。请注意,十六进制为1000(十进制为4096字节)。
  • 使该区段可执行,因为我们必须将Shellcode放在此节中,因此它必须是可读可写可执行的。
  • 将文件另存为原始文件。

avatar

现在执行该文件,它将无法运行,因为我们添加了一个1000h字节的新段,但是该区段为空。

avatar

所以只要我们填充了该区段就能正常执行。

所以我们在文件末尾添加1000h字节,因为现在文件包含一个1000字节的区段,但该部分为空,我们必须用什么填充它,现在选择用null(00)填充它。如下所示,使用任何十六进制编辑器在文件末尾添加1000个十六进制字节。

avatar

添加后保存并运行,此时程序就可以正常运行了(确保程序可执行后进入下一步)。

劫持执行流程

现在在Ollydbg中执行以下操作:转到内存部分,然后双击PE标头。

avatar

我们可以看到我们的新部分 .demo 已添加了指定的权限。下一步是将程序的执行流劫持到我们新添加的 .demo 段中。当我们执行程序时,它应指向 要放置shellcode的代码的.demo 部分。

首先复制前3个操作码到记事本,稍后在恢复执行流程时将需要它们。 我们复制 .demo的起始地址00412000 打开Ollydbg的程序,更换程序起始地址代码为JMP 00412000。

avatar

现在保存修改后的文件,此时文件的执行流程已经被劫持了。现在重新用Ollydbg打开,右键跟随jmp,你就会发现程序已经被劫持到我们所创建的那一片全为00的了。

msfvenom -p windows/messagebox text=”it’s demo” -f hex

右键复制到可执行文件,此时会进入数据块,使用msf生成payload,复制,在Ollydbg中选中那一块00段 右键 > 二进制 >二进制粘贴然后保存文件

avatar

此时修改后的程序就能成功执行我们的shellcode了。弹框证明。

avatar

此时shellcode已被执行,我们应该恢复程序正常的执行流程。

  • 将shellcode最后一句跳转改为nop.
  • 使用popfd,popod进行恢复堆栈的操作。
  • 然后将原程序起始位置的汇编码复制到这里。
  • 最后跳转回原来的执行地址。
  • 保存文件,程序应能正常工作并保留原有功能。

avatar

* 此时我们算是初步完成了,不过由于添加了新的区段导致了程序体积变大,所以我们会用另一种办法解决这个问题 *

事实上虽然程序大小有变化,但是我们可以无限制的放入shellcode,即我们可以使用复杂的shellcode,这将会对bypass AV有帮助。

代码空洞

代码空洞是程序存储器中的空块,可用于注入shellcode。我们可以使用现有的代码洞来植入我们的shellcode。我们几乎可以在任何PE中找到不同大小的代码空洞。代码空洞的大小很重要! 我们希望代码空洞大于我们的shellcode,以便我们可以注入shellcode,而不必将其拆分为较小的块。

在代码空洞中注入shellcode是不会影响程序大小的,唯一需要注意的是shellcode应尽可能的小。

在kali中使用cave_miner检查原程序(未经修改)是否存在代码空洞。

1
cave_miner search  /root/Hash.exe   #可用--size 筛选符合大小的空洞,适用于空洞特别多的程序。

avatar

在这里我们有一个899字节的空洞,就决定是它了。

记下空洞的虚拟地址。虚拟地址是洞穴的起始地址。我们将通过跳转到虚拟地址来劫持执行流程。现在我们需要将shellcode植入到空洞中。在这里可以看到代码洞穴仅是可读的,我们必须使其可写和可执行才能执行我们的shellcode。我们通过LORDPE来修改。

avatar

在用户交互时触发Shellcode

现在我们有了一个可以使用的代码空洞,所以就决定把shellcode放这里了。

此次汇编代码改为跳转到我们得到的空洞地址:jmp 0041123d ,保存

再次用Ollydbg打开,跟随jmp到我们的代码空洞。

avatar

右键>复制到可执行文件>选择,然后复制shellcode,右键>二进制>二进制粘贴

然后最后一句还是改为nop,然后添加popfd,popad,以恢复堆栈,然后保存。

avatar

如能正常执行shellcode即进入下一步,跳转回程序执行流程。

最后完整还原代码如图。

avatar

avatar

在文件大小不变的情况下,实现了shellcode注入,且程序功能不受影响。

参考链接:https://haiderm.com/fully-undetectable-backdooring-pe-file