飛艷小屋

          程序--人生--哲學___________________歡迎艷兒的加入

          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 天外飛仙 閱讀(2139) 評論(0)  編輯  收藏 所屬分類: .net
          主站蜘蛛池模板: 东安县| 石城县| 西畴县| 阿鲁科尔沁旗| 囊谦县| 平舆县| 建平县| 沙洋县| 鹿泉市| 永安市| 永福县| 辽源市| 襄汾县| 繁昌县| 达孜县| 建水县| 剑河县| 灵武市| 万山特区| 萝北县| 新巴尔虎左旗| 普兰店市| 南通市| 巴林左旗| 游戏| 淳化县| 宣城市| 手游| 嘉禾县| 友谊县| 彭阳县| 萝北县| 江油市| 齐齐哈尔市| 城市| 奈曼旗| 宜春市| 留坝县| 孟村| 宜丰县| 武冈市|