JProfiler?4.2?注冊分析
作者:舵手
申明:如轉載請保證文章的完整性以及出處
摘要:JProfiler是一款Java剖析器。JProfiler直觀的用戶界面能夠幫助你找到性能瓶頸,并指明你的內存漏洞和解決線程問題。
????JProfiler是通過EXE來執行,用十六進制編輯器很容易找到程序的入口類:com.jprofiler.frontend.FrontendApplication?如果你要通過命令行運行,得看看這個類的main方法,它需要兩個參數才能運行。簡單分析了一下該類,發現方法H完成了注冊碼的驗證,讓我們順藤摸瓜找到計算注冊碼的位置。
????public?boolean?H()
????{
????????E?e1?=?com.jprofiler.frontend.E.H.A3().A2();
??//由于代碼經過了混淆,以E命名的類有n多,所以千萬要找正確,否則會浪費你的保寶貴時間
??//com.jprofiler.frontend.E.D.E——E的完整類路徑
????????int?i1?=?e1.A(null,?this);
????????switch(i1)
????????{
????????case?-2:?
????????????if(l())
????????????{
????????????????System.err.println("Your?license?key?has?expired.");
????????????????return?false;
????????????}
????????????int?j1?=?A(p,?"Your?license?key?has?expired.\nIf?you?were?not?able?to?evaluate?JProfiler,?
please\nrequest?a?new?key?at?"?+?L(),?new?String[]?{
????????????????"Enter?new?key",?"Send?mail"
????????????},?0);
????????????if(j1?==?1)
????????????{
????????????????O();
????????????????return?false;
????????????}
????????????if(!A(((String)?(null)),?true))
????????????????return?false;
????????????break;
????????case?-1:?
????????????break;
????????case?-3:?
????????????if(!A("Your?license?key?is?invalid.?Please?check?your?key.",?true))
????????????????return?false;
????????????break;
????????case?-5:?
????????????if(!A("There?was?an?error?communicating?with?the?license?server.\n
Please?check?your?license?key.",?true))
????????????????return?false;
????????????break;
????????case?-4:?
????????????if(!A("The?license?server?is?invalid.?\nPlease?check?your?license?key.",?true))
????????????????return?false;
????????????break;
????????case?-6:?
????????????A(com.jprofiler.frontend.E.D.C.B(),?false);
????????????return?false;
????????default:
????????????if(i1?<?0)
????????????????throw?new?RuntimeException("Unknown?license?status?"?+?i1);
????????????e1.A(i1);
????????????break;
????????}
????????e1.AA();
????????return?true;
????}
????如果讓e1.A(null,?this)返回-1,那問題就解決了。如果想暴破可以從這個方法入手,我們這里的任務是追出注冊算法:)
????首先我們跟進com.jprofiler.frontend.E.H.A3().A2();這兩個方法,發現只是對類做一些初始化,我們略過。
????跟進e1.A(null,?this),它又調用了重載方法A
????public?int?A(String?s,?C._A?_pa)
????{
????????return?A(s,?_pa,?true);
????}
????
????public?int?A(String?s,?C._A?_pa,?boolean?flag)
????{
????????if(s?==?null)
????????????s?=?F4;?//在該類初始化時已經給F4給了值,如果注冊文件存在,該值為注冊碼
????????if(flag?&&?!s.startsWith("FLOAT:")?&&?!s.startsWith("S-"))
????????????com.A.A.E.C.A(s,?_pa);//跟進這里,發現是網絡驗證,由于我訪問不了IP?228.7.6.9?所以沒有詳細分析,
??????//有時間了再補上。如果你那里通不過網絡驗證,把com.A.A.E.C$_B(C的內部類)里的IP改一下應該就沒問題
??????//可別問我怎么改,十六進制編輯器就可以了:)
????????return?S(s);?//我們再看這個方法
????}
????public?int?S(String?s)
????{
????????if(s?==?null)
????????????s?=?F4;//在該類初始化時已經給F4給了值,如果注冊文件存在,該值為注冊碼
????????if(s.startsWith("FLOAT:"))?//不知道這代表什么,直覺上不是好東西,先不進入,直接到else
????????{
????????????String?s1?=?s.substring("FLOAT:".length());
????????????int?i?=?-1;
????????????int?j?=?s1.lastIndexOf(':');
????????????if(j?>?-1)
????????????{
????????????????try
????????????????{
????????????????????i?=?Integer.parseInt(s1.substring(j?+?1));
????????????????}
????????????????catch(NumberFormatException?numberformatexception)?{?}
????????????????s1?=?s1.substring(0,?j);
????????????}
????????????int?k?=?C3();
????????????int?l?=?com.A.A.E.E.A(s1,?i,?k,?C7());
????????????FD?=?E.C();
????????????D(l?>?0?||?l?==?-1);
????????????return?l;
????????}?else
????????{
????????????return?Q(s);
????????}
????}
????Q(s)直接調用下面方法
????public?static?int?G(String?s)
????{//s為注冊碼
????????if(s?==?null)
????????????return?-3;
????????s?=?s.trim();
????????if(s.length()?<?3?||?s.charAt(1)?!=?'-'?||?s.indexOf('#')?==?-1)//長度大于3,第二位字符必須為-,必段有#
????????????return?-3;
????????switch(s.charAt(0))//取注冊碼中的第一個字符
????????{
????????case?69:?//?'E'??試用版
????????????int?i?=?A(s);//查檢當前日期是否過了試用期
????????????if(!F(s))
????????????????return?-3;
????????????else
????????????????return?i;
????????case?65:?//?'A'
????????case?76:?//?'L'//這三個有什么區別還沒有搞清
????????case?83:?//?'S'
????????????return?H(s);??//讓這里返回-1
????????}
????????return?-3;
????}
????private?static?int?H(String?s)
????{
????????if(B(s)?!=?2)//license串中的"-"必須等于兩個,B函數的作用是計算串中的"-"字符的個數
????????????return?-3;
????????return?F(s)???-1?:?-3;//這里F必須反回true
????}
????private?static?boolean?F(String?s)
????{
????????A?a?=?new?A(s);//傳入注冊碼,進行截取處理
????????if(!a.E())
????????????return?false;
????????String?s1?=?a.A();//返回注冊碼中第二個“-”后的所有字符
????????String?s2?=?E(s1);//把上面得到的字符串以“#”為界分開,“#”前的給s2
????????String?s3?=?D(s1);//“#”后的給s3
????????if(s3?==?null?||?s2?==?null)
????????????return?false;
????????else
????????????return?A(s3,?s2,?11,?7,?29);//重點所在
????}
????protected?static?boolean?A(String?s,?String?s1,?int?i,?int?j,?int?k)
????{
????????char?ac[]?=?s1.toCharArray();“#”前的串轉換為char
????????int?l?=?0;
????????char?ac1[]?=?ac;
????????int?i1?=?ac1.length;
????????for(int?j1?=?0;?j1?<?i1;?j1++)
????????{
????????????char?c?=?ac1[j1];
????????????l?+=?c;?//累加
????????}
????????String?s2?=?String.valueOf(l?%?i)?+?String.valueOf(l?%?j)?+?String.valueOf(l?%?k);
??//分別模11、7、29,結果相加,結果要和“#”后的那部分相等
????????return?s.equals(s2);
????}
????到這里我們已經知道注冊的算法了,其實很簡單:注冊碼必須以A、S、L其中一個字母開頭,第二個字符必須為“-”,“-”字符必須為兩個,至少一個“#”字符,從目前的分析可以看出注冊碼長度已以大于等于四了,程序代碼中<3時完蛋。接下來載取注冊碼中從第二個“-”字符位置加1開始到“#”前一個字符的子串,轉換為char后累加,再分別模11、7、29,把三次模運算的結果相加,這個值等于注冊碼中“#”后面的所有字符。
????下面給寫出它的注冊機
import?java.util.*;
/**
?*?<p>Title:?JProfiler4.2?注冊機</p>
?*?<p>Description:?每執行一次得到一個注冊碼</p>
?*?<p>Copyright:?Copyright?()?2006</p>
?*?@author?舵手
?*?@version?1.0
?*/
public?class?jprofiler4_keygen??
{
??public?static?void?main(String[]?args)?
??{
????String?s1?=?"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
????String?s2?=?"ALS";
????String?license?=?"";
????String?key?=?"";
????Random?rd?=?new?Random();
????int?j?=?rd.nextInt(3);
????license?+=?s2.substring(j,j+1)+"--";
????for?(int?i?=0?;?i?<?12?;?i++?)
????{
??????j?=?rd.nextInt(62);
??????license?+=?s1.substring(j,j+1);
??????key?+=?s1.substring(j,j+1);
????}
????license?+=?"#";
????char?ac[]?=?key.toCharArray();
????????int?l?=?0;
????????char?ac1[]?=?ac;
????????int?i1?=?ac1.length;
????????for(int?j1?=?0;?j1?<?i1;?j1++)
????????{
????????????char?c?=?ac1[j1];
????????????l?+=?c;
????????}
????????String?s3?=?String.valueOf(l?%?11)?+?String.valueOf(l?%?7)?+?String.valueOf(l?%?29);
????license?+=?s3;
????System.out.println(license);
??}
}
????通過上面的分析,我們可以用正則表達式表示出注冊碼[A|L|S]-.-[a-zA-Z0-9]#[0-9],第二個“-”后的字符到“#”字符前的字符串的長度并沒有限制,當然,不能為0,我只測試了長度為1和12,計算的注冊碼都沒有問題,有興趣的可以多試幾個:)“.”這個位置可以插入任意長度的任意字符。
????從注冊算法上說,這個程序的保護很簡單,但如果加上混淆和錯綜復雜的方法調用,會讓你頭痛好一陣子。這里我只列出了和計算注冊碼有關的一些方法,而在實際跟蹤中,牽扯到的類和方法數量是很大的,這就需要耐心。我一直以來都認為這樣的文章對那些想要從這里學到東西的人沒有什么用處,因為這種文章充其量只能算是授人以魚而不是授人以漁。對那些正在分析這個軟件的注冊算法的人來說,也許有那么一點點用處:)
????分析這個軟件的注冊只是個人愛好,由于水平有限,錯誤疏漏在所難免,歡迎大家提出寶貴意見!