// 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);
}
近期评论