一次失败的加壳经历
原因
也不知道从什么时候开始,C#编写的程序在部分杀毒软件下总是被视为病毒感染者、携带者。作为一个360的资深用户(第一次使用是07年),最开始用它还是在大学时期在电脑城装机的时候,用来清除Ghost系统捆绑的插件和内置启动项。
经过这些年360的迅猛成长,已经将它的触角越伸越长,长到让作为电脑拥有者的我感到在和它争抢系统的控制权,终于在2012年选择将其从系统中卸载,从此过上了安静祥和的日子。直到最近团队当中有新成员开始反馈某些工具被360视为病毒,并且直接隔离。
其实最开始的时候360对于C# 应用程序的歧视我们大多数人选择了忽视它,但这次在新手面前感到“前辈”所担负的责任,让我有了想将之解决的冲动。于是就有了接下来的经历,虽然这是一失败的经历,却为下一次成功做好了准备。
经过
首先在Google上进行了大肆的搜刮,Firefox标签被挤成了只剩图标,接下来就一个一个审阅。看到最后得出以下结果,并非全部:
- 改变程序大小(瘦身、增肥)
- 将exe压缩,或混淆(压缩执行文件,并非rar之类的将文件打包,这里也在网上找到一个不错的工具,名叫:Visual MPRESS 2014 预览版)
- 修改文件头,以骗过扫描(未验证,有网友说现在的杀毒软件已经变得聪明了骗不鸟了)
- 代码层面加壳(正是本文所涉及的)
对于瘦身或增肥试了下,有效果但找不到应用场景。而第二种方式被利用起来,可以给心爱的程序一个保障。那下面就来说说本次加密代码的大概逻辑。杀毒软件在扫描文件时查找可执行文件的特征码,若发现可疑的特征码则发出预警,而这段代码是意义在于改变程序入口使得杀毒软件不能正确的查找全部文件,以此躲避扫描。大概就这意思,对于杀毒软件我是没有特别的研究过。
第一次采用了将exe压缩的方法来躲避360的扫描,完成后用本机的杀毒软件进行测试发现一切正常,于是在群里高调的宣告自己解决了C#应用程序的尴尬问题,没想到下午就有人在群里截图,内容是360再次将文件隔离,我感觉我的脸被狠狠的扇了一巴掌,火辣辣的那种。于是再次打开浏览器进行搜索,经历一番查找后再次找到了第四种方法。
之所以说是再次是因为前面尝试过一次,但始终无法运行,不同的是这次找到了不能运行的原因,原因就是我先将可执行文件加密后再放入文件编译,导致程序不能正确加载,下面就是那段代码。
using System;
using System.IO;
using System.Reflection;
namespace Publish.Shell
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("命名空间.应用程序名称.exe");
byte[] buffer = new byte[manifestResourceStream.Length];
manifestResourceStream.Read(buffer, 0, ((int)manifestResourceStream.Length) - 1);
Assembly.Load(buffer).EntryPoint.Invoke(null, null);
}
}
}
将该代码放置于 Program Main 方法中即可。哦还要将文件复制到项目中并设置为内嵌资源(Embedded Resource)。如此这般后该应用程序真正的代码就成了以上代码,通过编译后的IL代码为:
从IL代码来看,该应用程序看起来什么事也没做。这也就达到了代码加壳的目的了。进过本地的Defender、360安全卫士、360杀毒扫描测试,它们都一致认为该文件很安全。看起来所谓的问题似乎就这样完美的解决了,为此我这周的心情都十分的愉悦,感觉我的投入得到了回报,甚至感觉个人的能力得到了提升。
结局
随着时间的推移,我的自豪感和愉悦感也慢慢的消退,知道今天再次将编译好的新版直接发送给团队成员时,对方告诉我文件被隔离了。很显然该死的360又将特征库更新,再次将之认为是病毒携带者或传播者。于是为了总结出本次的经历,仅仅是经历,就有了这篇博客。同时望有良方的前辈高人慷慨解囊,救死扶伤。他日功成名就之时,定当不忘恩情。