因为悲催的专家系统,我要破个DLL。
另外: IL会把大量的FOR,WHILE 都变成switch语句。
于是我犯下大错。 拿着swtich直接阅读, 导致拖延了好几天进度, 幸好自己想到,应该做代码的转换。
1.首先, DLL文件的代码格式为:
.method public hidebysig virtual instance void a(int32 A_0) cil managed { .maxstack 3 .locals init ( [0] int32 num, [1] int32 num2, [2] int32 num3) L_0000: br.s L_003f L_0002: ldloc num3 L_0006: switch (L_012c, L_00c9, L_0152, L_00f5, L_00e2, L_00b7, L_0065, L_019b, L_0184, L_009d, L_0082, L_004e, L_0165) L_003f: ldc.i4.1 L_0040: stloc.0 L_0041: ldc.i4.0 L_0042: stloc.1 L_0043: ldc.i4 11 L_0048: stloc num3 L_004c: br.s L_0002 L_004e: br L_0157 L_0053: ldarg.0 L_0054: ldloc.0 L_0055: stfld int32 a::c L_005a: ldc.i4 6 L_005f: stloc num3 L_0063: br.s L_0002 L_0065: ldsfld class [System]System.Collections.Generic.SortedList`2<int32, int32> a::b L_006a: ldarg.0 L_006b: ldfld int32 a::e L_0070: callvirt instance bool [System]System.Collections.Generic.SortedList`2<int32, int32>::ContainsKey(!0) L_0075: brtrue.s L_00cb L_0077: ldc.i4 10 L_007c: stloc num3 L_0080: br.s L_0002 L_0082: ldc.i4.1 L_0083: br.s L_0088 L_0085: ldc.i4.0 L_0086: br.s L_0088 L_0088: brfalse.s L_008a L_008a: br L_012e L_008f: ldc.i4 9 L_0094: stloc num3 L_0098: br L_0002 L_009d: ldarg.0 L_009e: ldfld int32 a::c L_00a3: ldloc.0 L_00a4: beq L_019d L_00a9: ldc.i4 5 L_00ae: stloc num3 L_00b2: br L_0002 L_00b7: br.s L_0053 L_00b9: ldc.i4.0 L_00ba: stloc.0 L_00bb: ldc.i4 1 L_00c0: stloc num3 L_00c4: br L_0002 L_00c9: br.s L_008f L_00cb: ldarg.0 L_00cc: ldarg.1 L_00cd: ldc.i4.1 L_00ce: add L_00cf: call instance void a::a(int32) L_00d4: ldc.i4 4 L_00d9: stloc num3 L_00dd: br L_0002 L_00e2: br L_019d L_00e7: ldc.i4 3 L_00ec: stloc num3 L_00f0: br L_0002 L_00f5: ldsfld class [mscorlib]System.Collections.Generic.List`1<class a> a::a L_00fa: ldarg.0 L_00fb: ldfld class [mscorlib]System.Collections.Generic.List`1<int32> a::f L_0100: ldloc.1 L_0101: callvirt instance !0 [mscorlib]System.Collections.Generic.List`1<int32>::get_Item(int32) L_0106: callvirt instance !0 [mscorlib]System.Collections.Generic.List`1<class a>::get_Item(int32) L_010b: ldfld int32 a::c L_0110: ldarg.0 L_0111: ldfld class [mscorlib]System.Collections.Generic.List`1<int32> a::g L_0116: ldloc.1 L_0117: callvirt instance !0 [mscorlib]System.Collections.Generic.List`1<int32>::get_Item(int32) L_011c: beq.s L_0189 L_011e: ldc.i4 0 L_0123: stloc num3 L_0127: br L_0002 L_012c: br.s L_00b9 L_012e: ldsfld class [System]System.Collections.Generic.SortedList`2<int32, int32> a::b L_0133: ldarg.0 L_0134: ldfld int32 a::e L_0139: ldarg.0 L_013a: ldfld int32 a::e L_013f: callvirt instance void [System]System.Collections.Generic.SortedList`2<int32, int32>::Add(!0, !1) L_0144: ldc.i4 2 L_0149: stloc num3 L_014d: br L_0002 L_0152: br L_00cb L_0157: ldc.i4 12 L_015c: stloc num3 L_0160: br L_0002 L_0165: ldloc.1 L_0166: ldarg.0 L_0167: ldfld class [mscorlib]System.Collections.Generic.List`1<int32> a::f L_016c: callvirt instance int32 [mscorlib]System.Collections.Generic.List`1<int32>::get_Count() L_0171: blt L_00e7 L_0176: ldc.i4 8 L_017b: stloc num3 L_017f: br L_0002 L_0184: br L_008f L_0189: ldloc.1 L_018a: ldc.i4.1 L_018b: add L_018c: stloc.1 L_018d: ldc.i4 7 L_0192: stloc num3 L_0196: br L_0002 L_019b: br.s L_0157 L_019d: ret } |
|
因为这段代码不好看懂。于是使用工具reflector.net工具。得到C#代码
注意:一定要 展开代码。
Expand Methods
关于 静态的字段 和构造函数, 一定要 在展开后再仔细查看。 我因为没展开,摸不着头脑,浪费了时间。
// Methods
static b();
public b();
2.看看小代码
public override void a(int A_0) { // This item is obfuscated and can not be translated. int num; int num2; int num3; goto Label_003F; Label_0002: switch (num3) { case 0: num = 0; num3 = 1; goto Label_0002; case 1: case 8: num3 = 9; goto Label_0002; case 2: goto Label_00CB; case 3: if (a.a[base.f[num2]].c == base.g [num2]) { num2++; num3 = 7; } else { num3 = 0; } goto Label_0002; case 4: return; case 5: base.c = num; num3 = 6; goto Label_0002; case 6: if (a.b.ContainsKey(base.e)) { goto Label_00CB; } num3 = 10; goto Label_0002; case 7: case 11: num3 = 12; goto Label_0002; case 9: if (base.c == num) { return; } num3 = 5; goto Label_0002; case 10: goto Label_0088; if (1 == 0) { } a.b.Add(base.e, base.e); num3 = 2; goto Label_0002; case 12: if (num2 < base.f.Count) { num3 = 3; } else { num3 = 8; } goto Label_0002; } Label_003F: num = 1; num2 = 0; num3 = 11; goto Label_0002; Label_00CB: base.a(A_0 + 1); num3 = 4; goto Label_0002; } |
于是我就拿着一堆这样的C#代码去在VS中跑。发现大量goto Label_0088; 这种找不到的标签。
很容易发现,标签就在 函数 上面和下面, 标记上,OK。 可是发现转换后的C#代码是逻辑上有问题的。
无奈,(阅读IL文件)每个方法对应IL代码的流程 去做了修改。 (费劲啊,费劲啊)
修改完成之后,终于能运行了。 发现没有出错。
3.看看小代码
public override void a_af(int A_0) { //重写A类中a_af方法,即E类可以使用 int num = 1; int num2 = 0; int num3 = 11; Label_0002: switch (num3) { case 0: num = 0; num3 = 1; goto Label_0002; case 1: case 8: num3 = 9; goto Label_0002; case 2: base.a_af(A_0 + 1); num3 = 4; goto Label_0002; case 3: if (a.a_ap[base.a_fp[num2]].a_cp == base.a_gp[num2]) { //C类的结论中的 // 找到对应事实索引的C类 比对 cp 与 结论的原状态。 状态一直不做操作。 num2++; num3 = 7; } else { num3 = 0; } goto Label_0002; case 4: return; case 5: base.a_cp = num; //规则的CP=num num3 = 6; goto Label_0002; case 6: if (a.a_bp.ContainsKey(base.a_ep)) // abp是空 aep也是未用到的值。 { base.a_af(A_0 + 1); num3 = 4; } else { num3 = 10; } goto Label_0002; case 7: case 11: num3 = 12; goto Label_0002; case 9: if (base.a_cp == num) // 规则的CP=Num吗? { break; } else { num3 = 5; goto Label_0002; } case 10: a.a_bp.Add(base.a_ep, base.a_ep); num3 = 2; goto Label_0002; case 12: if (num2 < base.a_fp.Count) // 结论的事实索引的数量 { num3 = 3; } else { num3 = 8; } goto Label_0002; } } |
++++++++++++++++++++悲催的逻辑理解开始了。++++++++++
这种swtich的特别难理解。 我用了两天天才理解出来一部分,稍复杂的地方,还不理解。
确实在稍复杂的地方卡壳了。 而且我有点小急。于是越急越分析不明白。 后来心态踏实下来。即使不能按时搞定,也要踏实的分析明白,于是我才下决心动手修改。
一修改不打紧,发现修改后阅读效率高太多了。我要早修改,肯定能早做出来了。
4.先修改的是which版本的。
修改which版 两个注意
4.1 先把 case中的 一部分零散的不是主要逻辑的地方合并起来。
4.2 先把swtich修改成 which(true) ,这样后面改起来方便。
然后根据逻辑嵌入到which中即可,break部分改为return。
(先不要管是否代码简略,执行测试成功。)
5.成功后。 为了阅读更方便,代码更简略。仔细看看每个方法的结构。
是否可以改成for循环。
/// <summary> /// 一条规则中的多个条件 /// </summary> /// <param name="A_0"></param> public override void QListFRule(int A_0)//重写A类中方法 { int suc = 1;//初始规则成立 for (int i = 0; i < base.A_RuleQIndex.Count; i++) { if (RulesRelationBasic.RulesList[base.A_RuleQIndex[i]].IsSuc != base.A_State[i]) { //条件不成立 suc = 0; break; } } if (base.IsSuc != suc) //上次其他条件计算的本规则的IsSuc,与本次(条件不成立num=0,)(算完了num=1)是否相同 { base.IsSuc = suc; //规则成立 =本次结果。(条件不成立num=0,)(算完了num=1) if (RulesRelationBasic.Result.ContainsKey(base.Index)) //此规则index是否存在Result 成立结论中。 { base.QListFRule(A_0 + 1); return; } else { RulesRelationBasic.Result.Add(base.Index, base.Index); base.QListFRule(A_0 + 1); return; } } } |
改完之后。发现真好阅读,难怪高级语言发展这么快,难怪项目要求编码格式和简略。
到这里再次执行,正常。
到这里我才能快速的去学习DLL中的代码思路。 真是浪费了不少时间。共享给大家,一起怀挺。
总结: 请按照本文5步走去做IL的反编译。 能省不少弯路。
本人声明:沐海(http://my.oschina.net/mahaisong) 以上文章是经过本人设计实践和阅读其他文档得出。如果需要探讨或指教可以留言!欢迎交流!