www.pudn.com > remote_thread.zip > exe_load.cpp


/*  Remote Run Library 
    Copyright (C) 2001, Sting Feng(冯越) 
 
    This program is free software; you can redistribute it and/or modify 
    it under the terms of the GNU General Public License as published by 
    the Free Software Foundation; either version 2 of the License, or 
    (at your option) any later version. 
 
    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; if not, write to the Free Software 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
	The author of this program may be contacted at fenny@163.net. */ 
 
 
#include "stdafx.h" 
#include  
#include  
#include  
#include "exe_load.h" 
 
//---------------------------------------------------------- 
// 一些和pe header有关的macros 
//---------------------------------------------------------- 
#define NTSIGNATURE(ptr) ((LPVOID)((BYTE *)(ptr) + ((PIMAGE_DOS_HEADER)(ptr))->e_lfanew)) 
#define SIZE_OF_NT_SIGNATURE (sizeof(DWORD)) 
#define PEFHDROFFSET(ptr) ((LPVOID)((BYTE *)(ptr)+((PIMAGE_DOS_HEADER)(ptr))->e_lfanew+SIZE_OF_NT_SIGNATURE)) 
#define OPTHDROFFSET(ptr) ((LPVOID)((BYTE *)(ptr)+((PIMAGE_DOS_HEADER)(ptr))->e_lfanew+SIZE_OF_NT_SIGNATURE+sizeof(IMAGE_FILE_HEADER))) 
#define SECHDROFFSET(ptr) ((LPVOID)((BYTE *)(ptr)+((PIMAGE_DOS_HEADER)(ptr))->e_lfanew+SIZE_OF_NT_SIGNATURE+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER))) 
#define RVATOVA(base,offset) ((LPVOID)((DWORD)(base)+(DWORD)(offset))) 
#define VATORVA(base,offset) ((LPVOID)((DWORD)(offset)-(DWORD)(base))) 
 
 
//---------------------------------------- 
// NtMapViewOfSection使用它 
//---------------------------------------- 
typedef enum _SECTION_INHERIT { 
    ViewShare = 1, 
    ViewUnmap = 2 
} SECTION_INHERIT; 
 
typedef DWORD (WINAPI *PFN_NtMapViewOfSection)( HANDLE SectionHandle, 
												HANDLE ProcessHandle, 
												PVOID *BaseAddress, 
												ULONG ZeroBits, 
												ULONG CommitSize, 
												PLARGE_INTEGER SectionOffset, 
												PULONG ViewSize, 
												SECTION_INHERIT InheritDisposition, 
												ULONG AllocationType, 
												ULONG Protect 
											); 
 
 
//------------------------------------------------- 
// 声明这些变量 
//------------------------------------------------- 
CRITICAL_SECTION _cs; 
UINT _nInitCount = 0; 
BOOL _fModified; 
WORD _OriginalCharacteristics; 
BYTE _abTrampolineNtMapViewOfSection[DETOUR_TRAMPOLINE_SIZE]; 
BYTE _abTrampolineDllMain[DETOUR_TRAMPOLINE_SIZE]; 
 
 
//----------------------------------------------------------- 
// LoadLibrary会调用DllMain,但是exe没有DllMain,用这个顶替 
//----------------------------------------------------------- 
static BOOL APIENTRY PseudoDllMain( HMODULE hModule, DWORD  dwReason, LPVOID lpReserved ) 
{ 
	if( dwReason == DLL_PROCESS_ATTACH ) 
		::DisableThreadLibraryCalls( hModule ); 
	return TRUE; 
} 
 
 
//----------------------------------------------------------- 
// 把exe伪装成dll或把伪装复原,欺骗OS 
//----------------------------------------------------------- 
static BOOL SetImageCharacteristics( PVOID hModule, WORD dwAdded, WORD dwRemoved, WORD* OldCharacteristics ) 
{ 
	PIMAGE_FILE_HEADER pfh; 
	PIMAGE_OPTIONAL_HEADER poh; 
	pfh = (PIMAGE_FILE_HEADER)PEFHDROFFSET(hModule); 
	poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(hModule); 
 
	WORD newCharacteristics = pfh->Characteristics; 
	if( OldCharacteristics != NULL ) 
		*OldCharacteristics = newCharacteristics; 
	 
	newCharacteristics |= dwAdded; 
	newCharacteristics &= ~dwRemoved; 
 
	DWORD newProtect, oldProtect; 
	newProtect = PAGE_EXECUTE_WRITECOPY; 
	VirtualProtect(hModule,poh->SizeOfHeaders,newProtect,&oldProtect); 
 
	pfh->Characteristics = newCharacteristics; 
	 
	VirtualProtect(hModule,poh->SizeOfHeaders,oldProtect,&newProtect); 
 
	return TRUE; 
} 
 
 
//--------------------------------------------------- 
// OS把exe映射进进程空间后,马上进行伪装, 
// 因此我们要截获NtMapViewOfSection 
//--------------------------------------------------- 
static DWORD WINAPI Mine_NtMapViewOfSection( 
    HANDLE SectionHandle, 
    HANDLE ProcessHandle, 
    PVOID *BaseAddress, 
    ULONG ZeroBits, 
    ULONG CommitSize, 
    PLARGE_INTEGER SectionOffset, 
    PULONG ViewSize, 
    SECTION_INHERIT InheritDisposition, 
    ULONG AllocationType, 
    ULONG Protect 
    ) 
{ 
	PFN_NtMapViewOfSection fnNtMapViewOfSection = 
		(PFN_NtMapViewOfSection)&_abTrampolineNtMapViewOfSection[0]; 
 
 
	//------------------------------------- 
	// 先把exe映射到进程空间 
	//------------------------------------- 
	DWORD retval = fnNtMapViewOfSection( SectionHandle, 
									ProcessHandle, 
									BaseAddress, 
									ZeroBits, 
									CommitSize, 
									SectionOffset, 
									ViewSize, 
									InheritDisposition, 
									AllocationType, 
									Protect 
								); 
 
	//--------------------------------- 
	// 只修改一次 
	//--------------------------------- 
	if( _fModified ) 
		return retval; 
	_fModified = TRUE; 
 
	PVOID hImage = *BaseAddress; 
 
	//------------------------------------ 
	// 进行伪装 
	//------------------------------------ 
	SetImageCharacteristics( hImage, IMAGE_FILE_DLL, IMAGE_FILE_EXECUTABLE_IMAGE, &_OriginalCharacteristics ); 
	 
	 
	PIMAGE_OPTIONAL_HEADER poh; 
	poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(hImage); 
 
	//-------------------------------------------------------------- 
	// 给这个冒牌的dll提供一个DllMain,否则, 
	// OS会调用WinMain,DllMain和WinMain的声明和调用目的都不同, 
	// 因此我们不能让OS调用WinMain 
	//-------------------------------------------------------------- 
	DetourFunctionWithEmptyTrampoline( _abTrampolineDllMain, 
		(PBYTE)((DWORD)hImage+poh->AddressOfEntryPoint), 
		(PBYTE)PseudoDllMain ); 
 
	return retval; 
} 
 
 
BOOL InitializeEXELoad() 
{ 
	if( _nInitCount++ == 0 ) 
		::InitializeCriticalSection( &_cs ); 
	return TRUE; 
} 
 
BOOL UninitializeExeLoad() 
{ 
	if( --_nInitCount == 0 ) 
		::DeleteCriticalSection( &_cs ); 
	return TRUE; 
} 
 
HMODULE WINAPI LoadEXEW( LPCWSTR lpszExePath ) 
{ 
	::EnterCriticalSection( &_cs ); 
 
 
	FARPROC NtMapViewOfSection = ::GetProcAddress( GetModuleHandleW( L"NTDLL.DLL" ), "NtMapViewOfSection" ); 
 
	//-------------------------- 
	// initialize with NOP 
	//-------------------------- 
	memset( _abTrampolineNtMapViewOfSection, 0x90, sizeof(_abTrampolineNtMapViewOfSection) ); 
	memset( _abTrampolineDllMain, 0x90, sizeof(_abTrampolineDllMain) ); 
 
 
	//--------------------------------- 
	// detour NtMapViewOfSection 
	//--------------------------------- 
	DetourFunctionWithEmptyTrampoline( _abTrampolineNtMapViewOfSection, 
		(PBYTE)NtMapViewOfSection, 
		(PBYTE)Mine_NtMapViewOfSection ); 
 
 
	//------------------------------------------------- 
	// 让OS加载exe,我们做了一些手脚,让OS以为这是个 
	// dll,这样他会帮我们解决IAT和重定位表 
	//------------------------------------------------- 
	_fModified = FALSE; 
	HMODULE h = LoadLibraryW(lpszExePath); 
	_fModified = TRUE; 
 
 
	//------------------------------------------------- 
	DetourRemove( _abTrampolineDllMain, (PBYTE)PseudoDllMain ); 
	DetourRemove( _abTrampolineNtMapViewOfSection, (PBYTE)Mine_NtMapViewOfSection ); 
 
 
	//------------------------------------------------- 
	// 解除伪装 
	//------------------------------------------------- 
	if( h != NULL ) 
		SetImageCharacteristics( h, _OriginalCharacteristics, IMAGE_FILE_DLL, NULL ); 
 
 
	::LeaveCriticalSection( &_cs ); 
 
	return h; 
} 
 
HMODULE WINAPI LoadEXEA( LPCSTR lpszExePath ) 
{ 
	WCHAR szPath[MAX_PATH]; 
 
	::MultiByteToWideChar( CP_ACP, 0, 
		lpszExePath, -1, 
		szPath, sizeof(szPath) ); 
 
	return LoadEXEW(szPath); 
} 
 
 
//---------------------------------- 
// 卸载exe 
//---------------------------------- 
BOOL WINAPI FreeEXE( HMODULE hModule ) 
{ 
	::EnterCriticalSection( &_cs ); 
 
	memset( _abTrampolineDllMain, 0x90, sizeof(_abTrampolineDllMain) ); 
 
	PIMAGE_OPTIONAL_HEADER poh; 
	poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(hModule); 
 
	 
	//------------------------------------------------- 
	// 基于同样的理由,我们必须给exe提供一个DllMain 
	//------------------------------------------------- 
	DetourFunctionWithEmptyTrampoline( _abTrampolineDllMain, 
		(PBYTE)((DWORD)hModule+poh->AddressOfEntryPoint), 
		(PBYTE)PseudoDllMain ); 
	 
 
	FreeLibrary( hModule ); 
	 
 
	::LeaveCriticalSection( &_cs ); 
 
	return TRUE; 
}