Click here to Skip to main content
15,892,059 members
Articles / Programming Languages / ASM

Inject your code to a Portable Executable file

Rate me:
Please Sign up or sign in to vote.
4.97/5 (203 votes)
27 Dec 2005GPL333 min read 917.5K   42.7K   690  
This article demonstrates five steps to inject your code in a portable executable (EXE, DLL, OCX,...) file without recompiling source code.
/* loader.cpp --

   This file is part of the "PE Maker".

   Copyright (C) 2005-2006 Ashkbiz Danehkar
   All Rights Reserved.

   "PE Maker" library are free software; you can redistribute them
   and/or modify them under the terms of the GNU General Public License as
   published by the Free Software Foundation.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYRIGHT.TXT.
   If not, write to the Free Software Foundation, Inc.,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

   yodap's Forum:
   http://yodapforum.has.it/

   yodap's Site:
   http://yodap.has.it
   http://yodap.cjb.net
   http://yodap.sourceforge.net

   Ashkbiz Danehkar
   <ashkbiz@yahoo.com>
*/
#include "stdafx.h"
#include "loader.h"
#include "itmaker.h"

#ifdef _DEBUG
#define DEBUG_NEW
#endif

__stdcall void DynLoader();
//---------------------------------------------------------
// Thanks FEUERRADER [AHTeam] for idea about using _emit 0! 
//---------------------------------------------------------
// byte ptr		(1 bytes)
#define byte_type(x)			__asm _emit x 
// word ptr		(2 bytes)
#define word_type(x)			byte_type((x>>(0*8))&0xFF)	byte_type((x>>(1*8))&0xFF)
// dword ptr	(4 bytes)
#define dword_type(x)			byte_type((x>>(0*8))&0xFF)	byte_type((x>>(1*8))&0xFF)	byte_type((x>>(2*8))&0xFF)	byte_type((x>>(3*8))&0xFF)
// dword64 ptr	(8 bytes)
#define dword64_type(x)			dword_type(x)	dword_type(x)
// dword64 ptr	(16 bytes)
#define dword128_type(x)		dword64_type(x)	dword64_type(x)
//---------------------------------------------------------
#define bb(x)					__asm _emit x 
#define db						byte_type(0xCC)
#define __random_code1__		dword64_type(0X90909090) // Reserve for random code generation
#define __jmp_api				byte_type(0xFF)	byte_type(0x25)

//----------------------------------------------------------------
__stdcall void DynLoader()
{
_asm
{
//----------------------------------
	dword_type(DYN_LOADER_START_MAGIC)
//----------------------------------
_main_0:
	pushad	// save the registers context in stack
	call _main_1
_main_1:	
	pop ebp
	sub ebp,offset _main_1 // get base ebp
	//----------------------------------------------------
	//====================================================
	//---------------- support dll, ocx  -----------------
_support_dll_0:
	jmp _support_dll_1 // nop; nop; // in the secon time OEP
	jmp _support_dll_2
_support_dll_1:
	test [ebp+_p_dwFileType],IMPORT_TABLE_OCX
	jz _no_dll_pe_file_0
		mov eax,[esp+24h]// imagebase
		mov ebx,[esp+30h]// oep
		cmp eax,ebx
		ja _no_dll_pe_file_0
			cmp word ptr [eax],IMAGE_DOS_SIGNATURE
			jne _no_dll_pe_file_0
				mov [ebp+_p_dwImageBase],eax
_no_dll_pe_file_0:
	//----------------------------------------------------
	//====================================================
	mov eax,[ebp+_p_dwImageBase]
	add eax,[eax+03Ch]
	add eax,080h
	mov ecx,[eax]	// image_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
	add ecx,[ebp+_p_dwImageBase]
	add ecx,010h	// image_import_descriptor.FirstThunk
	mov eax,[ecx]
	add eax,[ebp+_p_dwImageBase]
	mov ebx,[eax]
	mov [ebp+_p_LoadLibrary],ebx
	add eax,04h
	mov ebx,[eax]
	mov [ebp+_p_GetProcAddress],ebx
	//----------------------------------------------------
	//====================================================
	//------- load library and build api call-jmp --------
	lea edi,[ebp+_p_szKernel32]
	lea ebx,[ebp+_p_GetModuleHandle]
	lea ecx,[ebp+_jmp_GetModuleHandle]
	add ecx,02h
_api_get_lib_address_loop:
		push ecx
		//-------------------
		push edi
		mov eax,offset _p_LoadLibrary
		call [ebp+eax]// LoadLibrary(lpLibFileName);
		//-------------------
		pop ecx
		mov esi,eax	// esi -> hModule
		push edi
		call __strlen
		add esp,04h
		add edi,eax
_api_get_proc_address_loop:
			push ecx
			//-------------------
			push edi
			push esi
			mov eax,offset _p_GetProcAddress
			call [ebp+eax]// GetModuleHandle=GetProcAddress(hModule, lpProcName);
			//--------------------
			pop ecx
			mov [ebx],eax
			mov [ecx],ebx
			add ebx,04h
			add ecx,06h
			push edi
			call __strlen
			add esp,04h
			add edi,eax
			mov al,byte ptr [edi]
		test al,al
		jnz _api_get_proc_address_loop
		inc edi
		mov al,byte ptr [edi]
	test al,al
	jnz _api_get_lib_address_loop
	//----------------------------------------------------
	//====================================================

	// Place your code here ...


	//----------------------------------------------------
	//====================================================
	//----------- get write access for headers -----------
	mov edi,[ebp+_p_dwImageBase]
	add edi,[edi+03Ch]// edi -> IMAGE_NT_HEADERS
	// get write permission by VirtualProtect()
	lea eax,[ebp+_p_ptempbuffer]
	push eax
	push PAGE_READWRITE
	push [edi+0x54]//IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders
	push [ebp+_p_dwImageBase]
	call _jmp_VirtualProtect
	//VirtualProtect(dwImageBase,image_nt_header.OptionalHeader.SizeOfHeaders,PAGE_READWRITE,ptempbuffer);
	//----------------------------------------------------
	//--------------- import table fix up ----------------
	call _it_fixup
	//----------------------------------------------------
	//====================================================
	//---------------- support dll, ocx  1 ---------------
	//by set second way to oep and relocation table effect
	mov edi,[ebp+_p_dwImageBase]
	add edi,[edi+03Ch]// edi -> IMAGE_NT_HEADERS
	mov ax,word ptr [edi+016h]// edi -> image_nt_headers->FileHeader.Characteristics
	// .IF ((image_nt_headers->FileHeader.Characteristics&IMAGE_FILE_DLL) ==IMAGE_FILE_DLL)
	test ax,IMAGE_FILE_DLL
	jz _no_dll_pe_file_1
		//--------------- relocation fix up --------------
		call _reloc_fixup
		//------------------------------------------------
		mov ax,9090h
		mov word ptr [ebp+_support_dll_0],ax
	// .ENDIF
_no_dll_pe_file_1:
	//----------------------------------------------------
	//====================================================
_support_dll_2:
	//----------------------------------------------------
	//====================================================
	//--------- Prepare the SEH for OEP approach ---------
	mov eax,[ebp+_p_dwImageBase]
	add eax,[ebp+_p_dwOrgEntryPoint]
	mov [esp+10h],eax	// pStack.Ebx <- eax
	lea eax,[ebp+_except_handler1_OEP_Jump]
	mov [esp+1Ch],eax	// pStack.Eax <- eax
	popad	// restore the first registers context from stack
	//----------------------------------------------------
  	// the structured exception handler (SEH) installation 
	push eax
	xor  eax, eax
	push dword ptr fs:[0]		// NT_TIB32.ExceptionList
	mov fs:[0],esp	// NT_TIB32.ExceptionList <-ESP
	dword_type(0xCCCCCCCC)// raise a (int 3) exception
	//----------------------------------------------------
	//====================================================
//--------------------------------------------------------
//========================================================
//------------- t_size strlen(LPCTSTR lpStr) -------------
__strlen:
	push ebp
	mov ebp,esp
	push ecx
	push esi
	push ebx
	mov esi,[ebp+08h]// -> destination
	mov ecx,255// -> length
	xor ebx,ebx
_strlenloop:
		lods byte ptr ds:[esi]
		cmp al,00h
		jz _endbufstrlen
		inc ebx
	loop _strlenloop
_endbufstrlen:
	mov eax,ebx
	inc eax
	pop ebx
	pop esi
	pop ecx
	mov esp,ebp
	pop ebp
	ret
//--------------------------------------------------------
//========================================================
//------------------- fix up relocation ------------------
// I have stolen this reloc fix-up code from Morphine 2.7 !!
// so Thanks Holy_Father && Ratter/29A for it. (www.hxdef.org)
_reloc_fixup:
	mov eax,[ebp+_p_dwImageBase]
	mov edx,eax
	mov ebx,eax
	add ebx,[ebx+3Ch] // edi -> IMAGE_NT_HEADERS
	mov ebx,[ebx+034h]// edx ->image_nt_headers->OptionalHeader.ImageBase
	sub edx,ebx // edx -> reloc_correction
	je _reloc_fixup_end
	mov ebx,[ebp+_p_dwRelocationVirtualAddress]
	test ebx,ebx
	jz _reloc_fixup_end
	add ebx,eax
_reloc_fixup_block:
	mov eax,[ebx+004h]			//ImageBaseRelocation.SizeOfBlock
	test eax,eax
	jz _reloc_fixup_end
	lea ecx,[eax-008h]			//ImageBaseRelocation.SizeOfBlock - sizeof(TImageBaseRelocation)
	shr ecx,001h				//WORD((ImageBaseRelocation.SizeOfBlock - sizeof(TImageBaseRelocation)) / sizeof(Word))
	lea edi,[ebx+008h]			//PImageBaseRelocation + sizeof(TImageBaseRelocation)
_reloc_fixup_do_entry:
		movzx eax,word ptr [edi]//Entry
		push edx
		mov edx,eax
		shr eax,00Ch			//Type = Entry >> 12

		mov esi,[ebp+_p_dwImageBase]//ImageBase
		and dx,00FFFh
		add esi,[ebx]			//ImageBase + ImageBaseRelocation.VirtualAddress
		add esi,edx				//ImageBase + ImageBaseRelocation.VirtualAddress+Entry & 0x0FFF
		pop edx
		//------------------------------
		//---- IMAGE_REL_BASED_HIGH ----
_reloc_fixup_HIGH:
		dec eax
		jnz _reloc_fixup_LOW
			mov eax,edx
			shr eax,010h		//HIWORD(Delta)
			jmp _reloc_fixup_LOW_fixup
		//------------------------------
		//---- IMAGE_REL_BASED_LOW -----
_reloc_fixup_LOW:
			dec eax
		jnz _reloc_fixup_HIGHLOW
		movzx eax,dx			//LOWORD(Delta)
_reloc_fixup_LOW_fixup:
			add word ptr [esi],ax
		jmp _reloc_fixup_next_entry
		//------------------------------
		//-- IMAGE_REL_BASED_HIGHLOW ---
_reloc_fixup_HIGHLOW:
			dec eax
		jnz _reloc_fixup_next_entry
		add [esi],edx
		//------------------------------
_reloc_fixup_next_entry:
		inc edi
		inc edi						//Entry++
		loop _reloc_fixup_do_entry
	
_reloc_fixup_next_base:
	add ebx,[ebx+004h]				//ImageBaseRelocation + ImageBaseRelocation.SizeOfBlock
	jmp _reloc_fixup_block
_reloc_fixup_end:
	// clean relocation table
/*	mov eax,[ebp+_p_dwImageBase]
	add eax,[ebp+_p_dwRelocationVirtualAddress]
	lea edi,[eax]
	xor eax,eax
	add ecx,[ebp+_p_dwRelocationSize]
	rep stos byte  ptr [edi]*/
	ret
//--------------------------------------------------------
//========================================================
//--------------- fix up the import table ----------------
// I have stolen this IT fix-up code from Morphine 2.7 !!
// so Thanks Holy_Father && Ratter/29A for it. (www.hxdef.org)
_it_fixup:
	mov ebx,[ebp+_p_dwImportVirtualAddress]
	test ebx,ebx
	jz _it_fixup_end
	mov esi,[ebp+_p_dwImageBase]
	add ebx,esi									// dwImageBase + dwImportVirtualAddress
_it_fixup_get_lib_address_loop:
		mov eax,[ebx+00Ch]						// image_import_descriptor.Name
		test eax,eax
		jz _it_fixup_end
		
		mov ecx,[ebx+010h]						// image_import_descriptor.FirstThunk
		add ecx,esi
		mov [ebp+_p_dwThunk],ecx				// dwThunk
		mov ecx,[ebx]							// image_import_descriptor.Characteristics
		test ecx,ecx
		jnz _it_fixup_table
			mov ecx,[ebx+010h]
_it_fixup_table:
		add ecx,esi
		mov [ebp+_p_dwHintName],ecx				// dwHintName
		add eax,esi								// image_import_descriptor.Name + dwImageBase = ModuleName
		push eax								// lpLibFileName
		mov eax,offset _p_LoadLibrary
		call [ebp+eax]							// LoadLibrary(lpLibFileName);

		test eax,eax
		jz _it_fixup_end
		mov edi,eax
_it_fixup_get_proc_address_loop:
			mov ecx,[ebp+_p_dwHintName]			// dwHintName
			mov edx,[ecx]						// image_thunk_data.Ordinal
			test edx,edx
			jz _it_fixup_next_module
			test edx,080000000h					// .IF( import by ordinal )
			jz _it_fixup_by_name
				and edx,07FFFFFFFh				// get ordinal
				jmp _it_fixup_get_addr
_it_fixup_by_name:
			add edx,esi							// image_thunk_data.Ordinal + dwImageBase = OrdinalName
			inc edx
			inc edx								// OrdinalName.Name
_it_fixup_get_addr:
			push edx							// lpProcName
			push edi							// hModule						
			mov eax,offset _p_GetProcAddress
			call [ebp+eax]						// GetProcAddress(hModule, lpProcName);

			mov ecx,[ebp+_p_dwThunk]			// dwThunk
			mov [ecx],eax
			add dword ptr [ebp+_p_dwThunk],004h	// dwThunk => next dwThunk
			add dword ptr [ebp+_p_dwHintName],004h// dwHintName => next dwHintName
		jmp _it_fixup_get_proc_address_loop
_it_fixup_next_module:
		add ebx,014h							// sizeof(IMAGE_IMPORT_DESCRIPTOR)
	jmp _it_fixup_get_lib_address_loop
_it_fixup_end:
	ret
//----------------------------------------------------------
//--------------------------------------------------------
//========================================================
// -------- exception handler expression filter ----------
_except_handler1_OEP_Jump:
	push ebp
	mov ebp,esp
	mov eax,[ebp+010h]	// PCONTEXT: pContext <- eax
	//---------------
	push edi
	// restore original SEH
	mov edi,[eax+0C4h]	// pContext.Esp
	push dword ptr ds:[edi]
	pop dword ptr fs:[0]
	add dword ptr [eax+0C4h],8	// pContext.Esp
	
	// set the Eip to the OEP
	mov edi,[eax+0A4h] // eax <- pContext.Ebx
	mov [eax+0B8h],edi // pContext.Eip <- eax
	// 
	pop edi
	//---------------
	mov eax, EXCEPTION_CONTINUE_SEARCH
	leave
	ret
//--------------------------------------------------------
//========================================================
	dword_type(DYN_LOADER_START_DATA1)
//----------------------------------
_p_dwFileType:					dword_type(0xCCCCCCCC)
_p_dwImageBase:					dword_type(0xCCCCCCCC)
_p_dwOrgEntryPoint:				dword_type(0xCCCCCCCC)
_p_dwImportVirtualAddress:		dword_type(0xCCCCCCCC)
_p_dwRelocationVirtualAddress:	dword_type(0xCCCCCCCC)
_p_dwRelocationSize:			dword_type(0xCCCCCCCC)								
//----------------------------------
_p_szKernel32:				//db "Kernel32.dll",0,13
		db db db db db db db db db db db db db
_p_szGetModuleHandle:		//db "GetModuleHandleA",0,17
		db db db db db db db db db db db db db db db db db
_p_szVirtualProtect:		//db "VirtualProtect",0,15
		db db db db db db db db db db db db db db db
_p_szGetModuleFileName:	//db "GetModuleFileNameA",0,19
		db db db db	db db db db	db db db db db db db db db db db
_p_szCreateFile:			//db "CreateFileA",0,12
		db db db db db db db db db db db db
_p_szGlobalAlloc:			//db "GlobalAlloc",0,12
		db db db db db db db db db db db db
		byte_type(0)
		byte_type(0)
//----------------------------------
_p_LoadLibrary:					dword_type(0xCCCCCCCC)
_p_GetProcAddress:				dword_type(0xCCCCCCCC)
_p_GetModuleHandle:			
								dword_type(0xCCCCCCCC)
								dword_type(0xCCCCCCCC)
								dword_type(0xCCCCCCCC)
								dword_type(0xCCCCCCCC)
								dword_type(0xCCCCCCCC)

_jmp_GetModuleHandle:			__jmp_api	dword_type(0xCCCCCCCC)
_jmp_VirtualProtect:			__jmp_api	dword_type(0xCCCCCCCC)
_jmp_GetModuleFileName:			__jmp_api	dword_type(0xCCCCCCCC)
_jmp_CreateFile:				__jmp_api	dword_type(0xCCCCCCCC)
_jmp_GlobalAlloc:				__jmp_api	dword_type(0xCCCCCCCC)
_p_dwThunk:						dword_type(0xCCCCCCCC)
_p_dwHintName:					dword_type(0xCCCCCCCC)
_p_ptempbuffer:					dword_type(0xCCCCCCCC)
//----------------------------------
	dword_type(DYN_LOADER_END_MAGIC)
//----------------------------------
}
}
//----------------------------------------------------------------

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Germany Germany
Ashkbiz Danehkar studied electrical engineering and computational science at the University of Rostock, Germany, where he obtained a Master of Science in Computational Engineering in the special field of Electrical Engineering in 2007. He worked as a software and hardware developer for some private limited companies until 2005, mostly focusing on industrial automation and microcontroller programming. During 2005–2006, he worked part-time remotely as a software reverse engineer for Panda Security (Bilbao, Spain). His master's thesis in 2007 was about the development of a microcontroller-based measurement system using an embedded system equipped with a real-time operating system (RTOS) and an AVR microcontroller to monitor the neuromuscular blockade and control the anesthesia.

Comments and Discussions