合并DLLWord下载.docx

上传人:b****6 文档编号:18076190 上传时间:2022-12-13 格式:DOCX 页数:15 大小:25.67KB
下载 相关 举报
合并DLLWord下载.docx_第1页
第1页 / 共15页
合并DLLWord下载.docx_第2页
第2页 / 共15页
合并DLLWord下载.docx_第3页
第3页 / 共15页
合并DLLWord下载.docx_第4页
第4页 / 共15页
合并DLLWord下载.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

合并DLLWord下载.docx

《合并DLLWord下载.docx》由会员分享,可在线阅读,更多相关《合并DLLWord下载.docx(15页珍藏版)》请在冰豆网上搜索。

合并DLLWord下载.docx

程序实现。

首先,把要合并的DLL作为资源加入到项目的资源文件中,然后在程序运行时,从资源中载入该资源,以得到该DLL在内存中的位置:

LPVOIDsRawDll;

//资源文件在内存中的地址

HRSRChRes;

HMODULEhLibrary;

HGLOBALhResourceLoaded;

charlib_name[MAX_PATH];

GetModuleFileName(hInstance,lib_name,MAX_PATH);

//得到运行程序的名字

hLibrary=LoadLibrary(lib_name);

//就象载入一个DLL一样载入运行程序到内存中

if(NULL!

=hLibrary)

{

//得到指定的资源文件在内存中的位置

hRes=FindResource(hLibrary,MAKEINTRESOURCE(IDR_DATA1),RT_RCDATA);

if(NULL!

=hRes)

{

//将资源文件载入内存

hResourceLoaded=LoadResource(hLibrary,hRes);

if(NULL!

=hResourceLoaded)&

nbsp;

{

//得到资源文件大小

SizeofResource(hLibrary,hRes);

//锁定资源以得到它在内存中的地址

sRawDll=(LPVOID)LockResource(hResourceLoaded);

}

}

elsereturn1;

FreeLibrary(hLibrary);

}

elsereturn1;

然后,从资源中载入DLL到内存函数LoadPbDllFromMemory将载入DLL到内存中,该函数有两个参数,第一个参数是指向DLL资源在内存中的地址的指针,也就是前面代码中的LockResource函数的返回值。

第二个参数是一个空的指针,如果函数LoadPbDllFromMemory运行成功,该指针将指向重新组合后的内存中的DLL的起始地址。

该函数还有一个功能就是如果运行成功,它将手动地用DLL_PROCESS_ATTACH参数调用DLL的入口函数DllMain来初始化该DLL。

除此之外,它还会手动地载入合并的DLL的入口表中导入的DLL并调整它们在内存中的相对地址。

以下是该函数代码:

DWORDLoadPbDllFromMemory(LPVOIDlpRawDll,LPVOIDlpImageDll)

SYSTEM_INFOsSysInfo;

PIMAGE_DOS_HEADERdosHeader;

PIMAGE_NT_HEADERSpNTHeader;

PIMAGE_SECTION_HEADERsection;

PIMAGE_IMPORT_DESCRIPTORpImportDesc;

PIMAGE_IMPORT_BY_NAMEpOrdinalName;

PIMAGE_BASE_RELOCATIONbaseReloc;

PDWORDlpLink;

unsignedcharProtection[4096];

HINSTANCEhDll;

WORDi;

DWORDImagePages,fOldProtect,j,MaxLen,HdrLen,Addr1,Addr2,Pg,Pg1,Pg2;

char*sDllName;

if(NULL==lpRawDll)return1;

dosHeader=(PIMAGE_DOS_HEADER)lpRawDll;

//IsthistheMZheader?

if((TRUE==IsBadReadPtr(dosHeader,sizeof(IMAGE_DOS_HEADER)))||

(IMAGE_DOS_SIGNATURE!

=dosHeader->

e_magic))&

return2;

//GetthePEheader.

pNTHeader=MakePtr(PIMAGE_NT_HEADERS,dosHeader,dosHeader->

e_lfanew);

//IsthisarealPEimage?

if((TRUE==IsBadReadPtr(pNTHeader,sizeof(IMAGE_NT_HEADERS)))||

(IMAGE_NT_SIGNATURE!

=pNTHeader->

Signature))

return3;

if((pNTHeader->

FileHeader.SizeOfOptionalHeader!

=

sizeof(pNTHeader->

OptionalHeader))||

(pNTHeader->

OptionalHeader.Magic!

=IMAGE_NT_OPTIONAL_HDR32_MAGIC))

return4;

if(pNTHeader->

FileHeader.NumberOfSections<

1)return5;

section=IMAGE_FIRST_SECTION(pNTHeader);

intHeaderSize=sizeof(IMAGE_SECTION_HEADER);

//节头长度

HdrLen=(DWORD)section-(DWORD)dosHeader+

HeaderSize*pNTHeader->

FileHeader.NumberOfSections;

//找出最大的节的长度,此节一般是代码所在的节(.text节)

MaxLen=HdrLen;

intii=0;

for(i=0;

i<

(DWORD)pNTHeader->

i++)//findMaxLen

if(MaxLen<

section[i].VirtualAddress+section[i].SizeOfRawData)

MaxLen=section[i].VirtualAddress+section[i].SizeOfRawData;

if(strcmp((constchar*)section[i].Name,"

.rsrc"

)==0)ii=i;

GetSystemInfo(&

sSysInfo);

ImagePages=MaxLen/sSysInfo.dwPageSize;

if(MaxLen%sSysInfo.dwPageSize)ImagePages++;

//分配所需的内存

DWORDNeededMemory=ImagePages*sSysInfo.dwPageSize;

lpImageDll=VirtualAlloc(NULL,NeededMemory,MEM_COMMIT,PAGE_EXECUTE_READWRITE);

if(lpImageDll==NULL)return6;

//分配内存失败

MoveMemory(lpImageDll,lpRawDll,HdrLen);

//复制节头

DWORDOrgAddr=0;

DWORDNewAddr=0;

DWORDSize=0;

//复制.text节数据

iFileHeader.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;

//Switchtonewimage

pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)dosHeader+dosHeader->

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;

DWORDimportsStartRVA;

//Lookupwheretheimportssectionis(normallyinthe.idatasection)

//butnotnecessarilyso.Therefore,grabtheRVAfromthedatadir.

importsStartRVA=GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_IMPORT);

if(!

importsStartRVA)&

VirtualFree(dosHeader,0,MEM_RELEASE);

return7;

pImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)pNTHeader->

OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

if(pImportDesc!

=0)

pImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDesc+(DWORD)dosHeader);

else&

return8;

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'

'

tfindrequiredDll"

"

ErrorinLoadPbDllFromMemory()"

0);

VirtualFree(dosHeader,0,MEM_RELEASE);

return9;

DWORD*lpFuncNameRef=(DWORD*)(pImportDesc->

OriginalFirstThunk+

(DWORD)dosHeader);

DWORD*lpFuncAddr=(DWORD*)(pImportDesc->

FirstThunk+

while(*lpFuncNameRef!

pOrdinalName=(PIMAGE_IMPORT_BY_NAME)(*lpFuncNameRef+

(DWORD)dosHeader);

DWORDpIMAGE_ORDINAL_FLAG=0x80000000;

if(*lpFuncNameRef&

pIMAGE_ORDINAL_FLAG)

*lpFuncAddr=(DWORD)GetProcAddress(hDll,

(constchar*)(*lpFuncNameRef&

0xFFFF));

else

(constchar*)pOrdinalName->

Name);

if(lpFuncAddr==0)&

{

VirtualFree(dosHeader,0,MEM_RELEASE);

return10;

//Can'

tGetProcAddress

}

lpFuncAddr++;

lpFuncNameRef++;

pImportDesc++;

DWORDTpOffset;

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!

PWORDlpTypeOffset=(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);

return10;

}

lpTypeOffset++;

baseReloc=(PIMAGE_BASE_RELOCATION)((DWORD)baseReloc+

(DWORD)baseReloc->

SizeOfBlock);

//取得原始的内存状态

memset(Protection,0,4096);

=pNTHeader->

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

0x40000000)Protection[Pg]|=2;

//Read

0x80000000)Protection[Pg]|=4;

//Write

//恢复原始的内存状态

Addr1=(DWORD)dosHeader;

for(Pg=0;

=ImagePages;

switch(Protection[Pg])

case2:

fOldProtect=PAGE_READONLY;

break;

case3:

fOldProtect=PAGE_EXECUTE_READ;

case6:

fOldProtect=PAGE_READWRITE;

default:

//Ignorestrangecombinations

fOldProtect=PAGE_EXECUTE_READWRITE;

if(fOldProtect!

=PAGE_EXECUTE_READWRITE)

if(VirtualProtect((void*)Addr1,

sSysInfo.dwPageSize,

fOldProtect,

&

fOldProtect)==0)

return11;

Addr1+=sSysInfo.dwPageSize;

EntryPoint=(LPENTRYPOINT)((DWORD)pNTHeader->

OptionalHeader.AddressOfEntryPoint+

(DWORD)dosHeader);

LPVOIDlpReserved=0;

EntryPoint((HINSTANCE)dosHeader,DLL_PROCESS_ATTACH,lpReserved);

lpImageDll2=lpImageDll;

return0;

一但DLL被正确地载入到内存中,我们就可以通过自定义函数GetProcAddressDirectly来获取某函数在内存中的地址,并根据该地址来调用该函数,该函数也有两个参数,第一个参数是指向载入到内存中的DLL的起始地址的指针,第二个是要调用的函数的函数名。

以下是GetProcAddressDirectly函数代码:

DWORDGetProcAddressDirectly(PIMAGE_DOS_HEADERdosHeader,char*FuncName)

{

PIMAGE_NT_HEADERSpNTHead

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1