WINDOWS+PE权威指南读书笔记(23)

目录

PE 病毒提示器

基本思路:

志愿者的选择条件:

判断病毒感染的原理:

手工打造 PE 病毒提示器:

分析目标文件的导入表:

补丁程序的源代码:

补丁程序的字节码

修正函数地址:

测试运行:

补丁版的 PE 病毒提示器:

将提示器写入启动项:

检测特定位置校验和:(临时文件的)

测试运行:

小结:


PE 病毒提示器

本章采用两种方式开发 PE 病毒提示器 ,一种是程序加手工的半自动化方法,另一种是全补丁的自动化方法。

该 PE 病毒提示器不具备病毒预警功能,也无法阻止 PE 病毒的入侵,只是对 PE 病毒起到提示作用,让用户知道当前电脑的安全状况。

基本思路:

PE 病毒指 Windows 操作系统下,以 PE 文件为感染目标的病毒,有时也称为 Win32 病毒,属于文件型病毒的一种。

什么是文件型病毒:

所有通过操作系统的文件进行感染的病毒都称为文件型病毒。其主要目标是操作系统中的可执行文件,但不排除其他类型的文件,如宏病毒感染的就是 OFFICE 系列文件。这些可执行文件主要是以扩展名为 “.com”,“.exe” 结尾的文件。本章所描述的文件型病毒专指以 “.exe” 为结尾的PE文件。

打造该病毒提示器的总体思路为:

首先,将某个系统 PE 文件(志愿者)作为这次打造生成病毒提示器的源,给该志愿者打补丁;然后通过分析嵌入到志愿者文件中的补丁代码,实现对入侵 PE 病毒的检测与提示。

志愿者的选择条件:

志愿者即感染病毒的对象。大部分感染 PE 文件的病毒在传染时,都会对目标文件的大小进行检测。通常小于某一个值时不去感染,因为这种文件有好多是病毒分析者设置的 “蜜罐”,可以通过这种方法很容易获得嵌入到蜜罐里的病毒代码,从而制定有效的杀毒方案。所以,确定志愿者时,一定要选择一个文件相对较大的程序。

例如,本章选择采用系统的记事本程序 notepad.exe,它在 Windows 2000 下的标准大小为 50960,在 Windows XP SP3 下的标准大小为 66560 。

此外,文件型病毒人侵以后,大部分都会感染硬盘上的可执行文件。如果病毒无限制地感染磁盘文件,势必会导致硬盘指示灯不停闪烁,造成 CPU 占用时间过高。这种外在的表现会被细心的用户发现病毒的威胁。 因此,现在大部分文件型病毒在感染时都采取一定的策略。比如,挟持运行程序的函数,当程序运行时才感染;或者有阶段、有步

又地对系统目录、程序文件夹等进行小批量的感染操作,这样,用户从表面上是很难发觉病毒的。

本章打造的病毒提示器正好运用病毒感染的这个原理,选择系统自带的文件 (记事本程序 notepad.exe) 作为志愿者。

并从以下两方面积极地拉近与病毒之间的物理距离:

口将自己放到系统文件夹中,即 %WINDIR%。

口将自己添加到注册表项中,每次开机都运行一遍。

这样做的目的就是让自己充分暴露给病毒,告诉病毒;: 你来的时候一定通知我哦 !

判断病毒感染的原理:

绝大多数情况下,病毒提示器一旦被病毒感染,其文件头就会发生相应的变化(文件头部的数据结构包括 DOS MZ HEADER、DOS STUB、IMAGE_FILE_HEADER、IMAGE_OPTIONAL_HEADER、IMAGE_SECTION_HEADER)。

文件头部的数据结构 IMAGE_SECTION_HEADER 记录了PE 文件中存在的每个节的相关统计信息。如果病毒文件修改了文件头部,或者修改了节区内容,那么通过对文件头部数据的分析就能得出 PE 文件是否被修改的结论。一旦发现文件被修改,程序会发给用户一个友好的提示,告诉他可能有病毒

入侵。

如何实现自我修复功能:

通过对本章应用的扩展,也可以实现 PE 文件感染病毒后的自身修复功能。因为文件型病毒要获得执行控制权,首先要劫持目标入口地址或入口代码,目前,常见的文件型病毒,要么修改头部字段 IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint,要么修改该地址指向的指令字节码。所以,只要将这两部分内容和这两部分内容的校验码保存到补丁程序里,当发现 PE 被修改的时候,提示用户,并重新修正该地址的值,便能达到自我修复的目的。

手工打造 PE 病毒提示器:

清楚了编程思路以及原理之后,我们首先通过半自动化的过程开发 PE 病毒提示器。本补丁实例的目标是特定的 PE 文件一一记事本。在程序设计部分先不使用嵌入补丁框架,目的是学习在补丁代码中如何利用目标程序导入表中提供的现有函数。

编程思路:

补丁程序的设计大致分为以下三步:

步骤1:获取函数地址。

要获取地址的函数在记事本原始的导入表中并不存在,必须通过调用 LoadLibraryA 加载相应的动态链接库,然后调用 获取这些函数的入口地址。

这些函数包括:

步骤2:在注册表的以下位置增加新项,名称为 note,类型为 REG_SZ,值为 virNote.exe。

加入启动项的目的是每次开机都会运行这个补丁后的记事本程序 virNote.exe,以便随时监测机器是否被文件型病毒感染 。

步骤3:定位到该文件的头部,生成节表的校验值,并与 virNote.exe 文件头部 4ch 偏移处存放的值进行比较。如果一致,则表示文件没有被修改过,退出不显示提示,否则显示病毒入侵的提示信息。下面对目标文件进行简单分析。

分析目标文件的导入表:

下面将使用 PEInfo 小工具对目标文件 (notepad.exe)的导入表进行分析,查看它使用了哪些动态链接库的哪些函数,以便确定补丁代码中是否可以直接使用这些函数。

PEInfo 小工具对 notepad.exe 导入表的分析结果显示如下:

从以上所列内容 (加黑部分) 可以看出,记事本程序中使用了 kernel32.dll 中的两个最重要的函数: LoadLibraryA 和 GetProcAddress 。

这对编写补丁代码来说是幸运的,因为使用这两个函数,其他任何动态链接库的任何函数地址都可以轻而易举地得到。这样,就免去了获取 kernel32.dll 基地址,以及通过其导出表获取这两个函数的工作。

除此之外,记事本程序的原始导入表中还包含了补丁程序中要调用的几个函数:

补丁代码调用以上这些函数的位置,可以直接使用 invoke 指令和原始函数名,无需再对这些函数的地址进行获取操作。

补丁程序的源代码:

本实例的补丁代码将实现以下几项功能:

1) 在注册表启动项中加入补丁后的记事本程序 virNote.exe。

2) 复制当前进程的所有字节码到临时文件中。

3) 验证临时文件中的校验和是否正确。

4) 根据校验和是否正确决定是否进行病毒提示。

补丁程序的源代码见代码清单 22-1:

以上代码使用了重定位技术和动态加载技术。因为这次打补丁的目标文件很明确,即记事本程序,所以,动态加载仅限于对那些在记事本程序导入表中不存在的函数。

阅读以上补丁代码时,需要特别注意那些已经在记事本导入表中存在的,同时补丁代码中也会调用的函数;记事本程序一旦运行,这些函数的地址就会被操作系统加载强解析出来并存储在 IAT 中。所以,后面的手工部分会将对这些函数的调用指令操作数进行修正,使其指向 IAT 中函数对应的地址。

补丁程序没有自己的导入表,直接把函数指针变量名取原程序导入表桥 2 指向的 IAT,因为函数名指针变量已经定义好了,只要个地址而已。

由于有些位置的代码复用了记事本导入表中存在的函数,所以这些位置标示出的函数地址必须得到修正。这些位置包括行 103、行 121、行 184、行 210、行 301 等,这些位置在源代码中以注释 “;!!!!!!!!需要修正” 重点标出。

补丁程序的字节码

补丁程序的字节码如下:(virwarn.exe)

以上所示为补丁字节码的代码段内容。显示的所有字节码共需要空间大小为 05B9h 个字节,而记事本程序的 .rsrc 节一共有 0C700-0B800=0F00 (对齐大小减真实大小)个字节的剩余空间可以使用,所以,基本确定补丁代码可以嵌入到记事本程序的 .rsrc 节中。

注意:补丁字节码第一个红框部分为补丁代码开始处的 call @F,而蓝框 FF 25 之后地址部分则是代码中需要修正的地址。

修正函数地址:

由于在补丁程序中复用了记事本程序导入表中已存在的几个函数,补丁后的代码地址必须予以修正。

从反汇编代码中获得这几个需要修正的地址如表 22-1 所示:(反汇编就是进程中映像,IAT 已修正)

表中 3一8 项是在 notepad.exe 导入表中存在的 API 函数,这些函数也被补丁代码直接使用。

以第 8 项函数 RegCloseKey 为例,计算其 VA 的具体步骤如下:

步骤1:从 notepad.exe 导入表中得到该函数的导入部分描述。

具体描述如下所示:

步骤2:计算该函数的 RVA。

如上所示,一个绑定导入数据结构(IMAGE_BOUND_IMPORT_DESCRIPTOR) 对应一整个动态链接库,FirstThunk 指向了该库导入函数的第一个 RVA,而每个引入 API 函数是以 4 个字节(dword) 对齐的。

所以 RegCloseKey 的 RVA = FirstThunk +(序号 - 1) *4=00001000h + (7-1) *4=00001018h ;这里序号从 1 开始

步骤3:计算该函数的 VA。

将第 2 步计算得出的 RVA 加上基地址 01000000h 就是函数的入口地址 VA 了,基地址是 IMAGE_OPTIONAL_HEADER32.ImageBase 字段,程序被加载到内存后的起始 VA。

所以 RegCloseKey 的 VA = 01000000 + 00001018 = 01001018h

表 22-1 中标示的其他函数也采用这样的运算方法,更正以后的字节码如下:

接下来,使用 FlexHex 手工对 notepad.exe 执行如下操作:

步骤1:文件偏移 244h 处将 .rsrc 节的属性更改为 0e0000040h (也就是将节标记为可读/可写/可执行),因为补丁代码塞到这段后要给变量填充数据。

步骤2:文件偏移 100h 处修改新的入口地址为 0a000h+ (0B800-7200h) +248h=0E848h。

即:.rsrc 段起始 RVA + 原 .rsrc 段真实大小 + 补丁代码的数据段大小 = 补丁代码 start 段处

步骤3:将修正以后的 5B9h 个字节码覆盖到文件 0B800h 开始的地方。

步骤4:算出文件节表的校验和为 0AF16h ( virNote 的为74ddh),将其填入文件偏移 124h (virNote 的为 104h,即 PE 头开始的 4ch) 处,win32versionvalue 字段,原来说必须为 0,但是这里却可以更改。注意,校验和为一个字。

测试运行:

执行到这里,文件型病毒提示器就完成了,将该提示器改个名字 (例如 virNote.exe) 并复制到操作系统的系统目录下,然后进行以下测试。

模拟病毒手动修改经过改造的 notepad.exe 的节表,使 virNote.exe 的节表发生变化。例如,在文件偏移 0x01d5 处(.text 节的名称处) 将 00h 修改为30h,然后保存。重新运行 virNote.exe 程序,发现文件型病毒提示器的对话框接着就弹出来了,弹出对话框如下图所示。

将 virNote.exe 复制到 Windows 操作系统的系统目录下(如 C:\windows,因为源代码中获取的系统目录是 %windir% ),先运行一次,系统将不会有任何提示,但注册表的启动项中将会增加一个 note 项。

正常情况下,每次开机都会运行 virNote.exe 程序(该程序实时计算校验和),因为该程序的节表未被修改或破坏,校验和不变; 也就是说,它与存储在文件头部 4ch 偏移处的原始校验和是一致的,所以并不会出现任何提示。

一旦 virNote.exe 被文件型病毒感染了,它就会弹出对话框提醒用户,该电脑已经被文件型病毒感染了。

补丁版的 PE 病毒提示器:

上一节使用半自动化的补丁程序,通过手工修改实现了 PE 病毒提示器。本节将使用全自动化的方法实现该病毒提示器,通过对志愿者打补丁的方法来实现人侵病毒提示的功能。

补丁程序必须具备以下两个功能:

第一:将补丁程序本身写人系统启动项;

第二:能够检测特定位置的校验和是否被修改。下面分别介绍这两部分代码的编写。

将提示器写入启动项:

为了能实现每次开机运行该提示器,以增加被感染的几率,补丁代码需要将补丁后的目标程序写入注册表的启动位置。

由于键值中没有带路径,所以补丁代码还必须将病毒提示器复制到默认系统搜索路径中,比如 Windows 系统目录。

以下是将提示器写入启动项的相关代码:

代码首先调用函数 RegCreateKey 创建键,然后使用 RegSetValueEx 设置键的值,最后调用函数 RegCloseKey 关闭新创建的键。

检测特定位置校验和:(临时文件的)

本实例将 PE 病毒提示器放置在 C:\windows 子目录中,名称为 virNote.exe。每次开机即运行,运行时先通过函数 CopyFile 将自己复制到临时文件 C:\windows\virNote_Bak.exe 中 ; 然后,通过内存映射函数 MapViewOfFile 获取操作句柄,检查 PE 文件头部开始 4ch 处的校验和与计算生成的值是否一致。如果一致,表示未被修改; 否则提示感染病毒信息,并显示记事本程序。

相关代码见代码清单 22-2:

以上代码与 22.2.3 节介绍的代码基本一致,不同之处是对记事本程序导入表中已经存在的函数的处理 : 为了免去手工操作,即对记事本程序导入表中已经存在的函数的地址修正,在代码中对这些函数全部采用动态加载技术。如代码行 116 — 127 对函数 MapViewOfFile 的调用、代码行 203 一 204 对函数 CloseHandle 的调用等。另外,补丁代码还使用了嵌入补丁框架结构。

测试运行:

使用第 17 章的补丁工具为记事本打补丁。因为节表的校验和还没有写入特定位置,所以,第一次运行生成的 bindD.exe 弹出了对话框提示。在病毒提示器正式工作之前,需要手动将校验和写入其文件头部开始的 4ch 处。

校验和是通过 OD 的单步调试过程获得的,图 22-2 是获得校验和时的 OD 运行界面图:

如图所示,esi 指向的数据区刚好是 PE 文件头的 PE 标志,从这个地方开始往下找 4ch 偏移,读出的字为 0000。而当前 EIP 所处的位置刚好是动态获取到的校验和与该处值相减的指令,此时,指示 eax 的值为 0F34BH。这个值就是 bindD.exe 的节数据的校验和。

获取该校验和后,将该值写入 PE 文件头的 PE 标志开始的 4ch 偏移处,作为记事本程序原始的校验和。

依次生成补丁程序 patch.exe,补了工具程序 bind.exe (取自第 17 章生成的补丁工具)。用 bind.exe 对 notepad.exe 打补丁,最终生成 patch_notepad.exe。

第一次运行 patch_notepad.exe,因为校验和未写入,所以会显示病毒提示,该提示是不真实的。将校验和 0F34Bh 手动写入 patch_notepad.exe 文件 PE 头部 4ch 处,并更改文件名为 virNote.exe。再次运行 virNote.exe 时不会有任何提示(TMD 文本框都没有了),至此,PE 病毒提示器完成。

将 virNote.exe 复制到 C:\windows 目录中,PE 病毒提示器就处于工作状态了,

注意:

在测试时不要把防病毒软件打开,因为用这种方法生成的 virNote.exe 会被杀毒软件误认为是病毒而被拦截。

你也可以参考本书第21 章介绍的免杀技术,将 virNote.exe 实施加密,就不会出现这样的提示了。

假设 PE 文件病毒侵犯了我们的电脑,提示器会再次弹出提示窗口,此时虽无法杜绝病毒的运行,但可以明确提醒: 您的电脑已经受到 PE 病毒的攻击了。如果想测试该提示器的运行效果,可以找到 virNote.exe,将特定位置的校验和修改一下,或者把节表中的任何一处进行修改,都能达到测试目的。

例如,以下是修改节 .text 名称的字节码:

如上所示,将节 .text 任意修改 后,即可引发病毒提示器,并且显示提示信息:

小结:

本章采用两种开发方式实现了 PE 病毒提示器,该程序可以在电脑感染 PE 病毒后提醒用户注意。原理是在 PE 文件头部存储一个节表信息校验和,由补丁程序计算当前校验和,并与存储的校验和进行对比, 以判断文件是否被修改。由于本提示器是在病毒执行以后再执行,所以它不有具备病毒的预警功能,只有具备提示功能。

大家也可以扩展本章的程序,使用补丁对 PE 文件进行自修复。当发现电脑被病毒感染时,重新修复入口地址和代码段的起始 N 个字节,并提醒用户。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐一 · 林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值