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