Guest User

Thread-safe DLL injection

a guest
Dec 1st, 2012
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.14 KB | None | 0 0
  1. #include <windows.h>
  2. #include <stdio.h>
  3.  
  4. DWORD Inject( HANDLE hProcess,const char* dllPath,const char* functionName );
  5.  
  6. int main( int argc,char* argv[ ] ) {
  7.     if( argc < 3 ) {
  8.         printf( "Usage: Inject <executable> <injected DLL>\n" );
  9.         return 1;
  10.     }
  11.  
  12.     STARTUPINFO si;
  13.     PROCESS_INFORMATION pi;
  14.     char szLibPath[ MAX_PATH + 1 ];
  15.    
  16.     // Start our process in suspended mode
  17.     ZeroMemory( &si,sizeof( si ) );
  18.     ZeroMemory( &pi,sizeof( pi ) );
  19.     CreateProcess( argv[ 1 ],NULL,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,&pi );
  20.     printf( "Process created\n" );
  21.     DWORD exitCode = Inject( pi.hProcess,argv[ 2 ],"HotpatchMessageBox" );
  22.     printf( "Injection returned with exit code %d\n",exitCode );
  23.     // Resume the primary thread of our process
  24.     ResumeThread( pi.hThread );
  25. }
  26.  
  27. DWORD Inject( HANDLE hProcess,const char* dllPath,const char* functionName ) {
  28.     // Get the address of the KERNEL32.DLL
  29.     HMODULE kernel32 = LoadLibrary( "KERNEL32.DLL" );
  30.  
  31.     // Get needed functions
  32.     FARPROC loadlibrary = GetProcAddress( kernel32,"LoadLibraryA" );
  33.     FARPROC getprocaddress = GetProcAddress( kernel32,"GetProcAddress" );
  34.     FARPROC exitthread = GetProcAddress( kernel32,"ExitThread" );
  35.  
  36.     // Create the workspace
  37.     LPBYTE workspace = ( LPBYTE ) HeapAlloc( GetProcessHeap( ),HEAP_ZERO_MEMORY,1024 );
  38.  
  39.     // Allocate space for the codecave in the process
  40.     LPVOID codecaveAddress = VirtualAllocEx( hProcess,0,1024,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE );
  41.     DWORD dwCodecaveAddress = PtrToUlong( codecaveAddress );
  42.  
  43.     DWORD workspaceIndex = 0;
  44.     DWORD dwTmpSize = 0;
  45.  
  46.     // First, let's define some data and room for pointers
  47.     // Leave a 4-bytes slot for DLL address
  48.     DWORD dllAddr = dwCodecaveAddress + workspaceIndex;
  49.     workspaceIndex += 4;
  50.  
  51.     // A slot for function name
  52.     DWORD funcNameAddr = dwCodecaveAddress + workspaceIndex;
  53.     dwTmpSize = ( DWORD ) strlen( functionName ) + 1;
  54.     memcpy( workspace + workspaceIndex,functionName,dwTmpSize );
  55.     workspaceIndex += dwTmpSize;
  56.  
  57.     // A slot for DLL path
  58.     DWORD dllPathAddr = workspaceIndex + dwCodecaveAddress;
  59.     dwTmpSize = ( DWORD ) strlen( dllPath ) + 1;
  60.     memcpy( workspace + workspaceIndex,dllPath,dwTmpSize );
  61.     workspaceIndex += dwTmpSize;
  62.  
  63.     // Store where the codecave execution should begin
  64.     DWORD startAddress = workspaceIndex + dwCodecaveAddress;
  65.  
  66.     // Actual executable instructions start here
  67.     // PUSH 0x00000000 - Push the address of the DLL path to use in LoadLibraryA
  68.     workspace[ workspaceIndex++ ] = 0x68;
  69.     memcpy( workspace + workspaceIndex,&dllPathAddr,4 );
  70.     workspaceIndex += 4;
  71.  
  72.     // MOV EAX, ADDRESS - Move the address of LoadLibraryA into EAX
  73.     workspace[ workspaceIndex++ ] = 0xB8;
  74.     memcpy( workspace + workspaceIndex,&loadlibrary,4 );
  75.     workspaceIndex += 4;
  76.  
  77.     // CALL EAX - Call LoadLibraryA
  78.     workspace[ workspaceIndex++ ] = 0xFF;
  79.     workspace[ workspaceIndex++ ] = 0xD0;
  80.  
  81.     // MOV [ADDRESS], EAX - Save the address to our variable
  82.     workspace[ workspaceIndex++ ] = 0xA3;
  83.     memcpy( workspace + workspaceIndex,&dllAddr,4 );
  84.     workspaceIndex += 4;
  85.  
  86.     // PUSH 0x000000 - Push the address of the function name to load
  87.     workspace[ workspaceIndex++ ] = 0x68;
  88.     memcpy(workspace + workspaceIndex,&funcNameAddr,4 );
  89.     workspaceIndex += 4;
  90.  
  91.     // Push EAX, module to use in GetProcAddress
  92.     workspace[ workspaceIndex++ ] = 0x50;
  93.  
  94.     // MOV EAX, ADDRESS - Move the address of GetProcAddress into EAX
  95.     workspace[ workspaceIndex++ ] = 0xB8;
  96.     memcpy( workspace + workspaceIndex,&getprocaddress,4 );
  97.     workspaceIndex += 4;
  98.  
  99.     // CALL EAX - Call GetProcAddress. Address will be in EAX.
  100.     workspace[workspaceIndex++] = 0xFF;
  101.     workspace[workspaceIndex++] = 0xD0;
  102.  
  103.     // CALL EAX - Call requested function by using it's address from EAX.
  104.     workspace[workspaceIndex++] = 0xFF;
  105.     workspace[workspaceIndex++] = 0xD0;
  106.  
  107.     // Push 0 (exit code)
  108.     workspace[ workspaceIndex++ ] = 0x6A;
  109.     workspace[ workspaceIndex++ ] = 0x00;
  110.  
  111.     // MOV EAX, ADDRESS - Move the address of ExitThread into EAX
  112.     workspace[ workspaceIndex++ ] = 0xB8;
  113.     memcpy( workspace + workspaceIndex,&exitthread,4 );
  114.     workspaceIndex += 4;
  115.  
  116.     // CALL EAX - Call ExitThread
  117.     workspace[workspaceIndex++] = 0xFF;
  118.     workspace[workspaceIndex++] = 0xD0;
  119.    
  120.     DWORD oldProtect = 0;
  121.     DWORD bytesRet = 0;
  122.  
  123.     VirtualProtectEx( hProcess,codecaveAddress,workspaceIndex,PAGE_EXECUTE_READWRITE,&oldProtect );
  124.  
  125.     // Write out the patch
  126.     WriteProcessMemory( hProcess,codecaveAddress,workspace,workspaceIndex,&bytesRet );
  127.  
  128.     // Restore page protection
  129.     VirtualProtectEx( hProcess,codecaveAddress,workspaceIndex,oldProtect,&oldProtect );
  130.  
  131.     // Make sure our changes are written right away
  132.     FlushInstructionCache( hProcess,codecaveAddress,workspaceIndex );
  133.  
  134.     HeapFree( GetProcessHeap( ),0,workspace );
  135.  
  136.     HANDLE hThread = CreateRemoteThread( hProcess,NULL,0,
  137.         ( LPTHREAD_START_ROUTINE ) ( void* ) startAddress,0,0,NULL );
  138.     // Wait for our thread to terminate
  139.     WaitForSingleObject( hThread,INFINITE );
  140.  
  141.     // Get exit code from our remote thread
  142.     DWORD exitCode = 0;
  143.     GetExitCodeThread( hThread,&exitCode );
  144.     // And finally close the handle
  145.     CloseHandle( hThread );
  146.  
  147.     // Free the memory in the process that we allocated
  148.     VirtualFreeEx( hProcess,codecaveAddress,0,MEM_RELEASE );
  149.  
  150.     return exitCode;
  151. }
Advertisement
Add Comment
Please, Sign In to add comment