现在.NET的程序越来越多了,很多人开始关注如何破解.NET的程序。其实个人感觉,.NET程序的破解比传统的容易多了。只要没有被加密,一般的写过程序的人,都可以按照本文的步骤,破解.NET程序。

首先,要准备几样东西:
1,ILDasm,.NET的反汇编工具,.NET Framework SDK自带的,用于程序的反汇编;
2,MSIL的参考书,比如Inside Microsoft IL之类,主要是在对IL不太熟练的情况下,用来查指令码。
3,Anakrino,.NET的反编译工具,可以把.NET的Assembly反编译成c#或者c++的代码。用于分析程序流程。下载地址:
http://test.saurik.net/anakrino/
4,UltraEdit,二进制编辑器,用于搜索、修改.NET可执行程序。

这次我们的目标是一个c#代码生成器,在这里下载:
http://www.gavinjoyce.com/nTierGen/default.aspx 。安装了试用版之后,在 c:\program files\www.gavinjoyce.com\.net n-tier framework generator evaluation 1.2 里面找到 nTierGen.eval.1.2.exe 和 Microsoft.ApplicationBlocks.Data.DLL。后一个dll好像跟破解没有太大关系。OK,Let’’s go!

第一步:分析定位代码。用Anakrino打开 nTierGen.eval.1.2.exe。在Atweb.CodeGet.Wizard名字空间下,有一个frmWizard。这就是程序的主窗口了。在主窗口里面,有一个事件响应方法叫做 btnNext_Click,在里面找到了这样的代码:
if (this.panel2.Visible) {
local2 = Helper.IsCaseStudy(this.proj.dbTree);
if (this.chkListTables.CheckedItems.Count > this.MAX_TABLES && !(local2))
MessageBox.Show("This evaluation release is restricted to " + this.MAX_TABLES.ToString() + " tables. Extra tables have been removed.");
local3 = new TableCollection();
local4 = 0;
while (local4 < this.chkListTables.Items.Count) {
local5 = (String) this.chkListTables.Items.get_Item(local4);
if (this.chkListTables.GetItemChecked(local4) && local3.Count < this.MAX_TABLES || local2)
local3.Add(this.proj.dbTree.Tables.Item(local5));
this.proj.dbTree.Tables.Remove(this.proj.dbTree.Tables.Item(local5).ToString());
local4++;
}
this.proj.dbTree.Tables = local3;
this.Panel2Init();
this.HidePanels();
this.panel3.Visible = true;
this.RefreshViewList();
return;
}

可以看出,当用户选定了表之后,按Next按钮,他就检查选择的数量。如果>this.MAX_TABLES,就Show出一个MessageBox,接下来就只选择前this.MAX_TABLES个表。OK,目标就在这里了。

第二步:制定策略。显然,这个MAX_TABLES是程序里面的一个常量,用于限制表的个数。我们只要把这个常量改得大一些,不就行了吗?好,试试看。

.class /*0200003F*/ public auto ansi beforefieldinit ”frmWizard”
extends [”System.Windows.Forms”/* 23000002 */>”System.Windows.Forms”.”Form”/* 01000004 */
{
.field /*04000098*/ private int32 ”MAX_TABLES”
.field /*04000099*/ private bool ”ENCRYPT_TREE”
.field /*0400009A*/ private string ”LICENSED_TO”
.field /*0400009B*/ private string ”LICENSED_TO_COMPANY”
…..


instance void .ctor() cil managed
// SIG: 20 00 01
{
// Method begins at RVA 0xb0b8
// Code size 218 (0xda)
.maxstack 5
.locals /*11000049*/ init (string[> V_0)
IL_0000: /* 02 | */ ldarg.0
IL_0001: /* 19 | */ ldc.i4.3
IL_0002: /* 7D | (04)000098 */ stfld int32 ”Atweb.CodeGen.Wizard”.”frmWizard”/* 0200003F */::”MAX_TABLES” /* 04000098 */

在frmWizard的构造函数里面,IL_0001这个地方,ldc.i4.3,让MAX_TABLES=3。再看看IL的指令:
ldc.i4 <int32> (0×20) Load <int32> on the stack.
ldc.i4.s <int8> (0×1F) Load <int8> on the stack.
ldc.i4.m1 (ldc.i4.M1) (0×15) Load -1 on the stack.
ldc.i4.0 (0×16) Load 0.
ldc.i4.1 (0×17) Load 1.
ldc.i4.2 (0×18) Load 2.
ldc.i4.3 (0×19) Load 3.
ldc.i4.4 (0×1A) Load 4.
ldc.i4.5 (0×1B) Load 5.
ldc.i4.6 (0×1C) Load 6.
ldc.i4.7 (0×1D) Load 7.
ldc.i4.8 (0×1E) Load 8. (I should have listed these in reverse order so then we could imagine ourselves on Cape Canaveral.)
ldc.i8 <int64> (0×21) Load <int64> on the stack.
ldc.r4 <float32> (0×22) Load <float32> (single-precision) on the stack.
ldc.r8 <float64> (0×23) Load <float64> (double-precision) on the stack. ILAsm permits the use of integer parameters in both the ldc.r4 and ldc.r8 instructions; in such cases, the integers are interpreted as binary images of the floating-point numbers.


可以看出,IL只用了一个byte来给MAX_TABLE赋值,跟我们以往的x86 ASM有所不同。把ldc.i4.3改成ldc.i4.8,也就是把0×19改称0×1E,看看效果如何。用UltraEdit搜索出02 19 7D 98 00 00 04,然后把19改成1E,保存,运行,程序显示“最大8个表”等等,看来就着一个地方了。
从IL指令来看,一个byte最大赋值8,显然8个表还是太少了。怎么办?


IL_0197: /* 09 | */ ldloc.3
IL_0198: /* 6F | (0A)000017 */ callvirt instance int32 [”mscorlib”/* 23000001 */>”System.Collections”.”CollectionBase”/* 01000002 */::”get_Count”() /* 0A000017 */
IL_019d: /* 02 | */ ldarg.0
IL_019e: /* 7B | (04)000098 */ ldfld int32 ”Atweb.CodeGen.Wizard”.”frmWizard”/* 0200003F */::”MAX_TABLES” /* 04000098 */
IL_01a3: /* 32 | 03 */ blt.s IL_01a8

IL_01a5: /* 08 | */ ldloc.2
IL_01a6: /* 2C | 1D */ brfalse.s IL_01c5

IL_01a8: /* 09 | */ ldloc.3
IL_01a9: /* 02 | */ ldarg.0


在IL_01a3这个地方,比较MAX_TABLE,如果小于则跳转。OK,如果我们在赋值的时候,给一个-1,然后把有符号数的比较改成无符号数的比较,不就可以支持最多256个表了吗?OK!

第五步:最后的修改。搜索出上次02 19 7D 98 00 00 04的地方,把19改成15,也就是变成ldc.i4.m1;再搜索出7B 98 00 00 04 32这个地方,把blt.s改成blt.un.s,也就是把32改成37,保存,运行,程序显示支持"-1"个表,实际上支持256个表,。。。。

最后总结:.NET程序修改过程中,很容易出执行引擎的错误,所以修改的地方越少越好。当然,熟练之后可以想怎么改就怎么改了。另外,熟悉c#语言,熟悉IL也非常有帮助。怎么样,想不想马上试试看?


评论

该日志第一篇评论

发表评论

评论也有版权!