众所周知,作为一款优秀的可执行文件压缩工具,UPX受到程序开发者的广泛欢迎。然而一些病毒、木马和其他恶意程序使用了UPX来隐藏自身行为,这使得它拥有不好的名声,导致了杀毒引擎对一些无害的应用程序的误报。有些杀毒引擎甚至将所有加了UPX壳的程序视为病毒,比如ClaimAV、Comodo、F-Prot等等。
其实,不仅是UPX,其它的压缩壳,比如ASPack、PECompact也是如此。今天我们要讨论的,是使用最为广泛的UPX。
所以,我们需要做的,就是让自己的程序不具备,或者说,不完全具备UPX壳的特征。这既能够有效避免杀毒软件的误报发生,又能使自己的程序不容易被轻易查壳脱壳并任意篡改其中的数据。(UPX壳不是加密壳,若有防破解的特殊需求,建议使用加密壳)
首先,我们来讲一讲查壳的原理。不论是压缩壳,还是加密壳,都有特定的算法。加同种壳的不同应用程序,有一部分机器码是相同的,它们被称为“签名”或者“特征码”。有些壳还会将自身的一些信息写入可执行程序。
主流的杀毒引擎,比如360杀毒,会借助特征码技术来查毒,比如,当一个加了UPX壳的木马被识别后,其部分代码被记入病毒库中,而这可能会导致同样是加了UPX壳的无害应用程序在被进行深入的行为分析前草率地被识别为木马。
下面我们拿我以前写的一个简单的数学工具为例。使用EXEinfoPE,可以发现它没有加壳,以及它是用VS2013的Visual C++编写的。
上传至Virscan.org发现只有F-Prot报毒。这是一次误报,因为程序并没有访问网络的行为。
现在我们用最新的UPX给它加壳。使用“强制压缩”命令来提高压缩比,并将其保存到一个新文件。可以看到,压缩效果还是不错的。
现在我们再用EXEinfoPE查看加壳后的程序。可以发现它识别出了UPX壳,并提供了较为直接的脱壳方法:UPX的“upx -d”命令。
我们把加壳后的程序上传至Virscan.org,发现有三个杀毒软件报毒。其中,来自Hacksoft的产品TheHacker怀疑这是个蠕虫,ClaimAV表示这个程序加了UPX壳,F-Prot表示这个程序加了个“未知壳”。
360的QVM引擎也误报了这个程序。
现在来分析一下文件数据。用任何一个十六进制编辑器(UltraEdit,还有VS自带的十六进制编辑器等等都可以,但是不如WinHex)打开加壳后的程序。可以看到三个区段名。“UPX0”和“UPX1”是加UPX壳后的两个区段名。其中UPX1区段包含了需要解压的数据块。“.rsrc”是程序资源信息区段名,这个区段含有原资源段的完整头部以及图标、Manifest、版本等未被压缩的资源,当然还有UPX自身需要的导入信息等(如果程序自身不含资源段,加壳后就是“UPX2”)。“UPX0”和“UPX1”可以被随意改成任何字符串,虽然这样改用处不大,但是也能起到伪装的作用。
再向后翻页,可以看到UPX头部,这些数据的内容大致内容如下所示。具体不再赘述,参见UPX的源码。UPX头是供UPX通过“upx-d”命令脱壳用的,并不影响程序运行。我们可以把它全部抹去(写0),或者把它改成无效数据,这样就无法使用命令“upx -d”快速脱壳了。
现在可以看到,UPX已经不能够脱自己加的壳了。
在我们破坏UPX头部后,EXEinfoPE依然能够识别出UPX壳。那它又是如何识别出来的呢?点击编辑框右边的小箭头。
可以看到,EXEinfoPE是通过userdb.txt文件中的特征码库来辨别壳的。其中,UPX的特征码有一段“60 BE ?? ?? ?? 00 8D BE ?? ?? ?? FF”。“??”可以对应任意字节。
使用任意反汇编工具(比如OllyDbg)打开它。可以发现,程序的入口点就在这里。现在需要做的,就是在不影响程序运行的情况下破坏特征码的匹配。方法有很多,这里提供最简单的一种。如下图,抹去此处的pushad并不会影响程序的运行,所以可以把它改成nop(对应的机器码是90)。nop是一个空指令,处理器什么都不做,但是会产生一个极短(通常为几微秒)的延迟。
保存以后,由于匹配不上特征码,ExEinfoPE已经识别不出UPX了。但是它依然具备壳的特征,再加上有三个区段,所以ExEinfoPE猜测这是个UPX。
360杀毒并没有误报。
上传到VirScan.org以后,发现TheHacker不再认为该程序是蠕虫。但是ClaimAV依然识别为UPX(说明UPX还有不少可用作识别的特征),但那并不重要。因为我们已经解决了误报问题,杀毒软件没有直接把它识别为恶意软件或者木马,这就足够了。
UPX会采取多种方式尝试压缩程序以获得较优压缩率,所以有时会匹配到其他的特征码。下面我再举一个例子。这次还是用3.91版本的UPX,但压缩的是一个体积800多KB的程序,最终匹配到了UPX V2.0的特征码。
这段特征码比较长,我们打开反汇编工具,找到它的尾部。
把“push 0x0”改成“push 0x1”即可。
上传到Virscan.org以后发现,江民杀毒软件对它的误报解除了。同时可以看到,ClaimAV这次无法识别出UPX壳。
最后,我们可以使用以下方法来进一步防止查壳。先打开刚才修改过的Dec2Frac2.exe。0x3C和0x3D对应“00 01”的是PE头的地址(反过来写,实际上地址是0x100)从0x40开始一直到PE头之前的数据可以被抹去或者覆盖,不会影响程序正常运行。“E0 00”是PE头的默认长度(224字节),我们现在可以将这224个字节覆盖到0x48这个地址上,其余的部分都写0。
覆盖以后,PE头的偏移地址为0x48,所以填“48 00”,长度为408字节,即0x198,所以填“98 01”。(注:PE头可以覆盖在0x40到原PE头地址之间的任意位置)
现在可以发现EXEinfoPE无法找到程序的入口点。(提示:如果ExEinfoPE仍然能够正常识别这个程序,把PE头靠近末尾的几个字节写0一般就可以了)但这样做可能会导致更多的杀毒引擎将其识别为可疑程序。
大家可以举一反三,尝试一下其他压缩壳的修改,并测试一下防误报的效果。
|