飞艳小屋

程序--人生--哲学___________________欢迎艳儿的加入

BlogJava 首页 新随笔 联系 聚合 管理
  52 Posts :: 175 Stories :: 107 Comments :: 0 Trackbacks
最近为了使单片机的通信扩展到Internet使用了Lantronix公司生产的XPort(串口—网络口数据转发模块),在使用它带的软件DeviceInstaller进行软件的配置的时候,发现安装完毕启动时出现异常,异常信息如下

未处理的“System.NotSupportedException”类型的异常出现在 mscorlib.dll 中。

其他信息: 区域性“zh-CHS”是非特定区域性。它不能用于格式化和分析,因此不能设置为线程的当前区域性。

使用。Net反编译工具,打开主程序XTool.exe,找到主窗体,此软件没有綺过混淆,代码很清晰,在Form1种
public Form1()
{
CultureInfo info1;
Version version1;
string text1;
DialogResult result1;
DialogResult result2;
string text2;
string text3;
string[] array1;
int num1;
ListViewColumnSorter sorter1;
base..ctor();
CultureInfo.CurrentCulture.ClearCachedData();
info1 = CultureInfo.CurrentCulture;
if (info1.TwoLetterISOLanguageName == "zh")
{
 Thread.CurrentThread.CurrentCulture = new CultureInfo(info1.Parent.LCID);// //此部分出错
Thread.CurrentThread.CurrentUICulture = new CultureInfo(info1.Parent.LCID);// dl.bitsCN.com网管软件下载
 }
this.InitializeComponent();
 
}
就是Thread.CurrentThread.CurrentCulture = new CultureInfo(info1.Parent.LCID);将new 的
CultureInfo(info1.Parent.LCID)赋给Thread.CurrentThread.CurrentCulture,出现了异常,因此不能设置为线程的当前区域性的异常。可能是程序为了比较好的支持国际化,而这样写的带代码,看来有些多余。看来只要不让出错的语句运行即可,而这最好的实现方式就是修改比较条件。

可以使用两种方法进行修改
1.使用ildasm进行反汇编,得到中间代码,修改中间代码,然后重新编译即可。
使用ildasm进行反汇编后得到一大堆代码,下面仅仅列出相关的
// 相关的汇编代码
.maxstack 6
.locals (CultureInfo V_0, Version V_1, string V_2, Exception V_3, DialogResult V_4, DialogResult V_5, string V_6, string V_7, string[] V_8, int V_9, ListViewColumnSorter V_10)
.try L_0132 to L_014a catch object L_014a to L_014d
.try L_014d to L_0574 catch Exception L_0574 to L_0584
.try L_0739 to L_0754 catch object L_0754 to L_0768
L_0000: ldarg.0
L_0001: call Form..ctor
L_0006: call CultureInfo.get_CurrentCulture bitsCN全力打造网管学习平台
L_000b: callvirt CultureInfo.ClearCachedData
L_0010: call CultureInfo.get_CurrentCulture
L_0015: stloc.0
L_0016: ldloc.0
L_0017: callvirt CultureInfo.get_TwoLetterISOLanguageName
L_001c: ldstr "zh" ------------将此处的字符串改为aa


再使用ilasm 将修改后的相关代码进行编译得到新程序即可。重新编译后,生成的程序比訽来的小了(可能有部分资源没有编译进去),不知道什么訽因,但是没有发现影响使用的状况

2.简单的处理方式,一般的.net程序中使用的常量字符串,在.net程序中都有相应的储存位置(存储格式为unicode 形式),所以使用WinHex打开程序,查找字符串zh,选中unicode项,发现文件中仅能搜索到一次,毫无疑问,就是他了,直接将字符串
7A 00 68 00 改为其他的不同字节即可。存盘后,程序正常运行


小弟最近一直在做.net下串行通信方面的程序,.net下没有自带的串口控件,使用以前的com组件又不甘心,所以在网上找到了sax.net组件(破解)版本,使用的时候,比较满意,但是在使用的过程中,出现了

System.ArgumentOutOfRangeException: 长度不能小于 0。

参数名: newlength

 at System.Text.StringBuilder.set_Length(Int32 value)

 at Sax.Communications.SerialConnection.a(UInt32 A_0)

 at Sax.Communications.SerialConnection.a(IntPtr A_0, c& A_1)

 at Sax.Communications.SerialConnection.get_Available()

 at Sax.Communications.SerialConnection.b()

 

异常

尤其是使用ISP线与单片机通信的时候,几乎每次插拔ISP线都会出现异常。异常后,控件的串口数据监视线程退出以后再也不能收发数据,只能重新启动软件。綺过仔细调试,发现
异常出现在插拔数据线的时候,有数据收到,产生了DataAvailable事件中

private void serialConnection_DataAvailable(object sender, EventArgs e) //受到数据时的处理函数
  {
 //在这之前出现了异常
dl.bitsCN.com网管软件下载

 int length = serialConnection.Available;
// Debug.WriteLine(length.ToString());
 if(length<=0) return;
 
 Byte[] buffer = new byte[length]; //输入缓冲区有多少数据?
 serialConnection.Read(buffer,0,length);
 
 //分析数据
 if( length > 0 )
 {
  HandleDataReceive(buffer);
 }
  }


就是在发生事件之后,在int length = serialConnection.Available;之前发生了异常。根据VS.net
的提示信息,初步确定是在给一个StringBuilder对象builder设置其Length的时候,传入的参数<0导
致的。

好了,使用.net的反编译工具Reflector(我用的版本4.0.18)打开控件,找到SerialConnection类;由于此控件綺过混淆,所以在反编译后出现了大量的比如a,或者b这样的看不出作者意图的函数名。不过没有关系,因为异常出现在serialConnection.Available附近,直接找到Available的实现代码

public override int get_Available()

{

  z.c c1;

  this.c();
dl.bitsCN.com网管软件下载
  c1 = new z.c();

  this.a(this.a, ref c1);

  if (this.b != -1)

  {

  return ((int) (c1.b + 1));

  }

  return ((int) c1.b);

}
 

在里面寻找出错的函数
找到this.a(this.a, ref c1);这个

private string a(IntPtr A_0, ref z.c A_1)

{

  uint num1 = 0;

  z.ClearCommError(A_0, ref num1, ref A_1);

  if (num1 != 0)

  {

  return this.a(num1);

  }

  return null;

}
 

有追踪到return this.a(num1);

private string a(uint A_0)

{

  StringBuilder builder1 = new StringBuilder("UART Error:", 60);

  if (builder1.Length <= 0)

  {

  goto Label_005F;

  }

  goto Label_00D0; bitsCN.com中国网管联盟

Label_001B:

  builder1 = builder1.Append(" Parity,");

  goto Label_00B1;

Label_002C:

  builder1 = builder1.Append(" Receive Overflow,");

  goto Label_0069;

Label_003D:

  builder1 = builder1.Append(" Framing,");

  goto Label_0095;

Label_004E:

  builder1 = builder1.Append(" Transmit Overflow,");

  goto Label_00A3;

Label_005F:

  if ((A_0 & 8) == 0)

  {

  goto Label_0095;

  }

  goto Label_003D;

Label_0069:

  if ((A_0 & 4) == 0)

  {

  goto Label_00B1;

  }

  goto Label_001B;

Label_0073:

  builder1 = builder1.Append(" <Unknown>,");

  goto Label_00FA; bbs.bitsCN.com国内最早的网管论坛

Label_0084:

  builder1 = builder1.Append(" Overrun,");

  goto Label_00ED;

Label_0095:

  if ((A_0 & 1024) == 0)

  {

  goto Label_00E3;

  }

  goto Label_00BF;

Label_00A3:

  if ((A_0 & 1287) == 0)

  {

  goto Label_00FA;

  }

  goto Label_0073;

Label_00B1:

  if ((A_0 & 256) == 0)

  {

  goto Label_00A3;

  }

  goto Label_004E;

Label_00BF:

  builder1 = builder1.Append(" IO,");

  goto Label_00E3;

Label_00D0:

  builder1.Remove(0, builder1.Length);

  goto Label_005F;

Label_00E3:

  if ((A_0 & 2) != 0)

  { bitsCN.com中国网管联盟

  goto Label_0084;

  }

Label_00ED:

  if ((A_0 & 1) == 0)

  {

  goto Label_0069;

  }

  goto Label_002C;

Label_00FA:

  builder1.Length -= 1;//!!!!!!!!!!!!!!!!!!错误的来源

  return builder1.ToString();

}

我靠,也没有想细读为什么要将builder1.Length 减去1,节省内存,没有必要把?!!
反正是这句出错了,将后builder1.Length 小于0了

查看前面的代码,没有对builder1.Length 赋值的语句,看来将这句改掉就行了,

查看il代码,
最后的几句为
L_00fa: ldloc.0
L_00fb: ldloc.0
L_00fc: callvirt StringBuilder.get_Length
L_0101: ldc.i4.1 //装载常数1--将此处改为装载常数0,即可
L_0102: sub
L_0103: callvirt StringBuilder.set_Length
L_0108: ldloc.0
L_0109: callvirt StringBuilder.ToString
L_010e: ret

查找il的汇编指令
发现(格式指令 ---十六进制数)
ldloc.0 ----06 play.bitsCN.com累了吗玩一下吧
ldloc.0 ----06
callvirt StringBuilder.get_Length ---- 6F X X X X (X不知道具体的值,可以通过模糊匹配来确定要修改的指令在文件的位置)
ldc.i4.1 ---- 17



sub ----59
L_0103: callvirt---- StringBuilder.set_Length 6F X X X X
L_0108: ldloc.0---- 06
L_0109: callvirt---- StringBuilder.ToString 6F X X X X
L_010e: ret ----28


使用WinHEx打开文件,使用16进制搜索,对于上面的X 使用模糊匹配的訽则
找到偏移0x34B0处,在0x34BD处的将0x17 改为0x16(IL指令ldc.i4.0 ,就是将Length-0等于不减)
存盘退出,将修改好的dll文件覆盖訽来的dll,运行软件,怎么插拔ISP线都没有问题出现了!


参考资料
Inside Microsoft.net IL Assesmbler



posted on 2007-06-28 12:53 天外飞仙 阅读(2119) 评论(0)  编辑  收藏 所属分类: .net

只有注册用户登录后才能发表评论。


网站导航: