/* 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.
NTCore's site:
http://www.ntcore.com/
yodap's Site:
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 --------
call _api_load
//----------------------------------------------------
//====================================================
//----------- 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 ----------------
lea eax,[ebp+_ShellAbout_NewCode]
push eax
lea eax,[ebp+_p_szShellAbout]
push eax
lea eax,[ebp+_p_szSHELL32_r]
push eax
push [ebp+_p_dwImportVirtualAddress]
push [ebp+_p_dwImageBase]
call _it_fixup_1
//--------------- 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 ----------------
/*
ebp+18h [ebp+_ShellAbout_NewCode]
ebp+14h [ebp+_p_szShellAbout]
ebp+10h [ebp+_p_szSHELL32_r]
ebp+0ch _p_dwImportVirtualAddress
ebp+08h _p_dwImageBase
---------------------------------
ebp-04h x
ebp-08h _p_dwThunk
ebp-0ch _p_dwHintName
ebp-10h _p_dwLibraryName
ebp-14h _p_dwAPIaddress
ebp-18h _p_dwFunctionName
*/
_it_fixup_1:
push ebp
mov ebp,esp
add esp,-18h
mov ebx,[ebp+0ch]
test ebx,ebx
jz _it_fixup_1_end
mov esi,[ebp+08h]
add ebx,esi // dwImageBase + dwImportVirtualAddress
_it_fixup_1_get_lib_address_loop:
mov eax,[ebx+0ch] // image_import_descriptor.Name
test eax,eax
jz _it_fixup_1_end
mov ecx,[ebx+10h] // image_import_descriptor.FirstThunk
add ecx,esi
mov [ebp-08h],ecx // dwThunk
mov ecx,[ebx] // image_import_descriptor.Characteristics
test ecx,ecx
jnz _it_fixup_1_table
mov ecx,[ebx+10h]
_it_fixup_1_table:
add ecx,esi
mov [ebp-0ch],ecx // dwHintName
add eax,esi // image_import_descriptor.Name + dwImageBase = ModuleName
push eax // lpLibFileName
mov [ebp-10h],eax
call _jmp_LoadLibrary // LoadLibrary(lpLibFileName);
test eax,eax
jz _it_fixup_1_end
mov edi,eax
_it_fixup_1_get_proc_address_loop:
mov ecx,[ebp-0ch] // dwHintName
mov edx,[ecx] // image_thunk_data.Ordinal
test edx,edx
jz _it_fixup_1_next_module
test edx,080000000h // .IF( import by ordinal )
jz _it_fixup_1_by_name
and edx,07FFFFFFFh // get ordinal
jmp _it_fixup_1_get_addr
_it_fixup_1_by_name:
add edx,esi // image_thunk_data.Ordinal + dwImageBase = OrdinalName
inc edx
inc edx // OrdinalName.Name
_it_fixup_1_get_addr:
push edx // lpProcName
mov [ebp-18h],edx
push edi // hModule
call _jmp_GetProcAddress // GetProcAddress(hModule, lpProcName);
mov [ebp-14h],eax //_p_dwAPIaddress
//================================================================
//mov [ecx],eax//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
push edi
push esi
push ebx
mov ebx,[ebp-10h]
push ebx
push ebx
call _char_upper
mov esi,[ebp-10h]
mov edi,[ebp+010h] // [ebp+_p_szShell32]
_it_fixup_1_check_dll_redirected:
push edi
call __strlen
add esp, 4
mov ebx,eax
mov ecx,eax
push edi
push esi
repe cmps //byte ptr [edi], byte ptr [esi]
jz _it_fixup_1_check_func_name
jmp _it_fixup_1_no_check_func_name
_it_fixup_1_check_func_name:
mov edi,[ebp+014h] // [ebp+_p_szShellAbout]
push edi
call __strlen
add esp, 4
mov ecx,eax
mov esi,[ebp-18h]
mov edi,[ebp+014h] // [ebp+_p_szShellAbout]
repe cmps //byte ptr [edi], byte ptr [esi]
jz _it_fixup_1_do_normal_it_0
_it_fixup_1_no_check_func_name:
pop esi
pop edi
add edi,ebx
cmp byte ptr [edi],0
jnz _it_fixup_1_check_dll_redirected
mov ecx,[ebp-08h]
mov eax,[ebp-014h]
mov [ecx],eax
jmp _it_fixup_1_do_normal_it_1
_it_fixup_1_do_normal_it_0:
pop esi
pop edi
mov ecx,[ebp-08h]
mov edi,[ebp+18h]
mov [ecx],edi
_it_fixup_1_do_normal_it_1:
pop ebx
pop esi
pop edi
//================================================================
add dword ptr [ebp-08h],004h // dwThunk => next dwThunk
add dword ptr [ebp-0ch],004h// dwHintName => next dwHintName
jmp _it_fixup_1_get_proc_address_loop
_it_fixup_1_next_module:
add ebx,014h // sizeof(IMAGE_IMPORT_DESCRIPTOR)
jmp _it_fixup_1_get_lib_address_loop
_it_fixup_1_end:
mov esp,ebp
pop ebp
ret 14h
//--------------------------------------------------------
//========================================================
//-- char_upper(LPCTSTR lpDestination, LPCTSTR lpSource )
_char_upper:
push ebp
mov ebp,esp
push ecx
push eax
push esi
push edi
mov edi,dword ptr [ebp+08h]// -> Destination
mov esi,dword ptr [ebp+0Ch]// -> Source
mov ecx,255// -> Length
xor eax,eax
__makeupperloop:
lods byte ptr [esi]//ESI
cmp al,00h
jz endofbuffer
cmp al,60h
jc notinlowerfield
cmp al,7bh
jnc notinlowerfield
sub al,20h
notinlowerfield:
stos byte ptr [edi]//EDI
loop __makeupperloop
endofbuffer:
pop edi
pop esi
pop eax
pop ecx
pop ebp
retn 08h
//--------------------------------------------------------
//========================================================
//------------- load necessary api functions -------------
_api_load:
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
ret
//--------------------------------------------------------
//========================================================
_ShellAbout_NewCode:
_local_0:
pushad // save the registers context in stack
call _local_1
_local_1:
pop ebp
sub ebp,offset _local_1 // get base ebp
push MB_OK | MB_ICONINFORMATION
lea eax,[ebp+_p_szCaption]
push eax
lea eax,[ebp+_p_szText]
push eax
push NULL
call _jmp_MessageBox
// MessageBox(NULL, szText, szCaption, MB_OK | MB_ICONINFORMATION) ;
//...
//...
//...
// Place your code here ...
//...
//...
//...
popad // restore the first registers context from stack
ret 10h
//----------------------------------------------------------
//--------------------------------------------------------
//========================================================
// -------- 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] // edi <- pContext.Ebx
mov [eax+0B8h],edi // pContext.Eip <- edi
//
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)
//----------------------------------
_tls_dwStartAddressOfRawData: dword_type(0xCCCCCCCC)
_tls_dwEndAddressOfRawData: dword_type(0xCCCCCCCC)
_tls_dwAddressOfIndex: dword_type(0xCCCCCCCC)
_tls_dwAddressOfCallBacks: dword_type(0xCCCCCCCC)
_tls_dwSizeOfZeroFill: dword_type(0xCCCCCCCC)
_tls_dwCharacteristics: 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
_p_szVirtualAlloc: //db "VirtualAlloc",0,13
db db db db db db db db db db db db db
_p_szLoadLibrary: //db "LoadLibraryA",0,13
db db db db db db db db db db db db db
_p_szGetProcAddress: //db "GetProcAddress",0,15
db db db db db db db db db db db db db db db
byte_type(0)
_p_szUser32: //db "User32.dll",0,11
db db db db db db db db db db db
_p_szMessageBox: //db "MessageBoxA",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)
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)
_jmp_VirtualAlloc: __jmp_api dword_type(0xCCCCCCCC)
_jmp_LoadLibrary: __jmp_api dword_type(0xCCCCCCCC)
_jmp_GetProcAddress: __jmp_api dword_type(0xCCCCCCCC)
_jmp_MessageBox: __jmp_api dword_type(0xCCCCCCCC)
_p_szSHELL32_r:
//db "SHELL32.DLL",0,12
bb('S') bb('H') bb('E') bb('L') bb('L') bb('3') bb('2') bb('.') bb('D') bb('L') bb('L') bb(0)
byte_type(0)
_p_szShellAbout:
//db "ShellAboutW",0,12
bb('S') bb('h') bb('e') bb('l') bb('l') bb('A') bb('b') bb('o') bb('u') bb('t') bb('W') bb(0)
_p_szCaption:
bb('A') bb('s') bb('h') bb('k') bb('b') bb('i') bb('z') bb(0)
_p_szText:
bb('T') bb('h') bb('i') bb('s') bb(' ') bb('E') bb('x') bb('a') bb('m') bb('p') bb('l')
bb('e') bb(' ') bb('s') bb('h') bb('o') bb('w') bb('s') bb(' ') bb('h') bb('o') bb('w')
bb(' ') bb('A') bb('P') bb('I') bb(' ') bb('r') bb('e') bb('d') bb('i') bb('r') bb('e')
bb('c') bb('t') bb('i') bb('o') bb('n') bb(' ') bb('t') bb('e') bb('c') bb('h') bb('n')
bb('i') bb('q') bb('u') bb('e') bb(' ') bb('w') bb('o') bb('r') bb('k') bb('s') bb('.')
bb(0)
_p_dwThunk: dword_type(0xCCCCCCCC)
_p_dwHintName: dword_type(0xCCCCCCCC)
_p_ptempbuffer: dword_type(0xCCCCCCCC)
//----------------------------------
dword_type(DYN_LOADER_END_MAGIC)
//----------------------------------
}
}
//----------------------------------------------------------------