打造DLL内存加载引擎学习笔记
来源:互联网 发布:七了个三淘宝 编辑:程序博客网 时间:2024/06/08 19:58
原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题
首先看下我们内存加载引擎的流程。
1. 申请一段大小为dll映射内存后的映像大小的内存空间。
2. 移动各个区段的数据到申请的内存。
2. 修复引入表结构的地址表。
4. 通过重定位结构修复需要重定位的地址。
5. 调用DllMain入口点
流程解析:
- pe结构中nt header结构当中的ImageSize存放的是我们整个文件映射到内存后的映像大小,这个大小是经过对齐的, 读取这个成员值,来申请内存空间,内存空间的属性为“可读可写可执行”,VirtualAlloc来申请。
- 读取各个节表结构的各区段的物理偏移和物理大小,然后移动各区段数据到节表结构对应的的内存空间中(注意:实际上就是将节表结构的VirtualAddress + 申请的内存空间地址),移动的大小则为我们物理大小.
- 修复导入表结构的地址表。其实就是修复导入表结构FirstThunk指向的地址表,因为我们的程序api调用的也是FirstThunk所指向的地址表成员。程序在未加载之前FirstThunk指向的地址表成员都指向的是一个IMAGE_IMPORT_BY_NAME结构,当加载后这个地址表的成员都被替换成相应的函数地址。所以处理导入表过程函数可以直接读取FirstThunk来取得相应的引入函数名称及序号等,没必要读取OriginalFirstThunk来读取.
- 通过重定位结构修复需要重定位的地址,连接器在链接可执行程序的时候会将需要重定位的偏移存放到一个结构中,这样pe loader读取重定位结构就可以定位到需要重定位的地址。
- 压入参数, 取得入口点rva+申请目标空间地址然后call调用即可
代码:
.386.model flat, stdcalloption casemap:noneinclude windows.incinclude user32.incinclude kernel32.incincludelib user32.libincludelib kernel32.libpushad_eax equ 1ch.dataszFileNamedb 'test.dll', 0hFiledd 0hMapdd 0.codeEntry:invoke CreateFile, addr szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, \OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULLcmp eax, INVALID_HANDLE_VALUEje _Retmov hFile, eaxinvoke CreateFileMapping, eax, NULL, PAGE_READONLY, 0, 0, NULL.if eax == NULLinvoke CloseHandle, hFilejmp _Ret.endifmov hMap, eaxinvoke MapViewOfFile, eax, FILE_MAP_READ, 0, 0, 0.if eax == NULLinvoke CloseHandle, hMapinvoke CloseHandle, hFilejmp _Ret.endifpush eaxcall DllMemLoad_Ret:ret;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; dll内存加载函数; Arguments:; [esp]- return address; [esp + 4 * 1]- pDllMemory; Return Value:; eax = ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DllMemLoad:pushadmov ebx, [esp + 4 * 8 + 4]; ebx = pDllMemorycmp word ptr [ebx], 'ZM'jnz _RetFalsepush ebxmov edi, ebx; edi = Dos Headeradd edi, [edi + 3ch]; edi = NT Headercmp word ptr [edi], 'EP'jnz _RetFalseinvoke VirtualAlloc, 0, [edi + 50h], MEM_COMMIT, PAGE_EXECUTE_READWRITEtest eax, eaxje _RetFalsexchg eax, ebp; ebp = lpMemroylea esi, [edi + 14h]xor eax, eaxlodsw; eax = IMAGE_OPTIONAL_HEADER sizelea esi, [esi + 2 + eax]; esi -> section table;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 移动节到分配的内存;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>movzx ecx, word ptr [edi + 06h]; ecx = section num_MoveSection:push ecxmov edx, [esi + 14h]; edx = physical offsetadd edx, [esp + 4]; [esp + 4] = pDllMemory, edx = source section vamov eax, [esi + 0ch]; eax = VirtualAddressadd eax, ebp; ebp = lpMemory, eax = dest section vainvoke RtlMoveMemory, eax, edx, dword ptr [esi + 10h]add esi, 28h; esi -> next sectionpop ecxloop _MoveSection;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 处理导入段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>mov edx, ebp; edx = lpMemorymov eax, edi; eax = NT Headercall InitImport;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 处理重定位;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>mov edx, ebp; edx = lpMemorymov eax, edi; eax = NT Headercall InitFixupsmov edx, [edi + 28h]; edx = EntryPoint RVAadd edx, ebp; ebp = lpMemory, edx = EntryPoint VA;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; DllMain;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>push 0push 1push ebpcall edx; call DllMain_RetTrue:pop ecxpush ebppop dword ptr [esp + pushad_eax]; eax = lpMemorypopadret 4_RetFalse:popadxor eax, eaxret 4;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 初始化导入表函数; Arguments:; [esp]- return address; eax- NT Header; edx- Alloc mem base; Return Value:; eax = true or eax = false;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>InitImport:pushadpush edx; [esp] = alloc mem basemov edi, [eax + 80h]; edi = Import RVAadd edi, edx; edi = Import VA_NextImport:cmp dword ptr [edi + 0ch], 0; [edi + 0ch] = Namejz _II_RetTruemov edx, [edi + 0ch]; edx = Nameadd edx, [esp]; edx = import dll name stringinvoke LoadLibrary, edxtest eax, eaxjz _II_RetFalsexchg eax, ebx; ebx = load dll basemov esi, [edi + 10h]add esi, [esp]; esi = FirstThunkcld_NextIat:lodsdtest eax, eaxje _Nextbt eax, 31; eax 31-bit copy to CFjnc _IatName;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Iat ordinal;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>movzx edx, ax; edx = ordinalinvoke GetProcAddress, ebx, edx; ebx = load dll basemov [esi - 4], eaxjmp _NextIat;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Iat Name;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>_IatName:add eax, [esp]; eax = IMAGE_IMPORT_BY_NAMElea edx, [eax + 2]; edx -> api nameinvoke GetProcAddress, ebx, edxmov [esi - 4], eaxjmp _NextIat_Next:add edi, 14h; edi -> next Iat structjmp _NextImport_II_RetTrue:pop edxpopadxor eax, eaxinc eaxret_II_RetFalse:pop edxpopadxor eax, eaxret;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 初始化并修订重定位地址; Arguments:; [esp]- return address;eax - NT Header;edx- alloc mem base; Return Value:; eax - true or eax - false;;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>InitFixups:pushadmov esi, [eax + 0a0h]; esi = reloc rvatest esi, esije _IF_RetFalse; No reloccldadd esi, edx; esi = 重定位表的地址push [eax + 0a4h]; [esp] = 重定位表长度add [esp], esi; [esp] = 重定位表结束地址mov edi, edx; edi = alloc mem basemov ebp, edx; ebp = alloc mem basesub ebp, [eax + 34h]; ebp等于分配的地址与建议装载地址的差_NextFixups:cmp [esp], esi; 比较是否到了重定位表结束位置je _IF_RetTruelodsdxchg eax, ebx; ebx = 当前页起始地址RVAlodsdxchg eax, ecx; ecx = 当前重定位块的大小sub ecx, 8shr ecx, 1; ecx = 重定位项的数量_NextOffet:xor eax, eaxlodsw; eax = 读取重定位项bt eax, 13; 将eax的第13位复制到CFjnc _NextLoopand ax, 0fffh; 保留低12位add eax, ebxadd dword ptr [edi + eax], ebp; 修正,加上差值_NextLoop:loop _NextOffetjmp _NextFixups_IF_RetTrue:pop edxpopadxor eax, eaxinc eaxret_IF_RetFalse:popadxor eax, eaxretend Entry
- 打造DLL内存加载引擎学习笔记
- unity加载dll库的学习笔记
- 内存加载DLL
- DLL内存加载
- 从内存中加载DLL
- 动态加载内存中DLL
- 从内存中加载DLL
- 从内存中加载DLL
- 另类DLL加载方法(解析PE打造自己的GetProcAddress)
- HGE引擎学习笔记
- Nd2d引擎学习笔记
- [javase学习笔记]-4.3 函数的内存加载过程
- [javase学习笔记]-7.4 构造函数的内存加载
- [javase学习笔记]-8.6 静态的内存加载
- [转载]a从内存中加载DLL
- 从内存中加载DLL (修正版)
- 一个内存加载dll的代码
- 从内存中加载DLL DELPHI版
- Hadoop MapReduce之MapTask任务执行(二)
- 关注的博客
- eclipse最常用快捷键 调试技巧
- Android平台aac谷歌软解框架和流程、解码库学习
- [LeetCode]Container With Most Water
- 打造DLL内存加载引擎学习笔记
- extjs 导出Excel 解决方法 extjs export excel 信息 消息
- Communications link failure,The last packet successfully received from the server was *** millisecon
- 多个引用类型的变量“引用”同一个对象意味着什么
- 求该日为本年第几天(新的简便的)
- Unity3D的脚本-script入门
- MII
- css 中字体大小
- C++运算符重载(一)——必要性及重载原则