合并 DLL
2006-07-20 11:39:58 来源:WEB开发网核心提示: DWORD LoadPbDllFromMemory(LPVOID lpRawDll, LPVOID lpImageDll){SYSTEM_INFO sSysInfo;PIMAGE_DOS_HEADER dosHeader;PIMAGE_NT_HEADERS pNTHeader;PIMAGE
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 );
}
// 把指针指向新的 DLL 映像
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);
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:
// Ignore strange combinations
fOldProtect = PAGE_EXECUTE_READWRITE;
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;
}
一但 DLL 被正确地载入到内存中,我们就可以通过自定义函数 GetProcAddressDirectly 来获取某函数在内存中的地址,并根据该地址来调用该函数,该函数也有两个参数,第一个参数是指向载入到内存中的 DLL 的起始地址的指针,第二个是要调用的函数的函数名。以下是 GetProcAddressDirectly 函数代码:
- ››合并重载和停止 - 节约Firefox工具栏的空间
- ››DLL(Dynamic Link Libraries)专题
- ››合并聊天窗口 阿里旺旺 2008下载
- ››合并两个带头结点的有序循环链表合并为一个带头结...
- ››DLL文件基本原理及修改方法和通过改DLL来美化系统...
- ››DLL头文件的格式和应用
- ››DLL初学者指南(非MFC)
- ››DLL(Dynamic Link Libraries)全面剖析
- ››合并 DLL
- ››DLL的远程注入技术
- ››DLL(Dynamic Link Libraries)全面剖析(2)
- ››DLL(Dynamic Link Libraries)全面剖析(3)
更多精彩
赞助商链接