码迷,mamicode.com
首页 > 其他好文 > 详细

打造DLL内存加载引擎学习笔记

时间:2015-02-03 12:46:22      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:

原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题

 

首先看下我们内存加载引擎的流程。

  1. 申请一段大小为dll映射内存后的映像大小的内存空间。

  2. 移动各个区段的数据到申请的内存。

  2. 修复引入表结构的地址表。

  4. 通过重定位结构修复需要重定位的地址。

  5. 调用DllMain入口点

流程解析:

 

  1. pe结构中nt header结构当中的ImageSize存放的是我们整个文件映射到内存后的映像大小,这个大小是经过对齐的, 读取这个成员值,来申请内存空间,内存空间的属性为“可读可写可执行”,VirtualAlloc来申请。
  2. 读取各个节表结构的各区段的物理偏移和物理大小,然后移动各区段数据到节表结构对应的的内存空间中(注意:实际上就是将节表结构的VirtualAddress + 申请的内存空间地址),移动的大小则为我们物理大小.
  3. 修复导入表结构的地址表。其实就是修复导入表结构FirstThunk指向的地址表,因为我们的程序api调用的也是FirstThunk所指向的地址表成员。程序在未加载之前FirstThunk指向的地址表成员都指向的是一个IMAGE_IMPORT_BY_NAME结构,当加载后这个地址表的成员都被替换成相应的函数地址。所以处理导入表过程函数可以直接读取FirstThunk来取得相应的引入函数名称及序号等,没必要读取OriginalFirstThunk来读取.
  4. 通过重定位结构修复需要重定位的地址,连接器在链接可执行程序的时候会将需要重定位的偏移存放到一个结构中,这样pe loader读取重定位结构就可以定位到需要重定位的地址。
  5. 压入参数, 取得入口点rva+申请目标空间地址然后call调用即可
代码:
技术分享
 .386  
02.    .model flat, stdcall  
03.    option casemap:none  
04.      
05.include windows.inc  
06.include user32.inc  
07.include kernel32.inc  
08.includelib user32.lib  
09.includelib kernel32.lib  
10.  
11.pushad_eax equ 1ch  
12.  
13.    .data  
14.      
15.szFileName  db test.dll, 0  
16.hFile       dd 0  
17.hMap        dd 0  
18.      
19.    .code  
20.      
21.Entry:  
22.    invoke CreateFile, addr szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, \  
23.        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL  
24.    cmp eax, INVALID_HANDLE_VALUE  
25.    je _Ret  
26.    mov hFile, eax  
27.    invoke CreateFileMapping, eax, NULL, PAGE_READONLY, 0, 0, NULL  
28.    .if eax == NULL  
29.        invoke CloseHandle, hFile  
30.        jmp _Ret  
31.    .endif  
32.    mov hMap, eax  
33.    invoke MapViewOfFile, eax, FILE_MAP_READ, 0, 0, 0  
34.    .if eax == NULL  
35.        invoke CloseHandle, hMap  
36.        invoke CloseHandle, hFile  
37.        jmp _Ret  
38.    .endif  
39.    push eax  
40.    call DllMemLoad  
41.      
42._Ret:  
43.    ret  
44.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     
45.; dll内存加载函数  
46.; Arguments:  
47.;   [esp]           - return address  
48.;   [esp + 4 * 1]       - pDllMemory  
49.; Return Value:  
50.;   eax =   
51.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
52.DllMemLoad:  
53.    pushad  
54.    mov ebx, [esp + 4 * 8 + 4]          ; ebx = pDllMemory  
55.    cmp word ptr [ebx], ZM  
56.    jnz _RetFalse  
57.      
58.    push ebx  
59.      
60.    mov edi, ebx                    ; edi = Dos Header  
61.    add edi, [edi + 3ch]                ; edi = NT Header  
62.    cmp word ptr [edi], EP  
63.    jnz _RetFalse  
64.      
65.    invoke VirtualAlloc, 0, [edi + 50h], MEM_COMMIT, PAGE_EXECUTE_READWRITE  
66.    test eax, eax  
67.    je _RetFalse  
68.    xchg eax, ebp                   ; ebp = lpMemroy  
69.      
70.    lea esi, [edi + 14h]  
71.    xor eax, eax  
72.    lodsw                       ; eax = IMAGE_OPTIONAL_HEADER size  
73.    lea esi, [esi + 2 + eax]            ; esi -> section table  
74.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
75.; 移动节到分配的内存  
76.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
77.    movzx ecx, word ptr [edi + 06h]         ; ecx = section num  
78.      
79._MoveSection:  
80.    push ecx  
81.    mov edx, [esi + 14h]                ; edx = physical offset  
82.    add edx, [esp + 4]              ; [esp + 4] = pDllMemory, edx = source section va  
83.    mov eax, [esi + 0ch]                ; eax = VirtualAddress  
84.    add eax, ebp                    ; ebp = lpMemory, eax = dest section va  
85.    invoke RtlMoveMemory, eax, edx, dword ptr [esi + 10h]  
86.    add esi, 28h                    ; esi -> next section  
87.    pop ecx  
88.    loop _MoveSection  
89.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
90.; 处理导入段  
91.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
92.    mov edx, ebp                    ; edx = lpMemory  
93.    mov eax, edi                    ; eax = NT Header  
94.    call InitImport  
95.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
96.; 处理重定位  
97.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
98.    mov edx, ebp                    ; edx = lpMemory  
99.    mov eax, edi                    ; eax = NT Header  
100.    call InitFixups  
101.      
102.    mov edx, [edi + 28h]                ; edx = EntryPoint RVA  
103.    add edx, ebp                    ; ebp = lpMemory, edx = EntryPoint VA  
104.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
105.; DllMain  
106.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
107.    push 0  
108.    push 1  
109.    push ebp  
110.    call edx                    ; call DllMain  
111.      
112._RetTrue:  
113.    pop ecx  
114.    push ebp  
115.    pop dword ptr [esp + pushad_eax]        ; eax = lpMemory  
116.    popad  
117.    ret 4  
118.      
119._RetFalse:  
120.    popad  
121.    xor eax, eax  
122.    ret 4  
123.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
124.; 初始化导入表函数  
125.; Arguments:  
126.;   [esp]           - return address  
127.;   eax         - NT Header  
128.;   edx         - Alloc mem base  
129.; Return Value:  
130.;   eax = true or eax = false  
131.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
132.InitImport:  
133.    pushad  
134.    push edx                    ; [esp] = alloc mem base  
135.    mov edi, [eax + 80h]                ; edi = Import RVA  
136.    add edi, edx                    ; edi = Import VA  
137.      
138._NextImport:  
139.    cmp dword ptr [edi + 0ch], 0            ; [edi + 0ch] = Name  
140.    jz _II_RetTrue  
141.    mov edx, [edi + 0ch]                ; edx = Name  
142.    add edx, [esp]                  ; edx = import dll name string  
143.    invoke LoadLibrary, edx  
144.    test eax, eax  
145.    jz _II_RetFalse  
146.    xchg eax, ebx                   ; ebx = load dll base  
147.      
148.    mov esi, [edi + 10h]  
149.    add esi, [esp]                  ; esi = FirstThunk  
150.    cld  
151.  
152._NextIat:  
153.    lodsd  
154.    test eax, eax  
155.    je _Next  
156.      
157.    bt eax, 31                  ; eax 31-bit copy to CF  
158.    jnc _IatName  
159.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
160.; Iat ordinal  
161.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
162.    movzx edx, ax                   ; edx = ordinal  
163.    invoke GetProcAddress, ebx, edx         ; ebx = load dll base  
164.    mov [esi - 4], eax  
165.    jmp _NextIat  
166.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
167.; Iat Name  
168.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
169._IatName:  
170.    add eax, [esp]                  ; eax = IMAGE_IMPORT_BY_NAME  
171.    lea edx, [eax + 2]              ; edx -> api name  
172.    invoke GetProcAddress, ebx, edx  
173.    mov [esi - 4], eax  
174.    jmp _NextIat  
175.      
176._Next:  
177.    add edi, 14h                    ; edi -> next Iat struct  
178.    jmp _NextImport  
179.      
180._II_RetTrue:  
181.    pop edx  
182.    popad  
183.    xor eax, eax  
184.    inc eax  
185.    ret  
186.      
187._II_RetFalse:  
188.    pop edx  
189.    popad  
190.    xor eax, eax  
191.    ret  
192.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
193.; 初始化并修订重定位地址  
194.; Arguments:  
195.;   [esp]           - return address  
196.;   eax             - NT Header  
197.;   edx         - alloc mem base  
198.; Return Value:  
199.;   eax - true or eax - false;  
200.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
201.InitFixups:  
202.    pushad  
203.      
204.    mov esi, [eax + 0a0h]               ; esi = reloc rva  
205.    test esi, esi  
206.    je _IF_RetFalse                 ; No reloc  
207.    cld  
208.    add esi, edx                    ; esi = 重定位表的地址  
209.      
210.    push [eax + 0a4h]               ; [esp] = 重定位表长度  
211.    add [esp], esi                  ; [esp] = 重定位表结束地址  
212.      
213.    mov edi, edx                    ; edi = alloc mem base  
214.    mov ebp, edx                    ; ebp = alloc mem base  
215.    sub ebp, [eax + 34h]                ; ebp等于分配的地址与建议装载地址的差  
216.      
217._NextFixups:  
218.    cmp [esp], esi                  ; 比较是否到了重定位表结束位置  
219.    je _IF_RetTrue  
220.    lodsd  
221.    xchg eax, ebx                   ; ebx = 当前页起始地址RVA  
222.    lodsd  
223.    xchg eax, ecx                   ; ecx = 当前重定位块的大小  
224.    sub ecx, 8  
225.    shr ecx, 1                  ; ecx = 重定位项的数量  
226.      
227._NextOffet:  
228.    xor eax, eax  
229.    lodsw                       ; eax = 读取重定位项  
230.    bt eax, 13                  ; 将eax的第13位复制到CF  
231.    jnc _NextLoop  
232.      
233.    and ax, 0fffh                   ; 保留低12位  
234.    add eax, ebx  
235.    add dword ptr [edi + eax], ebp          ; 修正,加上差值  
236.      
237._NextLoop:  
238.    loop _NextOffet  
239.    jmp _NextFixups  
240.      
241._IF_RetTrue:  
242.    pop edx  
243.    popad  
244.    xor eax, eax  
245.    inc eax  
246.    ret  
247.      
248._IF_RetFalse:  
249.    popad  
250.    xor eax, eax  
251.    ret  
252.      
253.    end Entry  
View Code

 

打造DLL内存加载引擎学习笔记

标签:

原文地址:http://www.cnblogs.com/Acg-Check/p/4269443.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!