(應一些園友建議,我把敏感字段去掉)
其實當初我的目的是很純潔的,只是想找一個簡單的網站生成模板,由於對.net更熟悉一點,就去搜索了.net框架的CMS,看它的介紹挺強大的,符合最初的目的,但是下下來之后發現最新版本是要錢的,低一級的版本免費,但是免費的生成出來的東西會有他們公司的版權,這就讓我不能忍了,免費就免費啊,搞個純凈點的不行啊,GOOGLE是強大的,所以我嘗試的去搜索看有沒有破解的版本,發現搜出來的一律都是免費版的去掉版權的版本,擦,去個版權就叫破解了么,而且還是低一級的版本,略微坑爹。.NET的東西理論上沒有什么不可以破解的,之前由於項目需要,偶爾也會去破解一些商業的.NET軟件,學習學習嘛,破解也不是什么罪大惡極的事,只要你不破壞別人的利益就行,所以我就抱着學習的心態去看了一下P*****的源代碼,罪過罪過。只是學習。
本人聲明,下面的內容只是個人研究所用,不作為任何商業目的,如果有人看了本篇文章做出任何違法之事,本人不負任何責任責任。by Zengg
破解所需軟件:Reflector,ILSpy,de4dot
Reflector和ILSpy其實是一個性質的,都是用來查看別人的源代碼,由於有時我發現Reflector查看方法的時候會出現一些錯誤,所以就用ILSPY配合着用。
de4dot,脫殼和反混攪的利器,一般商業軟件都會加殼或者用了混攪代碼,讓一些人就算看到代碼也不明白寫的是什么,有了這個神器,媽媽再也不用擔心我看到亂碼了。。。當然有時也不是萬能的,90%都能還原吧。
P******版本:V3.0
這是V3.0的基本樣貌

按照官網的說法,只要把域名和對應的注冊碼填到web.config里面就可以了。
Web.config

可以看到Url是域名,License就是填寫注冊碼的地方,由於域名是唯一的,我們不難想象出Url肯定是作為生成注冊碼的主要參照物,說個題外話,破解嘛,看你是要暴力破解還是文藝破解,暴力破解就是把代碼注入他的DLL,從而繞過他的驗證達到注冊的目的,文藝嘛,就是大家有話好好說,不改動他的DLL,但是需要根據他提供的一些信息去推測軟件作者的加密思想,只要你明白了加密核心思想,就能從源碼中找出蛛絲馬跡,由於軟件里的源碼肯定只存在解密的步驟,加密的步驟就需要大家反推出來了,有木有一種當偵探的趕腳。。。。。當然,本人只是業余人士,大牛們看到心里鄙視就好,不用說出來。。會打擊人的.by Zengg
言歸正傳,我們已經知道了URL是生成注冊碼的參照物,以后就按着這個線索去查找,其實上面還有一個重要的線索,”License”,由於注冊碼肯定是要從配置文件讀取,讀取之后就是驗證的步驟,這驗證的步驟就是我們需要去的地方,讀取License的值,大家會想一下.NET的做法,是不是ConfigurationManager.AppSettings["License"],現在由於程序員的水平高低不齊,一般來說都會像上述那樣去寫,這樣就暴露了獲取驗證碼的地方,我們就可以定位到所有有”License”內容的代碼段去,所以說,以后大家寫核心解密代碼的時候多留一個心眼,把敏感字段寫入資源里面,至少給破解的人增加一點難度。
Bin目錄下有很多的DLL,其中一個肯定就是藏有解密的地方

當然由於我已經破解過了,篩選DLL的過程就不描述了,P*******.web.dll,就是解密的地方,用de4dot先給DLL脫殼。
然后我們用ILSPY打開這個DLL

會看到。。尼瑪還是這么坑爹,所有東西基本都是亂碼,讓人不能直視,具體為什么我也沒研究過,由於我們也不需要去明白這些亂碼寫的是神馬,按照上面的思路我們要查找所有含有License字段的代碼段,這步驟可以用軟件實現。

利用ILSPY,在SEARCH里填上License,就可以看到出來很多方法,當初很疑惑為什么有這么多地方用到驗證注冊碼,驗證的算法都是一樣的,難道作者以為你各個角落都驗證一遍就不能破解了么。。

仔細看了搜索出來的結果,他是一些重要的表操作時就會去驗證一遍,挺謹慎的嘛,上面標藍的地方就是登陸的時候主頁驗證,我們從這里開始。
點擊進入該方法

從上面代碼可以看出,其實注冊碼分為兩個部分,以’g’字符隔開,前面一部分是由MD5加密,后面一部分暫時不清楚,前面我們推論注冊碼是由URL來的,我們有理由懷疑
的this.j3G1XJp4Xe, this.EsQ1WjnrPD肯定有一個是URL字段,至於另一個是什么得去尋找,一般來說我們初始化的時候會在類的構造函數初始化,相信在構造函數里面,我們會知道這兩個字段的意思,忘記了這是web,我們應該從Page_load頁面加載里面去尋找:
protected void Page_Load(object sender, EventArgs e) { string connectionString; int[] num; while (true) { IL_24F: this.Qi911iK25u = ":" + master_login.tDhwcmhvMr4nRqlEc9G(base.Request)["SERVER_PORT"]; while (true) { IL_232: if (this.Qi911iK25u == ":80") { this.Qi911iK25u = ""; } this.EsQ1WjnrPD = this.Jbr136aAXj(master_login.MpkoQbh7EvS0PEFh1B3(master_login.rEXTLBh8uXG8glkV91p(ConfigurationManager.AppSettings, "Url").ToString())); master_login.xncn9GhN2hVekNKKcgK(); if (!master_login.DMFvcGhZ55jZPl06Jhl()) { goto IL_FA; } goto IL_215; IL_1CA: bool flag; while (!(flag = (base.Request.Form["username"] == null))) { this.NTR1li2VG4(); this.Yqx1ac8tvS = new Conn(); connectionString = master_login.lPkTddhObfF6vvZs9Ta(this.Yqx1ac8tvS); num = new int[] { 41, 0, 6, 4, 26, 3, 12, 8, 13, 93, 28, 38, 44 }; while (true) { this.j3G1XJp4Xe = this.Yqx1ac8tvS.GetString(num); num = new int[] { 87, 4, 17, 17, 14, 17, 76, 34, 13, 21, 0, 11, 8, 3, 73, 37, 8, 2, 4, 13, 18, 4 }; this.DDU1A3AUYe = this.Yqx1ac8tvS.GetString(num); int expr_AA = 7; if (master_login.xncn9GhN2hVekNKKcgK()) { switch (expr_AA) { case 0: goto IL_232; case 2: case 4: goto IL_FA; case 3: case 8: goto IL_215; case 5: goto IL_176; case 6: continue; case 7: goto IL_276; case 9: goto IL_2AE; case 10: goto IL_1CA; case 11: goto IL_24F; case 12: goto IL_2F5; case 13: return; } break; } break; } goto IL_187; } return; IL_FA: this.KpC1B5ZX4p = this.Jbr136aAXj(master_login.tDhwcmhvMr4nRqlEc9G(master_login.rnmK14hAjv0aZay85lt(this))["SERVER_NAME"].ToLower()); if (!master_login.MAaokyhM2irc0iduDgg(this.KpC1B5ZX4p, "localhost")) { goto IL_1CA; } int num2 = this.KpC1B5ZX4p.IndexOf(this.EsQ1WjnrPD); string a; if (num2 >= 0) { a = this.KpC1B5ZX4p.Substring(num2, this.KpC1B5ZX4p.Length - num2); goto IL_176; } master_login.a6dZyFh3MrLLslJyyx5(this).Write("<script>location.href='http://" + this.EsQ1WjnrPD + this.Qi911iK25u + "/e/master/login.aspx';</script>"); goto IL_215; IL_187: if (!flag) { this.KpC1B5ZX4p = this.EsQ1WjnrPD; goto IL_1CA; } master_login.a6dZyFh3MrLLslJyyx5(this).Write("<script>location.href='http://" + this.EsQ1WjnrPD + this.Qi911iK25u + "/e/master/login.aspx';</script>"); base.Response.End(); goto IL_1CA; IL_215: master_login.a6dZyFh3MrLLslJyyx5(this).End(); goto IL_1CA; IL_176: flag = !(a == this.EsQ1WjnrPD); goto IL_187; } } IL_276: num = new int[] { 87, 4, 17, 17, 14, 17, 76, 34, 13, 21, 0, 11, 8, 3, 73, 28, 14, 15, 24, 17, 8, 6, 7, 19 }; this.wht18BDAPc = this.Yqx1ac8tvS.GetString(num); num = new int[] { 75, 41, 14, 22, 4, 17, 4, 3, 93, 1, 24, 93, 41, 0, 6, 4, 26, 3, 12, 8, 13, 93, 28, 38, 44 }; IL_2AE: this.eA41Kphpj9 = this.Yqx1ac8tvS.GetString(num); this.kwo1i4CnR3 = this.ne91erSgMV(); this.GqT1YHkWWq = new OleDbConnection(connectionString); master_login.qOyjNXhFe7tECUDuWP7(this.GqT1YHkWWq); this.gII1QQxT9S(); this.aK41NqyDHj(); this.Tov1vquSFP(); IL_2F5: this.GqT1YHkWWq.Close(); }
仔細看上面的代碼,我們會發現,this.EsQ1WjnrPD就是URL,但是經過了一些處理,即去掉了域名前面的“WWW.”,this.j3G1XJp4Xe是經過特殊算法得出字符串。by Zengg
算法源碼:
{ int[] num = new int[]{ 41, 0, 6, 4, 26, 3, 12, 8, 13, 93, 28, 38, 44 }; this.j3G1XJp4Xe = GetString(num); } public string GetString(int[] num) { string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+-={}[]:\";'<>?,./\\| "; StringBuilder stringBuilder = new StringBuilder(); string result; if (num.Length > 0) { for (int i = 0; i < num.Length; i++) { stringBuilder.Append(text[num[i]]); } result = stringBuilder.ToString(); } else { result = ""; } return result; }
MD5算法:
public class Md5 { public string Get_Md5(string s) { MD5 mD = new MD5CryptoServiceProvider(); Encoding encoding = Encoding.GetEncoding("UTF-8"); string s2 = "pageadmin cms"; byte[] array = mD.ComputeHash(encoding.GetBytes(s)); byte[] array2 = mD.ComputeHash(encoding.GetBytes(s2)); StringBuilder stringBuilder = new StringBuilder(32); for (int i = 0; i < array.Length; i++) { stringBuilder.Append(((int)(array[i] + array2[i])).ToString("x").PadLeft(2, '0')); } return stringBuilder.ToString(); } public string Md5_Num(string s) { string text = ""; for (int i = 0; i < s.Length; i++) { if (i == s.Length - 1) { text += this.GetNum(s[i].ToString()).ToString(); } else { text = text + this.GetNum(s[i].ToString()).ToString() + ","; } } return text; } private int GetNum(string C) { string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+-={}[]:\";'<>?,./\\| "; int num = text.IndexOf(C); int result; if (num < 0) { result = -1; } else { result = num; } return result; } }
第一部分的注冊碼其實已經得出來的,即this.j3G1XJp4Xe+this.EsQ1WjnrPD的字符串經過MD5加密就是第一部分的注冊碼,下面我們去尋找第二部分的線索,重新回到上次搜索"License"的列表,經過一個個的排查,發現了重要線索。
進入這個方法
從上面的代碼可以推出,后部分注冊碼,其實就是URL的長度乘以2,到這里其實注冊碼差不多已經出來了,基本格式
MD5(this.j3G1XJp4Xe+this.EsQ1WjnrPD)+“g”+URL.Length*2+?....注冊碼例子:ef12a131357bb3e67396e01061141385da5149g143
剩余核心算法:
private static bool g031FKBmaF(string A_1) { string[] array = new string[5]; array[0] = "^127[.]0[.]0[.]1$"; array[1] = "^localhost$"; array[2] = "^10[.]\\d{1,3}[.]\\d{1,3}[.]\\d{1,3}$"; array[3] = "^172[.]((1[6-9])|(2\\d)|(3[01]))[.]\\d{1,3}[.]\\d{1,3}$"; array[4] = "^192[.]168[.]\\d{1,3}[.]\\d{1,3}$"; string[] array2 = array; int num = 0; IL_45: if (num >= array2.Length) { bool result = false; return result; } if (A_1 != null) { goto IL_64; } string arg_58_0 = ""; IL_55: if (Regex.IsMatch(arg_58_0, array2[num])) { bool result = true; return result; } num++; goto IL_45; IL_64: arg_58_0 = A_1; goto IL_55; } private static string Jbr136aAXj(string A_1) { bool arg_27_0; if (g031FKBmaF(A_1)) { arg_27_0 = false; goto IL_27; } arg_27_0 = (A_1.IndexOf(".") >= 0); IL_27: string result; if (!arg_27_0) { result = "localhost"; } else { result = A_1.Replace("www.", ""); } return result; }
寫了這么多也夠了,最后一個數字3代表的是.net后綴的域名,這里就不提供完整的程序源碼,可能會涉及一些侵權,我寫的其實也夠詳細了,
核心算法也貼出來,大家自己去寫一個注冊機吧,如果有想要域名對應的注冊碼的,請郵電我說明正當理由,我會考慮是否給你。
如果您看了本篇博客,覺得對您有所收獲,請點擊右下角的 [推薦]
如果您想轉載本博客,請注明出處
如果您對本文有意見或者建議,歡迎留言
感謝您的閱讀,請關注我的后續博客 Zengg
作者:Zengg
出處:http://www.cnblogs.com/01codeworld/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
