.net软件保护方式大观

最近调试一个运行于.net 2.0下的软件,发现该软件使用的保护方式很具有代表性,基本囊括了现在.net下的所有保护措施。实践证明,这些保护措施就像全真七子,单打独斗功力差了点儿,但结合起来应用还是有一定强度的。下面做以说明,供.net开发者参考。

1.加壳
    该软件使用MaxtoCode加壳,该壳会生成本地dll文件,在运行时通过动态挂钩.net内核解密,并且是each method解密,所以不会在内存中出现完整的assembly,使得传统的内存dump方法失效。类似的壳还有国外的Remotesoft Protector、XHEO CodeVeil、.Net Reactor。这类壳本身就提供了反调试功能,再加上壳的本地dll也被加壳,因此这一步便可以挡住80%的逆向分析者。
但是rick(http://rick.cnblogs.com)已经做出了脱壳机,所以对于这种保护的程序第一步仍是dump。脱壳后,便可利用ildasm将程序集反编译,将所有的引用本地dll的代码删除,再次编译后便可正常运行:
  .method private specialname rtspecialname static 
          void  .cctor() cil managed
  {
    // Code size       6 (0x6)
    .maxstack  8
    IL_0000:  //call       void InFaceMaxtoCode::Startup()
    IL_0005:  ret
  } // end of method xebd220b94e14b2d7::.cctor

为了减肥,也可将InFaceMaxtoCode的代码删除,这些代码还是占据了一些体积的。

2.混淆
    该软件使用了Xenocode Postbuild进行混淆,xenocode的保护包括了名称混淆和流程混淆。其中名称通常被改为如下形式:x485ea7930f0abd9a xdc0a6303c9bfe8dd。这样,代码的名称就无法代表原来的意义。
    除了名称混淆,该软件还使用了流程混淆,加入了许多垃圾代码,比如:
(1)永远为“true”或“false”的跳转判断
    IL_0086:  ldc.i4.0
    IL_0087:  brtrue.s   IL_0032

IL_0089:  ldc.i4.0
    IL_008a:  brfalse.s  IL_00e6

(2)将代码分块并添加多个跳转,所以在每个方法尾部会看到如下类似跳转表的代码
    IL_0296:  br.s       IL_029d

IL_0298:  br         IL_022c

IL_029d:  ldc.i4.0
    IL_029e:  brfalse.s  IL_026f

IL_02a0:  ldc.i4     0x3
    IL_02a5:  brtrue     IL_0227

IL_02aa:  br         IL_0204

IL_02af:  br         IL_0032

混淆过的方法在反编译为高级语言时已经非常难以分析,如下:
            if (Field34_4.Columns.Count != 0)
                goto label_11;
            bool flag2 = (flag1 - i) > 0xFFFFFFFF;
            if (!flag2)
                goto label_10;
            while (true)
            {
                if (!0)
                    goto label_4;
                Field34_1.Fill(Field34_4, Field34_2);
                return true;
            label_1:
                flag2 = (flag1 + flag1) > 0xFFFFFFFF;
                if (!flag2 && true)
                    goto label_7;
            label_2:
                Field34_4.Clear();
            }

3.字符串加密
    在win32下用wdasm查找字符串参考可能是逆向分析的第一步,.net中也是这样,一些敏感字符串会暴露程序作者的意图。不过现在的混淆程序都提供了源代码加密,比如:
    IL_0086:  ldstr      "bppkcahlaaolhafmbllmhpcnopjnikaogohoapoopjfpbpmpho"
    + "daiokainbbhnibgnpbnngclnncjmeddnlddmcepljeihafilhfbmofplfgfmmghhdh"
    IL_008b:  ldc.i4     0x3c9baf9d
    IL_0090:  call       string xb9d8bb5e6df032aa.x7841ead83ad1c299::_bc25ec13a5229081(string,int32)

这段代码解密出的字符是“This is an unregistered copy”,这样便有效地防止了程序在第一时间被定位至关键代码。开发者也可以在自己的程序中自行加入解码方法。

4.anti-deubg
    反调试就是当检测到有解密软件运行时,让程序自动退出。见如下代码:
  .method private static pinvokeimpl("user32" lasterr winapi) 
          bool  EnumWindows(class CodeLib.x41a6f5dc72fea230/xdd2ea1989d3fc452 xa479061352f99870,
                            native int x7a5eebe5d933ebbc) cil managed preservesig
  {
  }

IL_0114:  ldloc.2
    IL_0115:  ldstr      "agnhoheigglificjphjjbiakpghkkgokihflahmlahdm"//DeProtector
    IL_011a:  ldc.i4     0x50e67d1c
    IL_011f:  call       string xb9d8bb5e6df032aa.x7841ead83ad1c299::_bc25ec13a5229081(string,
                                                                                       int32)
    IL_0124:  call       string [mscorlib]System.String::Intern(string)
    IL_0129:  callvirt   instance int32 [mscorlib]System.String::IndexOf(string)
    IL_012e:  ldc.i4.m1
    IL_012f:  bgt        IL_009f

IL_0134:  br         IL_0010

IL_0139:  br         IL_01e4

IL_013e:  ldloc.2
    IL_013f:  ldstr      "mkbbemibanpbljgcimnceledjlldllcenljehgafikhfalofclfgpimgkkdhgjkhfjbiejii"//JetBrains dotTrace
    IL_0144:  ldc.i4     0x43ee1162
    IL_0149:  call       string xb9d8bb5e6df032aa.x7841ead83ad1c299::_bc25ec13a5229081(string,
                                                                                       int32)
    IL_014e:  call       string [mscorlib]System.String::Intern(string)
    IL_0153:  callvirt   instance int32 [mscorlib]System.String::IndexOf(string)
    IL_0158:  ldc.i4.m1
    IL_0159:  bgt        IL_009f

IL_015e:  ldloc.2
    IL_015f:  ldstr      "iofohpmojpdpmmkphobajoia"//WinDbg
    IL_0164:  ldc.i4     0xdd4e591
    IL_0169:  call       string xb9d8bb5e6df032aa.x7841ead83ad1c299::_bc25ec13a5229081(string,
                                                                                       int32)
    IL_016e:  call       string [mscorlib]System.String::Intern(string)
    IL_0173:  callvirt   instance int32 [mscorlib]System.String::IndexOf(string)
    IL_0178:  ldc.i4.m1
    IL_0179:  bgt        IL_009f

程序从user32.dll中调用EnumWindows枚举当前所有窗口并取得名称,和解码过的敏感字符串进行对比。虽然这种方法“层次较高”,但仍不失为一种自我保护的手段。再就是当软件要进行敏感操作,比如在注册表中保存信息,从某个文件中读取信息时,也可以使用这些手段。
    IL_0000:  ldnull
    IL_0001:  ldstr      "Registry Monitor - Sysinternals: www.sysinternals.com"
    IL_0006:  call       native int [CodeLibWin]CodeLib.Win32.WindowsAPI::FindWindow(string, string)

IL_0101:  ldnull
    IL_0102:  ldstr      "File Monitor - Sysinternals: www.sysinternals.com"
    IL_0107:  call       native int [CodeLibWin]CodeLib.Win32.WindowsAPI::FindWindow(string,string)

利用系统方法也可以进行检测是否有调试器:
    IL_002d:  call       bool [mscorlib]System.Diagnostics.Debugger::get_IsAttached()
    IL_0032:  ldc.i4.0
    IL_0033:  ceq

5.时间验证
    在关键代码处,如果进行单步跟踪调试,则从一句代码到另一句代码会运行较长时间。因此可以预估计一下正常的执行时间,然后进行对比,若超过这个时间界限,则认为被调试。代码如下:
    IL_22df:  ldloca.s   V_51
    IL_22e1:  ldloc.s    V_14
    IL_22e3:  call       instance valuetype [mscorlib]System.TimeSpan [mscorlib]System.DateTime::Subtract(valuetype [mscorlib]System.DateTime)
    IL_22e8:  stloc.s    V_52
    IL_22ea:  ldloca.s   V_52
    IL_22ec:  call       instance int32 [mscorlib]System.TimeSpan::get_Seconds()
    IL_22f1:  ldc.i4.3
    IL_22f2:  cgt

分别取两次系统时间,算出秒数差,和3秒进行对比,若大于3秒则跳转。

6.程序员自身的安全意识
    无论什么保护手段,都需要程序作者会熟练运用,并且加强自身的安全意识。不过个人觉得该软件的作者有点过了,后期基本没更新软件本身的什么功能,全用于加强保护了。汗!(另:好像还有网络验证,还没看到)

.net程序保护方式大观的更多相关文章

  1. 【.net 深呼吸】细说CodeDom(1):结构大观

    CodeDom 是啥东东?Html Dom听过吧,XML Dom听过吧.DOM一般可翻译为 文档对象模型,那 Code + DOM呢,自然是指代码文档模型了.如果你从来没接触过 CodeDom,你大概 ...

  2. PHP程序的常见漏洞攻击分析

    综述:PHP程序也不是固若金汤,随着PHP的广泛运用,一些黑客们也在无时不想找PHP的麻烦,通过PHP程序漏洞进行攻击就是其中一种.在节,我们将从全局变量,远程文件,文件上载,库文件,Session文 ...

  3. 如何保护java程序不被反编译

    Java是一种 跨平台的.解释型语言 Java 源代码编译中间“字节码”存储于class文件中.Class文件是一种字节码形式的中间代码,该字节码中包括了很多源代码的信息,例如变量名.方法名 等.因此 ...

  4. Java程序版权保护解决方案

    通常C.C++等编程语言开发的程序都被编译成目标代码,这些目标代码都是本机器的二进制可执行代码.通常所有的源文件被编译.链接成一个可执行文件.在这些可执行文件中,编译器删除了程序中的变量名称.方法名称 ...

  5. .net 程序加密

    .net 程序加密,一般是对生成的exe文件或者dll直接进行加壳,配合加密锁或者许可进行授权控制,既能保证安全性,又控制软件的使用. 加壳工具的选择 一般要考虑几点,第一是加壳的安全性,不能被轻易脱 ...

  6. 微信小程序省市区选择器对接数据库

    前言,小程序本身是带有地区选着器的(网站:https://mp.weixin.qq.com/debug/wxadoc/dev/component/picker.html),由于自己开发的程序的数据是很 ...

  7. DOS程序员手册(五)

    第8章磁           盘       学习编程语言,常常是从基本的输入和输出入手的(正如第5.6和第7章曾介绍的一 样).到目前为止,我们不仅学习了怎样输入和输出数据,还学习了如何进行数据操作 ...

  8. x86 保护方式 简介 一

    80386   三种工作方式   实模式    保护模式和虚拟86模式   只有在保护方式下  全部32条地址线才有效   可以寻址高达4g字节的物理地址空间 超过1m的内存空间  被成为扩展的内存空 ...

  9. 反混淆:恢复被OLLVM保护的程序

    译者序: OLLVM作为代码混淆的优秀开源项目,在国内主流app加固应用中也经常能看到它的身影,但是公开的分析研究资料寥寥.本文是Quarkslab团队技术博客中一篇关于反混淆的文章,对OLLVM项目 ...

随机推荐

  1. 百度2017春招<度度熊回家问题>

    题目: 一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家.现在他需要依次的从0号坐标走到N-1号坐标.但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个 ...

  2. ireport报表,打印时,报表加载失败的解决方法

    1.报表加载失败图示 2.解决方法 原创作者:DSHORE 作者主页:http://www.cnblogs.com/dshore123/ 原文出自:http://www.cnblogs.com/dsh ...

  3. mysql cursor游标的使用,实例

    mysql被oracle收购后,从mysql-5.5开始,将InnoDB作为默认存储引擎,是一次比较重大的突破.InnoDB作为支持事务的存储引擎,拥有相关的RDBMS特性:包括ACID事务支持,数据 ...

  4. 结构体对齐及#pragma详细解释

    在linux下c语言结构体对齐: 1.自然对齐 struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float 等)的变量,也可以是一些复合数据类型(如array.s ...

  5. mac pro上安装docker

    1.进入一下地址进行下载docker https://download.docker.com/mac/stable/Docker.dmg 进入后进行下载后进行安装 2.将其拖动到Appliaction ...

  6. span文字里面自动换行时怎么办

    可以用white-space:nowrap来强制文字不换行,知道遇到<br>为止

  7. Python 3.6安装教程

    0x01 安装Python 1.1 说明 目前,Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的. 本教程安装的是python-3.6.1-amd64版本. Python官 ...

  8. ActiveMQ objecmessage 无法调用问题。

    http://activemq.apache.org/objectmessage.html

  9. office 文档转pdf

    本地先安装 金山wps,并确保可用 工程目录 1.使用前,先执行install.bat 安装jacob 到maven本地仓库 2.复制 jacob-1.18-M2-x64.dlljacob-1.18- ...

  10. 前端JS框架系列之requireJS基础学习

    1 背景 伴随着项目功能的不断扩充,客户体验的不断完善,实现交互逻辑的JS代码变得越来越多.起初,为了管理JS代码,我们把JS从页面中解放出来独立成文件,接着又把相似的交互代码提取到公共的JS页面中. ...