├── .gitignore ├── KStealthInjector.sln ├── KStealthInjector ├── KStealthInjector.vcxproj ├── KStealthInjector.vcxproj.filters ├── PE.cpp ├── PE.h ├── Source.cpp ├── driver_bin.h ├── mapper.cpp ├── mapper.h ├── process.cpp ├── process.h ├── service.cpp ├── service.h ├── shellcode.cpp ├── shellcode.h ├── utils.cpp ├── utils.h ├── xigndriver.cpp └── xigndriver.h ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /KStealthInjector.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2003 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KStealthInjector", "KStealthInjector\KStealthInjector.vcxproj", "{4670F6F5-2F85-4DF2-A221-900153E684F3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Debug|x64.ActiveCfg = Debug|x64 17 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Debug|x64.Build.0 = Debug|x64 18 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Debug|x86.ActiveCfg = Debug|Win32 19 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Debug|x86.Build.0 = Debug|Win32 20 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Release|x64.ActiveCfg = Release|x64 21 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Release|x64.Build.0 = Release|x64 22 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Release|x86.ActiveCfg = Release|Win32 23 | {4670F6F5-2F85-4DF2-A221-900153E684F3}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {43DC0396-196A-4D49-82FF-FAFE3ABF155F} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /KStealthInjector/KStealthInjector.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {4670F6F5-2F85-4DF2-A221-900153E684F3} 24 | KStealthInjector 25 | 10.0.17134.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v141 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | C:\Users\Rohan\Documents\KStealthInjector\KStealthInjector\imgui;$(IncludePath) 74 | 75 | 76 | 77 | Level3 78 | Disabled 79 | true 80 | true 81 | 82 | 83 | 84 | 85 | Level3 86 | Disabled 87 | true 88 | true 89 | 90 | 91 | 92 | 93 | Level3 94 | Disabled 95 | true 96 | true 97 | true 98 | true 99 | C:\Users\Rohan\Documents\KStealthInjector\KStealthInjector\imgui;%(AdditionalIncludeDirectories) 100 | false 101 | 102 | 103 | true 104 | true 105 | HighestAvailable 106 | C:\Users\Rohan\Documents\KStealthInjector\KStealthInjector\imgui;%(AdditionalLibraryDirectories) 107 | 108 | 109 | 110 | 111 | Level3 112 | MaxSpeed 113 | true 114 | true 115 | true 116 | true 117 | 118 | 119 | true 120 | true 121 | C:\Program Files %28x86%29\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\lib\x64;%(AdditionalLibraryDirectories) 122 | RequireAdministrator 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /KStealthInjector/KStealthInjector.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | -------------------------------------------------------------------------------- /KStealthInjector/PE.cpp: -------------------------------------------------------------------------------- 1 | #include "PE.h" 2 | 3 | 4 | namespace PE 5 | { 6 | PVOID get_entrypoint(PVOID image) 7 | { 8 | return ((PBYTE)image + PE::get_entrypoint_offset(image)); 9 | } 10 | 11 | uint32_t get_entrypoint_offset(PVOID image) 12 | { 13 | auto dosHeader = (PIMAGE_DOS_HEADER)image; 14 | auto ntHeaders = (PIMAGE_NT_HEADERS)((uint64_t)image + dosHeader->e_lfanew); 15 | return ntHeaders->OptionalHeader.AddressOfEntryPoint; 16 | } 17 | 18 | PVOID get_exported_function(LPCSTR module_name, LPCSTR function_name) 19 | { 20 | PVOID image_base = LoadLibrary(module_name); 21 | PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)image_base; 22 | PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)((PUCHAR)image_base + pIDH->e_lfanew); 23 | PIMAGE_EXPORT_DIRECTORY pIED = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)image_base + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 24 | 25 | PULONG Functions = (PULONG)((PUCHAR)image_base + pIED->AddressOfFunctions); 26 | PULONG Names = (PULONG)((PUCHAR)image_base + pIED->AddressOfNames); 27 | PUSHORT Ordinals = (PUSHORT)((PUCHAR)image_base + pIED->AddressOfNameOrdinals); 28 | UINT64 i = 0; 29 | for (i = 0; i < pIED->NumberOfNames; i++) 30 | { 31 | if (!strcmp((char*)image_base + Names[i], function_name)) 32 | { 33 | return ((PUCHAR)image_base + Functions[Ordinals[i]]); 34 | } 35 | } 36 | 37 | return NULL; 38 | } 39 | 40 | uint64_t find_code_cave(PVOID image, uint32_t size) 41 | { 42 | auto dos_header = (PIMAGE_DOS_HEADER)image; 43 | auto nt_headers = (PIMAGE_NT_HEADERS64)((uint64_t)image + dos_header->e_lfanew); 44 | 45 | for (int x = 0, count = 0; x < nt_headers->OptionalHeader.SizeOfImage; x++) 46 | { 47 | auto item = *(uint8_t *)((uint64_t)image + x); 48 | 49 | if (item == 0x00 || item == 0xCC) 50 | count++; 51 | else 52 | count = 0; 53 | 54 | if (count > size + 2) 55 | { 56 | return ((uint64_t)image + x - size); 57 | } 58 | 59 | } 60 | 61 | return NULL; 62 | } 63 | } 64 | 65 | /* 66 | PE::PE(const char *dll_path) 67 | { 68 | auto temp_mem = utils::read_file(dll_path); 69 | auto ntHeaders = (PIMAGE_NT_HEADERS)((uint32_t)temp_mem + ((PIMAGE_DOS_HEADER)temp_mem)->e_lfanew); 70 | 71 | image_mem = VirtualAlloc(NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 72 | 73 | parse_sections(image_mem, temp_mem); 74 | parse_imports(); 75 | parse_strings(); 76 | 77 | VirtualFree(temp_mem, NULL, MEM_RELEASE); 78 | 79 | print_info(); 80 | } 81 | 82 | void PE::parse_sections(LPVOID dst_image, LPVOID src_image) 83 | { 84 | auto dos_header = (PIMAGE_DOS_HEADER)src_image; 85 | auto nt_headers = (PIMAGE_NT_HEADERS32)((uint32_t)src_image + dos_header->e_lfanew); 86 | auto sect_header = (PIMAGE_SECTION_HEADER)(&nt_headers->OptionalHeader + 1); 87 | 88 | memcpy(dst_image, src_image, nt_headers->OptionalHeader.SizeOfHeaders); 89 | for (auto count = 0; count < nt_headers->FileHeader.NumberOfSections; count++) 90 | { 91 | sections.push_back((const char *)sect_header[count].Name); 92 | memcpy((PBYTE)dst_image + sect_header[count].VirtualAddress, (PBYTE)src_image + sect_header[count].PointerToRawData, sect_header[count].SizeOfRawData); 93 | } 94 | } 95 | 96 | void PE::parse_imports() 97 | { 98 | auto nt_headers = (PIMAGE_NT_HEADERS)((LPBYTE)image_mem + ((PIMAGE_DOS_HEADER)image_mem)->e_lfanew); 99 | auto import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)image_mem + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 100 | for (; import_desc->Name; import_desc++) 101 | { 102 | imports.push_back(imported_module{ (LPCSTR)((uint32_t)image_mem + import_desc->Name), std::vector() }); 103 | 104 | auto _thunk_data = (PIMAGE_THUNK_DATA)((uint32_t)image_mem + import_desc->FirstThunk); 105 | auto thunk_data = (PIMAGE_THUNK_DATA)((uint32_t)image_mem + import_desc->OriginalFirstThunk); 106 | 107 | for (; thunk_data->u1.Function != NULL; thunk_data++, _thunk_data++) 108 | { 109 | auto import_name = (PIMAGE_IMPORT_BY_NAME)((uint32_t)image_mem + thunk_data->u1.AddressOfData); 110 | printf("%s::%s %X\n", (LPCSTR)((uint32_t)image_mem + import_desc->Name), import_name->Name,thunk_data->u1.Function); 111 | 112 | imports.back().function_names.push_back(import_name->Name); 113 | } 114 | } 115 | } 116 | 117 | void PE::parse_strings() 118 | { 119 | auto dosHeader = (PIMAGE_DOS_HEADER)image_mem; 120 | auto ntHeaders = (PIMAGE_NT_HEADERS)((uint32_t)image_mem + dosHeader->e_lfanew); 121 | auto sectHeader = (PIMAGE_SECTION_HEADER)(&ntHeaders->OptionalHeader + 1); 122 | 123 | for (auto count = 0; count < ntHeaders->FileHeader.NumberOfSections; count++) 124 | { 125 | auto section = (PBYTE)image_mem + sectHeader[count].PointerToRawData; 126 | auto size = sectHeader[count].SizeOfRawData; 127 | auto len = 0, df = 0; 128 | if (!_strcmpi((const char *)sectHeader[count].Name, ".rdata")) 129 | { 130 | for (auto index = 0; index + len < size; len++) 131 | { 132 | auto character = *(BYTE *)(section + index + len); 133 | 134 | if (character == 0x00) 135 | { 136 | if (df && len > 1) 137 | { 138 | df = false; 139 | len++; 140 | strings.push_back((const char *)(section + index)); 141 | index += len; 142 | len = -1; 143 | } 144 | else 145 | { 146 | index += len + 1; 147 | len = -1; 148 | } 149 | } 150 | else 151 | df = true; 152 | 153 | if (character && (character > 126 || character < 32)) 154 | { 155 | index += len + 1; 156 | len = -1; 157 | } 158 | } 159 | } 160 | } 161 | } 162 | 163 | void PE::print_info() 164 | { 165 | for (auto section : sections) 166 | printf("[Section]: %s\n", section.c_str()); 167 | 168 | for (auto imported_mod : imports) 169 | for (auto funct : imported_mod.function_names) 170 | printf("[Import] : %s::%s\n", imported_mod.module_name.c_str(), funct.c_str()); 171 | 172 | for (auto string : strings) 173 | printf("[String] : %s\n", string.c_str()); 174 | } 175 | */ -------------------------------------------------------------------------------- /KStealthInjector/PE.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utils.h" 8 | 9 | namespace PE 10 | { 11 | PVOID get_entrypoint(PVOID image); 12 | uint32_t get_entrypoint_offset(PVOID image); 13 | PVOID get_exported_function(LPCSTR module_name, LPCSTR function_name); 14 | uint64_t find_code_cave(PVOID image, uint32_t size); 15 | } -------------------------------------------------------------------------------- /KStealthInjector/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "process.h" 5 | #include "mapper.h" 6 | 7 | int main() 8 | { 9 | mapper::inject("FortniteLauncher.exe", "C:\\payload64.dll"); 10 | getchar(); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /KStealthInjector/mapper.cpp: -------------------------------------------------------------------------------- 1 | #include "mapper.h" 2 | 3 | namespace mapper 4 | { 5 | std::vector module_list; 6 | LPCSTR vuln_module = "kernel32.dll", vuln_function = "TlsSetValue"; 7 | 8 | PVOID inject(std::string target_proc, std::string dll) 9 | { 10 | xigndriver::initialize(); 11 | 12 | auto target_pid = process::get_process_id(target_proc); 13 | while (!target_pid) 14 | target_pid = process::get_process_id(target_proc); 15 | 16 | auto target_handle = xigndriver::open_process(target_proc); 17 | printf("%x\n", target_handle); 18 | 19 | if (target_handle) 20 | { 21 | auto image_base = inject_ex(target_handle, target_proc, dll); 22 | if (image_base) 23 | return image_base; 24 | else 25 | printf("Error injecting %s into %s", dll.c_str(), target_proc.c_str()); 26 | } 27 | else 28 | { 29 | printf("Error %X acquiring handle to %X-%s\n", GetLastError(), target_pid, target_proc.c_str()); 30 | } 31 | 32 | return NULL; 33 | } 34 | 35 | PVOID inject_ex(HANDLE target_handle, std::string target_proc, std::string dll) 36 | { 37 | auto local_image = utils::read_file(dll.c_str()); 38 | 39 | auto dosHeader = (PIMAGE_DOS_HEADER)local_image; 40 | auto ntHeaders = (PIMAGE_NT_HEADERS)((uint64_t)local_image + dosHeader->e_lfanew); 41 | auto sectHeader = (PIMAGE_SECTION_HEADER)(&ntHeaders->OptionalHeader + 1); 42 | 43 | auto fixed_image = VirtualAlloc(NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 44 | auto target_mem = VirtualAllocEx(target_handle, NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 45 | 46 | if (fixed_image && target_mem) 47 | { 48 | mapper::copy_sections(local_image, fixed_image); 49 | mapper::relocate_base(fixed_image, target_mem); 50 | mapper::fix_imports(target_handle, fixed_image, target_proc); 51 | 52 | if (!WriteProcessMemory(target_handle, target_mem, fixed_image, ntHeaders->OptionalHeader.SizeOfImage, NULL)) 53 | { 54 | printf("Unable to write relocated image to target image: %X\n", GetLastError()); 55 | VirtualFree(fixed_image, NULL, MEM_RELEASE); 56 | VirtualFree(local_image, NULL, MEM_RELEASE); 57 | VirtualFreeEx(target_handle, target_mem, NULL, MEM_RELEASE); 58 | return 0; 59 | } 60 | 61 | mapper::call_entrypoint(target_handle, target_mem, fixed_image); 62 | 63 | return target_mem; 64 | } 65 | else 66 | { 67 | printf("Unable to allocate memory for image (local: %X, remote: %X)\n", fixed_image, target_mem); 68 | } 69 | 70 | return NULL; 71 | 72 | } 73 | 74 | void copy_sections(LPVOID local_image, LPVOID fixed_image) 75 | { 76 | auto dos_header = (PIMAGE_DOS_HEADER)local_image; 77 | auto nt_headers = (PIMAGE_NT_HEADERS)((uint64_t)local_image + dos_header->e_lfanew); 78 | auto sect_header = (PIMAGE_SECTION_HEADER)(&nt_headers->OptionalHeader + 1); 79 | 80 | memcpy(fixed_image, local_image, nt_headers->OptionalHeader.SizeOfHeaders); 81 | for (auto count = 0; count < nt_headers->FileHeader.NumberOfSections; count++) 82 | { 83 | 84 | memcpy((PBYTE)fixed_image + sect_header[count].VirtualAddress, (PBYTE)local_image + sect_header[count].PointerToRawData, sect_header[count].SizeOfRawData); 85 | } 86 | } 87 | 88 | void relocate_base(LPVOID fixed_image, LPVOID target_mem) 89 | { 90 | auto nt_headers = (PIMAGE_NT_HEADERS)((LPBYTE)fixed_image + ((PIMAGE_DOS_HEADER)fixed_image)->e_lfanew); 91 | auto base_reloc = (PIMAGE_BASE_RELOCATION)((LPBYTE)fixed_image + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); 92 | auto delta = (uint64_t)((LPBYTE)target_mem - nt_headers->OptionalHeader.ImageBase); 93 | 94 | for (; base_reloc->VirtualAddress; base_reloc = (PIMAGE_BASE_RELOCATION)((PBYTE)base_reloc + base_reloc->SizeOfBlock)) 95 | { 96 | auto relocs = (relocation *)(base_reloc + 1); 97 | 98 | for (int x = 0; x < (base_reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); x++) 99 | { 100 | switch (relocs[x].type) 101 | { 102 | case IMAGE_REL_BASED_DIR64: 103 | *(uint64_t *)((LPBYTE)fixed_image + (base_reloc->VirtualAddress + relocs[x].offset)) += delta; 104 | break; 105 | 106 | case IMAGE_REL_BASED_HIGHLOW: 107 | *(uint32_t *)((LPBYTE)fixed_image + (base_reloc->VirtualAddress + relocs[x].offset)) += (uint32_t)delta; 108 | break; 109 | 110 | case IMAGE_REL_BASED_HIGH: 111 | *(uint16_t *)((LPBYTE)fixed_image + (base_reloc->VirtualAddress + relocs[x].offset)) += HIWORD(delta); 112 | break; 113 | 114 | case IMAGE_REL_BASED_LOW: 115 | *(uint16_t *)((LPBYTE)fixed_image + (base_reloc->VirtualAddress + relocs[x].offset)) += LOWORD(delta); 116 | break; 117 | 118 | case IMAGE_REL_BASED_ABSOLUTE: 119 | break; 120 | 121 | default: 122 | printf("Unable to catch relocation type %X", relocs[x].type); 123 | break; 124 | } 125 | } 126 | } 127 | } 128 | 129 | void fix_imports(HANDLE target_handle, LPVOID fixed_image, std::string target_process) 130 | { 131 | auto nt_headers = (PIMAGE_NT_HEADERS)((LPBYTE)fixed_image + ((PIMAGE_DOS_HEADER)fixed_image)->e_lfanew); 132 | auto import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)fixed_image + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 133 | 134 | if (import_desc) 135 | { 136 | for (; import_desc->Name; import_desc++) 137 | { 138 | module_info dependency = mapper::get_dependency(fixed_image, import_desc); 139 | auto remote_base = process::get_remote_module(GetProcessId(target_handle), dependency.dll_name); 140 | if (!remote_base) 141 | { 142 | for (auto module : module_list) 143 | { 144 | if (!_strcmpi(module.dll_name, dependency.dll_name)) 145 | remote_base = (PBYTE)module.base_address; 146 | } 147 | 148 | if (!remote_base) 149 | { 150 | remote_base = (PBYTE)inject_ex(target_handle, target_process, dependency.full_path_name); 151 | } 152 | } 153 | 154 | if (remote_base) 155 | { 156 | auto _thunk_data = (PIMAGE_THUNK_DATA)((uint64_t)fixed_image + import_desc->FirstThunk); 157 | auto thunk_data = (PIMAGE_THUNK_DATA)((uint64_t)fixed_image + import_desc->OriginalFirstThunk); 158 | 159 | for (; thunk_data->u1.Function != NULL; thunk_data++, _thunk_data++) 160 | { 161 | auto import_name = (PIMAGE_IMPORT_BY_NAME)((uint64_t)fixed_image + thunk_data->u1.AddressOfData); 162 | _thunk_data->u1.Function = (uint64_t)((uint64_t)GetProcAddress((HMODULE)dependency.base_address, import_name->Name) + (remote_base - dependency.base_address)); 163 | } 164 | } 165 | 166 | } 167 | } 168 | else 169 | { 170 | printf("Unable to locate import descriptor\n"); 171 | } 172 | } 173 | 174 | module_info get_dependency(LPVOID fixed_image, PIMAGE_IMPORT_DESCRIPTOR import_desc) 175 | { 176 | auto dependency_base = LoadLibrary((char *)((PBYTE)fixed_image + import_desc->Name)); 177 | char dependency_path[MAX_PATH]; 178 | GetModuleFileNameA(dependency_base, dependency_path, MAX_PATH); 179 | auto dependency_name = PathFindFileNameA(dependency_path); 180 | return { dependency_path, dependency_name, dependency_base }; 181 | } 182 | 183 | void call_entrypoint(HANDLE target_handle, PVOID target_mem, PVOID fixed_image) 184 | { 185 | DWORD funcProt, caveProt; 186 | 187 | uint8_t shellcode[] = { 188 | 0x9C, //pushfq 189 | 0x50, //push rax 190 | 0x53, //push rbx 191 | 0x51, //push rcx 192 | 0x52, //push rdx 193 | 0x41, 0x50, //push r8 194 | 0x41, 0x51, //push r9 195 | 0x41, 0x52, //push r10 196 | 0x41, 0x53, //push r11 197 | 0x55, //push rbp 198 | 0x48, 0x89, 0xE5, //mov rbp, rsp 199 | 0x48, 0x83, 0xE4, 0xF0, //and rsp, 0xFFFFFFFFFFFFFFF7 200 | 0x48, 0xB9, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, //mov rcx, 0xCCCCCCCCCCCCCCCC 201 | 0xC7, 0x01, 0x56, 0x02, 0x00, 0x00, //mov dword ptr ds:[rcx], 0x256 202 | 0x4D, 0x33, 0xC0, //xor r8, r8 203 | 0xBA, 0x01, 0x00, 0x00, 0x00, //mov edx, 0x1 204 | 0x51, //push rcx 205 | 0x48, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, //mov rbx, 0xCCCCCCCCCCCCCCCC 206 | 0x48, 0x81, 0xEC, 0x08, 0x02, 0x00, 0x00, //sub rsp, 208 207 | 0xFF, 0xD3, //call rbx 208 | 0x48, 0x81, 0xC4, 0x08, 0x02, 0x00, 0x00, //add rsp, 208 209 | 0x59, //pop rcx 210 | 0xC7, 0x01, 0x63, 0x02, 0x00, 0x00, //mov dword ptr ds:[rcx], 0x263 211 | 0x48, 0x89, 0xEC, //mov rsp, rbp 212 | 0x5D, //pop rbp 213 | 0x41, 0x5B, //pop r11 214 | 0x41, 0x5A, //pop r10 215 | 0x41, 0x59, //pop r9 216 | 0x41, 0x58, //pop r8 217 | 0x5A, //pop rdx 218 | 0x59, //pop rcx 219 | 0x5B, //pop rbx 220 | 0x58, //pop rax 221 | 0x9D, //popfq 222 | 0x48, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, //mov rax, 0xCCCCCCCCCCCCCCCC 223 | 0xFF, 0xE0 //jmp rax 224 | }; 225 | 226 | auto codecave = (PVOID)PE::find_code_cave(LoadLibrary("kernel32.dll"), sizeof(shellcode)); 227 | auto target_function = PE::get_exported_function(vuln_module, vuln_function); 228 | auto entry_point = (PBYTE)target_mem + PE::get_entrypoint_offset(fixed_image); 229 | 230 | *(uint64_t *)(shellcode + 23) = (uint64_t)target_mem; 231 | *(uint64_t *)(shellcode + 48) = (uint64_t)entry_point; 232 | *(uint64_t *)(shellcode + 98) = (uint64_t)target_function; 233 | 234 | if (target_function && codecave) 235 | { 236 | if (VirtualProtectEx(target_handle, target_function, sizeof(ULONGLONG), PAGE_EXECUTE_READWRITE, &funcProt) && VirtualProtectEx(target_handle, codecave, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &caveProt)) 237 | { 238 | uint64_t overwritten_bytes; 239 | 240 | auto success = ReadProcessMemory(target_handle, target_function, &overwritten_bytes, sizeof(uint64_t), NULL); 241 | success &= WriteProcessMemory(target_handle, codecave, &shellcode, sizeof(shellcode), NULL); 242 | if (!success) 243 | { 244 | printf("Unable to read vulnerable function or write shellcode: %X\n", GetLastError()); 245 | } 246 | 247 | uint8_t *jmp = shellcode::relative_jmp_64((PBYTE)codecave - target_function - 5); 248 | WriteProcessMemory(target_handle, target_function, jmp, sizeof(ULONGLONG), NULL); 249 | 250 | mapper::wait_for_exit(target_handle, target_mem, target_function, overwritten_bytes); 251 | 252 | mapper::post_injection(target_handle, target_mem, codecave); 253 | 254 | VirtualProtectEx(target_handle, target_function, sizeof(ULONGLONG), funcProt, &funcProt); 255 | VirtualProtectEx(target_handle, codecave, sizeof(shellcode), caveProt, &caveProt); 256 | } 257 | else 258 | { 259 | printf("Unable to gain access codecave or target function: %X\n", GetLastError()); 260 | } 261 | } 262 | else 263 | { 264 | printf("Unable to find codecave or target function: %s:%llx, %s:%llx\n", vuln_module, codecave, vuln_function, target_function); 265 | } 266 | } 267 | 268 | void wait_for_exit(HANDLE target_handle, PVOID target_mem, PVOID function_address, uint64_t overwritten_bytes) 269 | { 270 | USHORT injection_status; 271 | bool function_restored = false; 272 | while (ReadProcessMemory(target_handle, target_mem, &injection_status, 2, NULL)) 273 | { 274 | if (injection_status == RESTORE_FUNCTION && !function_restored) 275 | { 276 | WriteProcessMemory(target_handle, function_address, &overwritten_bytes, sizeof(uint64_t), NULL); 277 | function_restored = true; 278 | } 279 | if (injection_status == INJECTION_SUCCESS) 280 | { 281 | if (!function_restored) 282 | WriteProcessMemory(target_handle, function_address, &overwritten_bytes, sizeof(uint64_t), NULL); 283 | break; 284 | } 285 | 286 | } 287 | } 288 | 289 | void post_injection(HANDLE target_handle, PVOID target_mem, PVOID codecave) 290 | { 291 | auto zero_mem = VirtualAlloc(NULL, sizeof(codecave), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 292 | if (zero_mem) 293 | { 294 | RtlZeroMemory(zero_mem, sizeof(codecave)); 295 | WriteProcessMemory(target_handle, codecave, &zero_mem, sizeof(codecave), NULL); 296 | WriteProcessMemory(target_handle, target_mem, &codecave, 4096, NULL); 297 | 298 | VirtualFree(zero_mem, NULL, MEM_RELEASE); 299 | } 300 | else 301 | { 302 | printf("Unable to allocate buffer to zero codecave: %X\n", GetLastError()); 303 | } 304 | } 305 | } -------------------------------------------------------------------------------- /KStealthInjector/mapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma comment(lib, "Shlwapi.lib") 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "utils.h" 10 | #include "process.h" 11 | #include "PE.h" 12 | #include "shellcode.h" 13 | #include "xigndriver.h" 14 | 15 | #define INJECTION_SUCCESS 0x263 16 | #define RESTORE_FUNCTION 0x256 17 | 18 | struct module_info 19 | { 20 | LPCSTR full_path_name; 21 | LPCSTR dll_name; 22 | PVOID base_address; 23 | }; 24 | 25 | struct relocation 26 | { 27 | WORD offset : 12; 28 | WORD type : 4; 29 | }; 30 | 31 | namespace mapper 32 | { 33 | PVOID inject(std::string target_proc, std::string dll); 34 | PVOID inject_ex(HANDLE target_handle, std::string target_proc, std::string dll); 35 | void copy_sections(LPVOID local_image, LPVOID fixed_image); 36 | void relocate_base(LPVOID fixed_image, LPVOID target_mem); 37 | void fix_imports(HANDLE target_handle, LPVOID fixed_image, std::string target_process); 38 | module_info get_dependency(LPVOID fixed_image, PIMAGE_IMPORT_DESCRIPTOR import_desc); 39 | void call_entrypoint(HANDLE target_handle, PVOID target_mem, PVOID fixed_image); 40 | void wait_for_exit(HANDLE target_handle, PVOID target_mem, PVOID function_address, uint64_t overwritten_bytes); 41 | void post_injection(HANDLE target_handle, PVOID target_mem, PVOID codecave); 42 | } -------------------------------------------------------------------------------- /KStealthInjector/process.cpp: -------------------------------------------------------------------------------- 1 | #include "process.h" 2 | 3 | namespace process 4 | { 5 | uint64_t get_process_id(std::string process_name) 6 | { 7 | 8 | auto hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 9 | PROCESSENTRY32 pe32 = PROCESSENTRY32{ sizeof(PROCESSENTRY32) }; 10 | if (Process32First(hSnapshot, &pe32)) 11 | { 12 | do 13 | { 14 | if (_strcmpi(process_name.c_str(), pe32.szExeFile) == 0) 15 | { 16 | CloseHandle(hSnapshot); 17 | 18 | return pe32.th32ProcessID; 19 | } 20 | } while (Process32Next(hSnapshot, &pe32)); 21 | } 22 | 23 | CloseHandle(hSnapshot); 24 | return 0; 25 | } 26 | 27 | PBYTE get_remote_module(uint64_t target_pid, LPCSTR module_name) 28 | { 29 | auto hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, target_pid); 30 | MODULEENTRY32 me32 = MODULEENTRY32{ sizeof(MODULEENTRY32) }; 31 | 32 | if (Module32First(hSnapshot, &me32)) 33 | { 34 | do 35 | { 36 | if (!_strcmpi(me32.szModule, module_name)) 37 | return me32.modBaseAddr; 38 | } while (Module32Next(hSnapshot, &me32)); 39 | } 40 | 41 | CloseHandle(hSnapshot); 42 | return 0; 43 | } 44 | 45 | HANDLE get_vulnerable_thread(HANDLE process_handle) 46 | { 47 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 48 | THREADENTRY32 te32; 49 | te32.dwSize = sizeof(THREADENTRY32); 50 | auto process_id = GetProcessId(process_handle); 51 | 52 | if (Thread32First(snapshot, &te32)) { 53 | while (Thread32Next(snapshot, &te32)) { 54 | if (te32.th32OwnerProcessID == process_id) { 55 | CloseHandle(snapshot); 56 | return OpenThread(THREAD_ALL_ACCESS, 0, te32.th32ThreadID); 57 | } 58 | } 59 | } 60 | 61 | CloseHandle(snapshot); 62 | return 0; 63 | } 64 | } -------------------------------------------------------------------------------- /KStealthInjector/process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace process 8 | { 9 | uint64_t get_process_id(std::string process_name); 10 | HANDLE get_vulnerable_thread(HANDLE process_handle); 11 | PBYTE get_remote_module(uint64_t target_pid, LPCSTR module_name); 12 | } -------------------------------------------------------------------------------- /KStealthInjector/service.cpp: -------------------------------------------------------------------------------- 1 | #include "service.h" 2 | 3 | namespace service 4 | { 5 | std::uint64_t start_service(std::string driver_path, std::string service_name) 6 | { 7 | if (service::running(service_name)) 8 | return 1; 9 | 10 | SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 11 | if (!hSCManager) 12 | { 13 | printf("Service::start_service | Unable to open SCManager: %d\n", GetLastError()); 14 | return 0; 15 | } 16 | 17 | SC_HANDLE hService = CreateService(hSCManager, service_name.c_str(), service_name.c_str(), SC_MANAGER_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, driver_path.c_str(), NULL, NULL, NULL, NULL, NULL); 18 | if (!hService && GetLastError() == ERROR_SERVICE_EXISTS) 19 | { 20 | hService = OpenService(hSCManager, service_name.c_str(), SERVICE_ALL_ACCESS); 21 | if (!hService) 22 | { 23 | printf("Service::start_service | Unable to open service: %d\n", GetLastError()); 24 | CloseServiceHandle(hSCManager); 25 | return 0; 26 | } 27 | } 28 | else if (!hService) 29 | { 30 | printf("Service::start_service | Unable to start service: %d\n", GetLastError()); 31 | CloseServiceHandle(hSCManager); 32 | return 0; 33 | } 34 | 35 | if (StartService(hService, NULL, NULL)) 36 | { 37 | CloseServiceHandle(hSCManager); 38 | CloseServiceHandle(hService); 39 | return 1; 40 | } 41 | else 42 | { 43 | printf("Service::start_service | Couldn't Start Service: %d\n", GetLastError()); 44 | CloseServiceHandle(hSCManager); 45 | CloseServiceHandle(hService); 46 | return 0; 47 | } 48 | } 49 | 50 | bool exists(std::string service_name) 51 | { 52 | SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 53 | if (!hSCManager) 54 | { 55 | printf("Service::exists | Unable to open SCManager: %d\n", GetLastError()); 56 | return NULL; 57 | } 58 | 59 | SC_HANDLE hService = OpenService(hSCManager, service_name.c_str(), SERVICE_ALL_ACCESS); 60 | if (hService) 61 | { 62 | CloseServiceHandle(hSCManager); 63 | CloseServiceHandle(hService); 64 | return true; 65 | } 66 | else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) 67 | { 68 | CloseServiceHandle(hSCManager); 69 | CloseServiceHandle(hService); 70 | return false; 71 | } 72 | 73 | printf("Service::exists | Unable to open service: %d\n", GetLastError()); 74 | CloseServiceHandle(hSCManager); 75 | CloseServiceHandle(hService); 76 | return NULL; 77 | } 78 | 79 | bool running(std::string service_name) 80 | { 81 | SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 82 | if (!hSCManager) 83 | { 84 | printf("Service::running | Unable to open SCManager: %d\n", GetLastError()); 85 | return NULL; 86 | } 87 | 88 | SC_HANDLE hService = OpenService(hSCManager, service_name.c_str(), SERVICE_ALL_ACCESS); 89 | if (hService) 90 | { 91 | SERVICE_STATUS_PROCESS status; 92 | DWORD dwBytes; 93 | if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (PBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &dwBytes)) 94 | { 95 | printf("Service::running | Unable to query service status: %d\n", GetLastError()); 96 | CloseServiceHandle(hSCManager); 97 | CloseServiceHandle(hService); 98 | return NULL; 99 | } 100 | CloseServiceHandle(hSCManager); 101 | CloseServiceHandle(hService); 102 | return status.dwCurrentState == 4; 103 | } 104 | else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) 105 | { 106 | CloseServiceHandle(hSCManager); 107 | CloseServiceHandle(hService); 108 | return false; 109 | } 110 | 111 | printf("Service::running | Unable to open service: %d\n", GetLastError()); 112 | CloseServiceHandle(hSCManager); 113 | CloseServiceHandle(hService); 114 | return NULL; 115 | } 116 | 117 | HANDLE get_handle(std::string service_name) 118 | { 119 | char driver_path[256]; 120 | sprintf_s(driver_path, "\\\\.\\%s", service_name.c_str()); 121 | return CreateFile(driver_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 122 | } 123 | std::uint64_t kill_service(std::string service_name) 124 | { 125 | if (service::exists(service_name)) 126 | { 127 | SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 128 | SERVICE_STATUS status; 129 | if (!hSCManager) 130 | { 131 | printf("Service::kill_service | Unable to open SCManager: %d\n", GetLastError()); 132 | return 0; 133 | } 134 | 135 | SC_HANDLE hService = OpenService(hSCManager, service_name.c_str(), SERVICE_ALL_ACCESS); 136 | if (!hService) 137 | { 138 | printf("Service::kill_service | Unable to open service: %d\n", GetLastError()); 139 | CloseServiceHandle(hSCManager); 140 | return 0; 141 | } 142 | 143 | if (!ControlService(hService, SERVICE_CONTROL_STOP, &status)) 144 | { 145 | printf("Service::kill_service | Unable to stop service: %d\n", GetLastError()); 146 | CloseServiceHandle(hSCManager); 147 | CloseServiceHandle(hService); 148 | return 0; 149 | } 150 | 151 | if (!DeleteService(hService)) 152 | { 153 | printf("Service::kill_service | Unable to delete service: %d\n", GetLastError()); 154 | CloseServiceHandle(hSCManager); 155 | CloseServiceHandle(hService); 156 | return 0; 157 | } 158 | 159 | CloseServiceHandle(hSCManager); 160 | CloseServiceHandle(hService); 161 | } 162 | 163 | return 1; 164 | } 165 | } -------------------------------------------------------------------------------- /KStealthInjector/service.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace service 6 | { 7 | uint64_t start_service(std::string driver_path, std::string service_name); 8 | bool exists(std::string service_name); 9 | bool running(std::string service_name); 10 | HANDLE get_handle(std::string service_name); 11 | uint64_t kill_service(std::string service_name); 12 | } -------------------------------------------------------------------------------- /KStealthInjector/shellcode.cpp: -------------------------------------------------------------------------------- 1 | #include "shellcode.h" 2 | 3 | namespace shellcode 4 | { 5 | uint8_t *relative_jmp_64(uint32_t delta) 6 | { 7 | uint8_t jmp[] = { 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; 8 | *(uint32_t *)(jmp + 1) = (uint32_t)delta; 9 | 10 | return jmp; 11 | } 12 | } -------------------------------------------------------------------------------- /KStealthInjector/shellcode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace shellcode 6 | { 7 | uint8_t *relative_jmp_64(uint32_t delta); 8 | } -------------------------------------------------------------------------------- /KStealthInjector/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | namespace utils 4 | { 5 | LPVOID read_file(const char *file_path) 6 | { 7 | DWORD dwBytesRead; 8 | 9 | auto hFile = CreateFileA(file_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); 10 | if ((HANDLE)hFile == INVALID_HANDLE_VALUE) 11 | { 12 | printf("Unable to CreateFile %s: %d\n", file_path, GetLastError()); 13 | return 0; 14 | } 15 | 16 | auto file_size = GetFileSize((HANDLE)hFile, NULL); 17 | auto lpBuffer = VirtualAlloc(NULL, file_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 18 | if (!lpBuffer) 19 | { 20 | printf("Unable to Allocate Memory For Buffer: %d\n", GetLastError()); 21 | return 0; 22 | } 23 | 24 | if (!ReadFile((HANDLE)hFile, lpBuffer, file_size, &dwBytesRead, NULL)) 25 | { 26 | printf("Unable to ReadFile: %d\n", GetLastError()); 27 | return 0; 28 | } 29 | 30 | return lpBuffer; 31 | } 32 | } -------------------------------------------------------------------------------- /KStealthInjector/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace utils 6 | { 7 | LPVOID read_file(const char *file_path); 8 | } -------------------------------------------------------------------------------- /KStealthInjector/xigndriver.cpp: -------------------------------------------------------------------------------- 1 | #include "xigndriver.h" 2 | #include "driver_bin.h" 3 | 4 | namespace xigndriver 5 | { 6 | void initialize() 7 | { 8 | service::start_service("C:\\Windows\\System32\\iutwfsitabnsahbsogiwbiwslhf.sys", "iutwfsitabnsahbsogiwbiwslhf"); 9 | } 10 | 11 | HANDLE open_process(std::string process_name) 12 | { 13 | auto process_id = process::get_process_id(process_name.c_str()); 14 | while (!process_id) 15 | process_id = process::get_process_id(process_name.c_str()); 16 | 17 | return xigndriver::open_process(process_id); 18 | } 19 | 20 | HANDLE open_process(uint32_t process_id) 21 | { 22 | xign_packet *request = new xign_packet(); 23 | xign_response *response = new xign_response(); 24 | 25 | DWORD bytes_written; 26 | HANDLE hTarget; 27 | 28 | request->size = 0x270; 29 | request->magic_num = 0x345821AB; 30 | request->control_val = 0x13371337; 31 | request->function_type = 785; 32 | request->process_id = process_id; 33 | request->access_mode = PROCESS_ALL_ACCESS; 34 | request->output = (uint64_t)response; 35 | 36 | auto hDriver = service::get_handle("iutwfsitabnsahbsogiwbiwslhf"); 37 | 38 | if (!WriteFile(hDriver, request, sizeof(xign_packet), &bytes_written, NULL)) { 39 | printf("Driver Write Failed: %d\n", GetLastError()); 40 | hTarget = NULL; 41 | } 42 | 43 | hTarget = response->process_handle; 44 | 45 | CloseHandle(hDriver); 46 | return hTarget; 47 | } 48 | } -------------------------------------------------------------------------------- /KStealthInjector/xigndriver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "service.h" 7 | #include "process.h" 8 | 9 | namespace xigndriver 10 | { 11 | void initialize(); 12 | HANDLE open_process(std::string process_name); 13 | HANDLE open_process(uint32_t process_id); 14 | 15 | struct xign_packet 16 | { 17 | uint32_t size; 18 | uint32_t magic_num; 19 | uint32_t control_val; 20 | uint32_t function_type; 21 | uint64_t output; 22 | uint32_t process_id; 23 | uint32_t access_mode; 24 | uint8_t pad[592]; 25 | }; 26 | 27 | struct xign_response 28 | { 29 | uint32_t size; 30 | uint32_t magic_num; 31 | uint32_t control_val; 32 | NTSTATUS status; 33 | HANDLE process_handle; 34 | }; 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rohan Bapat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KStealthInjector 2 | Stealthy Injector that leverages a vulnerable driver and other exploits to remain undetected 3 | --------------------------------------------------------------------------------