dll加载

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <winnt.h>

// DllMain帪偺傾僞僢僠丄僨僞僢僠敾掕
#define DLL_ATTACH    0
#define DLL_DETACH    1

#define SIZE_OF_NT_SIGNATURE       (sizeof(DWORD))
#define SIZE_OF_PARAMETER_BLOCK    4096
#define IMAGE_PARAMETER_MAGIC      0xCDC31337

#define RVATOVA(base, offset) ( /
    (LPVOID)((DWORD)(base) + (DWORD)(offset)))

// NT僔僌僱僠儍
#define NTSIGNATURE(ptr) (  /
    (LPVOID)((PBYTE)(ptr) + /
    ((PIMAGE_DOS_HEADER)(ptr))->e_lfanew))

// PE僿僢僟僆僼僙僢僩
#define PEFHDROFFSET(ptr) ( /
    (LPVOID)((PBYTE)(ptr) + /
    ((PIMAGE_DOS_HEADER)(ptr))->e_lfanew + /
    SIZE_OF_NT_SIGNATURE))

// 僆僾僔儑儞僿僢僟僆僼僙僢僩
#define OPTHDROFFSET(ptr) ( /
    (LPVOID)((PBYTE)(ptr) + /
    ((PIMAGE_DOS_HEADER)(ptr))->e_lfanew + /
    SIZE_OF_NT_SIGNATURE +  /
    sizeof(IMAGE_FILE_HEADER)))

// 僙僋僔儑儞僿僢僟僆僼僙僢僩
#define SECHDROFFSET(ptr) ( /
    (LPVOID)((PBYTE)(ptr) + /
    ((PIMAGE_DOS_HEADER)(ptr))->e_lfanew + /
    SIZE_OF_NT_SIGNATURE +  /
    sizeof(IMAGE_FILE_HEADER) + /
    sizeof(IMAGE_OPTIONAL_HEADER)))

// 峔憿懱偺嫬奅傪1僶僀僩愝掕
#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;

// DLL僀儊乕僕僨乕僞偺峔憿懱
typedef struct __imageparameters{
    PVOID pImageBase;
    TCHAR svName[MAX_PATH];
    DWORD dwFlags;
    int nLockCount;
    struct __imageparameters *next;
} IMAGE_PARAMETERS, *PIMAGE_PARAMETERS;

#pragma pack(pop)

// DllMain偺億僀儞僞娭悢
typedef BOOL (WINAPI *DLLMAIN_T)(HMODULE, DWORD, LPVOID);

// DLL僨乕僞儀乕僗偺僩僢僾
PIMAGE_PARAMETERS g_pImageParamHead;
// 僋儕僥傿僇儖僙僋僔儑儞曄悢
CRITICAL_SECTION g_DLLCrit;


// -------------------------------------------------------------
// 弶婜壔張棟
// -------------------------------------------------------------
void InitializeDLLLoad(void)
{
    InitializeCriticalSection(&g_DLLCrit);
    g_pImageParamHead = NULL;
}


// -------------------------------------------------------------
// 廔椆張棟
// -------------------------------------------------------------
void KillDLLLoad(void)
{
    PIMAGE_PARAMETERS cur = g_pImageParamHead;

    while(cur != NULL){
        PIMAGE_PARAMETERS next = cur->next;
        delete [] cur;
        cur = next;
    }

    DeleteCriticalSection(&g_DLLCrit);
}


// -------------------------------------------------------------
// 僨乕僞儀乕僗偵怴偟偄DLL傪捛壛
// 堷悢丂丗DLL僴儞僪儖丄DLL柤乮幆暿巕乯
// 栠傝抣丗error -1, success(find 0, make 1)
// -------------------------------------------------------------
int AddDLLReference(PVOID pImageBase, 
                    PTCHAR szName,
                    DWORD dwFlags)
{
    // szName偑側偗傟偽僄儔乕
    if(szName == NULL)
        return -1;

    EnterCriticalSection(&g_DLLCrit);

    PIMAGE_PARAMETERS cur = g_pImageParamHead;
    
    // DLL傪専嶕
    while(cur != NULL){
        if(cur->pImageBase != pImageBase)
            cur = cur->next;
        else{
            cur->nLockCount++;
            LeaveCriticalSection(&g_DLLCrit);
            return 0;
        }
    }
     
    // 怴偟偄DLL偺惗惉
    if((cur = (PIMAGE_PARAMETERS)new IMAGE_PARAMETERS[1]) == NULL){
        LeaveCriticalSection(&g_DLLCrit);
        return -1;
    }
    cur->pImageBase = pImageBase;
    cur->nLockCount = 1;
    cur->dwFlags    = dwFlags;
    cur->next       = g_pImageParamHead;
    lstrcpyn(cur->svName, szName, MAX_PATH);

    g_pImageParamHead = cur;

    LeaveCriticalSection(&g_DLLCrit);
    return 1;
}


// -------------------------------------------------------------
// 僨乕僞儀乕僗偐傜DLL傪嶍彍
// 堷悢丂丗DLL僴儞僪儖丄DLL柤乮幆暿巕乯
// 栠傝抣丗error -1, success(keep 0, delete 1)
// -------------------------------------------------------------
int RemoveDLLReference(PVOID pImageBase, 
                       PTCHAR svName,
                       PDWORD pdwFlags)
{
    EnterCriticalSection(&g_DLLCrit);

    PIMAGE_PARAMETERS prev, cur = g_pImageParamHead;

    // DLL傪専嶕
    while(cur != NULL){
        if(cur->pImageBase == pImageBase)
            break;
        prev = cur;
        cur = cur->next;
    }

    // 敪尒偱偒側偐偭偨傜僄儔乕
    if(cur == NULL){
        LeaveCriticalSection(&g_DLLCrit);
        return -1;
    }
    
    cur->nLockCount--;
    *pdwFlags = cur->dwFlags;
    lstrcpyn(svName, cur->svName, MAX_PATH);

    // 僇僂儞僞偑傑偩0偠傖側偄側傜廔椆
    if(cur->nLockCount != 0){
        LeaveCriticalSection(&g_DLLCrit);
        return 0;
    }

    // 楢寢傪峏怴
    if(prev == NULL)
        g_pImageParamHead = g_pImageParamHead->next;
    else
        prev->next = cur->next;

    delete [] cur;
    LeaveCriticalSection(&g_DLLCrit);
    return 1;
}


// -------------------------------------------------------------
// 僷儔儊乕僞僥乕僽儖偐傜DLL傪専嶕偟偰偦偺僴儞僪儖傪曉偡
// 堷悢丂丗DLL僼傽僀儖柤
// 栠傝抣丗尒偮偐傟偽偦偺DLL偺僴儞僪儖丄尒偮偐傜側偗傟偽NULL
// -------------------------------------------------------------
HMODULE GetDLLHandle(PTCHAR svName)
{
    if(svName == NULL)
        return NULL;

    EnterCriticalSection(&g_DLLCrit);

    // 僷儔乕儊乕僞僥乕僽儖偺僩僢僾傪庢摼
    PIMAGE_PARAMETERS cur = g_pImageParamHead;
    
    // DLL傪専嶕
    while(cur != NULL){
        if(lstrcmpi(cur->svName, svName) != 0)
            cur = cur->next;
        else{
            // 尒偮偐偭偨傜僴儞僪儖傪曉偡
            LeaveCriticalSection(&g_DLLCrit);
            return (HMODULE)cur->pImageBase;
        }
    }

    // 尒偮偐傜側偗傟偽廔椆
    LeaveCriticalSection(&g_DLLCrit);
    return NULL;    
}


// -------------------------------------------------------------
// 僷儔儊乕僞僥乕僽儖偐傜DLL傪専嶕偟偰偦偺僼傽僀儖柤傪曉偡
// 堷悢丂丗DLL僴儞僪儖丄奿擺愭億僀儞僞丄奿擺椞堟偺僒僀僘
// 栠傝抣丗尒偮偐傟偽僼傽僀儖柤偺僒僀僘丄尒偮偐傜側偗傟偽0
// -------------------------------------------------------------
DWORD GetDLLFileName(HMODULE hModule, 
                     LPTSTR lpFileName, 
                     DWORD dwSize)
{
    if(hModule == NULL || lpFileName == NULL || dwSize == 0)
        return 0;
    
    // 傑偢偼捠忢偺GetModuleFileName偱挷傋傞
    DWORD dwRet = GetModuleFileName(hModule, lpFileName, dwSize);
    if(dwRet != 0)
        return dwRet;

    EnterCriticalSection(&g_DLLCrit);

    PIMAGE_PARAMETERS cur = g_pImageParamHead;
    
    // DLL傪専嶕
    while(cur != NULL){
        if(cur->pImageBase != hModule)
            cur=cur->next;
        else{
            // 尒偮偐偭偨傜暥帤楍偲僒僀僘傪曉偡
            LeaveCriticalSection(&g_DLLCrit);
            lstrcpyn(lpFileName, cur->svName, dwSize);
            return lstrlen(lpFileName);
        }
    } 

    LeaveCriticalSection(&g_DLLCrit);
    return 0;    
}
                    

// -------------------------------------------------------------
// DLL撪偵偁傞僄僋僗億乕僩娭悢傪専嶕偡傞
// 堷悢丂丗DLL僴儞僪儖丄娭悢柤
// 栠傝抣丗惉岟側傜娭悢傾僪儗僗丄幐攕側傜NULL
// -------------------------------------------------------------
FARPROC GetDLLProcAddress(HMODULE hModule, 
                          LPCSTR lpProcName)
{
    // hModule偑NULL側傜偽僄儔乕
    if(hModule == NULL)
        return NULL;
    
    // 僨傿儗僋僩儕僇僂儞僩庢摼
    PIMAGE_OPTIONAL_HEADER poh = 
        (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(hModule);
    int nDirCount = poh->NumberOfRvaAndSizes;
    if(nDirCount < 16)
        return FALSE;

    // 僄僋僗億乕僩僨傿儗僋僩儕僥乕僽儖庢摼
    DWORD dwIDEE = IMAGE_DIRECTORY_ENTRY_EXPORT;
    if(poh->DataDirectory[dwIDEE].Size == 0)
        return NULL;
    DWORD dwAddr = poh->DataDirectory[dwIDEE].VirtualAddress;
    PIMAGE_EXPORT_DIRECTORY ped = 
        (PIMAGE_EXPORT_DIRECTORY)RVATOVA(hModule, dwAddr);    
    
    // 彉悢庢摼
    int nOrdinal = (LOWORD(lpProcName)) - ped->Base;
    
    if(HIWORD(lpProcName) != 0){
        int count = ped->NumberOfNames;
        // 柤慜偲彉悢傪庢摼
        DWORD *pdwNamePtr = (PDWORD)
            RVATOVA(hModule, ped->AddressOfNames);
        WORD *pwOrdinalPtr = (PWORD)
            RVATOVA(hModule, ped->AddressOfNameOrdinals);
        // 娭悢専嶕
        int i;
        for(i=0; i < count; i++, pdwNamePtr++, pwOrdinalPtr++){
            PTCHAR svName = (PTCHAR)RVATOVA(hModule, *pdwNamePtr);
            if(lstrcmp(svName, lpProcName) == 0){
                nOrdinal = *pwOrdinalPtr;
                break;
            }
        }
        // 尒偮偐傜側偗傟偽NULL傪曉媝
        if(i == count)
            return NULL;
    }
    
    // 敪尒偟偨娭悢傪曉偡
    PDWORD pAddrTable = (PDWORD)
        RVATOVA(hModule, ped->AddressOfFunctions);
    return (FARPROC)RVATOVA(hModule, pAddrTable[nOrdinal]);
}


// -------------------------------------------------------------
// DLL偺DLLMain娭悢傪憱傜偣傞娭悢
// 堷悢丂丗DLL僴儞僪儖丄DLL僒僀僘丄Attach or Detach偺僼儔僌
// 栠傝抣丗error -1, success(keep 0, delete 1)
// -------------------------------------------------------------
static BOOL RunDLLMain(PVOID pImageBase, 
                       DWORD dwImageSize, 
                       BOOL bDetach)
{
    // 僼儔僌偺専嵏
    PIMAGE_FILE_HEADER pfh = (PIMAGE_FILE_HEADER)
        PEFHDROFFSET(pImageBase);
    if((pfh->Characteristics & IMAGE_FILE_DLL) == 0)
        return TRUE;

    // DLLMain娭悢偺傾僪儗僗庢摼
    PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)
        OPTHDROFFSET(pImageBase);
    DLLMAIN_T pMain = (DLLMAIN_T)
        RVATOVA(pImageBase, poh->AddressOfEntryPoint);

    // 僨僞僢僠帪or傾僞僢僠帪
    if(bDetach)
        return pMain((HMODULE)pImageBase, DLL_PROCESS_DETACH, NULL);
    else
        return pMain((HMODULE)pImageBase, DLL_PROCESS_ATTACH, NULL);
}


// -------------------------------------------------------------
// 僀儞億乕僩娭悢偺傾僪儗僗夝寛娭悢
// 堷悢丂丗DLL僼傽僀儖僀儊乕僕丄DLL僼傽僀儖僀儊乕僕偺僒僀僘
// 栠傝抣丗惉岟TRUE丄幐攕FALSE
// -------------------------------------------------------------
BOOL PrepareDLLImage(PVOID pMemoryImage, 
                     DWORD dwImageSize)
{
    PIMAGE_OPTIONAL_HEADER poh = 
        (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(pMemoryImage);
    int nDirCount = poh->NumberOfRvaAndSizes;
    if(nDirCount < 16)
        return FALSE;

    PIMAGE_SECTION_HEADER psh = 
        (PIMAGE_SECTION_HEADER)SECHDROFFSET(pMemoryImage);

    DWORD dwIDEI = IMAGE_DIRECTORY_ENTRY_IMPORT;

    if(poh->DataDirectory[dwIDEI].Size != 0){
        PIMAGE_IMPORT_DESCRIPTOR pid = 
            (PIMAGE_IMPORT_DESCRIPTOR)RVATOVA(pMemoryImage, 
            poh->DataDirectory[dwIDEI].VirtualAddress);

        for(; pid->OriginalFirstThunk != 0; pid++){
            PTCHAR svDllName = (PTCHAR)
                RVATOVA(pMemoryImage, pid->Name);
            HMODULE hDll = GetModuleHandle(svDllName);
            if(hDll == NULL){
                if((hDll = LoadLibrary(svDllName)) == NULL)
                    return FALSE;
            }

            if(pid->TimeDateStamp != 0)
                continue;
            
            pid->ForwarderChain = (DWORD)hDll;
            pid->TimeDateStamp  = IMAGE_PARAMETER_MAGIC;

            typedef struct{
                union{
                    DWORD Function;
                    DWORD Ordinal;
                    DWORD AddressOfData;
                } u1;
            } MY_IMAGE_THUNK_DATA, *PMY_IMAGE_THUNK_DATA;

            PMY_IMAGE_THUNK_DATA ptd_in = (PMY_IMAGE_THUNK_DATA)
                RVATOVA(pMemoryImage, pid->OriginalFirstThunk);
            PMY_IMAGE_THUNK_DATA ptd_out = (PMY_IMAGE_THUNK_DATA)
                RVATOVA(pMemoryImage, pid->FirstThunk);
                
            for(; ptd_in->u1.Function != NULL; ptd_in++, ptd_out++){

                FARPROC func;
                if(ptd_in->u1.Ordinal & 0x80000000){
                    func = GetProcAddress(hDll, 
                        MAKEINTRESOURCE(ptd_in->u1.Ordinal));
                }else{
                    PIMAGE_IMPORT_BY_NAME pibn = 
                        (PIMAGE_IMPORT_BY_NAME)RVATOVA(
                        pMemoryImage, ptd_in->u1.AddressOfData);
                    func = GetProcAddress(hDll, (PTCHAR)pibn->Name);
                }
                
                if(func == NULL)
                    return FALSE;
                    
                ptd_out->u1.Function = (DWORD)func;
            }
        }
    }

    DWORD dwIDEB = IMAGE_DIRECTORY_ENTRY_BASERELOC;
    DWORD delta = (DWORD)pMemoryImage - (DWORD)poh->ImageBase;

    if((delta == 0) || (poh->DataDirectory[dwIDEB].Size == 0))
        return TRUE;
    
    PIMAGE_FIXUP_BLOCK pfb = (PIMAGE_FIXUP_BLOCK)RVATOVA(
        pMemoryImage, poh->DataDirectory[dwIDEB].VirtualAddress);

    while(pfb->dwPageRVA != 0){
        
        int count = (pfb->dwBlockSize - sizeof(
            IMAGE_FIXUP_BLOCK)) / sizeof(IMAGE_FIXUP_ENTRY);
        PIMAGE_FIXUP_ENTRY pfe = (PIMAGE_FIXUP_ENTRY)
            ((PTCHAR)pfb + sizeof(IMAGE_FIXUP_BLOCK));

        for(int i=0; i < count; i++, pfe++){

            PVOID fixaddr = RVATOVA(
                pMemoryImage, pfb->dwPageRVA + 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:
                *((WORD *)fixaddr) = HIWORD(
                    ((*((WORD *)fixaddr)) << 16) | 
                    (*(WORD *)(pfe+1))+ delta + 0x00008000);
                pfe++;
                break;
            default:
                return FALSE;
            }
        }

        pfb = (PIMAGE_FIXUP_BLOCK)((PTCHAR)pfb + pfb->dwBlockSize);
    }
    return TRUE;
}


// -------------------------------------------------------------
// DLL僀儊乕僕傪僾儘僥僋僩偡傞
// 堷悢丂丗DLL僼傽僀儖僀儊乕僕
// 栠傝抣丗惉岟TRUE丄幐攕FALSE
// -------------------------------------------------------------
BOOL ProtectDLLImage(PVOID pMemoryImage)
{
    // 僙僋僔儑儞悢庢摼
    PIMAGE_FILE_HEADER pfh = 
        (PIMAGE_FILE_HEADER)PEFHDROFFSET(pMemoryImage);
    int nSectionCount = pfh->NumberOfSections;

    // 僙僋僔儑儞僿僢僟庢摼
    PIMAGE_SECTION_HEADER psh = 
        (PIMAGE_SECTION_HEADER)SECHDROFFSET(pMemoryImage);

    for(int i=0; i < nSectionCount; i++, psh++){

        // 僙僋僔儑儞傾僪儗僗偲僒僀僘偺庢摼
        PVOID secMemAddr = (PTCHAR)
            RVATOVA(pMemoryImage, psh->VirtualAddress);
        
        DWORD chr = psh->Characteristics;
        // 僾儘僥僋僩僼儔僌偺愝掕
        BOOL bWrite  = (chr & IMAGE_SCN_MEM_WRITE)   ? TRUE : FALSE;
        BOOL bRead   = (chr & IMAGE_SCN_MEM_READ)    ? TRUE : FALSE;
        BOOL bExec   = (chr & IMAGE_SCN_MEM_EXECUTE) ? TRUE : FALSE;
        BOOL bShared = (chr & IMAGE_SCN_MEM_SHARED)  ? TRUE : FALSE;
        
        DWORD newProtect = 0;
        // 僼儔僌惍棟
        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(chr & IMAGE_SCN_MEM_NOT_CACHED)
            newProtect |= PAGE_NOCACHE;

        if(newProtect == 0)
            return FALSE;

        DWORD oldProtect;
        // 僾儘僥僋僩幚峴
        VirtualProtect(secMemAddr, 
            psh->SizeOfRawData, newProtect, &oldProtect);
    }
    return TRUE;
}


// -------------------------------------------------------------
// DLL僀儊乕僕傪僐僺乕偡傞娭悢
// 堷悢丂丗DLL僼傽僀儖僀儊乕僕丄僐僺乕愭億僀儞僞
// 栠傝抣丗惉岟TRUE丄幐攕FALSE
// -------------------------------------------------------------
BOOL MapDLLFromImage(PVOID pDLLFileImage, 
                     PVOID pMemoryImage)
{
    // PE僿僢僟偲僙僋僔儑儞僿僢僟傪僐僺乕
    PIMAGE_OPTIONAL_HEADER poh = 
        (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(pDLLFileImage);
    memcpy(pMemoryImage, pDLLFileImage, poh->SizeOfHeaders);

    // 僙僋僔儑儞悢傪庢摼
    PIMAGE_FILE_HEADER pfh = (PIMAGE_FILE_HEADER)
        PEFHDROFFSET(pDLLFileImage);
    int nSectionCount = pfh->NumberOfSections;

    // 僙僋僔儑儞僿僢僟億僀儞僞庢摼
    PIMAGE_SECTION_HEADER psh = 
        (PIMAGE_SECTION_HEADER)SECHDROFFSET(pDLLFileImage);

    // 偡傋偰偺僙僋僔儑儞偺僐僺乕
    for(int i=0; i < nSectionCount; i++, psh++){
        PTCHAR secMemAddr  = (PTCHAR)
            ((PTCHAR)pMemoryImage + psh->VirtualAddress);
        PTCHAR secFileAddr = (PTCHAR)
            ((PTCHAR)pDLLFileImage + psh->PointerToRawData);
        int secLen = psh->SizeOfRawData;
        memcpy(secMemAddr, secFileAddr, secLen);
    }
    return TRUE;
}


// -------------------------------------------------------------
// DLL僀儊乕僕偐傜DLL傪儘乕僪偡傞娭悢
// 堷悢丂丗DLL僼傽僀儖僀儊乕僕丄儅僢僺儞僌柤乮幆暿巕乯丄僼儔僌
// 栠傝抣丗惉岟DLL僴儞僪儖丄幐攕NULL
// -------------------------------------------------------------
HMODULE LoadDLLFromImage(LPVOID pDLLFileImage, 
                         PTCHAR szMappingName,
                         DWORD dwFlags)
{
    // 儅僢僺儞僌柤偑側偗傟偽僄儔乕
    if(szMappingName == NULL)
        return NULL;

    // 儅僢僺儞僌柤偺僒僀僘傪敾掕
    if(lstrlen(szMappingName) >= MAX_PATH)
        return NULL;
    
    // PE僨乕僞偺敾掕
    PIMAGE_DOS_HEADER doshead = (PIMAGE_DOS_HEADER)pDLLFileImage;
    if(doshead->e_magic != IMAGE_DOS_SIGNATURE)
        return NULL;
    if(*(DWORD *)NTSIGNATURE(pDLLFileImage) != IMAGE_NT_SIGNATURE)
        return NULL;
    PIMAGE_OPTIONAL_HEADER poh = 
        (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(pDLLFileImage);
    if(poh->Magic != 0x010B)
        return NULL;

    // 僙僋僔儑儞悢庢摼
    PIMAGE_FILE_HEADER pfh = 
        (PIMAGE_FILE_HEADER)PEFHDROFFSET(pDLLFileImage);
    int nSectionCount = pfh->NumberOfSections;

    DWORD pPreferredImageBase = poh->ImageBase;
    DWORD dwImageSize = poh->SizeOfImage;

    PVOID pImageBase;
    HANDLE hmapping = NULL;
    // DLL僴儞僪儖偑尒偮偐傜側偗傟偽怴偟偔惗惉
    if((pImageBase = GetDLLHandle(szMappingName)) == NULL){
        BOOL bCreated = FALSE;
        // 偡偱偵儅僢僺儞僌偝傟偰偄傞偐偳偆偐
        hmapping = OpenFileMapping(
            FILE_MAP_WRITE, TRUE, szMappingName);
        // 偝傟偰偄側偄側傜惗惉
        if(hmapping == NULL){
            hmapping = CreateFileMapping(
                INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 
                dwImageSize + SIZE_OF_PARAMETER_BLOCK, szMappingName);
            if(hmapping == NULL)
                return NULL;
            bCreated = TRUE;
        }

        // 儅僢僺儞僌偝傟偰偄傞僨乕僞偺愭摢傪pImageBase傊
        pImageBase = MapViewOfFileEx(
            hmapping, FILE_MAP_WRITE, 0, 0, 0, (LPVOID)pPreferredImageBase);
        if(pImageBase == NULL){
            pImageBase = MapViewOfFileEx(
                hmapping, FILE_MAP_WRITE, 0, 0, 0, NULL);
        }
        CloseHandle(hmapping);
        if(pImageBase == NULL)
            return NULL;

        // 怴偟偔惗惉偝傟偨偐丄儀乕僗傾僪儗僗偑曄傢偭偰偄偨傜
        if(bCreated || (pImageBase != (LPVOID)pPreferredImageBase)){
            // DLL僀儊乕僕傪儅僢僺儞僌
            if( ! MapDLLFromImage(pDLLFileImage, pImageBase)){
                UnmapViewOfFile(pImageBase);
                return NULL;
            }
        }
        
        // LOAD_LIBRARY_AS_DATAFILE偑棫偭偰側偄側傜偽
        if( ! (dwFlags & LOAD_LIBRARY_AS_DATAFILE)){
            // 
            if( ! PrepareDLLImage(pImageBase, dwImageSize)){
                UnmapViewOfFile(pImageBase);
                return NULL;
            }
            
            // 僼儔僌偵DONT_RESOLVE_DLL_REFERENCES偑棫偭偰側偗傟偽
            if( ! (dwFlags & DONT_RESOLVE_DLL_REFERENCES)){
                // DLLMain傪幚峴乮傾僞僢僠乯
                if( ! RunDLLMain(pImageBase, dwImageSize, DLL_ATTACH)){
                    UnmapViewOfFile(pImageBase);
                    return NULL;
                }
            }

            // 僾儘僥僋僩傪幚峴
            if( ! ProtectDLLImage(pImageBase)){
                UnmapViewOfFile(pImageBase);
                return NULL;
            }
        }
    }
    
    // DLL僨乕僞儀乕僗傊捛壛
    if(AddDLLReference(pImageBase, szMappingName, dwFlags) == -1){
        if(hmapping != NULL)
            UnmapViewOfFile(pImageBase);
        return NULL;
    }    

    return (HMODULE)pImageBase;    
}


// -------------------------------------------------------------
// DLL傪儘乕僪偡傞娭悢
// 堷悢丂丗DLL僼傽僀儖柤丄梊栺岅乮NULL屌掕乯丄僼儔僌
// 栠傝抣丗惉岟DLL僴儞僪儖丄幐攕NULL
// -------------------------------------------------------------
HMODULE LoadDLLEx(LPCTSTR lpLibFileName,
                  HANDLE hReserved,
                  DWORD dwFlags)
{
    // 戙懼僼傽僀儖専嶕曽朄巜掕
    // 乮LOAD_WITH_ALTERED_SEARCH_PATH乯偼僒億乕僩偟側偄
    if(dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH)
        return NULL;

    // DLL僷僗庢摼
    TCHAR szPath[MAX_PATH + 1], *szFilePart;
    int nLen = SearchPath(NULL, lpLibFileName, 
        ".dll", MAX_PATH, szPath, &szFilePart);
    if(nLen == 0)
        return NULL;

    // 僼傽僀儖儅僢僺儞僌
    HANDLE hFile = CreateFile(
        szPath, GENERIC_READ, FILE_SHARE_READ, 
        NULL, OPEN_EXISTING, 0, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
        return NULL;
    HANDLE hMapping = CreateFileMapping(
        hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    CloseHandle(hFile);
    LPVOID pBaseAddr = MapViewOfFile(
        hMapping, FILE_MAP_READ, 0, 0, 0);
    if(pBaseAddr == NULL){
        CloseHandle(hMapping);
        return NULL;
    }

    // DLL僀儊乕僕偺撉傒崬傒
    HMODULE hRet = LoadDLLFromImage(pBaseAddr, 
        szFilePart, dwFlags & ~LOAD_WITH_ALTERED_SEARCH_PATH);

    // 僼傽僀儖儅僢僺儞僌夝彍
    UnmapViewOfFile(pBaseAddr);
    CloseHandle(hMapping);
    return hRet;
}


// -------------------------------------------------------------
// DLL傪儘乕僪偡傞娭悢乮LoadDLLEx傊偺嫶搉偟乯
// 堷悢丂丗DLL僼傽僀儖柤
// 栠傝抣丗惉岟DLL僴儞僪儖丄幐攕NULL
// -------------------------------------------------------------
HMODULE LoadDLL(LPCTSTR lpLibFileName)
{
    return LoadDLLEx(lpLibFileName, NULL, 0);
}


// -------------------------------------------------------------
// DLL傪奐曻偡傞娭悢
// 堷悢丂丗DLL僴儞僪儖
// 栠傝抣丗惉岟TRUE丄幐攕FALSE
// -------------------------------------------------------------
BOOL FreeDLL(HMODULE hLibModule)
{
    // hLibModule偑NULL側傜栤戣奜
    if(hLibModule == NULL)
        return FALSE;
    
    // PE僨乕僞偺幆暿
    PIMAGE_DOS_HEADER doshead = (PIMAGE_DOS_HEADER)hLibModule;
    if(doshead->e_magic != IMAGE_DOS_SIGNATURE)
        return FALSE;
    if(*(PDWORD)NTSIGNATURE(hLibModule) != IMAGE_NT_SIGNATURE)
        return FALSE;
    PIMAGE_OPTIONAL_HEADER poh = 
        (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(hLibModule);
    if(poh->Magic != 0x010B)
        return FALSE;

    DWORD dwFlags;
    TCHAR szName[MAX_PATH];
    // DLL僨乕僞儀乕僗偐傜偼偢偡
    int dllaction = RemoveDLLReference(hLibModule, szName, &dwFlags);
    if(dllaction == -1)
        return FALSE;

    // DLL偺僨僞僢僠
    if( ! (dwFlags & (LOAD_LIBRARY_AS_DATAFILE | 
        DONT_RESOLVE_DLL_REFERENCES)))
    {    // 僇僂儞僞偑0乮dllaction=1乯側傜偽DLL傪僨僞僢僠偟偰廔椆
        if(dllaction){
            RunDLLMain(hLibModule, poh->SizeOfImage, DLL_DETACH);
            return UnmapViewOfFile(hLibModule);
        }
    }
    return TRUE;
}


typedef int (*PADDFUNC)(int, int);
typedef int (*PSUBFUNC)(int, int);


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    InitializeDLLLoad();
    HMODULE hHandle = LoadDLL(_T("test_dll"));
    PADDFUNC pAdd = (PADDFUNC)GetDLLProcAddress(hHandle, _T("add_num"));
    int a = (*pAdd)(3, 5);  // 3 + 5 = 8
    PSUBFUNC pSub = (PSUBFUNC)GetDLLProcAddress(
        GetDLLHandle(_T("test_dll.dll")), _T("sub_num"));
    int b = (*pSub)(8, 5);  // 8 - 5 = 3
    TCHAR szFileName[MAX_PATH];
    GetDLLFileName(hHandle, szFileName, sizeof(szFileName));
    TCHAR szBuffer[1024];
    wsprintf(szBuffer, _T(
        "FileName = %s/r/na = %d, b = %d/r/n"), szFileName, a, b);
    MessageBox(GetActiveWindow(), szBuffer, _T("Message"), MB_OK);
    FreeDLL(hHandle);
    KillDLLLoad();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值