记录下Apache Logs Viewer
的破解笔记
拿到软件先查壳,发现是.net
的,混淆过

de4dot
去混淆后

打开看看限制的功能和输入注册码那提示什么


随便输个,看看报错

关键词unlock code
去混淆后的软件载入dnspy
,全局搜下看看

搜到了2个主窗体的,直接看unlockCodeToolStripMenuItem_Click
方法

private void unlockCodeToolStripMenuItem_Click(object sender, EventArgs e) { string text = this.prefs_0.Key; if (!InputForm.smethod_3("Apache Logs Viewer | " + Class96.smethod_264(), Class96.smethod_143(), ref text)) { return; } if (text != null) { text = text.Trim(); } if (string.IsNullOrEmpty(text)) { this.prefs_0.Key = string.Empty; this.bool_0 = false; Prefs.Save(Prefs.Filename, this.prefs_0); this.method_2(this.bool_0); return; } try { this.Cursor = Cursors.WaitCursor; if (text.Length < 22) { throw new ApplicationException("Failed"); } if (Class2.smethod_1(Class2.smethod_0(text))) { this.prefs_0.Key = text; this.method_23(); Prefs.Save(Prefs.Filename, this.prefs_0); this.Cursor = Cursors.Default; this.lbStatusStripNotify.Text = Class96.smethod_253() + " Apache Logs Viewer."; MessageBox.Show(this, Class96.smethod_253() + " Apache Logs Viewer.", "Apache Logs Viewer", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); this.bool_0 = true; } else { MessageBox.Show(this, Class96.smethod_117(), "Apache Logs Viewer | " + Class96.smethod_264(), MessageBoxButtons.OK, MessageBoxIcon.Hand); this.bool_0 = false; } } catch (Exception) { this.Cursor = Cursors.Default; MessageBox.Show(this, Class96.smethod_90(), "Apache Logs Viewer | " + Class96.smethod_264(), MessageBoxButtons.OK, MessageBoxIcon.Hand); this.bool_0 = false; } finally { this.Cursor = Cursors.Default; } this.method_2(this.bool_0); }
|
暴力破解
直接将代码修改为

private void unlockCodeToolStripMenuItem_Click(object sender, EventArgs e) { string text = this.prefs_0.Key; if (!InputForm.smethod_3("Apache Logs Viewer | " + Class96.smethod_264(), Class96.smethod_143(), ref text)) { return; } this.prefs_0.Key = text; Prefs.Save(Prefs.Filename, this.prefs_0); this.Cursor = Cursors.Default; this.lbStatusStripNotify.Text = Class96.smethod_253() + " Apache Logs Viewer."; MessageBox.Show(this, Class96.smethod_253() + " Apache Logs Viewer.", "Apache Logs Viewer", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); this.bool_0 = true; this.method_2(this.bool_0); }
|
然后保存,这样不输入或输入任意字符都能注册了

但是这样有个问题,下次再重开还得再注册遍,推测有个重启校验的暗桩

再看看软件启动时的动作,定位到MainForm_Load
方法
其中发现bool_0
这个变量是用来对注册进行校验的,细看这个方法后找到了重启校验的地方

private void MainForm_Load(object sender, EventArgs e) { try { if (Class95.bool_2) { Prefs.DeletePrefs(); } ALV.Common.Debug.Info("Started.."); Prefs prefs = Prefs.Load(Prefs.Filename); if (string.IsNullOrEmpty(prefs.InstallID)) { prefs.InstallID = Guid.NewGuid().ToString(); } if (prefs.sizex > 10) { base.Width = prefs.sizex; } if (prefs.sizey > 10) { base.Height = prefs.sizey; } if (prefs.maximised) { base.WindowState = FormWindowState.Maximized; } if (prefs.x >= 0 && prefs.y >= 0) { base.Location = new Point(prefs.x, prefs.y); } this.prefs_0 = prefs; if (this.prefs_0.logColumns == null || this.prefs_0.logColumns.Count <= 0) { this.prefs_0.logColumns = LogColumn.ResetLogColumns(); } ALV.Common.Debug.Info("Loading Custom Columns"); this.prefsColumns_0 = PrefsColumns.Load(PrefsColumns.Filename); this.method_42(); DummyListView.prefs = prefs; ALV.Common.Debug.Info("Loading IP DB"); this.ip2Country_0 = new IP2Country(true, this.prefs_0.useCity); this.parser_0 = new Parser(this.ip2Country_0); this.parser_0.ParseCustomColumns = this.prefs_0.parseCustomColumns; Statistics.int_0 = this.prefs_0.topNumber; try { if (prefs.monitorAuto) { ALV.Common.Debug.Info("Opening Logs..."); foreach (LoggerInfo loggerInfo in prefs.logsToView) { if (loggerInfo.Highlight != null) { this.method_48(loggerInfo.Highlight, true); } try { this.method_6(loggerInfo); if (Class95.bool_0) { GC.Collect(); } } catch { } } } if (Class95.list_0 != null) { foreach (string text in Class95.list_0) { try { bool flag = this.parser_0.IsErrorLog(text); this.method_4(text, !flag, false); if (Class95.bool_0) { GC.Collect(); } } catch { } } } } catch (Exception) { MessageBox.Show(Class96.smethod_247()); } if (this.prefs_0.selTab >= 0 && this.tabControl1.TabPages.Count > this.prefs_0.selTab) { this.tabControl1.SelectedTabPageIndex = this.prefs_0.selTab; } try { if (!string.IsNullOrEmpty(this.prefs_0.Key)) { string string_ = Class2.smethod_0(this.prefs_0.Key); this.bool_0 = Class2.smethod_1(string_); } } catch (Exception) { this.bool_0 = false; } try { if (IsStoreApp.IsWindowsStoreApp) { this.bool_0 = true; this.bool_1 = true; this.method_0(); } } catch { } if (!this.bool_0) { this.lbStatusStripNotify.Text = Class96.smethod_270() + " Apache Logs Viewer..." + Class96.smethod_67(); this.method_2(false); } else { this.lbStatusStripNotify.Text = Class96.smethod_270() + " Apache Logs Viewer"; this.method_2(true); } ALV.Common.Debug.Info("Apply L..."); this.method_44(false); this.method_1(); ALV.Common.Debug.Info("Apply L Done"); } catch (Exception ex) { ALV.Common.Debug.Error("Error Load: " + ex.Message); if (this.prefs_0 == null) { this.prefs_0 = new Prefs(); } } finally { LoadForm.smethod_1(); } if (this.prefs_0.checkupdates) { new Thread(new ThreadStart(this.method_25)).Start(); } if (!this.bool_1) { if (File.Exists(Prefs.Filename + ".chk")) { ALV.Common.Debug.Info("Config Check"); if (File.ReadAllText(Prefs.Filename + ".chk") == "0") { MessageBox.Show(this, Class96.smethod_53(), "Apache Logs Viewer", MessageBoxButtons.OK, MessageBoxIcon.Hand); this.prefs_0.Key = string.Empty; this.unlockCodeToolStripMenuItem_Click(this, null); if (File.Exists(Prefs.Filename + ".chk") && this.bool_0) { Application.Exit(); } } else if (this.bool_0) { new Thread(new ThreadStart(this.method_23)).Start(); } } } else if (this.bool_0) { new Thread(new ThreadStart(this.method_23)).Start(); } this.timer_0.Interval = this.prefs_0.refreshtimeout * 1000; this.timer_0.Enabled = true; this.timer_0.Start(); GC.Collect(); if (base.Width <= 10) { base.Width = 668; } if (base.Height <= 10) { base.Height = 460; } this.menuStrip1.Visible = true; this.toolStripBtnScroll.CheckState = (this.prefs_0.scroll_last ? CheckState.Checked : CheckState.Unchecked); this.toolStripBtnRefresh.CheckState = (this.prefs_0.refreshAuto ? CheckState.Checked : CheckState.Unchecked); ALV.Common.Debug.Info("Started..OK"); }
|
method_23
、method_24
方法用作反馈winstore
版本
public void method_23() { if (this.bool_1) { this.method_24("winStore"); return; } this.method_24(this.prefs_0.Key); }
|
public void method_24(string string_0) { try { WebClient webClient = new WebClient(); try { if (webClient.DownloadString("http://www.apacheviewer.com/k/c5.php?k=" + string_0 + "&id=" + this.prefs_0.InstallID).StartsWith("failed", StringComparison.OrdinalIgnoreCase)) { try { using (StreamWriter streamWriter = File.CreateText(Prefs.Filename + ".chk")) { streamWriter.Write("0"); } } catch { } base.Invoke(new MainForm.Delegate0(this.method_26), new object[] { 5, string.Empty }); } else { try { if (File.Exists(Prefs.Filename + ".chk")) { File.Delete(Prefs.Filename + ".chk"); } } catch { } } } finally { ((IDisposable)webClient).Dispose(); } } catch (Exception) { } }
|
method_25
、method_26
用作检测更新
public void method_25() { try { string text = null; WebClient webClient = new WebClient(); try { if (this.bool_0) { text = webClient.DownloadString(string.Concat(new object[] { "http://www.apacheviewer.com/currentver5.php?v=", About.double_0, "&r1=U&id=", this.prefs_0.InstallID })); } else { text = webClient.DownloadString(string.Concat(new object[] { "http://www.apacheviewer.com/currentver5.php?v=", About.double_0, "&r1=F&id=", this.prefs_0.InstallID })); } } finally { ((IDisposable)webClient).Dispose(); } if (!string.IsNullOrEmpty(text)) { double num = 0.0; double.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out num); if (num > 0.0) { if (num > About.double_0) { if (num >= (double)About.int_0) { WebClient webClient2 = new WebClient(); try { text = webClient2.DownloadString("http://www.apacheviewer.com/upgrademsg.php"); } finally { ((IDisposable)webClient2).Dispose(); } base.Invoke(new MainForm.Delegate0(this.method_26), new object[] { 2, text.Trim() }); } else { base.Invoke(new MainForm.Delegate0(this.method_26), new object[] { 1, text.Trim() }); } } } } } catch (Exception) { } }
|
private void method_26(int int_0, string string_0) { switch (int_0) { case 1: if (MessageBox.Show(string.Concat(new string[] { Class96.smethod_42(), " v", string_0, " ", Class96.smethod_93(), ".\r\n ", Class96.smethod_66() }), "Apache Logs Viewer " + Class96.smethod_265(), MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes) { Process.Start("http://www.apacheviewer.com/download.php?up=1"); return; } break; case 2: if (MessageBox.Show(string_0 + "\r\n" + Class96.smethod_66(), "Apache Logs Viewer " + Class96.smethod_265(), MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes) { Process.Start("http://www.apacheviewer.com/download.php?up=1"); return; } break; case 3: case 4: goto IL_BD; case 5: MessageBox.Show(Class96.smethod_123(), "Apache Logs Viewer", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); Process.Start("http://www.apacheviewer.com"); Application.Exit(); return; default: goto IL_BD; } return; IL_BD: throw new ApplicationException("Unknown Update UI Command"); }
|
所以把MainForm_Load
方法直接修改为如下即可跳过验证和更新
private void MainForm_Load(object sender, EventArgs e) { try { if (Class95.bool_2) { Prefs.DeletePrefs(); } ALV.Common.Debug.Info("Started.."); Prefs prefs = Prefs.Load(Prefs.Filename); if (string.IsNullOrEmpty(prefs.InstallID)) { prefs.InstallID = Guid.NewGuid().ToString(); } if (prefs.sizex > 10) { base.Width = prefs.sizex; } if (prefs.sizey > 10) { base.Height = prefs.sizey; } if (prefs.maximised) { base.WindowState = FormWindowState.Maximized; } if (prefs.x >= 0 && prefs.y >= 0) { base.Location = new Point(prefs.x, prefs.y); } this.prefs_0 = prefs; if (this.prefs_0.logColumns == null || this.prefs_0.logColumns.Count <= 0) { this.prefs_0.logColumns = LogColumn.ResetLogColumns(); } ALV.Common.Debug.Info("Loading Custom Columns"); this.prefsColumns_0 = PrefsColumns.Load(PrefsColumns.Filename); this.method_42(); DummyListView.prefs = prefs; ALV.Common.Debug.Info("Loading IP DB"); this.ip2Country_0 = new IP2Country(true, this.prefs_0.useCity); this.parser_0 = new Parser(this.ip2Country_0); this.parser_0.ParseCustomColumns = this.prefs_0.parseCustomColumns; Statistics.int_0 = this.prefs_0.topNumber; try { if (prefs.monitorAuto) { ALV.Common.Debug.Info("Opening Logs..."); foreach (LoggerInfo loggerInfo in prefs.logsToView) { if (loggerInfo.Highlight != null) { this.method_48(loggerInfo.Highlight, true); } try { this.method_6(loggerInfo); if (Class95.bool_0) { GC.Collect(); } } catch { } } } if (Class95.list_0 != null) { foreach (string text in Class95.list_0) { try { bool flag = this.parser_0.IsErrorLog(text); this.method_4(text, !flag, false); if (Class95.bool_0) { GC.Collect(); } } catch { } } } } catch (Exception) { MessageBox.Show(Class96.smethod_247()); } if (this.prefs_0.selTab >= 0 && this.tabControl1.TabPages.Count > this.prefs_0.selTab) { this.tabControl1.SelectedTabPageIndex = this.prefs_0.selTab; } try { if (!string.IsNullOrEmpty(this.prefs_0.Key)) { string string_ = Class2.smethod_0(this.prefs_0.Key); this.bool_0 = true; } } catch (Exception) { this.bool_0 = true; } try { if (IsStoreApp.IsWindowsStoreApp) { this.bool_0 = true; this.bool_1 = true; this.method_0(); } } catch { } if (!this.bool_0) { this.lbStatusStripNotify.Text = Class96.smethod_270() + " Apache Logs Viewer..." + Class96.smethod_67(); this.method_2(true); } else { this.lbStatusStripNotify.Text = Class96.smethod_270() + " Apache Logs Viewer"; this.method_2(true); } ALV.Common.Debug.Info("Apply L..."); this.method_44(true); this.method_1(); ALV.Common.Debug.Info("Apply L Done"); } catch (Exception ex) { ALV.Common.Debug.Error("Error Load: " + ex.Message); if (this.prefs_0 == null) { this.prefs_0 = new Prefs(); } } finally { LoadForm.smethod_1(); } if (this.prefs_0.checkupdates) { new Thread(new ThreadStart(this.method_25)).Start(); } this.timer_0.Interval = this.prefs_0.refreshtimeout * 1000; this.timer_0.Enabled = true; this.timer_0.Start(); GC.Collect(); if (base.Width <= 10) { base.Width = 668; } if (base.Height <= 10) { base.Height = 460; } this.menuStrip1.Visible = true; this.toolStripBtnScroll.CheckState = (this.prefs_0.scroll_last ? CheckState.Checked : CheckState.Unchecked); this.toolStripBtnRefresh.CheckState = (this.prefs_0.refreshAuto ? CheckState.Checked : CheckState.Unchecked); ALV.Common.Debug.Info("Started..OK"); }
|
重新打开后,显示为已注册,所有功能已解锁


注册算法
该软件的注册算法如下
using System; using System.Globalization; using System.Text;
internal static class Class2 { public static string smethod_0(string string_0) { if (string_0.IndexOf('-') < 0) { return string_0; } string str = "DBV"; string_0 = string_0.Replace("-", string.Empty); string_0 = string_0.Replace('Q', '4'); string_0 = string_0.Replace('G', '4'); string_0 = string_0.Replace('V', '0'); string_0 = string_0.Replace('N', '3'); str + string_0; byte[] array = new byte[string_0.Length / 2]; for (int i = 0; i < string_0.Length; i += 2) { byte b; byte.TryParse(new string(new char[]{string_0[i],string_0[i + 1]}),NumberStyles.HexNumber, CultureInfo.InvariantCulture, out b); array[i / 2] = b; } string text = Encoding.ASCII.GetString(array); text = text.Insert(1, ":"); text = text.Insert(5, ":"); text = text.Insert(9, ":"); if (text.Length > 13) { text = text.Insert(13, ":"); } return text; }
public static bool smethod_1(string string_0) { bool flag = true; string a = string_0.Substring(4, 5); if (a == "IALV") { flag = false; } if (string_0[0] != 'F') { flag = false; } int num = int.Parse(string_0[2].ToString(), NumberStyles.HexNumber); if (num > 16) { flag = false; } if (a != "I:ALV") { flag = false; } num = int.Parse(string_0[3].ToString(), NumberStyles.HexNumber); if (num > 16) { flag = false; } if (!int.TryParse(string_0.Substring(10, 3), out num)) { flag = false; } if (string_0.Length <= 14) { throw new ApplicationException("Invalid Unlock Code"); } int num2 = int.Parse(string_0.Substring(15, 1)); if (num2 != 2 && num2 != 3) { throw new ApplicationException("Incorrect Code for Version"); } string s = string_0.Substring(0, 16); string b = string_0.Substring(16); int num3 = 0; byte[] bytes = Encoding.ASCII.GetBytes(s); for (int i = 0; i < bytes.Length; i++) { if (bytes[i] % 2 == 0) { num3++; } } return !(num3.ToString("00") != b) && flag; } }
|