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; }
void CRemoteCode::PushAllParameters( bool right_to_left ) { if( m_CurrentInvokeInfo.params.size() == 0 ) return; DebugShout( "Parameters for function [%i]", m_CurrentInvokeInfo.params.size() ); vector<parameter_info_t> currentParams = m_CurrentInvokeInfo.params; vector<parameter_info_t> pushOrder; if( right_to_left == false ) { //left-to-right for( int i = 0; i < (int)m_CurrentInvokeInfo.params.size(); i++ ) { pushOrder.push_back( m_CurrentInvokeInfo.params.at( i ) ); DebugShout( "Parameter found [%i][%i]", i, m_CurrentInvokeInfo.params.at( i ).ptype ); } } else { //right-to-left if( m_CurrentInvokeInfo.params.size() == 1 ) { pushOrder.push_back( m_CurrentInvokeInfo.params.at( 0 ) ); } else { int iBegin = (int)m_CurrentInvokeInfo.params.size() - 1; while( iBegin != -1 ) { pushOrder.push_back( m_CurrentInvokeInfo.params.at( iBegin ) ); DebugShout( "Parameter found [%i][%s]", iBegin, ParameterTypeToString( m_CurrentInvokeInfo.params.at( iBegin ).ptype ).c_str() ); iBegin--; } } } for( int p = 0; p < (int)pushOrder.size(); p++ ) { parameter_info_t *paraminfo = &pushOrder[p]; if( paraminfo == NULL ) continue; DebugShout( "Function Iter [%i]", p ); DebugShout( "Function Parameter [%s]", ParameterTypeToString( paraminfo->ptype ).c_str() ); if( paraminfo->pparam == NULL ) { AddByteToBuffer( 0x68 ); AddLongToBuffer( 0 ); continue; } switch( paraminfo->ptype ) { case PARAMETER_TYPE_SHORT: case PARAMETER_TYPE_POINTER: case PARAMETER_TYPE_INT: case PARAMETER_TYPE_FLOAT: { if( paraminfo->pparam ) { unsigned long ulParam = *(unsigned long *)paraminfo->pparam; AddByteToBuffer( 0x68 ); AddLongToBuffer( ulParam ); } else { //if it is PARAMETER_TYPE_POINTER with a NULL pointer //we don't want to crash AddByteToBuffer( 0x68 ); AddLongToBuffer( NULL ); } break; } case PARAMETER_TYPE_BYTE: { unsigned char ucParam = *(unsigned char *)paraminfo->pparam; AddByteToBuffer( 0x6A ); AddByteToBuffer( ucParam ); break; } case PARAMETER_TYPE_BOOL: { bool bParam = *(bool *)paraminfo->pparam; unsigned char ucParam = (bParam) ? 1 : 0; AddByteToBuffer( 0x6A ); AddByteToBuffer( ucParam ); break; } case PARAMETER_TYPE_STRING: { char *szParameter = (char *)paraminfo->pparam; void *AllocatedString = CommitMemory( szParameter, strlen( szParameter ) + 1 ); if( AllocatedString == NULL ) { DebugShout( "NULL Allocated ANSI string pointer...." ); continue; //bad beans } DebugShout( "Allocated string pointer at [0x%X]", AllocatedString ); AddByteToBuffer( 0x68 ); AddLongToBuffer( ( unsigned long ) AllocatedString ); break; } case PARAMETER_TYPE_WSTRING: { wchar_t *szParameter = (wchar_t *)paraminfo->pparam; void *AllocatedString = CommitMemory( szParameter, (wcslen( szParameter ) * 2) + 1 ); if( AllocatedString == NULL ) { DebugShout( "NULL Allocated UNICODE string pointer...." ); continue; //bad beans } AddByteToBuffer( 0x68 ); AddLongToBuffer((unsigned long)AllocatedString); break; } default: { DebugShout( "Unable to locate parameter type %i", paraminfo->ptype ); break; } } } }
void CRemoteCode::PushCall( calling_convention_t cconv, FARPROC CallAddress ) { DebugShout( "PushCall [0x%X][0x%X]", cconv, CallAddress ); int iFunctionBegin = (int)m_CurrentInvokeInfo.params.size(); m_CurrentInvokeInfo.calladdress = reinterpret_cast<unsigned long>( CallAddress ); m_CurrentInvokeInfo.cconv = cconv; switch( cconv ) { case CCONV_CDECL: { DebugShout( "Entering __cdecl" ); int iCalculateAddEsp = (iFunctionBegin * 4); PushAllParameters( true ); AddByteToBuffer( MOV_EAX_VALUE ); AddLongToBuffer( m_CurrentInvokeInfo.calladdress ); AddByteToBuffer( CALL_EXTERNAL ); AddByteToBuffer( 0xD0 ); //eax if( iCalculateAddEsp != 0 ) { bool bUseByte = (iCalculateAddEsp <= 0xFF); if( bUseByte ) { //add esp, [BYTE] AddByteToBuffer( 0x83 ); AddByteToBuffer( 0xC4 ); AddByteToBuffer((unsigned char)iCalculateAddEsp); } else { //add esp, [LONG] AddByteToBuffer( 0x81 ); AddByteToBuffer( 0xC4 ); AddLongToBuffer( iCalculateAddEsp ); } } break; } case CCONV_STDCALL: { DebugShout( "Entering __stdcall" ); PushAllParameters( true ); AddByteToBuffer( MOV_EAX_VALUE ); AddLongToBuffer( m_CurrentInvokeInfo.calladdress ); AddByteToBuffer( CALL_EXTERNAL ); AddByteToBuffer( 0xD0 ); //eax break; } case CCONV_THISCALL: { DebugShout( "Entering __thiscall" ); if( iFunctionBegin == 0 ) //no params... { DebugShout( "No parameters passed for __thiscall, requires at least one parameter (ECX)" ); break; } //first parameter of __thiscall is ALWAYS ECX. ALWAYS. //the parameter type should also be PARAMETER_TYPE_POINTER if( m_CurrentInvokeInfo.params[0].ptype != PARAMETER_TYPE_POINTER ) { DebugShout( "\"THIS\" parameter type invalid [%i]", m_CurrentInvokeInfo.params[0].ptype ); } void *pThis = m_CurrentInvokeInfo.params[0].pparam; if( pThis == NULL ) { DebugShout( "\"THIS\" parameter NULL for __thiscall function (ECX)" ); } AddByteToBuffer( 0x8B ); AddByteToBuffer( 0x0D ); AddLongToBuffer((unsigned long)pThis); //now we need to remove the first parameter from the vector, so when we execute the //parameter iteration function it is not included..... m_CurrentInvokeInfo.params.erase( m_CurrentInvokeInfo.params.begin() ); PushAllParameters( true ); AddByteToBuffer( MOV_EAX_VALUE ); AddLongToBuffer( m_CurrentInvokeInfo.calladdress ); AddByteToBuffer( CALL_EXTERNAL ); AddByteToBuffer( 0xD0 ); //eax break; } case CCONV_FASTCALL: { DebugShout( "Entering __fastcall" ); if( iFunctionBegin == 0 ) { PushCall( CCONV_STDCALL, CallAddress ); return; } else if( iFunctionBegin == 1 ) { unsigned long ulEdxParam = *(unsigned long *)m_CurrentInvokeInfo.params[0].pparam; AddByteToBuffer( 0xBA ); AddLongToBuffer( ulEdxParam ); m_CurrentInvokeInfo.params.erase( m_CurrentInvokeInfo.params.begin() ); PushCall( CCONV_STDCALL, CallAddress ); return; } else { unsigned long ulEdxParam = *(unsigned long *)m_CurrentInvokeInfo.params[0].pparam; unsigned long ulEaxParam = *(unsigned long *)m_CurrentInvokeInfo.params[1].pparam; AddByteToBuffer( 0xBA ); AddLongToBuffer( ulEdxParam ); AddByteToBuffer( MOV_EAX_VALUE ); AddLongToBuffer( ulEaxParam ); m_CurrentInvokeInfo.params.erase( m_CurrentInvokeInfo.params.begin() ); m_CurrentInvokeInfo.params.erase( m_CurrentInvokeInfo.params.begin() ); PushAllParameters( true ); AddByteToBuffer( 0xBB ); AddLongToBuffer( m_CurrentInvokeInfo.calladdress ); AddByteToBuffer( CALL_EXTERNAL ); AddByteToBuffer( 0xD3 ); //ebx } break; } } //clear data m_CurrentInvokeInfo.params.clear(); m_CurrentInvokeInfo.calladdress = NULL; }
HMODULE CRemoteLoader::LoadLibraryByPathW( PWCHAR Path ) { if( Path == NULL ) { DebugShout( "[LoadLibraryByPathW] szString is NULL" ); return NULL; } FARPROC RemoteLoadLibraryW = GetRemoteProcAddress( "kernel32.dll", "LoadLibraryW" ); if( RemoteLoadLibraryW == NULL ) { DebugShout( "[LoadLibraryByPathW] LoadLibraryW Resolve Failure" ); return NULL; } DebugShout( "[LoadLibraryByPathW] LoadLibraryW = 0x%X", RemoteLoadLibraryW ); PVOID ReturnPointerValue = RemoteAllocateMemory( sizeof( DWORD ) ); PushUNICODEString( Path ); PushCall( CCONV_STDCALL, RemoteLoadLibraryW ); //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 ) { DebugShout( "[LoadLibraryByPathW] ExecuteRemoteThreadBuffer failed" ); RemoteFreeMemory( ReturnPointerValue, sizeof( DWORD ) ); return NULL; } DebugShout( "[LoadModuleByNameW] ExecuteRemoteThreadBuffer succeeded" ); DWORD RemoteModuleHandle = 0; if( ReadProcessMemory( GetProcess(), ReturnPointerValue, &RemoteModuleHandle, sizeof( DWORD ), NULL ) == TRUE ) { RemoteFreeMemory( ReturnPointerValue, sizeof( DWORD ) ); } else { RemoteFreeMemory( ReturnPointerValue, sizeof( DWORD ) ); if( RemoteModuleHandle == 0 ) { RemoteModuleHandle = ( DWORD ) GetRemoteModuleHandleW( Path ); } } return ( HMODULE ) RemoteModuleHandle; }