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