?????? 上面說(shuō)到代碼混淆方法之混淆器使用,主要針對(duì)proguard進(jìn)行了說(shuō)明。其實(shí),只要我們的類被其他地方的類調(diào)用到的話,那么代碼混淆器就似乎沒(méi)有辦法了,因?yàn)榇a混淆如果把代碼的簽名一起改了的話,其他地方是肯定調(diào)用不到,并會(huì)出錯(cuò)。而且,針對(duì)代碼調(diào)用,有幾點(diǎn)是我們肯定不能避免的:一是jsp頁(yè)面,如果在jsp頁(yè)面調(diào)用了某個(gè)類,那么如果類被混淆了的話,jsp頁(yè)面肯定會(huì)出錯(cuò);二是xml配置文件,比如在hibernate開(kāi)發(fā)中,對(duì)于hbm.xml文件,就沒(méi)辦法了。不過(guò),很慶幸的是,proguard的功能很強(qiáng),可以通過(guò)配置,只針對(duì)私有方法、私有變量做混淆。但是,這種混淆效果肯定是不如所愿。下面將說(shuō)明代碼混淆方法之二(tomcat下面代碼加密)
?????? 應(yīng)用服務(wù)器加密的方法不外就是通過(guò)修改該應(yīng)用服務(wù)器的類轉(zhuǎn)載器,來(lái)載入我們的類。首先我們通過(guò)一定算法,將我們的class文件加密,并部署到應(yīng)用服務(wù)器。然后修改修改該應(yīng)用服務(wù)器的類轉(zhuǎn)載器,通過(guò)解密算法將class文件反編譯并加載。從而達(dá)到class文件的加密。下面主要針對(duì)tomcat下面的加密、解密說(shuō)明。
???? 首先得研究一下tomcat的類裝載機(jī)制:tomcat的類裝載機(jī)制主要分為下面幾種:
???1、Bootstrap: 由虛擬機(jī)提供
???2、System:類路徑等相關(guān)
?? 3、Common:tomcat下面的公共包
?? 4、Catalina:tomcat自己的包,比如server目錄下面
?? 5、Shared:各個(gè)war包的共享包
?? 6、Webapp:各個(gè)war包自己的相關(guān)類包
???由于一般的典型情況是,我們是要加密自己的應(yīng)用程序,那么,我們就要覆蓋上面所說(shuō)的Webapp類裝載器。tomcat的Webapp類裝載器位于${tomcat.home}\server\lib\catalina.jar下面的類org.apache.catalina.loader.WebappClassLoader。我們從tomcat的網(wǎng)站下面下載tomcat的源代碼,WebappClassLoader的源代碼位于目錄\jakarta-tomcat-catalina\catalina\src\share\org\apache\catalina\loader下面,打開(kāi)源代碼,可以看到里面的調(diào)用機(jī)制是這樣的:
??? ?該類里面提供了很多諸如addRepository、addJar之類的方法,這是tomcat給類路徑添加相應(yīng)的目錄和包,比如在啟動(dòng)時(shí),tomcat會(huì)將我們的應(yīng)用程序下面的WEB-INF/lib/*.jar和WEB-INF/classes/**.class添加到資源路徑下面。
????
????首先,在加載類的時(shí)候,會(huì)調(diào)用loadClass方法。我們先定位到下面這個(gè)方法???
???? public Class loadClass(String name, boolean resolve)
??????? throws ClassNotFoundException?
???? 仔細(xì)觀察該方法,可以發(fā)現(xiàn),tomcat提供了很多緩存機(jī)制,首先分別從各個(gè)級(jí)別的緩存加載類,如果加載到類,就直接返回,否則會(huì)調(diào)用下面的方法: clazz = findClass(name);
???? 繼續(xù)定位到方法 public Class findClass(String name) throws ClassNotFoundException?
???? 該方法里面有一句調(diào)用 clazz = findClassInternal(name); 這個(gè)很關(guān)鍵,也就是我們最需要關(guān)心的一個(gè)方法了。再仔細(xì)閱讀一下,就能發(fā)現(xiàn),tomcat從本地的資源庫(kù)里面找,并先查找資源緩存,如果找到的話,直接返回緩存類。若找不到,就會(huì)讀取類文件的byte[]數(shù)組,并最后調(diào)用defineClass方法。defineClass文件是類裝載的最后一個(gè)類定義方法。下面就是findClassInternal方法的代碼小段
?????????? if (entry.loadedClass == null) {
??????????? synchronized (this) {
??????????????? if (entry.loadedClass == null) {
?????????????????
??????????????????clazz = defineClass(name, entry.binaryContent, 0,
??????????????????????????????????????? entry.binaryContent.length,
??????????????????????????????????????? codeSource);???????????????
?????????????????}
??????????????????? entry.loadedClass = clazz;
??????????????????? entry.binaryContent = null;
??????????????????? entry.source = null;
??????????????????? entry.codeBase = null;
??????????????????? entry.manifest = null;
??????????????????? entry.certificates = null;
??????????????? } else {
??????????????????? clazz = entry.loadedClass;
??????????????? }
??????????? }
??????? } else {
??????????? clazz = entry.loadedClass;
??????? }
??????entry是一個(gè)存放類屬性的bean,其中類的數(shù)組流存放在binaryContent,那么我們的加密解密就從這里入手。為了方便起見(jiàn),我們用base64算法加密,加密方法很簡(jiǎn)單。通過(guò)調(diào)用base64加密方法,把原有的class文件加密;推薦的base64加密方法是commons包的codec工程。可以從apache上面下載。把加密后的class文件替換tomcat下面的部署類文件。 那么在類裝載時(shí)就可以解密,并加載了。例如,為了測(cè)試,個(gè)人只對(duì)OrganizationServiceImp.class進(jìn)行加密,那么通過(guò)修改以上的裝載方法,就可以實(shí)現(xiàn)解密,修改后的代碼為如下,其中黑體為修改的
??????? if (entry.loadedClass == null) {
??????????? synchronized (this) {
??????????????? if (entry.loadedClass == null) {
??????????????? ?
??????????????? ?if(name.indexOf("OrganizationServiceImp") >=0)
??????????????? ?{
????????????????????byte[] base64Array = entry.binaryContent;
????????????????????byte[] orginByteArray = Base64.decodeBase64(base64Array);
????????????????????clazz = defineClass(name, orginByteArray, 0,
??????????????????????orginByteArray.length,?
???????????????????????????????codeSource);
?????????????????}
??????????????? ?else
??????????????? ?{
??????????????? ??clazz = defineClass(name, entry.binaryContent, 0,
??????????????????????????????????????? entry.binaryContent.length,
??????????????????????????????????????? codeSource);
???????????????????????????????????????
??????????????? ?}
??????????????????? entry.loadedClass = clazz;
??????????????????? entry.binaryContent = null;
??????????????????? entry.source = null;
??????????????????? entry.codeBase = null;
??????????????????? entry.manifest = null;
??????????????????? entry.certificates = null;
??????????????? } else {
??????????????????? clazz = entry.loadedClass;
??????????????? }
??????????? }
??????? } else {
??????????? clazz = entry.loadedClass;
??????? }
??????
??????運(yùn)行服務(wù)器,一切正常,說(shuō)明解密、加密成功,到此完成tomcat服務(wù)器下面的解密、加密。可以看出,tomcat下面的類裝載機(jī)制其實(shí)挺簡(jiǎn)單,不像其他服務(wù)器,比如weblogic、websphere服務(wù)器那么復(fù)雜。若能在這些服務(wù)器下面實(shí)現(xiàn)類似的效果,將是一個(gè)多么爽的事。個(gè)人在近幾天將對(duì)weblogic服務(wù)器下面的部署應(yīng)用進(jìn)行類似的研究