www.pudn.com > remote_thread.zip > dll_load.cpp
/* Back Orifice 2000 - Remote Administration Suite
Copyright (C) 1999, Cult Of The Dead Cow
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 dildog@l0pht.com. */
// DLL_LOAD by dildog@l0pht.com
// This is pretty far from a fully-implemented PE Executable
// Loader, but it does the trick for loading DLLs from an image.
// That way, we don't have to hit the disk too much, and it
// allows one to package DLLs as resources (kinda like static linking a DLL... :)
// Differences from Win32 DLL Loader:
// GOOD Differences
// 1. GetDLLProcAddress returns the -REAL- entry point of exported functions
// instead of some bullshit stub set up by the loader.
// 2. New flags for loading 'REBIND_IMAGE_IMPORTS' allows you to load an
// image that has already been loaded and rebind its import table.
// 3. New flag 'RWX_PERMISSIONS' allows you to load a DLL with read/write/execute
// permissions on all sections.
// 4. New flag 'FORCE_LOAD_NEW_IMAGE' allows you to load a single DLL more than
// once at different base addresses.
// BAD Differences
// 1. Never sets GetLastError code. Just don't fuck up.
// 2. Shared segments don't work in Windows 9x. They also don't work in either 9x or NT if the DLL is forced to be rebased.
// 3. LOAD_WITH_ALTERED_SEARCH_PATH doesn't work.
// 4. Only loads PE executables (well duh)
// 5. 'Thread Attaching' doesn't work (so neither does TLS in most cases)
// This is because I don't have access to the kernel necessarily (can't touch
// the thread information tables. Hell, if I could, I wouldn't need this stuff)
// 6. Loading DLLs in different processes with different "dwFlags" via LoadDLLEx
// may have undesirable effects under Windows NT. Use with caution.
// 7. 'Forwarder' support is kinda bunky. Kinda works tho.
// 8. Resources can not be loaded from DLLs. Sigh. The problem is known
// and being worked on. May not have a solution.
#include "stdafx.h"
#include
#include
#include"dll_load.h"
#pragma pack(push,1)
typedef struct {
DWORD dwPageRVA;
DWORD dwBlockSize;
} IMAGE_FIXUP_BLOCK, *PIMAGE_FIXUP_BLOCK;
typedef struct {
WORD offset:12;
WORD type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
#pragma pack(pop)
//-----------------------------------------------------
// 根据各个section的指定,对他们实施保护
//-----------------------------------------------------
BOOL ProtectDLLImage(void *pMemoryImage, BOOL bRWX)
{
//-----------------------------
// Get Number of Sections
//-----------------------------
PIMAGE_FILE_HEADER pfh;
int nSectionCount;
pfh=(PIMAGE_FILE_HEADER) PEFHDROFFSET(pMemoryImage);
nSectionCount=pfh->NumberOfSections;
//-------------------------------------------------
// Get PE Header Length + Section Header Length
//-------------------------------------------------
PIMAGE_OPTIONAL_HEADER poh;
DWORD hdrlen;
poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(pMemoryImage);
hdrlen=poh->SizeOfHeaders;
//-------------------------------------------------
// Protect sections one by one
//-------------------------------------------------
int i;
PIMAGE_SECTION_HEADER psh;
psh=(PIMAGE_SECTION_HEADER) SECHDROFFSET(pMemoryImage);
for(i=0;iVirtualAddress);
secLen = psh->SizeOfRawData;
//-------------------------------------------------
// Parse Characteristics and protect memory appropriately
//-------------------------------------------------
DWORD newProtect=0,oldProtect;
BOOL bWrite, bRead, bExec, bShared;
bWrite = (psh->Characteristics & IMAGE_SCN_MEM_WRITE)?TRUE:FALSE;
bRead = (psh->Characteristics & IMAGE_SCN_MEM_READ)?TRUE:FALSE;
bExec = (psh->Characteristics & IMAGE_SCN_MEM_EXECUTE)?TRUE:FALSE;
bShared = (psh->Characteristics & IMAGE_SCN_MEM_SHARED)?TRUE:FALSE;
if(bWrite && bRead && bExec && bShared) newProtect=PAGE_EXECUTE_READWRITE;
else if(bWrite && bRead && bExec) newProtect=PAGE_EXECUTE_WRITECOPY;
else if(bRead && bExec) newProtect=PAGE_EXECUTE_READ;
else if(bExec) newProtect=PAGE_EXECUTE;
else if(bWrite && bRead && bShared) newProtect=PAGE_READWRITE;
else if(bWrite && bRead) newProtect=PAGE_WRITECOPY;
else if(bRead) newProtect=PAGE_READONLY;
if(bRWX) newProtect=PAGE_WRITECOPY;
if(psh->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) newProtect |= PAGE_NOCACHE;
if(newProtect==0) return FALSE;
VirtualProtect(secMemAddr,secLen,newProtect,&oldProtect);
psh++;
}
return TRUE;
}
//-------------------------------------------------
// 解决IAT(Import Address Table)和重定位表
//-------------------------------------------------
BOOL PrepareDLLImage(void *pMemoryImage, DWORD dwImageSize, BOOL bResolve, BOOL bRebind)
{
//-----------------------------------------------
// Get headers
//-----------------------------------------------
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (pMemoryImage);
psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (pMemoryImage);
//-----------------------------------------------
// Get number of image directories in list
//-----------------------------------------------
int nDirCount;
nDirCount=poh->NumberOfRvaAndSizes;
if(nDirCount<16) return FALSE;
//-----------------------------------------------
// Process import table
//-----------------------------------------------
if(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size!=0) {
PIMAGE_IMPORT_DESCRIPTOR pid;
pid=(IMAGE_IMPORT_DESCRIPTOR *)RVATOVA(pMemoryImage,poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
//---------------------------------------------------
// For all imported DLLs
// 原来的处理有bug:对于由borland的linker编译的image
// OriginalFirstThunk永远都是0
//---------------------------------------------------
// while(pid->OriginalFirstThunk!=0) {
while( 1 ) {
//---------------------------------------------------
// 新的方法用他们判断是否结束
//---------------------------------------------------
if ( (pid->TimeDateStamp==0 ) && (pid->Name==0) )
break;
char *svDllName;
svDllName=(char *) RVATOVA(pMemoryImage,pid->Name);
//-------------------------------------------------------------
// Map library into address space (could also use LoadDLL())
//-------------------------------------------------------------
HMODULE hDll;
hDll=GetModuleHandleA(svDllName);
if(hDll==NULL) hDll=LoadLibraryA(svDllName);
if(hDll==NULL)
return FALSE;
//-------------------------------------------------------------
// Bind if not bound already
//-------------------------------------------------------------
if(pid->TimeDateStamp==0 || bRebind) {
//-------------------------------------------------------------
// Store DLL infoz
//-------------------------------------------------------------
pid->ForwarderChain=(DWORD)hDll;
//-------------------------------------------------------------
// This is bullshit cuz I don't want to call libc.
//-------------------------------------------------------------
pid->TimeDateStamp=0xCDC31337;
//-------------------------------------------------------------
// Fill in Import Address Table
//-------------------------------------------------------------
PIMAGE_THUNK_DATA ptd_in,ptd_out;
ptd_in=(PIMAGE_THUNK_DATA) RVATOVA(pMemoryImage, pid->OriginalFirstThunk);
ptd_out=(PIMAGE_THUNK_DATA) RVATOVA(pMemoryImage, pid->FirstThunk);
if( pid->OriginalFirstThunk == 0 ) // No OriginalFirstThunk field?
{
if( pid->FirstThunk == 0 ) // No FirstThunk field? Ooops!!!
break;
//-------------------------------------------------------------
// Yes! Gotta have a non-zero FirstThunk field then.
//-------------------------------------------------------------
ptd_in = ptd_out;
}
while(ptd_in->u1.Function!=NULL) {
FARPROC func;
//-------------------------------------------------------------
// Determine if ordinal or name pointer
//-------------------------------------------------------------
if(ptd_in->u1.Ordinal & 0x80000000) {
// Ordinal
func=GetProcAddress(hDll,MAKEINTRESOURCEA(ptd_in->u1.Ordinal));
} else {
// Function name
PIMAGE_IMPORT_BY_NAME pibn;
pibn=(PIMAGE_IMPORT_BY_NAME) RVATOVA(pMemoryImage,ptd_in->u1.AddressOfData);
func=GetProcAddress(hDll,(char *)pibn->Name);
}
if(func==NULL)
return FALSE;
//-------------------------------------------------------------
// Write address to appropriate location
//-------------------------------------------------------------
ptd_out->u1.Function = (DWORD) func;
ptd_in++;
ptd_out++;
}
}
pid++;
}
}
//-------------------------------------------------------------
// Process relocation tables if necessary
//-------------------------------------------------------------
//-------------------------------------------------------------
// Calculate fixup delta
//-------------------------------------------------------------
DWORD delta;
delta=(DWORD)pMemoryImage - (DWORD)poh->ImageBase;
if((delta!=0) && (poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size!=0)) {
PIMAGE_FIXUP_BLOCK pfb;
pfb=(PIMAGE_FIXUP_BLOCK)RVATOVA(pMemoryImage,poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
//-------------------------------------------------------------
// For each fixup block
//-------------------------------------------------------------
while(pfb->dwPageRVA!=0) {
PIMAGE_FIXUP_ENTRY pfe;
int i,count;
count=(pfb->dwBlockSize-sizeof(IMAGE_FIXUP_BLOCK))/sizeof(IMAGE_FIXUP_ENTRY);
pfe=(PIMAGE_FIXUP_ENTRY)((char *)pfb + sizeof(IMAGE_FIXUP_BLOCK));
//-------------------------------------------------------------
// For each fixup entry
//-------------------------------------------------------------
for(i=0;idwPageRVA + pfe->offset);
switch(pfe->type) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
*((WORD *)fixaddr) += HIWORD(delta);
break;
case IMAGE_REL_BASED_LOW:
*((WORD *)fixaddr) += LOWORD(delta);
break;
case IMAGE_REL_BASED_HIGHLOW:
*((DWORD *)fixaddr) += delta;
break;
case IMAGE_REL_BASED_HIGHADJ: // This one's really fucked up.
adjust=((*((WORD *)fixaddr)) << 16) | (*(WORD *)(pfe+1));
adjust += delta;
adjust += 0x00008000;
*((WORD *)fixaddr) = HIWORD(adjust);
pfe++;
break;
default:
return FALSE;
}
pfe++;
}
pfb=(PIMAGE_FIXUP_BLOCK)((char *)pfb + pfb->dwBlockSize);
}
}
else {
//------------------------------------------------------------------------------
// if image base has changed but we cann't find the relocation table,
// we failed to fixup this image,
// which usually happens when this image is a release-version executable file.
//------------------------------------------------------------------------------
if( delta !=0 && poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0 )
return FALSE;
}
return TRUE;
}
BOOL MapDLLFromImage(void *pDLLFileImage, void *pMemoryImage)
{
//------------------------------------------------------------------------------
// Get Number of Sections
//------------------------------------------------------------------------------
PIMAGE_FILE_HEADER pfh;
int nSectionCount;
pfh=(PIMAGE_FILE_HEADER) PEFHDROFFSET(pDLLFileImage);
nSectionCount=pfh->NumberOfSections;
//------------------------------------------------------------------------------
// Get PE Header Length + Section Header Length
//------------------------------------------------------------------------------
PIMAGE_OPTIONAL_HEADER poh;
DWORD hdrlen;
poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(pDLLFileImage);
hdrlen=poh->SizeOfHeaders;
//------------------------------------------------------------------------------
// Copy PE Header + Section Headers
//------------------------------------------------------------------------------
memcpy(pMemoryImage,pDLLFileImage,hdrlen);
//------------------------------------------------------------------------------
// Copy Sections one by one
//------------------------------------------------------------------------------
int i;
PIMAGE_SECTION_HEADER psh;
psh=(PIMAGE_SECTION_HEADER) SECHDROFFSET(pDLLFileImage);
for(i=0;iVirtualAddress;
secFileAddr = (char *)pDLLFileImage + psh->PointerToRawData;
secLen = psh->SizeOfRawData;
memcpy(secMemAddr,secFileAddr,secLen);
psh++;
}
return TRUE;
}
//------------------------------------------------------------------------------
// LoadDLLFromImage() //
//------------------------------------------------------------------------------
HMODULE LoadDLLFromImage(void *pDLLFileImage, LPTSTR svMappingName, DWORD dwFlags)
{
//----------------------------------------------------
// Examine DOS Header
//----------------------------------------------------
PIMAGE_DOS_HEADER doshead;
doshead=(PIMAGE_DOS_HEADER) pDLLFileImage;
if(doshead->e_magic!=IMAGE_DOS_SIGNATURE) return NULL;
//----------------------------------------------------
// Ensure our input is of good length
//----------------------------------------------------
if(svMappingName!=NULL) {
if(lstrlen(svMappingName) >= MAX_PATH) return NULL;
}
//----------------------------------------------------
// Determine File Format
//----------------------------------------------------
if(*(DWORD *)NTSIGNATURE(pDLLFileImage) != IMAGE_NT_SIGNATURE) return NULL;
//----------------------------------------------------
// Get PE Header
//----------------------------------------------------
PIMAGE_FILE_HEADER pfh;
pfh=(PIMAGE_FILE_HEADER) PEFHDROFFSET(pDLLFileImage);
//----------------------------------------------------
// Ensure proper machine type
//if(pfh->Machine!=IMAGE_FILE_MACHINE_I386) return NULL;
// XXX Verify Characteristics
// XXX I don't bother to do this yet.
//----------------------------------------------------
//----------------------------------------------------
// Get Section Count
//----------------------------------------------------
int nSectionCount;
nSectionCount=pfh->NumberOfSections;
//----------------------------------------------------
// Get PE Optional Header
//----------------------------------------------------
PIMAGE_OPTIONAL_HEADER poh;
poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(pDLLFileImage);
//----------------------------------------------------
// Ensure we are an executable image, not a rom image
//----------------------------------------------------
if(poh->Magic!=0x010B) return NULL;
//----------------------------------------------------
// Get preferred image base and image length
//----------------------------------------------------
void *pPreferredImageBase;
DWORD dwImageSize;
pPreferredImageBase=(void *)poh->ImageBase;
dwImageSize=poh->SizeOfImage;
//----------------------------------------------------
// Get base address of virtual image
//----------------------------------------------------
void *pImageBase;
HANDLE hmapping=NULL;
BOOL bCreated=FALSE;
BOOL bRebased=FALSE;
//-------------------------------------------------------------
// === Windows NT DLL Loading (supports shared sections) ===
//-------------------------------------------------------------
if(svMappingName!=NULL) {
hmapping=OpenFileMapping(FILE_MAP_WRITE,TRUE,svMappingName);
bCreated=FALSE;
}
if(hmapping==NULL) {
hmapping=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,dwImageSize+SIZE_OF_PARAMETER_BLOCK,svMappingName);
if(hmapping==NULL) return NULL;
bCreated=TRUE;
//-----------------------------------------------------------------------------------------
// Try to load file mapping view at preferred image base (not gonna happen in Win9x..sigh)
//-----------------------------------------------------------------------------------------
pImageBase=MapViewOfFileEx(hmapping,FILE_MAP_WRITE,0,0,0,pPreferredImageBase);
if(pImageBase==NULL) {
pImageBase=MapViewOfFileEx(hmapping,FILE_MAP_WRITE,0,0,0,NULL);
}
CloseHandle(hmapping);
if(pImageBase==NULL) return NULL;
}
//-----------------------------------------------------------------------------------------
// Now map DLL from file image into appropriate memory image (if just created)
// Also remap if DLL is being rebased as well (gotta fix relocations)
//-----------------------------------------------------------------------------------------
if(bCreated || (pImageBase!=pPreferredImageBase)) {
if(!MapDLLFromImage(pDLLFileImage,pImageBase)) {
UnmapViewOfFile(pImageBase);
return NULL;
}
}
//-----------------------------------------------------------------------------------------
// Prepare DLL image (handle relocations/import/export/etc)
//-----------------------------------------------------------------------------------------
if(!(dwFlags & LOAD_LIBRARY_AS_DATAFILE)) {
if(!PrepareDLLImage(pImageBase, dwImageSize, (dwFlags & DONT_RESOLVE_DLL_REFERENCES)?FALSE:TRUE,(dwFlags & REBIND_IMAGE_IMPORTS)?TRUE:FALSE)) {
UnmapViewOfFile(pImageBase);
return NULL;
}
}
return (HMODULE) pImageBase;
}
//------------------------------------------------------------------
// LoadDLLEx()
//------------------------------------------------------------------
HMODULE WINAPI LoadDLLExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
WCHAR svPath[MAX_PATH+1];
WCHAR *svFilePart;
int nPathLen;
//-------------------------------------------------
// Find DLL File
//-------------------------------------------------
if(dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) {
return NULL;
} else {
nPathLen=SearchPathW(NULL,lpLibFileName,L".exe",MAX_PATH,svPath,&svFilePart);
if(nPathLen==0) return NULL;
}
//-------------------------------------------------
// Open File
//-------------------------------------------------
HANDLE hfile=CreateFile(svPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if(hfile==INVALID_HANDLE_VALUE) return NULL;
//-------------------------------------------------
// Create a file mapping
//-------------------------------------------------
HANDLE hmapping;
hmapping=CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
//-------------------------------------------------
// Close file handle since we don't need it anymore
//-------------------------------------------------
CloseHandle(hfile);
//-------------------------------------------------
// Map file mapping object to memory image
//-------------------------------------------------
void *baseaddr;
baseaddr=MapViewOfFile(hmapping,FILE_MAP_READ,0,0,0);
if(baseaddr==NULL) {
CloseHandle(hmapping);
return NULL;
}
//-------------------------------------------------
// Now pass off to LoadDLLFromImage
//-------------------------------------------------
HMODULE ret;
if(dwFlags & FORCE_LOAD_NEW_IMAGE) {
ret=LoadDLLFromImage(baseaddr, NULL, dwFlags & ~LOAD_WITH_ALTERED_SEARCH_PATH);
} else {
ret=LoadDLLFromImage(baseaddr, svFilePart, dwFlags & ~LOAD_WITH_ALTERED_SEARCH_PATH);
}
//-------------------------------------------------
// Close file mapping
//-------------------------------------------------
UnmapViewOfFile(baseaddr);
CloseHandle(hmapping);
//-------------------------------------------------
// Return base address as an instance handle
//-------------------------------------------------
return (HMODULE) ret;
}
HMODULE WINAPI LoadDLLExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
WCHAR szPath[MAX_PATH];
::MultiByteToWideChar( CP_ACP, 0,
lpLibFileName, -1,
szPath, sizeof(szPath) );
return LoadDLLExW(szPath,hFile,dwFlags);
}
//-------------------------------------------------
// LoadDLLW()
//-------------------------------------------------
HMODULE WINAPI LoadDLLW(LPCWSTR lpLibFileName)
{
return LoadDLLExW(lpLibFileName,NULL,0);
}
HMODULE WINAPI LoadDLLA(LPCSTR lpLibFileName)
{
return LoadDLLExA(lpLibFileName,NULL,0);
}
//-------------------------------------------------
// FreeDLL()
//-------------------------------------------------
BOOL WINAPI FreeDLL(HMODULE hLibModule)
{
if(hLibModule==NULL) return FALSE;
return UnmapViewOfFile(hLibModule);
}
BOOL WINAPI CheckTlsSectionExist( HMODULE hImage )
{
PIMAGE_FILE_HEADER pfh;
int i, nSectionCount;
pfh=(PIMAGE_FILE_HEADER) PEFHDROFFSET(hImage);
nSectionCount=pfh->NumberOfSections;
//----------------------------------------------------
// Search for .tls section
//----------------------------------------------------
PIMAGE_SECTION_HEADER psh;
psh=(PIMAGE_SECTION_HEADER) SECHDROFFSET(hImage);
for(i=0;iName, ".tls" ) == 0 )
return TRUE;
psh++;
}
return FALSE;
}
typedef struct _UNICODE_STRING
{
WORD Length;
WORD MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
//--------------------------------------------------------------------
// LoadLibraryEx根据几个flags加载模块:
// -- DONT_RESOLVE_DLL_REFERENCES: 加载模块,对各个section实行保护,
// 不解决IAT和重定位表
// -- LOAD_LIBRARY_AS_DATAFILE: 仅仅把文件映射到进程空间
// -- LOAD_WITH_ALTERED_SEARCH_PATH: 使用不同的路径搜索策略
// LoadLibraryEx内部用LdrLoadDll完成实际加载工作。
// 下面实现的LoadImageExW增加了一个功能:加载模块,解决IAT和重定位表,
// 但是不调用DllMain
//--------------------------------------------------------------------
typedef DWORD (WINAPI *PNtLdrLoadDll)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*);
typedef DWORD (WINAPI *PNtLdrLoadDllEx)(LPCWSTR, DWORD*, UNICODE_STRING*, HMODULE*, BOOL fCallDllMain);
typedef DWORD (WINAPI *PNtRtlInitUnicodeString)(UNICODE_STRING*, LPCWSTR);
PNtLdrLoadDll LdrLoadDll = (PNtLdrLoadDll)::GetProcAddress( ::GetModuleHandleW( L"NtDll.dll" ), "LdrLoadDll" );
PNtRtlInitUnicodeString RtlInitUnicodeString = (PNtRtlInitUnicodeString)::GetProcAddress( ::GetModuleHandleW( L"NtDll.dll" ), "RtlInitUnicodeString" );
PNtLdrLoadDllEx Find_LdrLoadDllEx()
{
DWORD fun = 0;
for( PBYTE p = (PBYTE)LdrLoadDll; *p != 0xC2 && *p != 0xC3; p++ ) // *p != RET
{
//-----------------------------------------------
// 0xE8为intel系列的相对调用指令
//-----------------------------------------------
if( *p == 0xE8 )
{
//-----------------------------------------------
// 取得LdrLoadDllEx的相对地址
// (相对于call的下一条指令,即call的返回地址)
//-----------------------------------------------
DWORD rva = *((DWORD*)(p+1));
//-----------------------------------------------
// 一个call指令占5个字节,因此要加上5
//-----------------------------------------------
fun = (DWORD)p+rva+5;
break;
}
}
return (PNtLdrLoadDllEx)fun;
}
//-------------------------------------------------------------------------
// 如果最后一个参数为0,LdrLoadDllEx将解决IAT和重定位表,但不调用DllMain
// 但是winnt没有导出这个函数。下面的地址仅仅对Winnt 4.0+sp6有效
//-------------------------------------------------------------------------
PNtLdrLoadDllEx LdrLoadDllEx = Find_LdrLoadDllEx(); // (PNtLdrLoadDllEx)0x77F5B333;
//-------------------------------------------------------------------
// 加载dll,解决IAT和重定位表,但不调用DllMain
//-------------------------------------------------------------------
HMODULE WINAPI LoadImageExW( LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags )
{
if( dwFlags != -1 )
//-----------------------------------
// 调用缺省实现
//-----------------------------------
return ::LoadLibraryExW( lpFileName, hFile, dwFlags );
HMODULE hModule;
DWORD Flags = 0;
UNICODE_STRING FileName;
WCHAR svPath[MAX_PATH+1];
WCHAR *svFilePart;
//------------------------------------------------
// 确定image file的全路径
//------------------------------------------------
if( SearchPathW( NULL, lpFileName, NULL, MAX_PATH, svPath, &svFilePart ) == 0 )
return NULL;
//------------------------------------------------
// 构造UNICODE_STRING
//------------------------------------------------
RtlInitUnicodeString( &FileName, svPath );
//--------------------------------------------------
// 以最后一个参数为0,禁止LdrLoadDllEx调用DllMain
//--------------------------------------------------
DWORD e = LdrLoadDllEx( L".", &Flags, &FileName, &hModule, 0);
if( e == 0 )
return hModule;
return NULL;
}
HMODULE WINAPI LoadImageExA( LPCSTR lpFileName, HANDLE hFile, DWORD dwFlags )
{
WCHAR szPath[MAX_PATH];
::MultiByteToWideChar( CP_ACP, 0,
lpFileName, -1,
szPath, sizeof(szPath) );
return LoadImageExW(szPath,hFile,dwFlags);
}