Chinaunix首页 | 论坛 | 博客
  • 博客访问: 225597
  • 博文数量: 14
  • 博客积分: 1415
  • 博客等级: 上尉
  • 技术积分: 780
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-22 08:45
文章分类

全部博文(14)

文章存档

2011年(1)

2009年(1)

2008年(12)

我的朋友

分类:

2008-05-06 17:43:52

Dot Net项目用Reflector反编译时的switch问题
DotNet的DLL和程序没有混淆时,可以用Reflector反编译产生源码,技术难度如此之低,完全是体力活;
但是问题产生在原始程序是用VB写的,这下项目组给反编成C#了;
这样的结果是产生的try catch结构和VB的try catch endtry不一样;
问题也随之而来;
vb中catch部分的代码里如果有goto语句,是可以跳回try部分的;
但是c#中catch里的goto语句就没办法跳回try部分了;
 
这个问题尤其突出的体现在vb代码中使用了 on error resume next这样的语句时;
虽然那不是个好习惯,但仍然有许多人在用;
鬼知道创建遗留工程的人是什么样的;
vb代码中使用on error语句的时,会在结果IL里面附加一个switch结构,并在每一行代码前面加一个标号;
这样就可以在每次出错时处理完异常后跳回出错的地方继续执行下一条语句;
以下是一个测试用的vb函数:
    Private Sub Test() 
        On Error Resume Next
        Dim num2 As Integer = 5
        Dim i As Integer = 0
        Do While (i <= num2)
            If num2 > 5 Then
                Return
            End If
            i += 1
        Loop
    End Sub
 
 
以下是用Reflector反出来的C#代码;
private  ()
{
    // This item is obfuscated and can not be translated.
     VB$ResumeTarget;
    try
    {
         VB$CurrentStatement;
    Label_0001:
        .();
         VB$ActiveHandler = -2;
    Label_000A:
         = 2;
         num2 = 5;
    Label_000F:
         = 3;
         i = 0;
        goto Label_0033;
    Label_0016:
         = 6;
        if ( > 5)
        {
            goto Label_00D5;
        }
    Label_002A:
         = 9;
        ++;
    Label_0033:
         = 5;
        if ( <= )
        {
            goto Label_0016;
        }
        goto Label_00D5;
    Label_004C:
         = 0;
        switch (( + 1))
        {
            case 1:
                goto Label_0001;

            case 2:
                goto Label_000A;

            case 3:
                goto Label_000F;

            case 4:
            case 5:
            case 10:
                goto Label_0033;

            case 6:
                goto Label_0016;

            case 7:
            case 11:
                goto Label_00D5;

            case 8:
            case 9:
                goto Label_002A;

            default:
                goto Label_00CA;
        }
    Label_008A:
         = ;
        switch ((( > -2) ?  : 1))
        {
            case 0:
                goto Label_00CA;

            case 1:
                goto Label_004C;
        }
    }
    catch ( obj1) when (?)
    {
        .(() );
        goto Label_008A;
    }
Label_00CA:
    throw .(-2146828237);
Label_00D5:
    if ( != 0)
    {
        .();
    }
}
从代码里可以看到,实际上vb的编译器为代码增加了异常处理的结构;
VB$ResumeTarget; VB$CurrentStatement;
这两个东西用来保存保存状态,保证异常处理后回到事发地点;
程序从入口处顺序执行,
执行任何一条代码之前先给 设置数值,起到程序指针的作用;
一旦运行的代码出错,程序转入catch部分运行,
catch部分仅仅设置一个异常对象后转到Label_008A 处;之后转入switch部分;
switch部分根据VB$ResumeTarget决定跳回何处继续运行;
思路明确了就知道如何修改了;
Label_004C: 到函数结尾的代码全部删除,这些和原始代码的逻辑没任何关系;
把所有 的赋值语句全部删除;
剩下的工作就是根据goto的逻辑恢复原来的if while 之类的结构,很简单了;
阅读(4555) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-05-07 10:45:09

very good