再記一次經典Net程式的逆向過程
- 2019 年 10 月 3 日
- 筆記
1.前言
上次發完,有網友問了一個問題:如果不繞過編譯,而是直接編譯怎麼辦?
記一次Net軟體逆向的過程:https://www.cnblogs.com/dotnetcrazy/p/10142315.html
今天就來說說:本次提供樣本:鏈接: https://pan.baidu.com/s/1ekYVKXt_Jz3ShwjoFknW0g 提取碼: ywf6
2.調試破解
1.查殼知道是Net程式
2.dnspy打開發現亂碼
3.de4dot脫殼
4.這個就是反混淆之後的程式
5.改名後重新打開就不亂碼了
6.直接運行看看效果,找到提示資訊
7.入口點下斷
8.單步走一波
9.在疑似關鍵函數處下斷,然後運行
10.單步走了幾下發現到動態載入的dll文件中了
11.在疑是關鍵點前後下斷,然後F11,跟進去看看
12.到達了Login的頁面
13.嘗試根據提示來搜索login裡面的驗證code(這個和上次講的不一樣,上次高度封裝,這個很亂)
14.發現這段驗證是在名稱叫ok的按鈕click事件中
15.發現有一段比較,下斷,然後把text4的值改成right的值,看看什麼效果
16.發現還有一處比較,不管的話運行依舊失敗
17.看到一個vipdata轉成datatime,那推測是和時間有關的
18.在loginfrom中搜索this.vipdate,發現了這處,那麼可以確定是時間格式的字元串了(依據:可以轉時間,而且可以使用字元串拼接)
19.設斷然後單擊調試
20.調試過程中修改值
21.再修改下vipdata
22.發現成功了
那麼下面就是編譯修改了
3.編譯修改
1.編輯方法
2.修改完發現不能編譯
PS:這就是為啥我名字寫經典逆向的原因了(解決這個問題就解決了90%的Net逆向問題)
3.發現dnspy不能正確識別命名空間,而且程式碼太lou沒法變相繞過(沒有高度封裝)
4.沒關係,我們自己扒dll
5.把資源文件保存成一個個dll,找到我們需要的dll
6.那怎麼知道dll的真實名字呢?其實也很簡單,拖進Reflector就知道了
6.1.為了穩妥,我把Tianaya.x的dll都保存了(省得折騰)
7.重新運行後再編譯,發現uploadxx.dll的某個方法不能識別
PS:其實你在uploadxx.dll裡面搜一下就知道沒有這個方法了,然後理想Net裡面只有導入命名空間的方法才可以簡寫
8.其實你根據using的命令空間,或者去upload裡面看都是沒有Module1的,真正的命名空間是MyLibrary
9.這段可以刪掉
10.發現已經修改好了,那麼保存一下
11.只要這個放在原文件的根目錄下就可以破解了(如果遇到不能破解的,可以用上次我講的修改資源文件的方法)
4.小小驗證
貼一個GIF結束
附錄
貼一下我的ok_click:
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Threading; using System.Web; using System.Windows.Forms; using System.Xml; using Microsoft.VisualBasic; using Microsoft.VisualBasic.CompilerServices; using Microsoft.Win32; using Tianya.Data.SQLite; using Tianya.MyLibrary; using Tianya.UpLoadClient.My; namespace Tianya.UpLoadClient { // Token: 0x02000061 RID: 97 [DesignerGenerated] public partial class LoginForm : Form { // Token: 0x06000CD4 RID: 3284 RVA: 0x000BA510 File Offset: 0x000B8910 [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void OK_Click(object sender, EventArgs e) { try { this.Timer1.Enabled = false; this.OK.Enabled = false; string text = this.txtUsername.Text.Trim(); string text2 = this.txtPassword.Text.Trim(); if (text.Length < 1 | text2.Length < 1) { MessageBox.Show("請您輸入帳號密碼", "親愛的用戶", MessageBoxButtons.OK, MessageBoxIcon.Hand); } else { try { this.StrMacip = ClassGetRegCodeMD5.GetRegCodeMD5(16); } catch (Exception ex) { aModuleMain.MsgBox(ex.Message + "~Macip"); return; } if (Operators.CompareString(this.StrMacip, "", false) == 0) { aModuleMain.MsgBox("系統異常"); } else { this.Addlog("正在登入中..."); string str = Conversions.ToString(Operators.ConcatenateObject("txtUserName=" + this.txtUsername.Text.Trim() + "&txtPassword=" + this.txtPassword.Text.Trim() + "&macip=" + this.StrMacip + "&logintime=" + HttpUtility.UrlEncode(Conversions.ToString(DateAndTime.Now)) + "&model=" + Conversions.ToString((int)aModuleMain.AppWebsite) + "&appname=" + this.appname + "&ComputerInfo=", NewLateBinding.LateGet(null, typeof(HttpUtility), "UrlEncode", new object[] { RuntimeHelpers.GetObjectValue(this.GetMyComputerInfo()) }, null, null, null))); string right = Conversions.ToString(Conversion.Int(Conversions.ToDouble(Strings.Left(Conversions.ToString(this.strToAsc(this.txtUsername.Text.ToString().Trim())), 6)) + Conversion.Int(Conversions.ToDouble(Strings.Left(Conversions.ToString(this.strToAsc(this.txtPassword.Text.ToString().Trim())), 4))) * Conversion.Int(Conversions.ToDouble(Strings.Left(Conversions.ToString(this.strToAsc(Strings.Replace(Strings.Replace(this.StrMacip, ":", "", 1, -1, CompareMethod.Binary), ".", "", 1, -1, CompareMethod.Binary))), 5))))); int num = 1; checked { string text3; for (;;) { string getText = "/yahooreg/loginClient.aspx?" + str; text3 = Conversions.ToString(this.loginGeturl(getText, num, 30)); if (text3.Trim().Length < 1) { break; } int num2 = Strings.InStr(text3, "</root>", CompareMethod.Binary); if (num2 > 0 && Operators.CompareString(Strings.Right(text3, "</root>".Length), "</root>", false) != 0) { num2 += "</root>".Length; text3 = Strings.Left(text3, num2); } string text4 = ""; try { text4 = Regex.Match(text3, "\[(?<v>[^\[\]{}]+)\]").Groups["v"].Value.Trim(); this.vipdate = Regex.Match(text3, "\{(?<v>[^\[\]{}]+)\}").Groups["v"].Value.Trim(); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(text3); XmlNode xmlNode = xmlDocument.SelectSingleNode("root"); if (xmlNode.HasChildNodes & xmlNode.ChildNodes.Count > 2) { try { foreach (object obj in xmlNode.ChildNodes) { XmlElement xmlElement = (XmlElement)obj; if (Operators.CompareString(xmlElement.Name, "sid", false) == 0) { text4 = xmlElement.InnerText.Trim(); } else if (Operators.CompareString(xmlElement.Name, "vipdate", false) == 0) { this.vipdate = xmlElement.InnerText.Trim(); } } } finally { // delete } } } catch (Exception ex2) { if (num < 3) { num++; continue; } aModuleMain.MsgBox(ex2.Message + "~xml"); } goto IL_439; } aModuleMain.MsgBox("網路連接失敗"); return; IL_439: if (text3.Contains("帳號已過期")) { this.Addlog("帳號已過期,請您續費後使用"); this.TabControl1.SelectedTab = this.TabPage自助充值繳費; } else { string text4 = right; // add this.vipdate = "2029-10-01"; // add if (text4.Length > 0 && Operators.CompareString(text4, right, false) == 0) { if (Operators.CompareString(this.vipdate, "", false) == 0) { aModuleMain.MsgBox("登入出錯"); return; } DateTime date = DateAndTime.Now.AddYears(-1); DateTime.TryParse(this.vipdate, out date); int num3 = (int)DateAndTime.DateDiff(DateInterval.Second, date, DateAndTime.Now, FirstDayOfWeek.Sunday, FirstWeekOfYear.Jan1); if (num3 > 0) { aModuleMain.MsgBox("程式已到期,請續費後再使用" + Conversions.ToString(num3)); this.TabControl1.SelectedTab = this.TabPage自助充值繳費; return; } Thread thread = new Thread(delegate() { try { string setting = Interaction.GetSetting(Application.StartupPath, "cache", "time", ""); bool flag = true; if (!string.IsNullOrEmpty(setting)) { DateTime now = DateAndTime.Now; DateTime.TryParse(setting, out now); if (DateAndTime.DateDiff(DateInterval.Day, now, DateAndTime.Now, FirstDayOfWeek.Sunday, FirstWeekOfYear.Jan1) <= 0L) { flag = false; } } if (flag) { string text5 = Application.StartupPath + "\Cache"; this.Addlog("正在清理緩存..." + text5.Replace(Application.StartupPath, "")); ClassMy.DelOldFile(text5, "", 30); text5 = Application.StartupPath + "\upload"; this.Addlog("正在清理緩存..." + text5.Replace(Application.StartupPath, "")); ClassMy.DelOldFile(text5, "", 30); text5 = Application.StartupPath + "\test\login"; this.Addlog("正在清理緩存..." + text5.Replace(Application.StartupPath, "")); ClassMy.DelOldFile(text5, "", 30); text5 = Application.StartupPath + "\test\ThumbnailImage"; this.Addlog("正在清理緩存..." + text5.Replace(Application.StartupPath, "")); ClassMy.DelOldFile(text5, "", 30); text5 = Application.StartupPath + "\test\" + Application.ProductName; this.Addlog("正在清理緩存..." + text5.Replace(Application.StartupPath, "")); ClassMy.DelOldFile(text5, "", 30); Interaction.SaveSetting(Application.StartupPath, "cache", "time", DateAndTime.Now.ToString("s")); } this.Addlog("正在優化數據庫..."); // update MySQLiteCreateFile.Create(Tianya.MyLibrary.Module1.dbfile, LoginForm.ds); this.Addlog("正在備份數據庫..."); // update ClassMy.DBBackup(Tianya.MyLibrary.Module1.dbname, Tianya.MyLibrary.Module1.dbfile, delegate(string n) { this.Addlog("正在備份數據庫 " + n); }); } catch (Exception ex4) { aModuleMain.MsgBox(ex4.Message + "~2"); } }); Thread thread2 = thread; thread2.IsBackground = true; thread2.Start(); while (thread2.IsAlive) { Application.DoEvents(); Thread.Sleep(1); } LoginForm.IsLoginSucceeded = true; this.Addlog("登入成功,正在啟動中..."); this.Visible = false; this.checkmacip(); this.checkUpdate(false); this.ShowNotifyIcon1(this.NotifyIcon1); aModuleMain.LoginFormvipdate = this.vipdate; aModuleMain.LoginFormtxtUsername = this.txtUsername.Text.Trim(); aModuleMain.LoginFormtxtPassword = this.txtPassword.Text.Trim(); LoginForm.MethodInvoker1(); SystemEvents.PowerModeChanged += this.PowerModeChanged; this.Addlog("登入 - " + MyProject.Application.Info.AssemblyName); } else if (Strings.InStr(text3, "帳號或密碼不正確", CompareMethod.Binary) > 0 | Strings.InStr(text3, "資料不正確", CompareMethod.Binary) > 0) { this.TabControl1.SelectedIndex = 0; this.Addlog("帳號或密碼不正確"); } else if (Strings.InStr(text3, "帳號未激活", CompareMethod.Binary) > 0) { this.TabControl1.SelectedIndex = 0; this.Addlog("帳號已註冊未激活,請聯繫提供者"); } else { this.TabControl1.SelectedIndex = 0; this.Addlog("登入失敗,請稍後重試"); } this.formSaveSetting(); } } } } } catch (Exception ex3) { aModuleMain.MsgBox(ex3.Message + "~login"); } finally { this.OK.Enabled = !LoginForm.IsLoginSucceeded; } } } }