FARPROC CRemoteLoader::GetRemoteProcAddress( PCHAR Module, SHORT Function ) { HMODULE hKernel32 = LoadLibraryA( "Kernel32.dll" ); if( hKernel32 == NULL ) return NULL; DWORD GetProcAddressOffset = ( DWORD ) GetProcAddress - ( DWORD ) hKernel32; HMODULE hRemoteKernel32 = GetRemoteModuleHandleA( "Kernel32.dll" ); if( hRemoteKernel32 == NULL ) return NULL; HMODULE hRemoteModule = GetRemoteModuleHandleA( Module ); if( hRemoteModule == NULL ) return NULL; PVOID ReturnPointerValue = RemoteAllocateMemory( sizeof( DWORD ) ); PushInt( ( INT ) hRemoteModule ); // HACKHACK: Why is this an int? PushInt( ( INT ) Function ); PushCall( CCONV_STDCALL, ( FARPROC )( ( DWORD_PTR ) hRemoteKernel32 + ( DWORD_PTR ) GetProcAddressOffset ) ); //mov ptr, eax AddByteToBuffer( 0xA3 ); AddLongToBuffer( ( DWORD ) ReturnPointerValue ); //xor eax, eax AddByteToBuffer( 0x33 ); AddByteToBuffer( 0xC0 ); //retn 4 AddByteToBuffer( 0xC2 ); AddByteToBuffer( 0x04 ); AddByteToBuffer( 0x00 ); if( ExecuteRemoteThreadBuffer( m_CurrentRemoteThreadBuffer, true ) == false ) { RemoteFreeMemory( ReturnPointerValue, sizeof( DWORD ) ); return NULL; } DWORD ProcAddressRemote = 0; if( ReadProcessMemory( GetProcess(), ReturnPointerValue, &ProcAddressRemote, sizeof( DWORD ), NULL ) == TRUE ) { RemoteFreeMemory( ReturnPointerValue, sizeof( DWORD ) ); return ( FARPROC ) ProcAddressRemote; } RemoteFreeMemory( ReturnPointerValue, sizeof( DWORD ) ); return NULL; }
HMODULE CRemoteLoader::GetRemoteModuleHandleW( PWCHAR Module ) { CHAR ModuleAnsi[ MAX_PATH ] = { 0 }; wcstombs( ModuleAnsi, Module, MAX_PATH ); return GetRemoteModuleHandleA( ModuleAnsi ); }
int main(int argc, char* argv[]) { DWORD dwProcessId = GetCurrentProcessId(); char szProcessName[256] = {0}; char szModuleName[MAX_PATH] = {0}; for (int i = 1; i < argc; i++) { if (_stricmp(argv[i], "-pid") == 0 && i < (argc - 1)) { dwProcessId = atoi(argv[i + 1]); } if (_stricmp(argv[i], "-name") == 0 && i < (argc - 1)) { strcpy_s(szProcessName, argv[i + 1]); } if (_stricmp(argv[i], "-dll") == 0 && i < (argc - 1)) { strcpy_s(szModuleName, argv[i + 1]); } } if (strlen(szModuleName) == 0) { printf("Module name is required...\n"); return 0; } if (strlen(szProcessName) == 0 && dwProcessId == GetCurrentProcessId()) { printf("Invalid parameters!\n"); return 0; } if (strlen(szProcessName) > 0) { if (dwProcessId == GetCurrentProcessId()) { // Only change the processid if it's not already set dwProcessId = GetProcessIdFromProcessName(szProcessName); if (dwProcessId == GetCurrentProcessId()) { printf("Failed to obtain process \"%s\"...\n", szProcessName); return 0; } } } HMODULE hKernel = LoadLibraryA("kernel32.dll"); DWORD64 dwLoadLibraryA = (DWORD64) GetProcAddress(hKernel, "LoadLibraryA") - (DWORD64) hKernel; printf("kernel32.dll: %016llX\n", hKernel); printf("LoadLibraryA: %016llX\n", dwLoadLibraryA); printf("Module Name: %s\n", szModuleName); char szCurrentModulePath[MAX_PATH] = {0}; GetModuleFileNameA(GetModuleHandle(NULL), szCurrentModulePath, MAX_PATH); for (size_t i = strlen(szCurrentModulePath); i > 0; i--) { if (szCurrentModulePath[ i ] == '\\') { szCurrentModulePath[ i + 1 ] = 0; break; } } strcat_s(szCurrentModulePath, szModuleName); printf("Full Path: %s\n", szCurrentModulePath); DWORD dwFileAttributes = GetFileAttributesA(szCurrentModulePath); if (dwFileAttributes == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND) { printf("File not found...\n"); return 0; } printf("Injecting: %s\n", szCurrentModulePath); HMODULE hRemoteKernel = GetRemoteModuleHandleA(dwProcessId, "kernel32.dll"); if (hRemoteKernel == NULL) { printf("Failed to locate kernel32 in remote process...\n"); return 0; } printf("kernel32 (remote): 0x%016llX\n", hRemoteKernel); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == INVALID_HANDLE_VALUE) { printf("Failed to locate remote process...\n"); return 0; } LPVOID lpModuleName = VirtualAllocEx(hProcess, NULL, strlen(szCurrentModulePath) + 1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpModuleName == NULL) { printf("Failed to allocate module name in remote process...\n"); return 0; } if (WriteProcessMemory(hProcess, lpModuleName, szCurrentModulePath, strlen(szCurrentModulePath), NULL) == FALSE) { printf("Failed to write module name in remote process...\n"); return 0; } DWORD64 dwRemoteLoadLibraryAddress = ((DWORD64)hRemoteKernel + dwLoadLibraryA); printf("LoadLibraryA (remote): %016llX\n", dwRemoteLoadLibraryAddress); HANDLE hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE) dwRemoteLoadLibraryAddress, lpModuleName, 0, 0); printf("Injecting... "); WaitForSingleObject(hThread, INFINITE); printf("Injected!\n"); return 0; }
FARPROC GetRemoteProcAddress( HANDLE hProcess, char *pszModuleName, char *pszProcName ) { FARPROC fpReturnValue = NULL; HMODULE hLocalKernel = GetModuleHandleA( "Kernel32.dll" ); if( hLocalKernel ) { HMODULE hRemoteKernel = GetRemoteModuleHandleA( hProcess, "Kernel32.dll" ); if( hRemoteKernel ) { unsigned long RemoteGetProcAddress = ( unsigned long ) hRemoteKernel + ( unsigned long )( ( unsigned long ) GetProcAddress - ( unsigned long ) hLocalKernel ); void* ResultOfGetProcAddress = Allocate::Alloc( hProcess, sizeof( unsigned long ) ); void* CommitedProcName = Allocate::Commit( hProcess, pszProcName, strlen( pszProcName ) + 1 ); if( ResultOfGetProcAddress && CommitedProcName ) { unsigned char GetProcAddressThreadBuffer[ 27 ] = { 0x68, 0x00, 0x00, 0x00, 0x00, //push proc name 0x68, 0x00, 0x00, 0x00, 0x00, //push module address 0xB8, 0x00, 0x00, 0x00, 0x00, //mov eax, GetProcAddress 0xFF, 0xD0, //call eax 0xA3, 0x00, 0x00, 0x00, 0x00, //mov result, eax 0x33, 0xC0, //xor eax, eax (eax = 0) 0xC2, 0x04, 0x00 //retn 4 }; *( unsigned long* )( GetProcAddressThreadBuffer + 0x01 ) = ( unsigned long ) CommitedProcName; *( unsigned long* )( GetProcAddressThreadBuffer + 0x06 ) = ( unsigned long ) hRemoteKernel; *( unsigned long* )( GetProcAddressThreadBuffer + 0x0B ) = ( unsigned long ) RemoteGetProcAddress; *( unsigned long* )( GetProcAddressThreadBuffer + 0x12 ) = ( unsigned long ) ResultOfGetProcAddress; void* RemoteBufferToWrite = Allocate::Commit( hProcess, GetProcAddressThreadBuffer, sizeof( GetProcAddressThreadBuffer ) ); if( RemoteBufferToWrite ) { HANDLE hSpawnedThread = CreateRemoteThread( hProcess, 0, 0, ( LPTHREAD_START_ROUTINE ) RemoteBufferToWrite, 0, 0, 0 ); WaitForSingleObject( hSpawnedThread, INFINITE ); // Async.. ReadProcessMemory( hProcess, ResultOfGetProcAddress, &fpReturnValue, sizeof( unsigned long ), NULL ); Allocate::Free( hProcess, RemoteBufferToWrite, sizeof( GetProcAddressThreadBuffer ) ); } } if( ResultOfGetProcAddress ) { Allocate::Free( hProcess, ResultOfGetProcAddress, sizeof( unsigned long ) ); } if( CommitedProcName ) { Allocate::Free( hProcess, CommitedProcName, strlen( pszProcName ) + 1 ); } } } return fpReturnValue; }
BOOL CRemoteLoader::ProcessImportTable( PVOID BaseAddress, PVOID RemoteAddress, PCHAR OptionalPath ) { IMAGE_NT_HEADERS* ImageNtHeaders = ToNts( BaseAddress ); if( ImageNtHeaders == NULL ) return FALSE; if( ImageNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ].Size ) { IMAGE_IMPORT_DESCRIPTOR* ImageImportDescriptor = ( IMAGE_IMPORT_DESCRIPTOR* ) RvaToPointer( ImageNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ].VirtualAddress, BaseAddress ); if( ImageImportDescriptor ) { for( ; ImageImportDescriptor->Name; ImageImportDescriptor++ ) { PCHAR ModuleName = ( PCHAR ) RvaToPointer( ImageImportDescriptor->Name, BaseAddress ); if( ModuleName == NULL ) { DebugShout( "[ProcessImportTable] Module name for entry NULL" ); continue; } DebugShout( "[ProcessImportTable] Module Name [%s]", ModuleName ); HMODULE ModuleBase = GetRemoteModuleHandleA( ModuleName ); if( ModuleBase == NULL ) { ModuleBase = LoadLibraryByPathA( ModuleName ); } if( ModuleBase == NULL ) { DebugShout( "[ProcessImportTable] Failed to obtain module handle [%s]", ModuleName ); continue; } IMAGE_THUNK_DATA *ImageThunkData = NULL; IMAGE_THUNK_DATA *ImageFuncData = NULL; if( ImageImportDescriptor->OriginalFirstThunk ) { ImageThunkData = ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->OriginalFirstThunk, BaseAddress ); ImageFuncData = ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->FirstThunk, BaseAddress ); } else { ImageThunkData = ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->FirstThunk, BaseAddress ); ImageFuncData = ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->FirstThunk, BaseAddress ); } if( ImageThunkData == NULL ) { DebugShout( "[ProcessImportTable] Image Thunk Data is NULL" ); } if( ImageFuncData == NULL ) { DebugShout( "[ProcessImportTable] Image Func Data is NULL" ); } for( ; ImageThunkData->u1.AddressOfData; ImageThunkData++, ImageFuncData++ ) { FARPROC FunctionAddress = NULL; if( IMAGE_SNAP_BY_ORDINAL( ImageThunkData->u1.Ordinal ) ) { SHORT Ordinal = ( SHORT ) IMAGE_ORDINAL( ImageThunkData->u1.Ordinal ); FunctionAddress = ( FARPROC ) GetRemoteProcAddress( ModuleName, Ordinal ); DebugShout( "[ProcessImportTable] Processed (%s -> %i) -> (0x%X)", ModuleName, Ordinal, FunctionAddress ); if( this->GetProcess() == INVALID_HANDLE_VALUE ) { DebugShout( "[ProcessImportTable] Normal Value (0x%X)", GetProcAddress( GetModuleHandleA( ModuleName ), ( LPCSTR ) Ordinal ) ); } } else { IMAGE_IMPORT_BY_NAME* ImageImportByName = ( IMAGE_IMPORT_BY_NAME* ) RvaToPointer( *( DWORD* ) ImageThunkData, BaseAddress ); PCHAR NameOfImport = ( PCHAR ) ImageImportByName->Name; FunctionAddress = ( FARPROC ) GetRemoteProcAddress( ModuleName, NameOfImport ); DebugShout( "[ProcessImportTable] Processed (%s -> %s) -> (0x%X)", ModuleName, NameOfImport, FunctionAddress ); if( this->GetProcess() == INVALID_HANDLE_VALUE ) { DebugShout( "[ProcessImportTable] Normal Value (0x%X)", GetProcAddress( GetModuleHandleA( ModuleName ), NameOfImport ) ); } } ImageFuncData->u1.Function = ( DWORD ) FunctionAddress; } } return TRUE; } else { DebugShout( "[ProcessImportTable] Size of table confirmed but pointer to data invalid!" ); return FALSE; } } else { DebugShout( "[ProcessImportTable] No Imports" ); return TRUE; } return FALSE; }