📄 dllload.cpp
字号:
/*****************************************************************************/
/* DllLoad.cpp Copyright Project Software 1999 */
/* Tricks with DLL loading */
/*****************************************************************************/
// 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 "Utils.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;
typedef struct __imageparameters
{
void *pImageBase;
char svName[MAX_PATH];
DWORD dwFlags;
int nLockCount;
struct __imageparameters *next;
} IMAGE_PARAMETERS;
typedef BOOL (WINAPI *DLLMAIN_T)(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
#pragma pack(pop)
// Process-global variables
IMAGE_PARAMETERS *g_pImageParamHead;
CRITICAL_SECTION g_DLLCrit;
DWORD g_dwWinVer; // Major version of Windows
BOOL g_bIsWinNT; // TRUE is running on Windows NT
// Determine Operating System Version
static BOOL GetOSVersion()
{
OSVERSIONINFO osvi;
BOOL result = TRUE;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if(GetVersionEx(&osvi) == FALSE)
{
// DebugMessageBox(HWND_DESKTOP, "Unable to get version info", "GetOSVersion()", MB_OK);
result = FALSE;
}
if(osvi.dwPlatformId == VER_PLATFORM_WIN32s)
{
// DebugMessageBox( HWND_DESKTOP, "This application cannot run under WIN32s!", "Error", MB_OK);
result = FALSE;
}
g_dwWinVer = osvi.dwMajorVersion;
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
g_bIsWinNT = TRUE;
return result;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialization Routines //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void InitializeDLLLoad(void)
{
InitializeCriticalSection(&g_DLLCrit);
GetOSVersion();
g_pImageParamHead = NULL;
}
void KillDLLLoad(void)
{
IMAGE_PARAMETERS *cur,*next;
cur = g_pImageParamHead;
while(cur != NULL)
{
next=cur->next;
free(cur);
cur=next;
}
DeleteCriticalSection(&g_DLLCrit);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DLL control low-level functions //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
static DWORD * GetNTSignature(HINSTANCE hModule)
{
char * ptr = (char *)hModule;
// Move to address of "New EXE Header"
ptr += ((IMAGE_DOS_HEADER *)ptr)->e_lfanew;
return(DWORD *)ptr;
}
IMAGE_FILE_HEADER * GetFileHeader(HINSTANCE hModule)
{
char * ptr = (char *)GetNTSignature(hModule);
// Skip NT magic word
ptr += sizeof(DWORD);
return (IMAGE_FILE_HEADER *)ptr;
}
IMAGE_OPTIONAL_HEADER * GetOptionalHeader(HMODULE hModule)
{
char * ptr = (char *)GetFileHeader(hModule);
// Skip image header
ptr += sizeof(IMAGE_FILE_HEADER);
return (IMAGE_OPTIONAL_HEADER *)ptr;
}
IMAGE_SECTION_HEADER * GetSectionHeader(HMODULE hModule)
{
char * ptr = (char *)GetOptionalHeader(hModule);
// Skip optional header
ptr += sizeof(IMAGE_OPTIONAL_HEADER);
return (IMAGE_SECTION_HEADER *)ptr;
}
//-----------------------------------------------------------------------------
// Internal DLL management
static BOOL RunDLLMain(void * pImageBase, DWORD /* dwImageSize */, BOOL bDetach)
{
// Get entry point from header
IMAGE_OPTIONAL_HEADER * oh = GetOptionalHeader((HMODULE)pImageBase);
IMAGE_FILE_HEADER * pe = GetFileHeader((HINSTANCE)pImageBase);
DLLMAIN_T pDllMain;
if((pe->Characteristics & IMAGE_FILE_DLL) == 0)
return TRUE;
pDllMain = (DLLMAIN_T)MovePtr((HMODULE)pImageBase, oh->AddressOfEntryPoint);
// Call dllmain the right way
return pDllMain((HMODULE)pImageBase, (bDetach == TRUE) ? DLL_PROCESS_DETACH : DLL_PROCESS_ATTACH, (void *)1);
}
static int ProtectDLLImage(void *pMemoryImage, BOOL bRWX)
{
// Get Number of Sections
IMAGE_FILE_HEADER * pe = GetFileHeader((HMODULE)pMemoryImage);
// IMAGE_OPTIONAL_HEADER * oh = GetOptionalHeader((HMODULE)pMemoryImage);
IMAGE_SECTION_HEADER * sh = GetSectionHeader((HMODULE)pMemoryImage);
int nSectionCount = pe->NumberOfSections;
// DWORD hdrlen = oh->SizeOfHeaders;
// VirtualProtect fails on Win2K here
if(g_dwWinVer >= 5)
return ERROR_SUCCESS;
// Protect sections one by one
for(int i=0; i < nSectionCount; i++, sh++)
{
// Get section address and length
void * secMemAddr = (char *)MovePtr((HMODULE)pMemoryImage, sh->VirtualAddress);
int secLen = sh->SizeOfRawData;
DWORD newProtect = 0, oldProtect;
DWORD flags = sh->Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_SHARED);
// Parse Characteristics and protect memory appropriately
if(flags == (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_SHARED))
newProtect = PAGE_EXECUTE_READWRITE;
if(flags == (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE))
newProtect = PAGE_EXECUTE_WRITECOPY;
if(flags == (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE))
newProtect = PAGE_EXECUTE_READ;
if(flags == IMAGE_SCN_MEM_EXECUTE)
newProtect = PAGE_EXECUTE;
if(flags == (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED))
newProtect = PAGE_READWRITE;
if(flags == (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
newProtect = PAGE_WRITECOPY;
if(flags == (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
newProtect = PAGE_READONLY;
if(bRWX)
newProtect = PAGE_WRITECOPY;
if(sh->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
newProtect |= PAGE_NOCACHE;
if(newProtect == 0)
return FALSE;
if(!VirtualProtect(secMemAddr, secLen, newProtect, &oldProtect))
return GetLastError();
}
return 0;
}
// returns 0 if just ref count increment, 1 if this is a new addition, -1 on error
static int AddDLLReference(void *pImageBase, char *svName, DWORD dwFlags)
{
EnterCriticalSection(&g_DLLCrit);
// Find DLL in list
IMAGE_PARAMETERS *cur;
for(cur=g_pImageParamHead;cur!=NULL;cur=cur->next) {
if(cur->pImageBase==pImageBase) break;
}
if(cur!=NULL) {
// increment dll count
cur->nLockCount++;
LeaveCriticalSection(&g_DLLCrit);
return 0;
}
// Add new dll to list
cur=(IMAGE_PARAMETERS *)malloc(sizeof(IMAGE_PARAMETERS));
if(cur==NULL) {
LeaveCriticalSection(&g_DLLCrit);
return -1;
}
cur->pImageBase=pImageBase;
if(svName!=NULL) {
lstrcpyn(cur->svName,svName, MAX_PATH);
} else cur->svName[0]='\0';
cur->nLockCount=1;
cur->dwFlags=dwFlags;
cur->next=g_pImageParamHead;
g_pImageParamHead=cur;
LeaveCriticalSection(&g_DLLCrit);
return 1;
}
// returns 0 if just a reference count dec, 1 if fully removed from list, -1 on error
static int RemoveDLLReference(void *pImageBase, char *svName, DWORD *pdwFlags)
{
EnterCriticalSection(&g_DLLCrit);
// Find DLL in list
IMAGE_PARAMETERS *cur,*prev;
prev=NULL;
for(cur=g_pImageParamHead;cur!=NULL;cur=cur->next) {
if(cur->pImageBase==pImageBase) break;
prev=cur;
}
if(cur==NULL) {
LeaveCriticalSection(&g_DLLCrit);
return -1;
}
// decrement dll count
cur->nLockCount--;
// look up dll information
*pdwFlags=cur->dwFlags;
lstrcpyn(svName,cur->svName,MAX_PATH);
// Remove if time to go
if(cur->nLockCount==0) {
if(prev==NULL) {
g_pImageParamHead=g_pImageParamHead->next;
free(cur);
} else {
prev->next=cur->next;
free(cur);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -