⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dllload.cpp

📁 mpq文件的格式就是一种压缩格式
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************/
/* 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 + -