纠结的LoadLibraryA

lyramilk 2011-01-07 03:30:21
加载msvcr90.dll需要读取winsxs里面的东西,我不知道怎么去获得路径。。
读取kernel32.dll失败。。

求助。。。。。


#include "lyPELoader.h"
#define SIZE_OF_NT_SIGNATURE sizeof(DWORD)

HINSTANCE lyLoadLibraryA(char* filename){
FILE* fp;
char* dllbuff = NULL;
struct stat stbuf = {0};
unsigned int fd;
HINSTANCE hdll;
fp = fopen(filename,"rb+");
if(fp == NULL){
lyDbgPrintf("读取文件%s失败\n",filename);
return NULL;
}
fd = _fileno(fp);
fstat(fd,&stbuf);
if(stbuf.st_size > 1024*1024*100){
lyDbgPrintf("文件大小异常%d\n",(int)stbuf.st_size);
return NULL;
}
dllbuff = (char*)malloc(stbuf.st_size);
fread(dllbuff,1,stbuf.st_size,fp);
hdll = lyLoadLibraryFromMemory(dllbuff,stbuf.st_size);
free(dllbuff);
fclose(fp);
return hdll;
}

HINSTANCE lyLoadLibraryFromMemory(char* dllbuff,_off_t buffsize){
PIMAGE_DOS_HEADER doshdr = (PIMAGE_DOS_HEADER)dllbuff;
PIMAGE_NT_HEADERS nthdr;
PIMAGE_FILE_HEADER filehdr;
PIMAGE_OPTIONAL_HEADER opthdr;
PIMAGE_SECTION_HEADER sechdr;
int imagesize;
char *imagebase;
int sectioncount;
int headsize;
int index;
int falignchk;
int salignchk;

/*初始化文件头*/
nthdr = (PIMAGE_NT_HEADERS)((char*)doshdr + doshdr->e_lfanew);
filehdr = (PIMAGE_FILE_HEADER)((char*)nthdr + SIZE_OF_NT_SIGNATURE);
opthdr = (PIMAGE_OPTIONAL_HEADER)((char*)filehdr + sizeof(IMAGE_FILE_HEADER));
sechdr = (PIMAGE_SECTION_HEADER)((char*)opthdr + sizeof (IMAGE_OPTIONAL_HEADER));

/*检查有效性*/
if(IMAGE_DOS_SIGNATURE != *(unsigned short*)doshdr){
lyDbgPrintf("DOS标志错误\n");
return NULL;
}

/*初始化变量*/
imagesize = nthdr->OptionalHeader.SizeOfImage;
imagebase = VirtualAlloc((char*)nthdr->OptionalHeader.ImageBase,imagesize,MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);

sectioncount = nthdr->FileHeader.NumberOfSections;
headsize = (int)sechdr + sizeof(PIMAGE_SECTION_HEADER) - (int)doshdr;
falignchk = nthdr->OptionalHeader.FileAlignment - 1;
salignchk = nthdr->OptionalHeader.SectionAlignment - 1;

if(NULL == imagebase){
imagebase = VirtualAlloc(NULL,imagesize,MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(NULL == imagebase){
lyDbgPrintf("申请内存失败\n");
return NULL;
}
}

/*加载PE头*/
memcpy(imagebase,doshdr,headsize);

/*加载各段*/
for(index = 0; index < sectioncount; index++, sechdr++){
if((sechdr->VirtualAddress & salignchk) || (sechdr->SizeOfRawData & falignchk)){
lyDbgPrintf("段检查错误\n");
free(imagebase);
return NULL;
}
memcpy(imagebase + sechdr->VirtualAddress, (char*)doshdr + sechdr->PointerToRawData, sechdr->SizeOfRawData);
}
/*加载导入表*/
if(nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size > 0){
PIMAGE_IMPORT_DESCRIPTOR impdsc = (IMAGE_IMPORT_DESCRIPTOR *)(imagebase + nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
/*加载各导入表*/
for(;impdsc->Name != 0;impdsc++){
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(imagebase + impdsc->FirstThunk);
char* filename = imagebase + impdsc->Name;
HINSTANCE expdll;
if(strnicmp(filename,"msvcr",5) == 0){
filename = "C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e\\msvcr90.dll";
printf("修正%s为%s\n",imagebase + impdsc->Name,filename);
}

expdll = LoadLibrary(filename);
/*expdll = lyLoadLibraryA(filename);*/
/*HINSTANCE expdll = lyLoadLibraryA(imagebase + impdsc->Name);*/

if(expdll == NULL){
lyDbgPrintf("依赖项%s加载失败\n",(char*)imagebase + impdsc->Name);
free(imagebase);
return NULL;
}
lyDbgPrintf("依赖项%s加载成功\n",(char*)imagebase + impdsc->Name);

/*加载一个导入表中的各函数*/
for(;thunk->u1.Ordinal != 0; thunk++){
FARPROC proc;

if(thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32){
/*proc = GetProcAddress(expdll, (char*)(thunk->u1.Ordinal & 0x0000ffff));*/
proc = lyGetProcAddressA(expdll, (char*)(thunk->u1.Ordinal & 0x0000ffff));
}else{
/*proc = GetProcAddress(expdll, (char*)((IMAGE_IMPORT_BY_NAME *)(imagebase + thunk->u1.Ordinal))->Name);*/
proc = lyGetProcAddressA(expdll, (char*)((IMAGE_IMPORT_BY_NAME *)(imagebase + thunk->u1.Ordinal))->Name);
}
if(proc == NULL){
lyDbgPrintf("函数导入错误\n");
free(imagebase);
return NULL;
}
thunk->u1.Ordinal = (int)proc;
}
/*FreeLibrary(expdll); 争议*/
}
}
/*加载重定位表*/
if(nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size > 0){
PIMAGE_BASE_RELOCATION rel = (PIMAGE_BASE_RELOCATION)(imagebase + nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
int reldiff = (int)imagebase - nthdr->OptionalHeader.ImageBase;
/*加载各重定位表*/
for(;rel->VirtualAddress != 0;){
char* relpagebase = imagebase + rel->VirtualAddress;
int relitemcount = (rel->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) >> 1;
short* relitem = (short*)(rel + sizeof(IMAGE_BASE_RELOCATION));
/*加载一个重定位表中的各项*/
for(index = 0;index < relitemcount;index++){
int offset = relitem[index] & 0xfff;
int type = relitem[index] >> 12;
switch(type){
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
break;
case IMAGE_REL_BASED_LOW:
break;
case IMAGE_REL_BASED_HIGHLOW:
*(int *)(relpagebase + offset) += reldiff;
break;
case IMAGE_REL_BASED_HIGHADJ:
break;
case IMAGE_REL_BASED_MIPS_JMPADDR:
break;
}
}
rel = (PIMAGE_BASE_RELOCATION)(relitem + relitemcount);
}
}
/*调用DLL入口函数*/{
typedef BOOL WINAPI (*DllMain)(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved);
DllMain mainproc = (DllMain)lyGetProcAddressA((HINSTANCE)imagebase,"DllMain");
if(mainproc){
if(mainproc((HINSTANCE)imagebase,DLL_PROCESS_ATTACH,0) == FALSE){
VirtualFree((char*)imagebase,0,MEM_RELEASE);
}
}
}

return (HINSTANCE)imagebase;
}

void lyFreeLibrary(HINSTANCE module){
typedef BOOL WINAPI (*DllMain)(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved);
DllMain mainproc = (DllMain)lyGetProcAddressA(module,"DllMain");
if(mainproc){
mainproc(module,DLL_PROCESS_DETACH,0);
}
VirtualFree((char*)module,0,MEM_RELEASE);

}

FARPROC lyGetProcAddressA(HINSTANCE module,char* procname){
PIMAGE_DOS_HEADER doshdr = (PIMAGE_DOS_HEADER)module;
PIMAGE_NT_HEADERS nthdr;
PIMAGE_FILE_HEADER filehdr;
PIMAGE_OPTIONAL_HEADER opthdr;
PIMAGE_SECTION_HEADER sechdr;
PIMAGE_SECTION_HEADER edatasec;
PIMAGE_EXPORT_DIRECTORY expdir;
char *imagebase = (char*)module;
int sectioncount;
int index;
int procnamelength = strlen(procname);

/*初始化文件头*/
nthdr = (PIMAGE_NT_HEADERS)((char*)doshdr + doshdr->e_lfanew);
filehdr = (PIMAGE_FILE_HEADER)((char*)nthdr + SIZE_OF_NT_SIGNATURE);
opthdr = (PIMAGE_OPTIONAL_HEADER)((char*)filehdr + sizeof(IMAGE_FILE_HEADER));
sechdr = (PIMAGE_SECTION_HEADER)((char*)opthdr + sizeof (IMAGE_OPTIONAL_HEADER));

/*检查有效性*/
if(IMAGE_DOS_SIGNATURE != *(unsigned short*)doshdr){
lyDbgPrintf("DOS标志错误\n");
return NULL;
}

/*初始化变量*/
sectioncount = nthdr->FileHeader.NumberOfSections;
procnamelength = strlen(procname);
for (index=0,edatasec = sechdr;index < sectioncount;index++,edatasec++){
if (!strcmp ((char*)sechdr->Name, ".edata")){
break;
}
}
expdir = (PIMAGE_EXPORT_DIRECTORY)(imagebase + nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

for(index=0;index < expdir->NumberOfFunctions;index++){
int function = *(int*)(imagebase + expdir->AddressOfFunctions + index*sizeof(void*));
char* name = imagebase + (int)*(char**)(imagebase + expdir->AddressOfNames + index*sizeof(void*));
/*short ordinal = *(short*)(imagebase + expdir->AddressOfNameOrdinals + index*sizeof(void*)); 函数序号,因为不需要所以省略了*/

if(strnicmp(name,procname,procnamelength) == 0){
return (FARPROC)(function + (int)imagebase);
}
}

lyDbgPrintf("未找到符号\n");
return NULL;
}

...全文
242 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
linxren 2011-01-07
  • 打赏
  • 举报
回复
C:\WINDOWS\WinSxS路径是固定的,只是下面的子文件夹而已。先调用LoadLibary,如果失败,再接着在这个路径下搜索.dll文件,找到的话继续LoadLibary,这样不行吗?
linxren 2011-01-07
  • 打赏
  • 举报
回复
C:\WINDOWS\WinSxS路径是固定的,执行下面的子文件夹而已。先调研LoadLibary,如果失败,再接着在这个路径下搜索.dll文件,找到的话继续LoadLibary,这样不行吗?
linxren 2011-01-07
  • 打赏
  • 举报
回复
应该是看明白楼主的问题了:
楼主是无法找到IMAGE_IMPORT_DESCRIPTOR.Name的Dll名字的路径吗
lyramilk 2011-01-07
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 mnbqwe1 的回复:]

函数是自己写的?
下断点调吧
[/Quote]
lyLoadLibraryFromMemory 一半是抄的。
lyramilk 2011-01-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 linxren 的回复:]

看起来像是你自己写的LoadLibary的函数,直接从文件读取,载入内存?
[/Quote]
是的,lyLoadLibraryFromMemory无法完全处理DLL间互相依赖的情况,查找DLL的时候因为winsxs而非常纠结。lyGetProcAddressA倒是没发现过什么问题。跟系统的LoadLibrary组合也没发现什么问题。
mnbqwe1 2011-01-07
  • 打赏
  • 举报
回复
函数是自己写的?
下断点调吧
linxren 2011-01-07
  • 打赏
  • 举报
回复
看起来像是你自己写的LoadLibary的函数,直接从文件读取,载入内存?
bluesky12312388 2011-01-07
  • 打赏
  • 举报
回复
什么系统?
看你的程序是否具有相应的权限?

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧