.net程序保护方式大观
.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程序保护方式大观的更多相关文章
- 【.net 深呼吸】细说CodeDom(1):结构大观
CodeDom 是啥东东?Html Dom听过吧,XML Dom听过吧.DOM一般可翻译为 文档对象模型,那 Code + DOM呢,自然是指代码文档模型了.如果你从来没接触过 CodeDom,你大概 ...
- PHP程序的常见漏洞攻击分析
综述:PHP程序也不是固若金汤,随着PHP的广泛运用,一些黑客们也在无时不想找PHP的麻烦,通过PHP程序漏洞进行攻击就是其中一种.在节,我们将从全局变量,远程文件,文件上载,库文件,Session文 ...
- 如何保护java程序不被反编译
Java是一种 跨平台的.解释型语言 Java 源代码编译中间“字节码”存储于class文件中.Class文件是一种字节码形式的中间代码,该字节码中包括了很多源代码的信息,例如变量名.方法名 等.因此 ...
- Java程序版权保护解决方案
通常C.C++等编程语言开发的程序都被编译成目标代码,这些目标代码都是本机器的二进制可执行代码.通常所有的源文件被编译.链接成一个可执行文件.在这些可执行文件中,编译器删除了程序中的变量名称.方法名称 ...
- .net 程序加密
.net 程序加密,一般是对生成的exe文件或者dll直接进行加壳,配合加密锁或者许可进行授权控制,既能保证安全性,又控制软件的使用. 加壳工具的选择 一般要考虑几点,第一是加壳的安全性,不能被轻易脱 ...
- 微信小程序省市区选择器对接数据库
前言,小程序本身是带有地区选着器的(网站:https://mp.weixin.qq.com/debug/wxadoc/dev/component/picker.html),由于自己开发的程序的数据是很 ...
- DOS程序员手册(五)
第8章磁 盘 学习编程语言,常常是从基本的输入和输出入手的(正如第5.6和第7章曾介绍的一 样).到目前为止,我们不仅学习了怎样输入和输出数据,还学习了如何进行数据操作 ...
- x86 保护方式 简介 一
80386 三种工作方式 实模式 保护模式和虚拟86模式 只有在保护方式下 全部32条地址线才有效 可以寻址高达4g字节的物理地址空间 超过1m的内存空间 被成为扩展的内存空 ...
- 反混淆:恢复被OLLVM保护的程序
译者序: OLLVM作为代码混淆的优秀开源项目,在国内主流app加固应用中也经常能看到它的身影,但是公开的分析研究资料寥寥.本文是Quarkslab团队技术博客中一篇关于反混淆的文章,对OLLVM项目 ...
随机推荐
- 报错:/application/zabbix/sbin/zabbix_server: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object file: No such file or directory
启动zabbix_server时报错: /application/zabbix/sbin/zabbix_server: error while loading shared libraries: li ...
- Denoise Autoencoder简单理解
自编码器通过学习隐含特征来表达原始数据,那什么是denoise autoencoder呢? 关于Autoencoder参考:http://blog.csdn.net/on2way/article/de ...
- Java学习(一)Scanner报错java.util.NoSuchElementException
我在一个方法A中使用了Scanner的 Scanner input=new Scanner(System.in),随后又将其关闭了,因为Eclipse里面你若不关闭,他会有一个warning:Reso ...
- 458. Poor Pigs
There are 1000 buckets, one and only one of them contains poison, the rest are filled with water. Th ...
- day6 os模块
OS模块 提供对操作系统进行调用的接口 (1)os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 >>> os.getcwd() 获取 ...
- umask相关内容
umask权限过滤符新创建的文件的权限为666,即- rw- rw- rw-新创建的目录的权限为777,即d rwxrwxrwx如umask值为0022,后三位022,即 --- -w- -w-上述默 ...
- SQL 如何查找一个表里,每个班级各个学科的最高分?
SQL 如何查找一个表里,每个班级各个学科的最高分? 学生表:STUDENT(S#,SNAME,SAGE,SSEX,CLASSNO) 班级表:CLASS(CLASSNO,CLASSNAME) 课程表: ...
- sublimetext3-实用快捷键整理
实用快捷键 Ctrl+Shift+P:打开命令面板Ctrl+P:搜索项目中的文件Ctrl+G:跳转到第几行Ctrl+W:关闭当前打开文件Ctrl+Shift+W:关闭所有打开文件Ctrl+Shift+ ...
- 长沙理工大学第十二届ACM大赛-重现赛 L - 选择困难症
题目描述 小L有严重的选择困难症. 早上起床后,需要花很长时间决定今天穿什么出门. 假设一共有k类物品需要搭配选择,每类物品的个数为Ai,每个物品有一个喜欢值Vj,代表小L对这件物品的喜欢程度. 小L ...
- 应用服务攻击工具clusterd
应用服务攻击工具clusterd clusterd是一款Python语言编写的开源应用服务攻击工具.该工具支持七种不同的应用服务平台,如JBoss.ColdFusion.WebLogic.Tomc ...