C#反编译winform工程代码的改错方法总结

本次反编译用的是IL Spy工具,反编译的是winform程序,反编译后需要修改的代码主要有以下几种情况:
1、复杂lamda表达式反编译后会被拆解成多个部分,比较乱,如下例,出现这种情况的基本都是:

//反编译后代码
private sealed class <>c
{
	public static readonly ControlUtil。<>c <>9 = new ControlUtil.<>c(); 
	public static CancelEventHandler <>9__54_0;
	public static CancelEventHandler <>9__55_0;
 
	internal void <SetEditorString4Name>b__54_0(object s, CancelEventArgs e)
	{
		ControlUtil.txtEditor_EditValueChanging_4StringCommonName(s, new ChangingEventArgs(string.Empty, (s as TextEdit).Text));
	} 
}

//调用处
Control arg_4D_0 = txtEditor;
CancelEventHandler arg_4D_1;
if ((arg_4D_1 = DevControlUtil.<>c.<>9__54_0) == null)
{
	arg_4D_1 = (ControlUtil.<>c.<>9__54_0 = new CancelEventHandler(ControlUtil.<>c.<>9.<SetEditorString4Name>b__54_0));
}
arg_4D_0.Validating += arg_4D_1;

改成正常代码后应该是

public void SetEditorString4Name(TextEdit txtEditor)
{
    txtEditor.Validating += (sender, e) =>
    {
        ControlUtil.txtEditor_EditValueChanging_4StringCommonName(sender, new ChangingEventArgs(string.Empty, (sender as TextEdit).Text));
    };
}

出现以上情况的基本都是lamda表达式,只要熟悉c#语法,理解逻辑,然后转换成正常写法就可以了。

2、部分switch语句中,如果是switch后的表达式是字符型,反编译后也会出现乱码,如下所示:

//switch部分代码  完整代码太长了
uint num = <PrivateImplementationDetails>.ComputeStringHash(skinName);
if (num <= 1961623285u)
{
	if (num <= 1360554982u)
	{
		if (num != 721696580u)
		{
			if (num != 940092246u)
			{
				if (num != 1360554982u)
				{
					return;
				}
				if (!(skinName == "iMaginary"))
				{
					return;
				}
				this.iMaginary.Checked = true;
				return;
			}
			else
			{
				if (!(skinName == "Lilian"))
				{
					return;
				}
				this.iLilian.Checked = true;
				return;
			}
		}
		else
		{
			if (!(skinName == "Black"))
			{
				return;
			}
			this.iBlack.Checked = true;
			return;
		}
	} 
} 

修改后的代码为:

		
switch(skinName)
  {
       case "iMaginary":
           this.iMaginary.Checked = true;
           break;
       case "Lilian": 
           this.iLilian.Checked = true;
           break;
       case "Black":
           this.iBlack.Checked = true;
           break;
       case "London Liquid Sky.DevExpressEx":
           this.iLondoLiquidSky.Checked = true;
           break;
       case "Glass Oceans":
           this.iGlassOcean.Checked = true;
           break;
       case "Office 2007 Silver":
           this.iOffice2007Silver.Checked = true;
           break; 
   }

3、窗体文件还原
这块一开始我是参照正常窗体需要的文件格式去挨个还原的,即一个窗体有一个.cs文件,一个.Designer.cs文件,一个.resx文件。反编译后的文件是将前两个合到一个文件里了,资源文件是一个.resources文件,即一个.cs文件,一个.resources文件,而这个资源文件vs是不识别的。还原过程如下:
1)、参照其他人的提供的方法,用vs自带的开发人工具命令行通过resgen命令将.resources转为.resx。但是如果窗体中有引用到本身电脑系统中没有的库,会转换不成功,一般都是第三方库。因为我这反编译的窗体有用到devexpress,我电脑装的devexpress版本和原代码用的不一致,有些.resources就没有转换成功,但似乎不影响结果。
2)、.Designer.cs文件的还原:将反编译后的 .cs文件复制一份,文件名改为.Designer.cs结尾,类名前都要加上partial关键字。 在.Designer.cs中只保留控件声明和初始化方法InitializeComponent()和Dispose()方法,其余都删掉。而将原来的.cs文件里的这些都删掉。
里面有些属性会被以get_ 和set_显示,需将这些还原,
即get_properties()=>properties,
set_properties(val)=>properties=val
事件改写方式如下:

//例如
this.barBtnGoBack.add_ItemClick(new ItemClickEventHandler(this.barBtnGoBack_ItemClick));
//改写后
this.barBtnGoBack.ItemClick+=(new ItemClickEventHandler(this.barBtnGoBack_ItemClick));

在正常的.Designer.cs文件中,是没有引用命名空间的,所以就需要把一些类或属性前带上命名空间,然后将最前面的引用都删掉,就这样改完就好了
3)、.cs文件中也会出现get、set式调用属性,改法与上面相同。
4)、最后将.Designer.cs、.resx以添加文件的方式添加到vs解决方案中来,会自动识别到同名的.cs 文件夹下。
5)、将原来.resources从项目中排除,否则编译会报错。
6)、重新编译,界面正常显示就好了。

以上还原过程若没有资源文件缺失,基本上是完整还原的,但过程是有些麻烦。如果窗体多且复杂,工作量会非常大,也会非常费时间。

后来我发现,有些窗体反编译后不用改动也可以正常打开并显示,所以以上步骤其实可以简化的。2、3步中,可以不用分两个文件,就放一个文件中,将那些以get、set调用属性的错误代码改掉就好了,界面显示那块没有错误了,也不用转换.resources文件,编译后会自动生成.resx文件

4、因资源缺失界面不能正常显示
这种通常都是缺图标和图片资源导致,界面上会提示找不到资源,解决方发就是将代码中这部分代码先注释掉,让界面正常展示,要是有资源可以再手动加上就可以了。代码类似下图,通常是第一行那会报错。
资源相关代码
5、还有一种事件委托型的,反编译后代码如下

public event DoubleControlNumberValue OnDoubleControlValue
{
	[CompilerGenerated]
	add
	{
		DoubleControlNumberValue doubleControlNumberValue = this.OnDoubleControlValue;
		DoubleControlNumberValue doubleControlNumberValue2;
		do
		{
			doubleControlNumberValue2 = doubleControlNumberValue;
			DoubleControlNumberValue value2 = (DoubleControlNumberValue)Delegate.Combine(doubleControlNumberValue2, value);
			doubleControlNumberValue = Interlocked.CompareExchange<DoubleControlNumberValue>(ref this.OnDoubleControlValue, value2, doubleControlNumberValue2);
		}
		while (doubleControlNumberValue != doubleControlNumberValue2);
	}
	[CompilerGenerated]
	remove
	{
		DoubleControlNumberValue doubleControlNumberValue = this.OnDoubleControlValue;
		DoubleControlNumberValue doubleControlNumberValue2;
		do
		{
			doubleControlNumberValue2 = doubleControlNumberValue;
			DoubleControlNumberValue value2 = (DoubleControlNumberValue)Delegate.Remove(doubleControlNumberValue2, value);
			doubleControlNumberValue = Interlocked.CompareExchange<DoubleControlNumberValue>(ref this.OnDoubleControlValue, value2, doubleControlNumberValue2);
		}
		while (doubleControlNumberValue != doubleControlNumberValue2);
	}
}    

改写就是把花括号内的内容全部去掉,结果如下

public event DoubleControlNumberValue OnDoubleControlValue;
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值