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;
}