├── DllInjected
├── DllInjected.vcxproj.filters
├── main.cpp
└── DllInjected.vcxproj
├── CodeInjection
├── CodeInjection.vcxproj.filters
├── CodeInjection.vcxproj
└── main.cpp
├── DllInjection
├── DllInjection.vcxproj.filters
├── DllInjection.vcxproj
└── main.cpp
├── README.md
├── DllInjection.sln
└── .gitignore
/DllInjected/DllInjected.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CodeInjection/CodeInjection.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/DllInjection/DllInjection.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WinCodeInjection
2 |
3 | This repository contains 2 samples:
4 | * Dll Injector with a Dll to inject
5 | * Code Injector
6 |
7 | The Dll Injector sample use the undocumented function *NtCreateThreadEx* to launch a remote thread.
8 | If you want to use *CreateRemoteThread*, you have to remember that starting with Win Vista (Session Separation)
9 | a process situated in a session can't access to a process in a different session.
10 |
11 | The Code injector performs a change on the *image relocation table* to adjust it to the new base. In this sample I use the
12 | simple *CreateRemoteThread* to insert a custom function in another process.
13 |
--------------------------------------------------------------------------------
/DllInjected/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 |
5 | INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
6 | FILE *file;
7 |
8 | fopen_s( &file, "C:\\temp.txt", "a+" );
9 |
10 | switch(Reason)
11 | {
12 | case DLL_PROCESS_ATTACH:
13 | fprintf(file, "DLL attach function called\n");
14 | break;
15 | case DLL_PROCESS_DETACH:
16 | fprintf(file, "DLL detach function called\n");
17 | break;
18 | case DLL_THREAD_ATTACH:
19 | fprintf(file, "DLL thread attach function called\n");
20 | break;
21 | case DLL_THREAD_DETACH:
22 | fprintf(file, "DLL thread detach function called\n");
23 | break;
24 | }
25 |
26 |
27 | fclose(file);
28 |
29 | return TRUE;
30 | }
--------------------------------------------------------------------------------
/DllInjection.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CreateRemoteThread", "DllInjection\DllInjection.vcxproj", "{27755FC1-4274-4459-9727-B451AC796309}"
5 | EndProject
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllInjected", "DllInjected\DllInjected.vcxproj", "{173BD705-6661-4105-91CD-7619DA510F8D}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CodeInjection", "CodeInjection\CodeInjection.vcxproj", "{F2E35C30-4D8A-4BD9-9201-841B96102F2E}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Win32 = Debug|Win32
13 | Release|Win32 = Release|Win32
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {27755FC1-4274-4459-9727-B451AC796309}.Debug|Win32.ActiveCfg = Debug|Win32
17 | {27755FC1-4274-4459-9727-B451AC796309}.Debug|Win32.Build.0 = Debug|Win32
18 | {27755FC1-4274-4459-9727-B451AC796309}.Debug|Win32.Deploy.0 = Debug|Win32
19 | {27755FC1-4274-4459-9727-B451AC796309}.Release|Win32.ActiveCfg = Release|Win32
20 | {27755FC1-4274-4459-9727-B451AC796309}.Release|Win32.Build.0 = Release|Win32
21 | {27755FC1-4274-4459-9727-B451AC796309}.Release|Win32.Deploy.0 = Release|Win32
22 | {173BD705-6661-4105-91CD-7619DA510F8D}.Debug|Win32.ActiveCfg = Debug|Win32
23 | {173BD705-6661-4105-91CD-7619DA510F8D}.Debug|Win32.Build.0 = Debug|Win32
24 | {173BD705-6661-4105-91CD-7619DA510F8D}.Debug|Win32.Deploy.0 = Debug|Win32
25 | {173BD705-6661-4105-91CD-7619DA510F8D}.Release|Win32.ActiveCfg = Release|Win32
26 | {173BD705-6661-4105-91CD-7619DA510F8D}.Release|Win32.Build.0 = Release|Win32
27 | {173BD705-6661-4105-91CD-7619DA510F8D}.Release|Win32.Deploy.0 = Release|Win32
28 | {F2E35C30-4D8A-4BD9-9201-841B96102F2E}.Debug|Win32.ActiveCfg = Debug|Win32
29 | {F2E35C30-4D8A-4BD9-9201-841B96102F2E}.Debug|Win32.Build.0 = Debug|Win32
30 | {F2E35C30-4D8A-4BD9-9201-841B96102F2E}.Debug|Win32.Deploy.0 = Debug|Win32
31 | {F2E35C30-4D8A-4BD9-9201-841B96102F2E}.Release|Win32.ActiveCfg = Release|Win32
32 | {F2E35C30-4D8A-4BD9-9201-841B96102F2E}.Release|Win32.Build.0 = Release|Win32
33 | {F2E35C30-4D8A-4BD9-9201-841B96102F2E}.Release|Win32.Deploy.0 = Release|Win32
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | EndGlobal
39 |
--------------------------------------------------------------------------------
/DllInjected/DllInjected.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {173BD705-6661-4105-91CD-7619DA510F8D}
15 | DllInjected
16 |
17 |
18 |
19 | DynamicLibrary
20 | true
21 | v110
22 | MultiByte
23 |
24 |
25 | DynamicLibrary
26 | false
27 | v110
28 | true
29 | MultiByte
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Level3
45 | Disabled
46 |
47 |
48 | true
49 |
50 |
51 |
52 |
53 | Level3
54 | MaxSpeed
55 | true
56 | true
57 |
58 |
59 | true
60 | true
61 | true
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/DllInjection/DllInjection.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {27755FC1-4274-4459-9727-B451AC796309}
15 | DllInjection
16 | CreateRemoteThread
17 |
18 |
19 |
20 | Application
21 | true
22 | v110
23 | MultiByte
24 |
25 |
26 | Application
27 | false
28 | v110
29 | true
30 | MultiByte
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | Level3
46 | Disabled
47 |
48 |
49 | true
50 |
51 |
52 |
53 |
54 | Level3
55 | MaxSpeed
56 | true
57 | true
58 |
59 |
60 | true
61 | true
62 | true
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/CodeInjection/CodeInjection.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {F2E35C30-4D8A-4BD9-9201-841B96102F2E}
15 | CodeInjection
16 |
17 |
18 |
19 | Application
20 | true
21 | v110
22 | MultiByte
23 |
24 |
25 | Application
26 | false
27 | v110
28 | true
29 | MultiByte
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Level3
45 | Disabled
46 | true
47 |
48 |
49 | true
50 |
51 |
52 |
53 |
54 | Level3
55 | MaxSpeed
56 | true
57 | true
58 | true
59 |
60 |
61 | true
62 | true
63 | true
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
20 | !packages/*/build/
21 |
22 | # MSTest test Results
23 | [Tt]est[Rr]esult*/
24 | [Bb]uild[Ll]og.*
25 |
26 | #NUNIT
27 | *.VisualState.xml
28 | TestResult.xml
29 |
30 | *.ilk
31 | *.meta
32 | *.obj
33 | *.pch
34 | *.pgc
35 | *.pgd
36 | *.rsp
37 | *.sbr
38 | *.tlb
39 | *.tli
40 | *.tlh
41 | *.tmp
42 | *.tmp_proj
43 | *.log
44 | *.vspscc
45 | *.vssscc
46 | .builds
47 | *.pidb
48 | *.svclog
49 | *.scc
50 |
51 | # Chutzpah Test files
52 | _Chutzpah*
53 |
54 | # Visual C++ cache files
55 | ipch/
56 | *.aps
57 | *.ncb
58 | *.opensdf
59 | *.sdf
60 | *.cachefile
61 |
62 | # Visual Studio profiler
63 | *.psess
64 | *.vsp
65 | *.vspx
66 |
67 | # TFS 2012 Local Workspace
68 | $tf/
69 |
70 | # Guidance Automation Toolkit
71 | *.gpState
72 |
73 | # ReSharper is a .NET coding add-in
74 | _ReSharper*/
75 | *.[Rr]e[Ss]harper
76 | *.DotSettings.user
77 |
78 | # JustCode is a .NET coding addin-in
79 | .JustCode
80 |
81 | # TeamCity is a build add-in
82 | _TeamCity*
83 |
84 | # DotCover is a Code Coverage Tool
85 | *.dotCover
86 |
87 | # NCrunch
88 | *.ncrunch*
89 | _NCrunch_*
90 | .*crunch*.local.xml
91 |
92 | # MightyMoose
93 | *.mm.*
94 | AutoTest.Net/
95 |
96 | # Installshield output folder
97 | [Ee]xpress/
98 |
99 | # DocProject is a documentation generator add-in
100 | DocProject/buildhelp/
101 | DocProject/Help/*.HxT
102 | DocProject/Help/*.HxC
103 | DocProject/Help/*.hhc
104 | DocProject/Help/*.hhk
105 | DocProject/Help/*.hhp
106 | DocProject/Help/Html2
107 | DocProject/Help/html
108 |
109 | # Click-Once directory
110 | publish/
111 |
112 | # Publish Web Output
113 | *.Publish.xml
114 | *.azurePubxml
115 |
116 | # NuGet Packages Directory
117 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
118 | #packages/
119 | ## TODO: If the tool you use requires repositories.config, also uncomment the next line
120 | #!packages/repositories.config
121 |
122 | # Windows Azure Build Output
123 | csx/
124 | *.build.csdef
125 |
126 | # Windows Store app package directory
127 | AppPackages/
128 |
129 | # Others
130 | sql/
131 | *.Cache
132 | [Ss]tyle[Cc]op.*
133 | ~$*
134 | *~
135 | *.dbmdl
136 | *.dbproj.schemaview
137 | *.[Pp]ublish.xml
138 | *.pfx
139 | *.publishsettings
140 |
141 | # RIA/Silverlight projects
142 | Generated_Code/
143 |
144 | # Backup & report files from converting an old project file to a newer
145 | # Visual Studio version. Backup files are not needed, because we have git ;-)
146 | _UpgradeReport_Files/
147 | Backup*/
148 | UpgradeLog*.XML
149 | UpgradeLog*.htm
150 |
151 | # SQL Server files
152 | App_Data/*.mdf
153 | App_Data/*.ldf
154 |
155 | # Business Intelligence projects
156 | *.rdl.data
157 | *.bim.layout
158 | *.bim_*.settings
159 |
160 | # Microsoft Fakes
161 | FakesAssemblies/
162 |
163 | # =========================
164 | # Windows detritus
165 | # =========================
166 |
167 | # Windows image file caches
168 | Thumbs.db
169 | ehthumbs.db
170 |
171 | # Folder config file
172 | Desktop.ini
173 |
174 | .DS_Store
175 |
176 | objfre_*
177 | *Release
178 |
179 | tests/Plugins/cache.*
180 | tests/Plugins/catdb
181 | tests/bdnc.ipv*
182 | tests/smartdb-*.db
183 | tests/*.dll
184 | tests/*.pdb
185 | tests/*.ilk
186 | tests/*.lib
187 | tests/*.exp
188 |
189 | *.swp
190 | *.sdf
191 |
192 | avlab/www/webapp/app/cache/*.*
193 | avlab/www/webapp/app/uploads/*/*
194 |
--------------------------------------------------------------------------------
/CodeInjection/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #pragma comment(lib,"ntdll.lib")
7 |
8 | using namespace std;
9 |
10 |
11 | void WINAPI ThreadProc( HINSTANCE hInst )
12 | {
13 | MessageBox( 0, "Hello", "Welcome Message",1 );
14 |
15 | ExitThread(0);
16 | }
17 |
18 | bool IsWindowsNT( )
19 | {
20 | return ( GetVersion() < 0x80000000 ) ? true : false;
21 | }
22 |
23 | vector GetProcessListExeName( PCSTR szExeName )
24 | {
25 | HANDLE hSnapProcess = NULL;
26 | PROCESSENTRY32 pe32 = {0};
27 | vector ape32ProcessList;
28 |
29 | if( !IsWindowsNT( ) || !szExeName )
30 | return ape32ProcessList;
31 |
32 |
33 | if( !( hSnapProcess = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ) )
34 | return ape32ProcessList;
35 |
36 | pe32.dwSize = sizeof( PROCESSENTRY32 );
37 | if( Process32First( hSnapProcess, &pe32 ) )
38 | {
39 | do
40 | {
41 | if( strcmp( pe32.szExeFile, szExeName ) == 0 )
42 | {
43 | ape32ProcessList.push_back( pe32 );
44 | }
45 | }
46 | while( Process32Next( hSnapProcess, &pe32 ) );
47 | }
48 |
49 | CloseHandle(hSnapProcess);
50 |
51 | return ape32ProcessList;
52 | }
53 |
54 |
55 | BOOL SetPrivilege(
56 | HANDLE hToken,
57 | LPCTSTR lpPrivilege,
58 | BOOL bEnablePrivilege
59 | )
60 | {
61 | // Initializing variables
62 | TOKEN_PRIVILEGES tkp = {0};
63 | LUID luid = {0};
64 | TOKEN_PRIVILEGES tkpPrevious = {0};
65 | DWORD cbPrevious = 0;
66 |
67 | // Check the parameters passed to the function
68 | if( ( !hToken ) || ( !lpPrivilege ) )
69 | {
70 | return FALSE;
71 | }
72 |
73 | if( !LookupPrivilegeValue( NULL, lpPrivilege, &luid ) )
74 | {
75 | return FALSE;
76 | }
77 |
78 | tkp.PrivilegeCount = 1;
79 | tkp.Privileges[0].Luid = luid;
80 | tkp.Privileges[0].Attributes = 0;
81 |
82 | cbPrevious = sizeof( TOKEN_PRIVILEGES );
83 | AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof( TOKEN_PRIVILEGES ), &tkpPrevious, &cbPrevious );
84 | if( GetLastError() != ERROR_SUCCESS )
85 | {
86 | return FALSE;
87 | }
88 |
89 | tkpPrevious.PrivilegeCount = 1;
90 | tkpPrevious.Privileges[0].Luid = luid;
91 |
92 | if( bEnablePrivilege )
93 | {
94 | tkpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
95 | }
96 | else
97 | {
98 | tkpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tkpPrevious.Privileges[0].Attributes);
99 | }
100 |
101 | AdjustTokenPrivileges( hToken, FALSE, &tkpPrevious, cbPrevious, NULL, NULL );
102 | if( GetLastError() != ERROR_SUCCESS )
103 | {
104 | return FALSE;
105 | }
106 |
107 | return TRUE;
108 | }
109 |
110 |
111 | //
112 | // Set debug privilege
113 | //
114 | BOOL SetDebugPrivilege( BOOL bEnable )
115 | {
116 | HANDLE hToken = NULL;
117 |
118 | if( !OpenProcessToken( GetCurrentProcess( ), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
119 | return FALSE;
120 |
121 | // Enable/Disable Debug Privilege
122 | if( !SetPrivilege( hToken, SE_DEBUG_NAME, bEnable ) )
123 | {
124 | CloseHandle(hToken);
125 |
126 | return FALSE;
127 | }
128 |
129 | CloseHandle(hToken);
130 |
131 | return TRUE;
132 | }
133 |
134 | void main( int argc, char* argv[] )
135 | {
136 | PIMAGE_DOS_HEADER pImageDosHeader;
137 | PIMAGE_NT_HEADERS pImageHeaders;
138 | PIMAGE_DATA_DIRECTORY pImageDataDirectory;
139 | PIMAGE_BASE_RELOCATION pImageBaseRelocation;
140 |
141 | HMODULE hModule;
142 | HANDLE hProcess, hThread;
143 |
144 | LPVOID pRemoteMem = NULL;
145 | LPVOID pImage = NULL;
146 | PVOID StartAddress = NULL;
147 |
148 | DWORD dwSizeOfImage;
149 | DWORD dwPID;
150 | DWORD dwCount;
151 |
152 | DWORD_PTR delta, OldDelta;
153 |
154 | LPWORD list;
155 | PDWORD_PTR p;
156 |
157 | if( argc != 2 )
158 | {
159 | printf( "Usage : %s \n", argv[0] );
160 |
161 | return;
162 | }
163 |
164 | vector ape32ProcessList = GetProcessListExeName( argv[1] );
165 | if( ape32ProcessList.size() > 0 )
166 | {
167 | dwPID = ape32ProcessList[0].th32ProcessID;
168 | }
169 |
170 | SetDebugPrivilege(TRUE);
171 |
172 | hModule = GetModuleHandle(NULL);
173 | if( hModule == NULL )
174 | {
175 | printf("[ERROR] : GetModuleHandle failed with status 0x%08X\n", GetLastError() );
176 |
177 | return;
178 | }
179 |
180 | pImageDosHeader = (PIMAGE_DOS_HEADER)hModule;
181 |
182 | pImageHeaders = (PIMAGE_NT_HEADERS)( (BYTE*)pImageDosHeader + pImageDosHeader->e_lfanew );
183 |
184 | dwSizeOfImage = pImageHeaders->OptionalHeader.SizeOfImage;
185 |
186 | printf( "# Open Target PID : %d %d\n", dwPID, dwSizeOfImage );
187 |
188 | hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwPID );
189 | if( hProcess == NULL )
190 | {
191 | printf("[ERROR] : OpenProcess failed with status 0x%08X\n", GetLastError() );
192 |
193 | return;
194 | }
195 |
196 | pRemoteMem = VirtualAllocEx( hProcess, NULL, dwSizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
197 |
198 | if( pRemoteMem == NULL )
199 | {
200 | printf("[ERROR] : VirtualAllocEx failed with error 0x%08X\n", GetLastError() );
201 |
202 | goto end;
203 | }
204 |
205 | printf( "# Remote Memory allocated : 0x%08X\n", pRemoteMem );
206 |
207 | pImage = VirtualAlloc( NULL, dwSizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
208 |
209 | memcpy( pImage, hModule, dwSizeOfImage );
210 |
211 | pImageDataDirectory = &pImageHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
212 | pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)( (LPBYTE)pImage + pImageDataDirectory->VirtualAddress );
213 |
214 | delta = (DWORD_PTR)( (LPBYTE)pRemoteMem - pImageHeaders->OptionalHeader.ImageBase );
215 | OldDelta = (DWORD_PTR)( (LPBYTE)hModule - pImageHeaders->OptionalHeader.ImageBase );
216 |
217 | while( pImageBaseRelocation->VirtualAddress != 0 )
218 | {
219 | if( pImageBaseRelocation->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION) )
220 | {
221 | dwCount = ( pImageBaseRelocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof(WORD);
222 | list = (LPWORD)( (LPBYTE)pImageBaseRelocation + sizeof(IMAGE_BASE_RELOCATION) );
223 |
224 | for( unsigned int i = 0; i < dwCount; i++ )
225 | {
226 | if( list[i] > 0 )
227 | {
228 | p = (PDWORD_PTR)( (LPBYTE)pImage + ( pImageBaseRelocation->VirtualAddress + ( 0x0fff & (list[i]) ) ) );
229 |
230 | *p -= OldDelta;
231 | *p += delta;
232 | }
233 | }
234 | }
235 |
236 | pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)( (LPBYTE) pImageBaseRelocation + pImageBaseRelocation->SizeOfBlock );
237 | }
238 |
239 | printf("# Writing the image into target process.\n");
240 |
241 | int n = WriteProcessMemory( hProcess, pRemoteMem, pImage, dwSizeOfImage, NULL );
242 | if( n == 0 )
243 | {
244 | printf( "[ERROR] : NtWriteVirtualMemory failed with status 0x%08X\n", GetLastError() );
245 |
246 | goto end;
247 | }
248 |
249 | StartAddress = (PVOID)( (LPBYTE)pRemoteMem + (DWORD_PTR)(LPBYTE)ThreadProc - (LPBYTE)hModule );
250 |
251 | printf("# Creating remote thread.\n");
252 |
253 | hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)StartAddress, pRemoteMem, NULL, NULL );
254 | if( hThread == NULL )
255 | {
256 | printf( "[ERROR] : Can't create remote thread (0x%08X)\n", GetLastError() );
257 |
258 | goto end;
259 | }
260 |
261 |
262 | printf( "[SUCCESS] : the remote thread was successfully created\n" );
263 |
264 | WaitForSingleObject( hThread, INFINITE );
265 |
266 | CloseHandle(hThread);
267 |
268 | end:
269 |
270 | printf("# Freeing memory and handles.\n");
271 |
272 | if( pRemoteMem )
273 | {
274 | VirtualFreeEx( hProcess, pRemoteMem, 0, MEM_RELEASE );
275 | }
276 |
277 | if( hProcess )
278 | {
279 | CloseHandle(hProcess);
280 | }
281 |
282 | if( pImage )
283 | {
284 | VirtualFree( pImage, 0, MEM_RELEASE );
285 | }
286 |
287 | return;
288 | }
289 |
--------------------------------------------------------------------------------
/DllInjection/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | using namespace std;
7 |
8 | #define PROCESS_THREAD_ACCESS PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE
9 |
10 | // Undocumented function and relative structure
11 |
12 | // http://securityxploded.com/ntcreatethreadex.php
13 | // Using CreateRemoteThread :
14 | // Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process.
15 |
16 | typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx)
17 | (
18 | OUT PHANDLE hThread,
19 | IN ACCESS_MASK DesiredAccess,
20 | IN LPVOID ObjectAttributes,
21 | IN HANDLE ProcessHandle,
22 | IN LPTHREAD_START_ROUTINE lpStartAddress,
23 | IN LPVOID lpParameter,
24 | IN BOOL CreateSuspended,
25 | IN ULONG StackZeroBits,
26 | IN ULONG SizeOfStackCommit,
27 | IN ULONG SizeOfStackReserve,
28 | OUT LPVOID lpBytesBuffer
29 | );
30 |
31 | //Buffer argument passed to NtCreateThreadEx function
32 |
33 | struct NtCreateThreadExBuffer
34 | {
35 | ULONG Size;
36 | ULONG Unknown1;
37 | ULONG Unknown2;
38 | PULONG Unknown3;
39 | ULONG Unknown4;
40 | ULONG Unknown5;
41 | ULONG Unknown6;
42 | PULONG Unknown7;
43 | ULONG Unknown8;
44 | };
45 |
46 |
47 | bool IsWindowsNT( )
48 | {
49 | return ( GetVersion() < 0x80000000 ) ? true : false;
50 | }
51 |
52 | vector GetProcessListExeName( PCSTR szExeName )
53 | {
54 | HANDLE hSnapProcess = NULL;
55 | PROCESSENTRY32 pe32 = {0};
56 | vector ape32ProcessList;
57 |
58 | if( !IsWindowsNT( ) || !szExeName )
59 | return ape32ProcessList;
60 |
61 |
62 | if( !( hSnapProcess = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ) )
63 | return ape32ProcessList;
64 |
65 | pe32.dwSize = sizeof( PROCESSENTRY32 );
66 | if( Process32First( hSnapProcess, &pe32 ) )
67 | {
68 | do
69 | {
70 | if( strcmp( pe32.szExeFile, szExeName ) == 0 )
71 | {
72 | ape32ProcessList.push_back( pe32 );
73 | }
74 | }
75 | while( Process32Next( hSnapProcess, &pe32 ) );
76 | }
77 |
78 | CloseHandle(hSnapProcess);
79 |
80 | return ape32ProcessList;
81 | }
82 |
83 | BOOL SetPrivilege(
84 | HANDLE hToken,
85 | LPCTSTR lpPrivilege,
86 | BOOL bEnablePrivilege
87 | )
88 | {
89 | // Initializing variables
90 | TOKEN_PRIVILEGES tkp = {0};
91 | LUID luid = {0};
92 | TOKEN_PRIVILEGES tkpPrevious = {0};
93 | DWORD cbPrevious = 0;
94 |
95 | // Check the parameters passed to the function
96 | if( ( !hToken ) || ( !lpPrivilege ) )
97 | {
98 | return FALSE;
99 | }
100 |
101 | if( !LookupPrivilegeValue( NULL, lpPrivilege, &luid ) )
102 | {
103 | return FALSE;
104 | }
105 |
106 | tkp.PrivilegeCount = 1;
107 | tkp.Privileges[0].Luid = luid;
108 | tkp.Privileges[0].Attributes = 0;
109 |
110 | cbPrevious = sizeof( TOKEN_PRIVILEGES );
111 | AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof( TOKEN_PRIVILEGES ), &tkpPrevious, &cbPrevious );
112 | if( GetLastError() != ERROR_SUCCESS )
113 | {
114 | return FALSE;
115 | }
116 |
117 | tkpPrevious.PrivilegeCount = 1;
118 | tkpPrevious.Privileges[0].Luid = luid;
119 |
120 | if( bEnablePrivilege )
121 | {
122 | tkpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
123 | }
124 | else
125 | {
126 | tkpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tkpPrevious.Privileges[0].Attributes);
127 | }
128 |
129 | AdjustTokenPrivileges( hToken, FALSE, &tkpPrevious, cbPrevious, NULL, NULL );
130 | if( GetLastError() != ERROR_SUCCESS )
131 | {
132 | return FALSE;
133 | }
134 |
135 | return TRUE;
136 | }
137 |
138 |
139 | //
140 | // Set debug privilege
141 | //
142 | BOOL SetDebugPrivilege( BOOL bEnable )
143 | {
144 | HANDLE hToken = NULL;
145 |
146 | if( !OpenProcessToken( GetCurrentProcess( ), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
147 | return FALSE;
148 |
149 | // Enable/Disable Debug Privilege
150 | if( !SetPrivilege( hToken, SE_DEBUG_NAME, bEnable ) )
151 | {
152 | CloseHandle(hToken);
153 |
154 | return FALSE;
155 | }
156 |
157 | CloseHandle(hToken);
158 |
159 | return TRUE;
160 | }
161 |
162 | HANDLE GetHandleModuleInjected( DWORD dwPID, char *szModulePath )
163 | {
164 | HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
165 | MODULEENTRY32 me32;
166 |
167 | // Take a snapshot of all modules in the specified process.
168 | hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
169 | if( hModuleSnap == INVALID_HANDLE_VALUE )
170 | {
171 | printf( "[ERROR] : CreateToolhelp32Snapshot error 0x%08X\n", GetLastError() );
172 | return hModuleSnap;
173 | }
174 |
175 | // Set the size of the structure before using it.
176 | me32.dwSize = sizeof( MODULEENTRY32 );
177 |
178 | // Retrieve information about the first module,
179 | // and exit if unsuccessful
180 | if( !Module32First( hModuleSnap, &me32 ) )
181 | {
182 | printf( "[ERROR] : Module32First error 0x%08X\n", GetLastError() ); // show cause of failure
183 | CloseHandle( hModuleSnap ); // clean the snapshot object
184 | return hModuleSnap;
185 | }
186 |
187 | // Now walk the module list of the process,
188 | // and display information about each module
189 | do
190 | {
191 | if( strstr( szModulePath, me32.szModule ) )
192 | {
193 | break;
194 | }
195 | }
196 | while( Module32Next( hModuleSnap, &me32 ) );
197 |
198 | CloseHandle( hModuleSnap );
199 |
200 | return hModuleSnap;
201 | }
202 |
203 | void main( int argc, char* argv[] )
204 | {
205 | DWORD dwPID;
206 | HANDLE hThread = NULL;
207 | NTSTATUS status;
208 |
209 | char *szDllPath;
210 |
211 | LPVOID pRemoteMem = NULL;
212 |
213 | if( argc < 3 )
214 | {
215 | printf( "Usage : %s \n", argv[0] );
216 |
217 | return;
218 | }
219 |
220 | szDllPath = argv[2];
221 |
222 | vector ape32ProcessList = GetProcessListExeName( argv[1] );
223 | if( ape32ProcessList.size() > 0 )
224 | {
225 | dwPID = ape32ProcessList[0].th32ProcessID;
226 | }
227 |
228 | printf( "# Injecting %s in %s (PID %d)\n", szDllPath, argv[1], dwPID );
229 |
230 | SetDebugPrivilege(TRUE);
231 |
232 | // Open remote process
233 | HANDLE hProcess = OpenProcess( PROCESS_THREAD_ACCESS, FALSE, dwPID );
234 | if( hProcess == NULL )
235 | {
236 | printf( "[ERROR] : Can't open process (0x%08X)\n", GetLastError() );
237 |
238 | goto end;
239 | }
240 |
241 | // Load LoadLibraryA function address
242 | HMODULE hModule = GetModuleHandle("kernel32.dll");
243 | if( hModule == NULL )
244 | {
245 | printf( "[ERROR] : GetModuleHandle error (0x%08X)\n", GetLastError() );
246 |
247 | goto end;
248 | }
249 |
250 | PTHREAD_START_ROUTINE pThreadRoutine = (PTHREAD_START_ROUTINE)GetProcAddress( hModule, "LoadLibraryA" );
251 | if( pThreadRoutine == NULL )
252 | {
253 | printf( "[ERROR] : LoadLibrary not found (0x%08X)\n", GetLastError() );
254 |
255 | goto end;
256 | }
257 |
258 | HMODULE modNtDll = GetModuleHandle("ntdll.dll");
259 | if( modNtDll == NULL )
260 | {
261 | printf( "[ERROR] : GetModuleHandle error (0x%08X)\n", GetLastError() );
262 |
263 | goto end;
264 | }
265 |
266 | printf( "# Remote memory Allocation.\n" );
267 |
268 | pRemoteMem = (LPVOID)VirtualAllocEx( hProcess, NULL, strlen(szDllPath), MEM_COMMIT, PAGE_EXECUTE_READWRITE );
269 | if( pRemoteMem == NULL )
270 | {
271 | printf( "[ERROR] : Can't allocate memory (0x%08X)\n", GetLastError() );
272 |
273 | goto end;
274 | }
275 |
276 | printf( "# Remote memory allocated : 0x%08X\n", pRemoteMem );
277 |
278 | printf( "# Writing remote memory.\n" );
279 |
280 | int n = WriteProcessMemory( hProcess, pRemoteMem, szDllPath, strlen(szDllPath), NULL );
281 | if( n == 0 )
282 | {
283 | printf( "[ERROR] : Can't write on memory process (0x%08X)\n", GetLastError() );
284 |
285 | goto end;
286 | }
287 |
288 | //
289 | // We're using this undocumented func because the simple CreateRemoteThread can't access
290 | // from a session to another session (session separation)
291 | //
292 | LPFUN_NtCreateThreadEx funNtCreateThreadEx = (LPFUN_NtCreateThreadEx) GetProcAddress(modNtDll, "NtCreateThreadEx");
293 |
294 | if( !funNtCreateThreadEx )
295 | {
296 | printf( "[ERROR] : can't get function address (0x%08X)", GetLastError() );
297 |
298 | goto end;
299 | }
300 |
301 | NtCreateThreadExBuffer ntbuffer;
302 |
303 | memset (&ntbuffer,0,sizeof(NtCreateThreadExBuffer));
304 | DWORD temp1 = 0;
305 | DWORD temp2 = 0;
306 |
307 | ntbuffer.Size = sizeof(NtCreateThreadExBuffer);
308 | ntbuffer.Unknown1 = 0x10003;
309 | ntbuffer.Unknown2 = 0x8;
310 | ntbuffer.Unknown3 = &temp2;
311 | ntbuffer.Unknown4 = 0;
312 | ntbuffer.Unknown5 = 0x10004;
313 | ntbuffer.Unknown6 = 4;
314 | ntbuffer.Unknown7 = &temp1;
315 | ntbuffer.Unknown8 = 0;
316 |
317 | status =
318 | funNtCreateThreadEx(
319 | &hThread,
320 | 0x1FFFFF,
321 | NULL,
322 | hProcess,
323 | (LPTHREAD_START_ROUTINE) pThreadRoutine,
324 | pRemoteMem,
325 | FALSE,
326 | NULL,
327 | NULL,
328 | NULL,
329 | &ntbuffer
330 | );
331 |
332 |
333 | //ThreadID = CreateRemoteThread( hProcess, NULL, 0, pThreadRoutine, pRemoteMem, NULL, NULL );
334 | if( hThread == NULL )
335 | {
336 | printf( "[ERROR] : Can't create remote thread (0x%08X)\n", status );
337 | }
338 |
339 | DWORD dwInjectedDllBase = 0;
340 |
341 | printf( "[SUCCESS] : the remote thread was successfully created\n" );
342 |
343 | WaitForSingleObject( hThread, INFINITE );
344 |
345 | GetExitCodeThread( hProcess, &dwInjectedDllBase );
346 |
347 | CloseHandle(hThread);
348 |
349 | end:
350 | if( pRemoteMem != 0 )
351 | {
352 | VirtualFreeEx( hProcess, pRemoteMem, 0, MEM_RELEASE );
353 | }
354 |
355 | if( hProcess != NULL )
356 | {
357 | CloseHandle(hProcess);
358 | }
359 |
360 | return;
361 | }
--------------------------------------------------------------------------------