这篇文章我们将介绍怎么获取解密后的IL字节代码。
我们先回顾一下前文,在上一回我们提到“InFaceMaxtoCode.Startup 正常启动后,在整个程序集中只会运行一次。”。
当时这种说法是很武断的,如果 “InFaceMaxtoCode.C______(num2, num3)” 的返回值总是 false的话,该函数就会被执行多次,
不过根据后来动态调试的结果,我们证实了“InFaceMaxtoCode.C______(num2, num3)” 的返回值为 true,因此上次的说法是正确的。
现在言归正传,怎么取得解密后的代码呢?大概两个方向,
1.正面交锋,直接攻破maxtocode的运行库。
这就将问题直接回到了传统的win32层面,不过这个东西是业内人士写的在这方面的保护工作做得很好,像我这样的菜鸟就很难直接攻破了。
我曾有一个设想,就是通过分析运行库找到解密函数的入口,然后弄一个stub dll,hook这个地方,把解密后的il代码dump出来。
实际跟踪几次后我就放弃了。从跟踪到的信息来看,我猜测,运行库是通过 mscorwks.dll 挂接到 jit,在jit的前面实时解密代码。
理论上我们也可以挂一个到jit前面,在那里dump解密的il代码,不过这个实现的方式,还不清楚,如果弄明白了,也就能写一个同样原理的加密软件了。
这个难度比较大,所以我最终放弃了这个方案。
2.避开运行库,我们直接利用dotNet 2.0的特性获取IL代码。
如是我就试着用2.0写了一个winform程序,加密,运行,发现报错。
maxtocode3.1不支持2.0的winform程序,这就使我的这个方案实验夭折了。
两个月过去了,发现maxtocode升级到3.11了修正了这个bug,今天终于可以继续实验了。
我们来建一个简单的winform程序。一个窗体,然后一个按钮。
代码如下:
1
using
System;
2
using
System.Collections.Generic;
3
using
System.ComponentModel;
4
using
System.Data;
5
using
System.Drawing;
6
using
System.Text;
7
using
System.Windows.Forms;
8
using
System.Reflection;
9
using
Spaces;
10
namespace
Test5
11
{
12
public
partial
class
Form1 : Form
13
{
14
public
Form1()
15
{
16
InitializeComponent();
17
}
18
19
private
void
TestMethod()
20
{
21
//
[7/17/2006]
22
int
i
=
0
;
23
i
=
1
;
24
i
++
;
25
if
(i
>
0
)
26
{
27
MessageBox.Show(
"
OK
"
);
28
}
29
}
30
31
private
void
button1_Click(
object
sender, EventArgs e)
32
{
33
Type tp
=
this
.GetType();
34
35
MethodInfo mi
=
tp.GetMethod(
"
TestMethod
"
,
36
BindingFlags.NonPublic
|
BindingFlags.DeclaredOnly
|
37
BindingFlags.Public
|
BindingFlags.Static
38
|
BindingFlags.Instance);
39
if
(mi
==
null
)
40
{
41
MessageBox.Show(
"
err
"
);
42
return
;
43
}
44
MethodBody mb
=
mi.GetMethodBody();
45
byte
[] bt
=
mb.GetILAsByteArray();
46
StringBuilder sb
=
new
StringBuilder();
47
for
(
int
i
=
0
; i
<
bt.Length; i
++
)
48
{
49
sb.Append(bt[i].ToString(
"
X2
"
));
50
sb.Append(
"
"
);
51
}
52
string
stxt
=
sb.ToString();
53
MessageBox.Show(stxt);
54
55
}
56
57
}
58
}
编译运行,我们点击按钮就能看到 TestMethod 的IL字节码。
然后用maxtocode加密在运行,同样能看到 TestMethod 的IL字节码。
两次看到的结果一样的,这个是当然了,如果不一样,maxtocode就破坏了程序的正确性了。
好了,我们的实验成功了。
看到这里大家应该知道怎么获取解密后的IL代码了吧。
这种方式比在内存里面找代码或者hook到maxtocode解密后dump代码的方式要优越很多,
因为内存dump的方式你还要担心运行时的函数覆盖率,没有运行到的就dump不到。
这种方式我们利用 DotNet的反射机制,可以枚举出程序集中的所有类型,以及每个类型的所有方法,成员,字段,构造函数等。
初步实验了一下,对于加了密的dll文件还是比较好弄的,2.0的、1.1的都能弄出IL代码来。
对于exe文件还有一关需要解决,那就是如何将我们的DotNet dll程序集插入到exe的运行空间中去。
今回就先到这里了,下回再实际写程序演练获取解密后的IL字节代码。