-
-
[原创]LoadLibrary C版本
-
发表于:
2009-3-8 17:05
14889
-
继续前边2贴,现把LOADLIBRARY也一并贴上。
HMODULE __stdcall MyLoadLibraryA(char *szDllName)
{
void *pFileAddr;//文件隐射基地址
void *pImageBase;//加载DLL的基地址,作为返回数
IMAGE_DOS_HEADER *pDosHead;
IMAGE_OPTIONAL_HEADER *pOPHead;
IMAGE_FILE_HEADER *pFileHead;
DWORD dwSecNum;
IMAGE_SECTION_HEADER *pSecInfo;
IMAGE_IMPORT_DESCRIPTOR *pIID;
LPTHREAD_START_ROUTINE OEP;
IMAGE_BASE_RELOCATION *pIBR;
DWORD dwDllRVA; //实际装载地址与建议装载地址差。
HANDLE hFile = ::CreateFile(szDllName,GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
AfxMessageBox("Can't open file");
return 0;
}
HANDLE hMaping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
pFileAddr = MapViewOfFile(hMaping,FILE_MAP_READ,0,0,0);
pDosHead = (IMAGE_DOS_HEADER*)pFileAddr;
pFileHead = (IMAGE_FILE_HEADER*)(pDosHead->e_lfanew+4 +(DWORD)pFileAddr);
pOPHead = (IMAGE_OPTIONAL_HEADER*)((DWORD)pFileHead +
sizeof(_IMAGE_FILE_HEADER));
//申请内存,建立DLL内存空间,并COPY DLL
pImageBase = VirtualAlloc(NULL,pOPHead->SizeOfImage,MEM_COMMIT
,PAGE_EXECUTE_READWRITE);
if (pImageBase == NULL)
{
AfxMessageBox("分配空间失败");
return 0;
}
dwDllRVA = (DWORD)pImageBase - pOPHead->ImageBase;
pSecInfo = (IMAGE_SECTION_HEADER*)((DWORD)pOPHead + pFileHead->SizeOfOptionalHeader) ;
dwSecNum = pFileHead->NumberOfSections;
//COPY文件头
DWORD dwFileSize = pOPHead->SizeOfHeaders;
memcpy(pImageBase,pFileAddr,dwFileSize);
//COPY区段
for (DWORD i = 0; i < dwSecNum; i++)
{
void *des,*sour;
des = (void*)(pSecInfo->VirtualAddress + (DWORD)pImageBase);
sour = (void*)(pSecInfo->PointerToRawData + (DWORD)pFileAddr);
memcpy(des,sour,pSecInfo->Misc.VirtualSize);
pSecInfo++;
}
OEP = (LPTHREAD_START_ROUTINE)(pOPHead->AddressOfEntryPoint +
(DWORD)pImageBase);
// 修正重定位表。
pIBR = (IMAGE_BASE_RELOCATION*)(pOPHead->DataDirectory[5].VirtualAddress + (DWORD)pImageBase);
while (pIBR->VirtualAddress)
{
WORD *pTypeOffset = (WORD*)((DWORD)pIBR+ 8);
for (i = 0; i < pIBR->SizeOfBlock - 8; i += 2)
{
//pTypeOffset[i] & 0Xf000 == 0x3000 结果不对,郁闷。
if (pTypeOffset[i] >>12 == 3)
{
DWORD nTmp =((DWORD) pTypeOffset[i]) & 0xfff;
DWORD *pReloc = (DWORD*)(nTmp +(DWORD) pImageBase + pIBR->VirtualAddress);
*pReloc = *pReloc + dwDllRVA;
}
}
pIBR = (IMAGE_BASE_RELOCATION*)(pIBR->SizeOfBlock + (DWORD)pIBR);
}
//填充IAT表
pIID = (IMAGE_IMPORT_DESCRIPTOR*)((pOPHead->DataDirectory[1].VirtualAddress)
+ (DWORD)pImageBase);
while (pIID->Name != 0)
{
char *pDllName;
char *pFacName;
HMODULE hDll;
IMAGE_THUNK_DATA32 *pIDT,*pIAT;
PIMAGE_IMPORT_BY_NAME *pImByName;
pDllName = (char*)((DWORD)(pIID->Name) + (DWORD)pImageBase);
hDll = LoadLibrary((LPCSTR)pDllName);
pIDT = (IMAGE_THUNK_DATA32*)(pIID->OriginalFirstThunk +
(DWORD)pImageBase);
pIAT = (IMAGE_THUNK_DATA32*)(pIID->FirstThunk + (DWORD)pImageBase);
while (*(DWORD*)pIDT != 0)
{
pImByName = (PIMAGE_IMPORT_BY_NAME*)((DWORD)(pIDT->u1.AddressOfData)
+ (DWORD)pImageBase);
pFacName =(char*)pImByName+2;
pIAT->u1.Function = (PDWORD)GetProcAddress(hDll,pFacName);
pIDT++ ;
}
pIID++;
}
//调用DLLMAIN
_asm
{
pushad;
push 0;
push DLL_PROCESS_ATTACH;
push pImageBase;
call OEP;
add esp,0x4; //DLLMAIN未平衡堆栈。
popad
}
return (HMODULE)pImageBase;
}
用此函数加载的DLL。有部分API会发生问题。比如:GetProcAddress,GetModulHandle。另外,本函数也没有考虑TLS的处理。等以后有时间在慢慢修补吧。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!