dll加载

c++ 动态加载DLL和静态加载DLL以及DLL的编写 1、DLL的编写 新建win32控制台或者win32项目,然后选择DLL 下面是自动生成的文件MyDll.h // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 MYDLL_EXPORTS // 符号编译的。在使用此 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;
}
dll是在何时被加载?如何延迟加载dll? dll延迟加载,dll加载方式 阅读详情

相关推荐

C#中加载dll的问题

最近在做C#上进行H264解码的网络摄像头,通过各种折腾,还是没法解决,无奈之下只好使用在C#下加载ffmpeg的动态库进行,在加载的时候说不遇到问题那是不可能的。 下面就我遇到的问题和解决方案进行发表: 1.加载方法 很多人都想着通过右键引用的方法进行dll的加载,当然那是简便的方法,不过对于用C++编译的动态库貌似这方法行不通,往往会提示“未能添加XXX.dll的引用。请

AntKnight的专栏 9991

dll侧加载手册

dll sideloading 在恶意软件对抗中并不少用,快速使用和识别可以加速分析过程

jentle8的博客 570

vs2008加载dll深入

之前简单写过如何创建lib和dll文件及简单的使用(http://blog.youkuaiyun.com/betabin/article/details/7239200)。现在先再深入点写写dll的加载方式。 dll的加载方式主要分为两大类,显式和隐式链接。具体名词解释如下: 隐式链接有时称为静态加载或加载时动态链接。 显式链接有时称为动态加载或运行时动态链接。 这样我们就大概理解了这两种链接方式了,

BetaBin 8266

一种应用更广泛的DLL侧载方法

可以看到堆栈的情况,并没有调用LoadLibrary函数的情况,该dll加载先于程序的入口点,原始程序加载完dll运行一段时间就会退出,因此可以在msvcp140.dll被加载后将程序入口点patch阻断原始程序的运行流程。使用SharpDllProxy将msvcp140.dll的导出函数导出到文件中,该工具会生成一个.c的文件和一个dll,这个dll就是原始的msvcp140.dll。将上面导出的函数替换到下面代码的位置,然后编译生成dll文件,将该dll文件重命名为msvcp140.dll。

Mccc_li的博客 1215

DLL内存加载

动态加载dll 功能:      把一个处于内存里的dll直接加载并且使用。 用途:      免杀(静态文件查杀),外挂(防止游戏自己hook了loadlibrary等函数),以及其他。 原理:      假设目前处于内存里的dll是A,然后开辟一个新的内存空间B,根据A的文件头等相关信息,把B看做是加载内存。 然后把数据拷贝到B里,并且对齐相关节,然后修正iat等相关。然后在手动

天使也掉毛 7368

SharpDllProxy:从合法的DLL检索导出的函数,并生成用于DLL代理加载或侧载的代理DLL源代码模板

SharpDll代理 从合法的DLL检索导出的函数,并为DLL代理加载或侧载生成代理DLL源代码/模板 与redteaming.co.uk的博客文章一起创建-> 用法 利润 学分 Vivek Ramachandran将

C++函数动态链接库及静态链接

动态链接库的使用方法,动态链接库的动态调用(也叫显式调用)可以运用了,但是静态调用(也叫隐式调用)这种很少见。   (一)先回顾一下,动态链接库和静态链接库   静态链接库:lib中的函数不仅被连接,全部实现都被直接包含在最终生成的EXE文件中,只是实现是不可见的。   动态链接库:dll不必被包含在最终的EXE中,静态调用时仅把函数名或者变量名或者类名链接到EXE文件中,而这些东西的实体都只有

csh1915259502的博客 1214

DLLsForHackers:可以用于侧面加载和其他攻击媒介的Dll

DLLsForHackers 可用于侧面加载和其他攻击媒介的Dll。此Dll不会导致死锁,因为它仅使用如下所述的DllMain安全的功能。 为什么? 我看到太多的POC与在DLL_PROCESS_ATTACH执行的代码。实际上,大多数情况下,恶意代码无法按照Microsoft的说明进行工作( )。 您永远不要在DllMain中执行以下任务: 调用LoadLibrary或LoadLibraryEx(直接或间接)。这可能会导致死锁或崩溃。 调用GetStringTypeA,GetStringTypeEx或GetStringTypeW(直接或间接)。这可能会导致死锁或崩溃。 与其他线程同步。这可能会导致死锁。 获取由等待获取加载程序锁的代码所拥有的同步对象。这可能会导致死锁。 通过使用CoInitializeEx初始化COM线程。在某些情况下,此函数可以调用LoadLibraryEx。 调用注

@value 静态变量_调试实战 —— dll 加载失败之全局变量初始化篇

前言最近项目里总是遇到 dll 加载不上的问题,原因各种各样。今天先总结一个虽然不是项目中实际遇到的问题,但是却非常经典的情况。其它情况,后续慢慢总结。示例代码包含一个 exe 工程,两个 dll 工程。 exe 会加载两个 dll 并调用它们的导出函数(GetCallCount),结果只有一个 dll 的导出函数被成功调用。会是什么原因呢?现象运行效果如下图:通过 dumpbin 已经确认两个 ...

weixin_39931390的博客 281

Vue3多级路由缓存失效的深度解析与实战解决方案

本文深度解析了Vue3项目中多级路由嵌套下keep-alive缓存失效的根本原因,并提供了三种实战解决方案。通过剖析组件树、router-view与keep-alive的协作机制,揭示了缓存无法穿透多层router-view的技术本质。文章对比了路由扁平化重构、状态管理配合路由守卫以及使用社区插件等方案的优缺点与适用场景,为开发者解决这一常见难题提供了清晰的选型指导。

weixin_29001423的博客 273

WRF模式学习入门基础(建议收藏!!!)

本文详细介绍了WRF-ARW(Advanced Research WRF)模式的结构组成,重点讲解了前处理系统(WPS)和主模式中的各个关键程序的功能与流程。通过对geogrid、ungrib、metgrid、real和wrf等模块的逐步解析,帮助初学者全面理解数值天气预报模型在初始化和运行过程中所需的关键步骤。

2503_90234341的博客 3080

【DLL】【学习笔记】(一)DLL的两种加载方式的过程

DLL显式加载和隐式加载的过程说明

此地无银 4027

特斯拉数字孪生4.0体系解析:从“数字镜像“到“持续进化“的造车革命

当每一辆汽车都拥有自己的“数字分身”,我们正见证的不仅是技术革新,更是整个制造业文明形态的跃迁。其数字孪生体已超越“数字镜像”的被动属性,成为。特斯拉年服务收入超1200美元/车的业绩表明,数字孪生正在将汽车从“交通工具”转变为“持续增值的智能终端”。构建起覆盖设计、制造、使用、服务全链条的虚拟镜像体系,将物理世界与数字世界的融合推向新高度。:特斯拉的实践证明,数字孪生已从“技术选项”升级为“战略必选项”。不仅重塑了汽车产品的价值创造逻辑,更预示着整个制造业向“元宇宙工业”演进的新范式。

beige888的博客 1609

DLL的两种加载方式——静态加载和动态加载

案例简述 在某项目中,需要使用两个不同版本的HCNetSDK库,我们通常使用的静态加载DLL的方式不能满足该需求,故用到动态加载DLL的方式。 背景技术及术语解释 静态加载:也称隐式调用,指在运行程序之前由操作系统的加载器将DLL和EXE一起加载到内存里。注意这里与程序的静态链接区别开来,静态链接发生在编译过程之中,而DLL的静态加载是发生在程序运行之前。 动态加载:也称显示调用,指应用程序运行过程中程序自己完成对DLL的加载和卸载(DLL加载—DLL函数地址获取—DLL释放),应用程序在执行过程...

luyumiao1990的专栏 1万+

告别手动处理:用 Bruker NSMatlabUtilities 工具箱批量分析 AFM 力曲线数据的实战案例

本文介绍了如何使用 Bruker NSMatlabUtilities 工具箱实现 AFM 力曲线数据的批量分析,解决传统手动处理耗时且易出错的问题。通过实战案例展示工具箱的核心功能,包括数据读取、力曲线分析和可视化,帮助科研人员提升数据处理效率和准确性。

weixin_28362173的博客 214

【YOLOs-CPP-图像分类部署】04-项目优化(加速部署)

本文详细介绍了将YOLO图像分类C++部署项目从CMake迁移到Visual Studio控制台应用的全过程。针对低配CPU性能瓶颈问题,作者通过替换多线程HPP代码为官方实现,并采用448x448固定输入尺寸优化推理速度。项目配置包含OpenCV和ONNX Runtime环境设置,实现了图像批量处理、分类结果显示及结果日志输出功能。关键步骤包括依赖库配置、DLL部署和代码调试,最终在Windows平台成功实现高效CPU推理。该方案显著提升了低配硬件的兼容性,为图像分类任务提供了稳定的部署解决方案。

深耕CV 355

DLL的两种加载方式

DLL有两种调用方式 一,隐式加载(需要.lib和.dll) 二,显式加载(需要.dll)

enjoy5512的博客 1万+

AEJoy —— 表达式之仅限在某一维摆动【JS】

效果图 wiggle() 的作用仅限于水平方向 想法 wiggle() 确实是一个非常方便的工具,但有时您希望对它有更多的控制。在本例中,我们希望仅将摆动限制在水平方向。 设计 要理解 wiggle() 最重要的一点是,它生成的结果与应用它的属性具有相同的维度。例如,如果你将 wiggle() 应用于 3D 层的 position 属性,结果将是一个由三个元素组成的数组(x、y 和 z 各一个)。我们需要做的就是将 wiggle() 的结果捕捉到一个变量(我们称之为 “w” ),然后从这个变量中提取我们想

ShaderJoy 的兴趣技术杂货铺 2095

从内存中加载DLL

程序使用动态库DLL一般分为隐式加载和显式加载两种,分别对应两种链接情况。本文主要讨论显式加载的技术问题。我们知道,要显式加载一个DLL,并取得其中导出的函数地址一般是通过如下步骤:(1) 用LoadLibrary加载dll文件,获得该dll的模块句柄;(2) 定义一个函数指针类型,并声明一个变量;(3) 用GetProcAddress取得该dll中目标函数的地址,赋值给函数指针变量;(4) 调用

2765

SAP MM模块后续借记、后续贷记、贷方凭证简介

在SAP系统中,后续借记、后续贷记和贷方凭证是处理供应商发票、采购和付款过程中常见的财务交易。

我小时候很黑的博客 3273

S7-200SMART PLC中进行MODBUS RTU通信的3种方法(1)

S7-200SMART PLC中进行MODBUS RTU通信的3种方法(1)

Robot_PLC_HMI_Automation 4241

QT动态加载DLL包括加载DLL中的类及其成员函数

QT中加载DLL的方式有两种: 一种是静态方式的加载,需要有两个文件:lib文件和dll文件。lib文件就是导入库,里面定义了一些函数符号,在调用的时候会直接查找这些函数符号,然后根据这些函数符号,找到DLL对应的模块加载进来进行调用。 另一种就是动态调用。在使用的时候才会加载dll进来,使用QT本身自己的加载机制,利用QLibrary进行动态加载。 静态加载的方式比较常用,下面介绍一下动态加载的...

wb175208的专栏 1万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Java 加载 DLL 类库

Java 加载 dll 库

u014614478的博客 2747

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

内存加载DLL

1、前言 目前很多敏感和重要的DLL(Dynamic-link library) 都没有提供静态版本供编译器进行静态连接(.lib文件),即使提供了静态版本也因为兼容性问题导致无法使用,而只提供DLL版本,并且很多专业软件的授权部分的API,都是单独提供一个DLL来完成,而主模块通过调用DLL中的接口来完成授权功能。虽然这些软件一般都采用了加壳和反调试等保护,但是一旦这些功能失去作用,比如脱...

weixin_33709590的博客 1148

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

动态加载DLL和静态加载DLL的步骤

<br />动态加载DLL的步骤如下: <br />HINSTANCE    DLL库实例名=LoadLibrary(_T("DLL库名.dll"));//加载解密函数库<br />typedef BOOL (CALLBACK *函数类型名)(函数参数1,函数参数2...... );//定义函数类型,格式一<br />//typedef BOOL (__cdecl *函数类型名)(函数参数1,函数参数2...... );//定义函数类型,格式二,看原DLL函数的格式而定<br />函数类型名 使用时的函数

特权份子的专栏 1088
上一篇: A more stable way to locate real KiServiceTable
下一篇: Api Hijacking (sample included
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值