BOOL CRemoteLoader::CallEntryPoint( PVOID BaseAddress, FARPROC Entrypoint ) { PushInt( ( INT ) BaseAddress ); PushInt( DLL_PROCESS_ATTACH ); PushInt( 0 ); PushCall( CCONV_STDCALL, Entrypoint ); return ExecuteRemoteThreadBuffer( AssembleRemoteThreadBuffer() ); }
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 LoadCode(int fd, struct Module_st* CMData) { Word i,j; Word offset=CMData->CodeOffset; Word size=CMData->CodeSize; Byte* code; Byte opcode; ConstInd tmpIndex; INSTR_InstrCategory instrCat; INSTR_OperandType* opType; int argid=0; if(size<=0){ debug("No code for current module.\n"); return; } debug("Loading 0x%lx bytes of code at %lx to offset 0x%lx.\n",size,lseek(fd,0,SEEK_CUR),offset); code=(Byte*)LK_VECTOR_GetPtr(&Code,offset); debug("After get\n"); opcode=-1; instrCat=INSTR_CAT_X; opType=NULL; for(i=0;i<size;) { j=i; opcode=code[j++]=LK_FILE_GET1(fd); debug("\t%lx:%lx:[%x]%s\t",lseek(fd,0,SEEK_CUR)-1,i,opcode,INSTR_instrName(opcode)); if(opcode==call_link_only) { code[j]=LK_FILE_GET1(fd); tmpIndex=GetConstInd(fd,CMData); PushCall(CMData->Pit,tmpIndex,offset+i,code[j]); i += INSTR_instrSize(opcode); continue; } else if(opcode==execute_link_only) { tmpIndex=GetConstInd(fd,CMData); PushCall(CMData->Pit,tmpIndex,offset+i,-1); i += INSTR_instrSize(opcode); continue; } instrCat=INSTR_instrType(opcode); opType=INSTR_operandTypes(instrCat); argid=0; do{ switch(opType[argid]) { case INSTR_P: j++; break; case INSTR_WP: j+=sizeof(Word); break; case INSTR_SEG: LK_FILE_GET1(fd);//Consume dummy argument *(Byte*)(code+j)=CMData->SegmentID; debug("ID:%d\t",CMData->SegmentID); j+=sizeof(Byte); break; case INSTR_R: case INSTR_E: case INSTR_N: case INSTR_I1: case INSTR_CE: *(Byte*)(code+j)=LK_FILE_GET1(fd); debug("%d\t",*(Byte*)(code+j)); j+=sizeof(Byte); break; // case INSTR_I2: // *(TwoBytes*)(code+j)=GET2(); // j+=sizeof(TwoBytes); // break; case INSTR_C: *(TwoBytes*)(code+j)=PackConstInd(GetConstInd(fd,CMData)); debug("C:%d\t",*(TwoBytes*)(code+j)); j+=sizeof(TwoBytes); break; case INSTR_K: *(TwoBytes*)(code+j)=PackKindInd(GetKindInd(fd,CMData)); debug("K:%d\t",*(TwoBytes*)(code+j)); j+=sizeof(TwoBytes); break; case INSTR_MT: *(ImportTabInd*)(code+j)=GetImportTabInd(fd,CMData); debug("IT:%d\t",*(ImportTabInd*)(code+j)); j+=sizeof(ImportTabInd); break; case INSTR_IT: *(ImplGoalInd*)(code+j)=GetImplGoalInd(fd,CMData); debug("IG:%d\t",*(ImplGoalInd*)(code+j)); j+=sizeof(ImplGoalInd); break; case INSTR_HT: *(HashTabInd*)(code+j)=GetHashTabInd(fd,CMData); debug("HT:%d\t",*(HashTabInd*)(code+j)); j+=sizeof(HashTabInd); break; case INSTR_BVT: *(BvrTabInd*)(code+j)=GetBvrTabInd(fd,CMData); debug("BT:%d\t",*(BvrTabInd*)(code+j)); j+=sizeof(BvrTabInd); break; case INSTR_S: *(StringInd*)(code+j)=GetStringInd(fd,CMData); debug("S:%d\t",*(StringInd*)(code+j)); j+=sizeof(StringInd); break; case INSTR_L: *(CodeInd*)(code+j)=GetCodeInd(fd,CMData); debug("L:%d\t",*(CodeInd*)(code+j)); j+=sizeof(CodeInd); break; case INSTR_I: *(INT4*)(code+j)=LK_FILE_GET4(fd); debug("I:%d\t",*(INT4*)(code+j)); j+=sizeof(INT4); break; case INSTR_F: *(INT4*)(code+j)=GetFloat(fd); debug("F:%d\t",*(INT4*)(code+j)); j+=sizeof(INT4); break; case INSTR_X: break; default: bad("Unknown Operand Type %d\n",opType[argid]); EM_THROW(LK_LinkError); break; } argid++; } while(opType[argid]!=INSTR_X); debug("\n"); i += INSTR_instrSize(opcode); } debug("NOWD -> %d[%d,%d]\n",166,(*(ConstInd*)(code+166)).gl_flag,(*(ConstInd*)(code+166)).index); }
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; }