.net IL 反编译实战

因为悲催的专家系统,我要破个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) 以上文章是经过本人设计实践和阅读其他文档得出。如果需要探讨或指教可以留言!欢迎交流!

转载于:https://my.oschina.net/mahaisong/blog/140432

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值