// MergeDll.cpp : Defines the entry point for the application.
//http://blog.csdn.net/andyhebear/
//
#define WIN32_LEAN_AND_MEAN
#pragma comment ( linker,"/ALIGN:4096" )
#include <windows.h>
#include "resource.h"
#include <lmerr.h>
#include <stdio.h>
 
BOOL IsNT();
LPVOID lpImageDll2;
DWORD LoadPbDllFromMemory(LPVOID lpRawDll, LPVOID lpImageDll);
DWORD GetProcAddressDirectly(PIMAGE_DOS_HEADER dosHeader, char * FuncName);
DWORD UnloadPbDllFromMemory(PIMAGE_DOS_HEADER dosHeader);
void SetupResource(PIMAGE_DOS_HEADER dosHeader);
void DumpResourceSection(PBYTE pImageBase, PIMAGE_NT_HEADERS pNTHeader);
void DisplayErrorText( DWORD dwLastError );
 
//////////////////////////////////////////////////////////////////////////
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
#define GetImgDirEntryRVA( pNTHdr, IDE ) /
(pNTHdr->OptionalHeader.DataDirectory[IDE].VirtualAddress)
 
#define GetImgDirEntrySize( pNTHdr, IDE ) /
(pNTHdr->OptionalHeader.DataDirectory[IDE].Size)
 
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pNTHeader);
LPVOID GetPtrFromRVA( DWORD rva, PIMAGE_NT_HEADERS pNTHeader, PBYTE imageBase );
PBYTE pImageBase;
 
//////////////////////////////////////////////////////////////////////////
typedef char * (CALLBACK* LPFNDLLFUNC1)();
LPFNDLLFUNC1 lpfnDllFunc1;
 
typedef UINT (CALLBACK * LPENTRYPOINT) (HANDLE hInstance, DWORD Reason, LPVOID Reserved);
LPENTRYPOINT EntryPoint; // Function pointer
 
char * uReturnVal;
 
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,
                     int nCmdShow)
{
    // TODO: Place code here.
    LPVOID sRawDll;
    HRSRC hRes;
    
    HMODULE hLibrary;
    HGLOBAL hResourceLoaded;
    char lib_name[MAX_PATH];
    GetModuleFileName(hInstance, lib_name, MAX_PATH );
    hLibrary = LoadLibrary(lib_name);
    
    if (NULL != hLibrary)
    {
        hRes = FindResource(hLibrary, MAKEINTRESOURCE(IDR_DATA1), RT_RCDATA);
        if (NULL != hRes)
        {
            hResourceLoaded = LoadResource(hLibrary, hRes);
            if (NULL != hResourceLoaded) 
            {
                SizeofResource(hLibrary, hRes);
                sRawDll = (LPVOID)LockResource(hResourceLoaded);
            }
        }
        else return 1;
        FreeLibrary(hLibrary);
    }
    else return 1;
    
    try // 在错误处理中进行操作,一但发生错误,必须释放我们分配的内存
        // 以避免造成内存泄漏
    {
        lpImageDll2=NULL;
        LPVOID lpImageDll=NULL;
        
        // 从资源中载入 DLL 到内存
        if (LoadPbDllFromMemory(sRawDll, lpImageDll)) 
        {
            MessageBox(NULL,"Load Dll Failed!","",0);
            return 1;
        }
        
        // 取得要调用的函数的地址
        lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddressDirectly((PIMAGE_DOS_HEADER)lpImageDll2, "getbios");
        
        if(lpfnDllFunc1==0)
        {
            MessageBox(NULL,"Could not get Function address!","",0);
            return 1;
        }
        
        // 调用 DLL 中的函数 getbios 来获取主板 ID
        uReturnVal = lpfnDllFunc1();
        
        if(strlen(uReturnVal)!=0)
        {
            MessageBox(NULL,uReturnVal,"your mainboard id!",0);
        }
        else 
            MessageBox(NULL,"getbios 返回值为 NULL",":(",0);
        
        UnloadPbDllFromMemory((PIMAGE_DOS_HEADER)lpImageDll2);
    }
    catch(...)
    {
        MessageBox(NULL,"Error occus!",":(",0);
        if(lpImageDll2!=NULL) VirtualFree(lpImageDll2,0, MEM_RELEASE);
    }
    return 0;
}
 
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pNTHeader)
{
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
    unsigned i;
    
    for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
    {
        DWORD size = section->Misc.VirtualSize;
        if ( 0 == size ) size = section->SizeOfRawData;
        if ( (rva >= section->VirtualAddress) && (rva < (section->VirtualAddress + size))) return section;
    }
    return 0;
}
 
LPVOID GetPtrFromRVA( DWORD rva, PIMAGE_NT_HEADERS pNTHeader, PBYTE imageBase )
{
    PIMAGE_SECTION_HEADER pSectionHdr;
    INT delta;
    
    pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader );
    if ( !pSectionHdr ) return 0;
    
    delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
    return (PVOID) ( imageBase + rva - delta );
}
 
void DisplayErrorText( DWORD dwLastError ) // 标准的错误处理函数
{
    HMODULE hModule = NULL; // default to system source
    LPSTR MessageBuffer;
    DWORD dwBufferLength;
    
    DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_IGNORE_INSERTS |
        FORMAT_MESSAGE_FROM_SYSTEM ;
    
    if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) 
    {
        hModule = LoadLibraryEx(
            TEXT("hardware.dll"),
            NULL,
            LOAD_LIBRARY_AS_DATAFILE
            );
        
        if(hModule != NULL)
            dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
    }
    
    if(dwBufferLength = FormatMessageA(
        dwFormatFlags,
        hModule, // module to get message from (NULL == system)
        dwLastError,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
        (LPSTR) &MessageBuffer,
        0,
        NULL
        ))
    {
        MessageBox(NULL,MessageBuffer,0,0);
        LocalFree(MessageBuffer);
    }
    if(hModule != NULL) FreeLibrary(hModule);
}
 
DWORD GetProcAddressDirectly(PIMAGE_DOS_HEADER dosHeader, char * FuncName)
{
    PIMAGE_NT_HEADERS pNTHeader;
    PIMAGE_EXPORT_DIRECTORY pExportDir;
    PWORD lpNameOrdinals;
    LPDWORD lpFunctions;
    DWORD * lpName;
    char * lpExpFuncName;
    DWORD i;
    DWORD j;
    char * lpFuncName;
    
    if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0;
    
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + dosHeader->e_lfanew);
    
    if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) return 0;
    
    if ((pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(pNTHeader->OptionalHeader)) ||
        (pNTHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC))
        return 0;
    
    DWORD exportsStartRVA, exportsEndRVA;
    pImageBase = (PBYTE)dosHeader;
    
    // Make pointers to 32 and 64 bit versions of the header.
    pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,dosHeader->e_lfanew );
    
    exportsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_EXPORT);
    exportsEndRVA = exportsStartRVA +
        GetImgDirEntrySize(pNTHeader, IMAGE_DIRECTORY_ENTRY_EXPORT);
    
    // Get the IMAGE_SECTION_HEADER that contains the exports. This is
    // usually the .edata section, but doesn't have to be.
    PIMAGE_SECTION_HEADER header;
    header = GetEnclosingSectionHeader( exportsStartRVA, pNTHeader );
    if ( !header ) return 0;
    
    INT delta;
    delta = (INT)(header->VirtualAddress - header->PointerToRawData);
    pExportDir = (PIMAGE_EXPORT_DIRECTORY)GetPtrFromRVA(exportsStartRVA, pNTHeader, pImageBase);
    
    
    pExportDir =(PIMAGE_EXPORT_DIRECTORY) (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    
    if (pExportDir == 0)
    {
        MessageBox(NULL,"Error in GetProcAddressDirectly()",0,0);
        return 0;
    }
    
    pExportDir =(PIMAGE_EXPORT_DIRECTORY) ((DWORD)pExportDir + (DWORD)dosHeader);
    lpNameOrdinals =(PWORD)((DWORD)pExportDir->AddressOfNameOrdinals + (DWORD)dosHeader);
    lpName =(LPDWORD) (pExportDir->AddressOfNames + (DWORD)dosHeader);
    lpFunctions =(LPDWORD) (pExportDir->AddressOfFunctions + (DWORD)dosHeader);
    lpFuncName = FuncName;
    
    if(HIWORD(lpFuncName)!=0 )
    {
        for( i = 0;i<=pExportDir->NumberOfFunctions - 1;i++)
        {
            DWORD entryPointRVA = *lpFunctions;
            
            if ( entryPointRVA == 0 ) continue; // Skip over gaps in exported function
            
            for( j = 0;j<=pExportDir->NumberOfNames-1;j++)
            {
                if( lpNameOrdinals[j] == i)
                {
                    lpExpFuncName = (char *) (lpName[j] + (DWORD)dosHeader);
                    if(strcmp((char *)lpExpFuncName,(char *)FuncName)==0)
                        return (DWORD) (lpFunctions[i] + (DWORD)dosHeader);
                }
            }
        }
    }
    else
    {
        for (i = 0 ;i<=pExportDir->NumberOfFunctions - 1;i++)
        {
            if (lpFuncName == (char *)(pExportDir->Base + i))
            {
                if (lpFunctions[i]) return (unsigned long) (lpFunctions[i] + dosHeader);
            }
        }
    }
    return 0;
}
 
DWORD LoadPbDllFromMemory(LPVOID lpRawDll, LPVOID lpImageDll)
{
    SYSTEM_INFO sSysInfo;
    PIMAGE_DOS_HEADER dosHeader;
    PIMAGE_NT_HEADERS pNTHeader;
    PIMAGE_SECTION_HEADER section;
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
    PIMAGE_IMPORT_BY_NAME pOrdinalName;
    PIMAGE_BASE_RELOCATION baseReloc;
    PDWORD lpLink;
    unsigned char Protection[4096];
    HINSTANCE hDll;
    WORD i;
    DWORD ImagePages,fOldProtect,j,MaxLen,HdrLen,Addr1,Addr2,Pg,Pg1,Pg2;
    char * sDllName;
    
    if(NULL == lpRawDll) return 1 ;
    
    dosHeader = (PIMAGE_DOS_HEADER)lpRawDll;
    
    // Is this the MZ header?
    if ((TRUE == IsBadReadPtr(dosHeader,sizeof (IMAGE_DOS_HEADER))) || (IMAGE_DOS_SIGNATURE != dosHeader->e_magic)) 
        return 2;
    
    // Get the PE header.
    pNTHeader = MakePtr(PIMAGE_NT_HEADERS,dosHeader,dosHeader->e_lfanew);
    
    // Is this a real PE image?
    if((TRUE == IsBadReadPtr(pNTHeader,sizeof ( IMAGE_NT_HEADERS))) || ( IMAGE_NT_SIGNATURE != pNTHeader->Signature))
        return 3 ;
    
    if(( pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(pNTHeader->OptionalHeader)) ||
        (pNTHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC))
        return 4;
    
    if (pNTHeader->FileHeader.NumberOfSections < 1) return 5;
    
    section = IMAGE_FIRST_SECTION( pNTHeader );
    int HeaderSize = sizeof(IMAGE_SECTION_HEADER);
    
    // 节头长度
    HdrLen = (DWORD)section - (DWORD)dosHeader + HeaderSize * pNTHeader->FileHeader.NumberOfSections;
    
    // 找出最大的节的长度,此节一般是代码所在的节(.text 节)
    MaxLen = HdrLen;
    int ii=0;
    
    for (i = 0;i<(DWORD)pNTHeader->FileHeader.NumberOfSections;i++)// find MaxLen
    {
        if(MaxLen < section[i].VirtualAddress + section[i].SizeOfRawData)
        {
            MaxLen = section[i].VirtualAddress + section[i].SizeOfRawData;
        }
        if(strcmp((const char *)section[i].Name,".rsrc") == 0) ii=i;
    }
    
    GetSystemInfo(&sSysInfo);
    ImagePages = MaxLen / sSysInfo.dwPageSize;
    if (MaxLen % sSysInfo.dwPageSize) ImagePages++;
    
    // 分配所需的内存
    DWORD NeededMemory = ImagePages * sSysInfo.dwPageSize;
    lpImageDll = VirtualAlloc(NULL, NeededMemory, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    if (lpImageDll == NULL) return 6; // 分配内存失败
    
    MoveMemory( lpImageDll, lpRawDll, HdrLen ); // 复制节头
    
    DWORD OrgAddr = 0;
    DWORD NewAddr = 0;
    DWORD Size = 0;
    
    // 复制 .text 节数据
    for (i = 0;i<pNTHeader->FileHeader.NumberOfSections;i++)
    {
        OrgAddr = (DWORD)lpImageDll + (DWORD)section[i].VirtualAddress;
        NewAddr = (DWORD)lpRawDll + (DWORD)section[i].PointerToRawData;
        Size = (DWORD)section[i].SizeOfRawData;
        MoveMemory((void *)OrgAddr, (void *)NewAddr, Size );
    }
    dosHeader = (PIMAGE_DOS_HEADER) lpImageDll; // Switch to new image
    pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)dosHeader + dosHeader->e_lfanew);
    section = (PIMAGE_SECTION_HEADER) ((DWORD)pNTHeader + sizeof(IMAGE_NT_HEADERS));
    pImageBase = (PBYTE)dosHeader;
    
    if((ii!=0) && (IsNT()==TRUE))
    {
        section[ii].VirtualAddress = section[ii].VirtualAddress + (DWORD)lpRawDll;
        section[ii].PointerToRawData = section[ii].PointerToRawData + (DWORD)lpRawDll;
    }
    
    DWORD importsStartRVA;
    
    // Look up where the imports section is (normally in the .idata section)
    // but not necessarily so. Therefore, grab the RVA from the data dir.
    importsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_IMPORT);
    if ( !importsStartRVA ) 
    {
        VirtualFree(dosHeader,0, MEM_RELEASE);
        return 7;
    }
    
    pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    
    if(pImportDesc!= 0)
        pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD)pImportDesc + (DWORD)dosHeader);
    else 
    {
        VirtualFree(dosHeader,0, MEM_RELEASE);
        return 8;
    }
    
    while (1) // 处理各入口表中的 DLL
    {
        // 检查是否遇到了空的 IMAGE_IMPORT_DESCRIPTOR
        if ((pImportDesc->TimeDateStamp==0 ) && (pImportDesc->Name==0)) break;
        
        // 从磁盘载入必须的 Dll, 注意,载入的 DLL 是合并的 DLL 的入口表中的 DLL, 不是合并到 EXE 中的 DLL
        sDllName = (char *) (pImportDesc->Name + (DWORD)pImageBase);
        hDll = GetModuleHandle(sDllName);
        
        if (hDll == 0 ) hDll = LoadLibrary(sDllName);
        
        if (hDll == 0 )
        {
            MessageBox(NULL, "Can't find required Dll","Error in LoadPbDllFromMemory()",0);
            VirtualFree(dosHeader,0, MEM_RELEASE);
            return 9;
        }
        
        DWORD *lpFuncNameRef = (DWORD *) (pImportDesc->OriginalFirstThunk + (DWORD)dosHeader);
        DWORD *lpFuncAddr = (DWORD *) (pImportDesc->FirstThunk + (DWORD)dosHeader);
        
        while( *lpFuncNameRef != 0)
        {
            pOrdinalName = (PIMAGE_IMPORT_BY_NAME) (*lpFuncNameRef + (DWORD)dosHeader);
            DWORD pIMAGE_ORDINAL_FLAG = 0x80000000;
            
            if (*lpFuncNameRef & pIMAGE_ORDINAL_FLAG)
                *lpFuncAddr = (DWORD) GetProcAddress(hDll, (const char *)(*lpFuncNameRef & 0xFFFF));
            else
                *lpFuncAddr = (DWORD) GetProcAddress(hDll, (const char *)pOrdinalName->Name);
            
            if (lpFuncAddr == 0) 
            {
                VirtualFree(dosHeader,0, MEM_RELEASE);
                return 10;// Can't GetProcAddress
            }
            
            //================================
            lpFuncAddr++;
            lpFuncNameRef++;
        }
        pImportDesc++;
    }
    
    DWORD TpOffset;
    baseReloc = (PIMAGE_BASE_RELOCATION) ((DWORD) pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
    
    //int num=0;
    if (baseReloc !=0)
    {
        baseReloc = (PIMAGE_BASE_RELOCATION) ((DWORD)baseReloc + (DWORD)dosHeader);
        while(baseReloc->VirtualAddress != 0)
        {
            PWORD lpTypeOffset = (PWORD) ((DWORD)baseReloc + sizeof(IMAGE_BASE_RELOCATION));
            while (lpTypeOffset < (PWORD)((DWORD)baseReloc + (DWORD)baseReloc->SizeOfBlock))
            {
                TpOffset = *lpTypeOffset & 0xF000;
                if(TpOffset == 0x3000)
                {
                    lpLink = (PDWORD) ((DWORD)dosHeader + baseReloc->VirtualAddress + (*lpTypeOffset & 0xFFF));
                    *lpLink = (DWORD)dosHeader+ (*lpLink) -pNTHeader->OptionalHeader.ImageBase;
                }
                else
                {
                    if (TpOffset != 0) 
                    {
                        VirtualFree(dosHeader,0, MEM_RELEASE);
                        return 10;
                    }
                }
                lpTypeOffset++;
            }
            baseReloc = (PIMAGE_BASE_RELOCATION) ((DWORD)baseReloc + (DWORD)baseReloc->SizeOfBlock);
        }
    }
    
    // 取得原始的内存状态
    memset(Protection,0,4096);
    for (i = 0;i<=pNTHeader->FileHeader.NumberOfSections;i++)
    {
        if (i == pNTHeader->FileHeader.NumberOfSections)
        {
            Addr1 = 0;
            Addr2 = HdrLen;
            j = 0x60000000;
        }
        else
        {
            Addr1 = section[i].VirtualAddress;
            Addr2 = section[i].SizeOfRawData;
            j = section[i].Characteristics;
        }
        Addr2 += Addr1 - 1;
        
        Pg1 = Addr1 / sSysInfo.dwPageSize;
        Pg2 = Addr2 / sSysInfo.dwPageSize;
        for(Pg = Pg1 ;Pg<=Pg2;Pg++)
        {
            if (j & 0x20000000) Protection[Pg] |= 1; // Execute
            if (j & 0x40000000) Protection[Pg] |= 2; // Read
            if (j & 0x80000000) Protection[Pg] |= 4; // Write
        }
    }
    
    // 恢复原始的内存状态
    Addr1 = (DWORD)dosHeader;
    for (Pg = 0 ;Pg<= ImagePages;Pg++)
    {
        switch(Protection[Pg])
        {
        case 2: 
            fOldProtect = PAGE_READONLY;
            break;
        case 3: 
            fOldProtect = PAGE_EXECUTE_READ;
            break;
        case 6: 
            fOldProtect = PAGE_READWRITE;
            break;
        default: 
            fOldProtect = PAGE_EXECUTE_READWRITE; // Ignore strange combinations
            break;
        }
        //================================
        
        if (fOldProtect !=PAGE_EXECUTE_READWRITE)
        {
            if (VirtualProtect((void *)Addr1, sSysInfo.dwPageSize, fOldProtect, &fOldProtect) == 0)
            {
                VirtualFree(dosHeader,0, MEM_RELEASE);
                return 11;
            }
        }
        Addr1 += sSysInfo.dwPageSize;
    }
    
    EntryPoint = (LPENTRYPOINT) ((DWORD)pNTHeader->OptionalHeader.AddressOfEntryPoint + (DWORD)dosHeader);
    LPVOID lpReserved = 0;
    EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_ATTACH, lpReserved);
    lpImageDll2=lpImageDll;
    return 0;
}
 
DWORD UnloadPbDllFromMemory(PIMAGE_DOS_HEADER dosHeader)
{
    PIMAGE_NT_HEADERS pNTHeader;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + (DWORD)dosHeader->e_lfanew);
    EntryPoint = (LPENTRYPOINT)(pNTHeader->OptionalHeader.AddressOfEntryPoint + (DWORD)dosHeader);
    EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_DETACH, 0);
    return VirtualFree(dosHeader, 0, MEM_RELEASE);
}
 
BOOL IsNT()
{
    DWORD dwWinVer;
    dwWinVer = GetVersion();
    dwWinVer = dwWinVer >> 31;
    return (dwWinVer == 0 ? TRUE : FALSE);
}
近期评论