世上最完整的病毒分析及实例(108页).doc





《世上最完整的病毒分析及实例(108页).doc》由会员分享,可在线阅读,更多相关《世上最完整的病毒分析及实例(108页).doc(107页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、-世上最完整的病毒分析及实例-第 379 页第3章 病毒分析本章介绍病毒的原理与所使用的技术,以及防止病毒的方法: 常见病毒的原理; 可执行文件病毒修改文件的方法; 可执行文件病毒使用的常用技术; 优化可执行文件防病毒; 文件过滤驱动在反病毒上的应用。这是本章涉及的问题。1.1 病毒概述“计算机病毒”最早是由美国计算机病毒研究专家F.Cohen博士提出的。“计算机病毒”有很多种定义,国外流行的定义为:是一段附着在其他程序上的可以实现自我繁殖的程序代码。在中华人民共和国计算机信息系统安全保护条例中的定义为:“计算机病毒是指编制或者在计算机程序中插入的破坏计算机功能或者数据,影响计算机使用并且能够
2、自我复制的一组计算机指令或者程序代码”。世界上第一例被证实的计算机病毒是在1983年,出现了计算机病毒传播的研究报告。同时有人提出了蠕虫病毒程序的设计思想;1984年,美国人Thompson开发出了针对UNIX操作系统的病毒程序。1988年11月2日晚,美国康尔大学研究生罗特莫里斯将计算机病毒蠕虫投放到网络中。该病毒程序迅速扩展,造成了大批计算机瘫痪,甚至欧洲联网的计算机都受到影响,直接经济损失近亿美元。计算机病毒是人为编写的,具有自我复制能力,是未经用户允许执行的代码。一般正常的程序是由用户调用,再由系统分配资源,完成用户交给的任务。其目的对用户是可见的、透明的。而病毒具有正常程序的一切特性
3、,它隐藏在正常程序中,当用户调用正常程序时窃取到系统的控制权,先于正常程序执行,病毒的动作、目的对用户时未知的和未经用户允许的。它的主要特征有传染性、隐蔽性、潜伏性、破坏性和不可预见性。传染性是病毒最重要的一条特性。按照计算机病毒侵入的系统分类,分为DOS系统下的病毒、Windows系统下的病毒、UNIX系统下的病毒和OS/2系统下的病毒。按照计算机病毒的链接方式分类可分为源码型病毒、嵌入型病毒、外壳型病毒。按照传播介质分类,可以分为可分为单机病毒和网络病毒。随着Windows系统的发展,引导型病毒已经不再,宏病毒也少见。目前见得多的是感染本机可执行文件的PE病毒和通过网络在计算机之间传播的蠕
4、虫病毒比较常见。1.2 PE病毒分析Windows下常见的可执行文件,一种是二进制文件,就是扩展名为exe、dll、src和sys等的文件,它们的执行是由explorer.exe(资源管理器)、cmd.exe(控制台,类似DOS界面)或其它程序调用执行的。另一种是文本格式文件,例如扩展名为htm和html,可以由iexplorer.exe调用,由script.exe来解释执行的文件。 从Windows2000以后,其二进制文件文件为PE结构。PE的意思就是可移植的执行体(Portable Executable),它是 Windows的32位环境自身所带的执行体文件格式。它的一些特性继承自 Un
5、ix的 Coff (common object file format)文件格式,同时为了保证与旧版本MS-DOS及Windows操作系统的兼容,PE文件格式也保留了MS-DOS中那熟悉的MZ头部。病毒能够感染PE文件,因为病毒设计者深知其结构。1.2.1 PE病毒常用技术病毒也和正常的应用程序一样,涉及到函数的调用和变量的使用。1、调用API函数的方法API是“Application Programming Interface”的英文缩写,很象DOS下的中断。中断是系统提供的功能,在DOS运行后就被装载在内存中,而API函数是当应用程序运行时,通过将函数所在的动态连接库装载到内存后调用函数的
6、。请大家先在MSDN的“索引”中输入函数“MessageBox”然后回车,就可以查到该函数的使用方法。MSDN是微软提供的开发帮助,是在Windows下编程必备的资料文件。在Windows下设计应用程序不直接或间接使用API是不可能的,有些高级语言看似没有使用API,只不过它们提供的模块对API进了封装。API的使用分为静态和动态使用两种方式。在源程序中调用API两种方式都可以使用,但对未公开API因为无相应的头文件,只能使用动态方式。下面以VC+中调用MessageBox说明两种方式的区别。(1) 静态方式char note_inf=”谢谢使用”;char note_head=”提示信息”;
7、:MessageBox(0, note_inf, note_head,MB_OK); /:表示全局函数反汇编结果如图3-1。“PUSH 00000000”对应的是MB_OK常量入栈,“PUSH 0040302C”对应的是一个字符串的偏移地址入栈,“PUSH 00403020”对应的是另一个字符串偏移地址的入栈,第2行“PUSH 00000000”对应窗口句柄入栈。当程序执行时,装载器会将user32.dll装载到应用程序虚拟空间,同时将MessageBoxA(对应ANSI格式,另一种为UNICODE格式,用MessageBoxW表示。这是因为函数的参数有字符串,而字符串有两种格式所致)的入口地
8、址填充到虚拟地址004021B8h。虚拟地址004021B8h是由PE头中IMAGE_DATA_DIRECTORY数组来定位的,当编译器生成PE文件时就计算好了。 图3-1 API的汇编调用(2) 动态方式动态方式先定义函数指针,使用函数LoadLibrary装载要调用的函数所在的dll文件,获取模块句柄。然后调用GetProcAddress获取要调用的函数的地址。void CTestDlg:OnButton/定义MessageBox函数指针typedef int (WINAPI *_MessageBox)( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCapti
9、on, UINT uType /定义MessageBox指针变量_MessageBox new_MessageBox; /装载MessageBox函数所在dll文件HINSTANCE hb=LoadLibrary(user32.dll);/获取ANSI格式的MessageBox函数地址new_MessageBox=(_MessageBox)GetProcAddress(hb,MessageBoxA);/动态调用函数MessageBoxnew_MessageBox(0,欢迎使用!,提示信息,MB_OK);/释放MessageBox函数所在模块CloseHandle(hb);动态方式是在需要调用函
10、数时才将函数所在模块调入到内存的,同时也不需要编译器为该函数在导入表中建立相应的项。2、病毒调用API函数病毒要完成相应的功能,不可能不调用API函数。病毒感染PE文件可能是在源程序中加入病毒代码,但多数是在生成PE文件后通过修改PE文件感染的。对后种情况,病毒难以去为使用的API建立导入表项,只有使用第动态方式调用API。动态使用API的前提是预先知道LoadLibrary和GetProcAddress的地址,可以预先设定或搜索API的地址实现。一个正常的Windows程序,它至少需要调用模块kernel32.dll,因为应用程序正常退出时需要调用函数ExitProcess,而该函数位于模块
11、kernel32.dll内。然而函数LoadLibrary和GetProcAddress也位于模块kernel32.dll内。既然模块kernel32.dll总在内存,如果我们知道这两个函数地址,直接调用就可以了。(1) 检测函数地址先用间接方式检测函数的地址,代码如下,结果见图3-2。void CTestDlg:OnButton1() /定义函数LoadLibrary和GetProcAddress的原型typedef HINSTANCE (WINAPI *_LoadLibrary)( LPCTSTR lpLibFileName typedef FARPROC (WINAPI *_GetPro
12、cAddress)( HMODULE hModule, LPCSTR lpProcName /定义指针_LoadLibrary new_LoadLibrary; _GetProcAddress new_GetProcAddress;/装载函数所在模块HINSTANCE hb=LoadLibrary(kernel32.dll);/获取函数首地址new_LoadLibrary=(_LoadLibrary)GetProcAddress(hb,LoadLibraryA);new_GetProcAddress=(_GetProcAddress)GetProcAddress(hb,GetProcAddre
13、ss);/显示结果CString inf;inf.Format(LoadLibrary =%XhrnGetProcAddress=%Xh,new_LoadLibrary,new_GetProcAddress);:MessageBox(0,inf,地址信息,MB_OK);CloseHandle(hb); 图3-2 取函数地址(2) 在程序中直接使用函数地址如下的代码直接使用函数LoadLibrary和GetProcAddress地址,然后用它们动态调用函数MessageBox,执行的结果是显示信息框。void CTestDlg:OnButton2() /定义MessageBox原型typedef
14、 int (WINAPI *_MessageBox)( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType char funName=MessageBoxA;/定义地址DWORD LoadLibraryAddr =0x77E80221;DWORD GetProcAddressAddr =0x77E80CAB;_MessageBox new_MessageBox; /定义函数所在模块名HINSTANCE hb;char dllName=user32.dll;_asm ;VC+中嵌入汇编代码 lea eax, dllName push
15、eax mov ebx, LoadLibraryAddr call ebx ;调用LoadLibrary mov hb, eax /直接使用地址 lea eax,funName push eax push hb mov ebx, GetProcAddressAddr ;调用LoadLibrary call ebx mov new_MessageBox, eax/动态调用MessageBox,显示信息框new_MessageBox(0,欢迎使用!,提示信息,MB_OK);CloseHandle(hb);预先设定API地址使代码比较短,但只能局限在某个操作系统版本下运行,也必须先保证它所在模块在内
16、存中。同一个API函数,在不同的系统下的地址可能不相同。该方法,也叫“预编码”技术。(3) 搜索API地址只需要从虚拟内存搜索到LoadLibrary和GetProcAddress的地址,用这两个函数就可以获取其它函数的地址。前面已经介绍过,一般程序都会加载LoadLibrary和GetProcAddress所在的库文件kernel32.dll,那么在内存中搜索kernel32.dll所在基地址,然后再分析kernel32.dll的PE结构,就可以找到LoadLibrary和GetProcAddress的地址。分析多个Windows系统,可以知道kernel32.dll加载的大致地址,比如根据
17、在9X下其加载地址是0xBFF70000,在Windows 2000下加载基址是0x77E80000,然后可由该地址向高地址搜索可以找到其基址。也可以由高地址到低地址开始搜索,搜索开始的地址由程序入口处的ESP获得。程序装载器调用一个程序后将程序的返回地址入栈,然后转去执行该程序。经反汇编证明,返回地址是属于模块中。由于内存属性决定,有些内存可能因未分配而不能读,如果读它,将导致出错。为避免因错误而程序不能继续,必须使用SEH处理。SEH(“Structured Exception Handling”)即结构化异常处理,是Windows操作系统提供给程序设计者的强有力的处理程序错误或异常的武器
18、,有些类似于VISUAL C+中使用的_try _finally 和_try _except。后面的例子使用了从这些地址向高地址搜索的方法。如果搜索到Kernel32.DLL的加载地址,其头部一定是“MZ”标志,由模块起始偏移0x3C的双字确定e_lfanew,再由e_lfanew找到的PE头部标志必然是“PE”,因此可根据这两个标志判断是否找到了模块加载地址。经实验证明,该判断方法非常可靠,基本不会出现错误。因为所有版本的Windows系统下Kernel32.DLL的加载基址都是按照0x1000对齐的,根据这一特点可以不必逐字节搜索,按照0x1000对齐的边界地址搜索即可。以由程序入口处的E
19、SP为例,方法如下。下面的代码搜索LoadLibrary和GetProcAddress的地址。.586p.model flat, stdcalloption casemap :none ; case sensitiveincludelib masm32libuser32.lib GetApiAddress PROTO :DWORD,:DWORD .data Kernel32Addr dd ? ExportKernel dd ? GetProcAddr dd ? LoadLibraryAddr dd ? aGetProcAddr db GetProcAddress,0 GetProcAddLen
20、 equ $-aGetProcAddr-1 aLoadLibrary db LoadLibraryA,0 LoadLibraryLen equ $-aLoadLibrary-1 szTitle db 检测结果,0 temp1 db Kernel32.dll 基本地址:%8x,0dh,0ah db LoadLibrary 地址 :%8x,0dh,0ah db GetProcAddress 地址 :%8x,0dh,0ah,0 temp2 db 256 dup(?).codemain:Start: mov esi, esp ; esi为返回地址所在的页,例若esp=77e78f94h,esi=77e
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 世上 完整 病毒 分析 实例 108

限制150内