`
hellohank
  • 浏览: 146003 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Java防反编译技术实现探讨

阅读更多

综述(写在前面的废话)

Java从诞生以来,其基因就是开放精神,也正因此,其可以得到广泛爱好者的支持和奉献,最终很快发展壮大,以至于有今天之风光!但随着java的应用领域越来越广,特别是一些功能要发布到终端用户手中(如Android开发的app),有时候,公司为了商业技术的保密考虑,不希望这里面的一些核心代码能够被人破解(破解之后,甚至可以被简单改改就发布出去,说严重点,就可能会扰乱公司的正常软件的市场行为),这时候就要求这些java代码不能够被反编译。

这里要先说一下反编译的现象。因为java一直秉持着开放共享的理念,所以大家也都知道,我们一般共享一个自己写的jar包时,同时会共享一个对应的source包。但这些依然与反编译没有什么关系,但java的共享理念,不只是建议我们这样做,而且它自己也在底层上“强迫”我们这么做!在java写的.java文件后,使用javac编译成class文件,在编译的过程,不像C/C++C#那样编译时进行加密或混淆,它是直接对其进行符号化、标记化的编译处理,于是,也产生了一个逆向工程的问题:可以根据class文件反向解析成原来的java文件!这就是反编译的由来。

但很多时候,有些公司出于如上述的原因考虑时,真的不希望自己写的代码被别人反编译,尤其是那些收费的app或桌面软件(甚至还有一些j2eewen项目)!这时候,防止反编译就成了必然!但前面也说过了,因为开放理念的原因,class是可以被反编译的,那现在有这样的需求之后,有哪些方式可以做到防止反编译呢?经过研究java源代码并进行了一些技术实现(结果发现,以前都有人想到过,所以在对应章节的时候,我会贴出一些写得比较细的文章,而我就简单阐述一下,也算偷个懒吧),我总共整理出以下这几种方式:

代码混淆

这种方式的做法正如其名,是把代码打乱,并掺入一些随机或特殊的字符,让代码的可读性大大降低,“曲线救国”似的达到所谓的加密。其实,其本质就是打乱代码的顺序、将各类符号(如类名、方法名、属性名)进行随机或乱命名,使其无意义,让人读代码时很累,进而让人乍一看,以为这些代码是加过密的!

由其实现方式上可知,其实现原理只是扰乱正常的代码可读性,并不是真正的加密,如果一个人的耐心很好,依然可以理出整个程序在做什么,更何况,一个应用中,其核心代码才是人们想去了解的,所以大大缩小了代码阅读的范围!

当然,这种方式的存在,而且还比较流行,其原因在于,基本能防范一些技术人员进行反编译(比如说我,让我破解一个混淆的代码,我宁愿自己重写一个了)!而且其实现较为简单,对项目的代码又无开发上的侵入性。目前业界也有较多这类工具,有商用的,也有免费的,目前比较流行的免费的是:proguard(我现象临时用的就是这个)。

上面说了,这种方式其实并不是真正加密代码,其实代码还是能够被人反编译(有人可能说,使用proguard中的optimize选项,可以从字节流层面更改代码,甚至可以让JD这些反编译软件可以无法得到内容。说得有点道理,但有两个问题:1、使用optimizeJDK及环境要求较高,容易造成混淆后的代码无法正常运行;2、这种方式其实还是混淆,JD反编译有点问题,可以有更强悍的工具,矛盾哲学在哪儿都是存在的^_^)。那如何能做到我的class代码无法被人反编译呢?那就需要我们下面的“加密class”!

加密class

在说加密class之前,我们要先了解一些java的基本概念,如:ClassLoader。做java的人已经或者以后会知道,java程序的运行,是类中的逻辑在JVM中运行,而类又是怎么加载到JVM中的呢(JVM内幕之类的,不在本文中阐述,所以点到为止)?答案是:ClassLoaderJVM在启动时是如何初始化整个环境的,有哪些ClassLoader及作用是什么,大家可以自己问度娘,也不在本文中讨论。

让我们从最常见的代码开始,揭开一下ClassLoader的一点点面纱!看下面的代码:

 

public class Demo{
        public static void main(String[] args){
            System.out.println(“hello world!”);
        }
    }
 

 

上面这段代码,大家都认识。但我要问的是:如果我们使用javac对其进行编译,然后使用java使其运行(为什么不在Eclipse中使用Run as功能呢?因为Eclipse帮我们封闭,从而简化了太多东西,使我们忽略了太多的底层细节,只有从原始的操作上,我们才能看到本质),那么,它是怎么加载到JVM中的?答案是:通过AppClassLoader加载的(相关知识点可以参考:http://hxraid.iteye.com/blog/747625)!如果不相信的话,可以输出一下System.out.println(Thread.currentThrea().getContextLoader());看看。

那又有一个新的问题产生了:ClassLoader又是怎样加载class的呢?其实,AppClassLoader继承自java.lang.ClassLoader类,所以,基本操作都在这个类里面,让我们直接看下面这段核心代码吧:



 

看看这个方法中的逻辑,非常简单,先从内存中找,如果没有,则从父级或根先找,如果没找到,则再从自己的方法里面找!那findClass里面是什么样的呢?很不幸,这个方法是个抽象(abstract)的,也就是使用什么方式加载,由程序使用ClassLoader自己决定!这就给我们留下了巨大的“”!让我们看一下非常常见的一个ClassLoader的实现,那就是URLClassLoader(几乎所有的j2eeweb项目的容器使用的ClassLoader都是继承自它),让我们看一下它的findClass的实现:



 

这个方法里面的逻辑也很简单,从定义的ucp(就是各个jar包或class文件的具体路径)中读取指定的class文件的信息(如字节流之类),然后交给defineClass定义到JVM中,让我们继续看一下这个方法的核心部分:

 

 

看到这里,已经没有必要再往下面看了(再往下就是native方法了,这是一个重大伏笔哦),我们要做的手脚就在这里!

手脚怎么做呢?很简单,上面的代码逻辑告诉我们,ClassLoader只是拿到class文件中的内容byte[],然后交给JVM初始化!于是我们的逻辑就简单了:只要在交给JVM时是正确的class文件就行了,在这之前是什么样子无所谓!所以,我们的加密的整个逻辑就是:

    1. 在编译代码时(如使用ant或maven),使用插件将代码进行加密(加密方式自己选),将class文件里面的内容读取成byte[],然后进行加密后再写回到class文件(这时候class文件里面的内容不是标准的class,无法被反编译了)
    2. 在启动项目代码时,指定使用我们自定义的ClassLoader就行了,而自定义的部分,主要就是在这里做解密工作!

如此,搞定!以上的做法比较完整的阐述,可以仔细阅读一下这篇文章:http://www.ibm.com/developerworks/cn/java/l-secureclass/文章中的介绍。

通过这个方法貌似可以解决代码反编译的问题了!错!这里有一个巨大的坑!因为我们自定义的ClassLoader是不能加密的,要不然JVM不认识,就全歇菜了!如果我来反编译,呵呵,我只要反编译一下这个自定义的ClassLoader,然后把里面解密后的内容写到指定的文件中保存下来,再把这个加了逻辑的自定义ClassLoader放回去运行,你猜结果会怎样?没错,你会想死!因为你好不容易想出来的加密算法,结果人家根本不需要破解,直接就绕过去了!

现在,让我们总结一下这个方法的优缺点:实现方式简单有效,同时对代码几乎没有侵入性,不影响正常开发与发布。缺点也很明显,就是很容易被人破解!

当然啦,关于缺点问题,你也可以这么干:先对所有代码进行混淆、再进行加密,保证:1、不容易找到我们自定义的那个ClassLoader2、就算找到了,破解了,代码可读性还是很差,让你看得吐血!(有一篇文章,我觉得写得不错,大家可以看一看:http://cjnetwork.iteye.com/blog/851544

嗯,我觉得这个方法很好,我自己也差点被这个想法感动了,但是,作为一个严谨的程序员,我真的不愿意留下一个隐患在这里!所以,我继续思索!

高级加密class

前面我们说过有个伏笔来着,还记得吧?没错,就是那个nativenative定义的方法是什么方法?就是我们传说中的JNI调用!前面介绍过的有一篇文章中提到过,其实jvm的真实身份并不是java,而是c++写的jvm.dllwindows版本下),javadll文件的调用就是通过JNI实现的!于是,我们就可以这样想:JNI可以调用第三方语言的类库,那么,我们可不可以把解密与装载使用第三方语言写(如C++,因为它们生成的库是不好反编译的),这样它可以把解密出来的class内容直接调jvm.dll的加载接口进行初始化成class,再返回给我们的ClassLoader?这样,我们自定义的ClassLoader只要使用JNI调用这个第三方语言写的组件,整个解密过程,都在黑盒中进行,别人就无从破解了!

嗯,这个方法真的很不错的!但也有两个小问题:1.使用第三方语言写,得会第三方语言,我说的会,是指很溜!2.对于不同的操作系统,甚至同一操作系统不同的版本,都可能要有差异化的代码生成对应环境下的组件(如window下是exelinuxso等)!如果你不在乎这两个问题,我觉得,这个方式真的挺不错的。但对于我来说,我的信条是,越复杂的方式越容易出错!我个人比较崇尚简洁的美,所以,这个方法我不会轻易使用!

对了,如果大家觉得这个方法还算可行的话,可以推荐一个我无意中看到的东西给大家看看(我都没有用过的):jinstall,还有一个叫:http://download.csdn.net/detail/yzjcnlpj/3296134

更改JVM

看到这个标题,我想你可能会震惊。是的,你没看错,做为一个程序员,是应该要具有怀疑一切、敢想敢做的信念。如果你有意留心的话,你会发现JVM版本在业界其实也有好几个版本的,如:Sun公司的、IBM的、Apache的、Google的……

所以,不要阻碍自己的想象力,现在没有这个能力,并不代表不可能。所以,我想到,如果我把jvm改了,在里面对加载的类进行解密,那不就可以了吗?我在设计构思过程中,突然发现:人老了就是容易糊涂!前面使用第三方语言实现解密的两个问题,正好也是更改JVM要面对的两个问题,而且还有一个更大的问题:这个JVM就得跟着这个项目到处走啊!有一个类似的思路是这样:

http://wenku.baidu.com/link?url=T0LOwOI5DDFRoFGJp_vzwq8x6OADAcnHcNBOFqij5jz7Rvt1wsjLe8Qa2sJFUBQha88A5csGqDH5yXIjWVV4i54x-iXtYpPSO9kJtQLhvNy

于是,我把构思与设计从头又想了想,终于……放弃了!

确定方案

前面可以说,我能想到的方式,我都想到了,都不能令我满意。于是我在想,有没有一个让我感觉代价又小,但却无隐患的方式呢?

 

    这里,其实涉及到一个误区问题,就是为什么一定要把我们自定义的解密classClassLoader进行加密不让人看到呢?!其实,只要让别人无法窜改就可以了!如果能做到让别人就算看到了我们的源码,但他无法窜改我们自定义的这个ClassLoader,这和加密的效果其实是一样的了!那怎么做呢?

我们可以借鉴数字签名方式!其想法是:可以把解密并defineClass的功能委托给一个单独的类,这个类呢,我们使用一个私钥(私钥在公司管理的云端,不在系统发布的客户端)对其内容进行SHA256摘要,并将摘要记录在系统的某处,当我们自定义的ClassLoader在读取这个类时,先对其内容进行SHA256进行验证,看是不是被窜改过,如果被窜改,则系统拒绝工作!这样就可以了,核心代码简略如下:

 

private Object decoderLoader = null;//注意这里的定义类型,是Object,不是DecoderLoader,因为这个类我们需要单独对其进行加载并校验
 
……
 
if(decoderLoader == null){
    byte[] bs=FileUtils.readAsBytes(“具体DecoderLoader.class文件路径”);
    // 这里要对bs内容进行SHA256校验(需要带上私钥,私钥可以从服务器获取,也可以存储于系统的某个地方,反正每个用户可以不一样的私钥),如果校验不通过,抛出个异常,甚至可以直接System.exit(-1);
    DigestUtils.match("发布时生成好的签名",bs,"服务器获取的密钥");//验证是否一致,不一致就认为被窜改过,则直接抛出异常终止启动
    Class c = defineClass(具体DecoderLoader.class文件路径(/替换成.), bs, 0, bs.length, cs);
    decoderLoader = c.newInstance();
}
 
byte[] b = res.getBytes();//这里得到的是加密的class文件内容
// 使用上面的decoderLoader利用反射进行解密操作,decoderLoader的解密方法只传入参数为:b,密钥。(为什么不直接定义DecoderLoader类,非要用反射?自己想想吧,这跟ClassLoader加载机制有关,就不阐述了)
b = ReflectUtils.invoke(decoderLoader,”decode”,b,”密钥”);
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
return defineClass(name, b, 0, b.length, cs);

 

嗯,我很满意!

可是,当我看到自定义的ClassLoader里面的验证代码时,我又要感慨一下自己老了!这不还是绕回来了吗?!如果破解了自定义的ClassLoader,我还验证个毛啊,直接把类引用进来用就是了!毕竟,自定义的ClassLoader在加载时又没有校验!

 

等等!我们还是有回到初衷,我们到底要干什么?我们要加密我们的代码,防止被反编译,我们前面做到了,只是解密的问题却暴露出来了(更重要的是,人家可以绕过解密过程),所以,我们现在可以这样想:让他绕不过,不就行了吗?所以,我们上面使用一个单独类实现解密和defineClass一体功能的类。现在因为别人能看到自定义的ClassLoader源码,同时又能看到那个一体化功能的类,所以通过改写自定义的ClassLoader绕过校验、通过改写一体化功能的类保存解密后的内容到文件中,这样还是可以得到整个系统的源码!

整理了一下思路,我们发现,我们要处理的事情,其实已经很简单了:只要隐藏掉自定义的ClassLoader或一体化功能的类当中的任何一个,都可以达到目标!如何隐藏一个类?然后,我一个方法一个方法地去想:

class文件格式做文章。我们先学一些这方面的知识吧:可以学习一下这个文章中的知识:http://chenzhou123520.iteye.com/blog/1596693文章我还没看完,我突然发现,还是没有意义,因为代码混淆器就是干了这件事!——放弃!

借鉴数字签名的方式也在前面验证过不行!——放弃!

JNI方式是最好的方式!可是这种方式维护成本上有点高,我不喜欢!如果真没办法,那也用它是没办法的选择(相比改写JVM来说,它的代价是比较小的)!可是,真的可以吗?!java1.5开始,提供一个代理(instrument)功能(大家一定见过在Eclipse中启动有些项目进,要加-javaagent参数吧?)!Instrument是干什么的呢?举个简单的例子吧:如果把JVM处理校验并生成class或运行class逻辑看成webapp项目中的Servlet功能的话,那instrument就相当于Filter,在JVM操作class之前,JVM会先执行instrument,在instrument里面,我们可以做任何事情,包括改写class(于是许多AOP框架就是这么干的,如AspectJ)和监控JVM的各类信息(很多监控软件就是这么干的,如有些性能监控工具等)等等。等你使用JNI辛辛苦苦解密出来,也隐藏了代码的解密方式,结果,JVM在这一步把你整个出卖了!

Instrument方式。上面说了JNI其实也不可靠了!那我们就从Instrument这里调用JNI不就行了吗?接下来总没有地方出卖它了吧?我只能说“别天真了”!因为Instrument的加载是通过在启动时加上一个参数:-javaagent:xxx,很不幸的是,这个参数可以跟多个代理(简单理解为多个具有代理功能的jar包),而这些代理的执行顺序就是这个参数后面写的顺序,如:-javaagent:a.jar,b.jar,这里加载了两个代理,它们的执行顺序就是ab,如果想把顺序反过来,只要这样:-javaagent:b.jar,a.jar就行了,就跟webapp项目中web.xml中定义filter的顺序是一样一样的~

改写JVM方式。根据上面来看,我是几乎放弃了挣扎!所以,我想,嗯,还是改写JVM是最靠谱的!可是,JVM改写,要改写它运行instrument之后的地方,而且一旦改写,前面说的风险和代价是要承担的!

说到这儿,我想大家应该已经猜到了,反正我是不会为了防止人家破解我的java代码,还要搞这么大动静!只要意思一下,大概防一防就行了,能够达到“吓跑一大半,剩下的人要破解的话,花费的精力都可以自己写一个同样的系统”就行了!凡事要找个平衡嘛(或者说,有时候不需要追求完美,也是要有妥协的)!

最终的选择:就是上面那个混淆+自定义ClassLoader方式解密(然后在ClassLoader里面加一句类似本是同根生,请君多自重之类的话)。如果还不怕麻烦的话,再这个自定义的ClassLoader放到一个不起眼的第三方包中,增加查找的难度,仅此而已了~

    最后要说一句:考虑到性能问题,我们只用来加解密核心代码即可。

总结

经过对java不断深入研究,以及多年来对java知识的积累,最重要的是,一种遇到困难时执着向前的精神,最终使得问题的解决越来越完善!虽然走过弯路,但每条弯路上都有许多收获,就像我曾经做得的分享里面说的:同一个现象,不同的视野将得到不同的结果!如何提升自己视野?就在于平时不断的自我追求和强烈的求知欲!

PS:这个总结,算是自夸一下,也算是给新入行的“菜鸟”们一个建议吧~

  • 大小: 155 KB
  • 大小: 145.1 KB
  • 大小: 102.3 KB
10
2
分享到:
评论
11 楼 phoenixcwx 2016-05-05  
  新入行菜鸟感谢分享,学到不少东西,顺便问一句,Java中使用了反射和动态编译的代码也可以被反编译出来么?
10 楼 hellohank 2015-06-12  
wwwcomy 写道
hellohank 写道
wwwcomy 写道
有些奇怪的混淆方式(包括改classloader以及那块之下的内容)很容易造成jvm或web容器不兼容的情况。

比如Oracle的JDK环境Tomcat里跑的好好的webapp,拿到WebSphere就部署不上。

鱼与熊掌不可兼得啊。。


其实,只是从我上面的这种改写ClassLoader的方式(不是调用JNI,也不是增强型的混淆),并没有改变class的任何规范,所以其实是在任何JVM中可以运行的。之所以有些项目在Tomcat下面能跑而在WebSphere不能跑,是因为这些应用服务器本身实现上存在一些自己的差异,而如果这些项目正好在一些功能上用到了这些差异(如:静态资源配置、JNDI应用、JEE协议实现等等),会因为不同而造成webapp确实无法跑起来~但这些都跟JVM无关,真正跟JVM有关的就是class文件,如果在编译成class文件的过程中使用了特定的一些配置,如:指定了java版本、对其进行增强混淆,就会使得class文件中的一些JVM弱规范部分不一致,导致不同的JVM在解析时出现各种问题。
所以,我现在要做的,并不想改变class内容,我只想能不能让这个内容不会让人知道,只让JVM知道~
望多讨论~


   是的,理论上改写ClassLoader是蛮好,用自己写的classLoader去加载类,就能加入特殊逻辑并且达到混淆的效果。这个在做java桌面应用时候应该挺好用的

然而(神转折=。=),只是针对webapp说下,这个修改还是挺麻烦的,要知道Tomcat还好点,开源的,有WebappClassLoader的源码大概了解一下他的类加载机制、隔离和流程还好写点。但是复杂一点的EJB容器如JBoss,或者闭源的webSphere,classLoad机制还是比较复杂或者不清楚是怎么搞的。基本很难上手。

另外提醒一下,忘记前公司用的哪个混淆器了,在混淆前会自动优化代码,比如我RMI接口好好的声明着RemoteException,结果丫发现实现里面不会抛异常,于是就给我删了。。。

感觉普通应用做一下混淆就挺好了,或者仅仅在一些特殊场景,比如加解密或者传输这块写一些和classloader相关的东西,这样付出和回报比会更高~

PS: 支持LZ的研究精神,希望有进一步成果~~~


首先,感谢你的讨论和分享,对你说的这些,我说一下我现在最新的情况吧(这篇文章我已经写完了):

1、“针对webapp”,这个你说的对,不同的应用服务器因为具体实现及开源程度(我们可以称之为封装程度)不同,导致像你说的那样,JBoss、WebSphere、Resin等都无法使用自定义ClassLoader。我文章中忘了说了,相同原理的方式还有一种,就是instrument代理技术,这也是在运行代码前可以更改代码(因为JVM运行到了instrument这一步的时候,还没有进行class文件校验等操作,相当于webapp里面的filter这一步)。

2、关于混淆器,我试过几个,基本上都有三项功能组成(当然每项功能里面有很多配置项):混淆(obfuscate)、压缩(shrink)、优化(optimize),在不是很了解混淆器的深度操作时,最好不要使用压缩和优化,特别是优化,它可能会根据JDK的不同版本甚至不同的操作系统进行针对性优化,导致混淆之后的包可能根据无法使用!如果再加上它本身在有些bug什么的,我们只能呵呵了~

3、关于进一步成果,我这两天得出一个初步结果,比较悲观:除了改JVM,还真没什么不留隐患的方法,就是使用JNI都能破解(使用instrument就能做到,文章中有相关介绍)

现在就是不知道有哪位有过成功的经验可以交流一下,真没有的话,我只能使用混淆+自定义ClassLoader(我项目中使用的是集成Jetty)处理一下(然后在ClassLoader里面加一句类似“本是同根生,请君多自重”之类的话),然后将这个自定义的ClassLoader放到一个不起眼的第三方包中,增加查找的难度,真是没办法中的办法了
9 楼 wwwcomy 2015-06-11  
hellohank 写道
wwwcomy 写道
有些奇怪的混淆方式(包括改classloader以及那块之下的内容)很容易造成jvm或web容器不兼容的情况。

比如Oracle的JDK环境Tomcat里跑的好好的webapp,拿到WebSphere就部署不上。

鱼与熊掌不可兼得啊。。


其实,只是从我上面的这种改写ClassLoader的方式(不是调用JNI,也不是增强型的混淆),并没有改变class的任何规范,所以其实是在任何JVM中可以运行的。之所以有些项目在Tomcat下面能跑而在WebSphere不能跑,是因为这些应用服务器本身实现上存在一些自己的差异,而如果这些项目正好在一些功能上用到了这些差异(如:静态资源配置、JNDI应用、JEE协议实现等等),会因为不同而造成webapp确实无法跑起来~但这些都跟JVM无关,真正跟JVM有关的就是class文件,如果在编译成class文件的过程中使用了特定的一些配置,如:指定了java版本、对其进行增强混淆,就会使得class文件中的一些JVM弱规范部分不一致,导致不同的JVM在解析时出现各种问题。
所以,我现在要做的,并不想改变class内容,我只想能不能让这个内容不会让人知道,只让JVM知道~
望多讨论~


   是的,理论上改写ClassLoader是蛮好,用自己写的classLoader去加载类,就能加入特殊逻辑并且达到混淆的效果。这个在做java桌面应用时候应该挺好用的

然而(神转折=。=),只是针对webapp说下,这个修改还是挺麻烦的,要知道Tomcat还好点,开源的,有WebappClassLoader的源码大概了解一下他的类加载机制、隔离和流程还好写点。但是复杂一点的EJB容器如JBoss,或者闭源的webSphere,classLoad机制还是比较复杂或者不清楚是怎么搞的。基本很难上手。

另外提醒一下,忘记前公司用的哪个混淆器了,在混淆前会自动优化代码,比如我RMI接口好好的声明着RemoteException,结果丫发现实现里面不会抛异常,于是就给我删了。。。

感觉普通应用做一下混淆就挺好了,或者仅仅在一些特殊场景,比如加解密或者传输这块写一些和classloader相关的东西,这样付出和回报比会更高~

PS: 支持LZ的研究精神,希望有进一步成果~~~
8 楼 hellohank 2015-06-11  
near_sun 写道
改完之后就不是java。
改完 比较大的问题 就是日志问题,还有异常定位问题


是啊。java是开源理念,如果硬要使其反编译,确实有点反java~可是,现实总是残酷的呀。

其实日志总是和异常定位问题,在我的设计中,是可以避免的,因为我没有像http://cjnetwork.iteye.com/blog/851544里面说得,把自定义的ClassLoader反复加密并调用,这样当然就引起了堆栈超长且无用(这些超长的堆栈不仅影响性能,还严重浪费内存,更严重的,在有些JVM里面,这样反复调用一个ClassLoader容易出现加载class失败的现象)。
要是不综合考虑这些问题(如开发调试、测试与部署、性能/内存、JVM支持、维护成本等)的话,我还有好几种变态的方式实现,呵呵~
7 楼 hellohank 2015-06-11  
whywen_MoJian 写道
不错,顶一个。

谢谢~
6 楼 hellohank 2015-06-11  
wwwcomy 写道
有些奇怪的混淆方式(包括改classloader以及那块之下的内容)很容易造成jvm或web容器不兼容的情况。

比如Oracle的JDK环境Tomcat里跑的好好的webapp,拿到WebSphere就部署不上。

鱼与熊掌不可兼得啊。。


其实,只是从我上面的这种改写ClassLoader的方式(不是调用JNI,也不是增强型的混淆),并没有改变class的任何规范,所以其实是在任何JVM中可以运行的。之所以有些项目在Tomcat下面能跑而在WebSphere不能跑,是因为这些应用服务器本身实现上存在一些自己的差异,而如果这些项目正好在一些功能上用到了这些差异(如:静态资源配置、JNDI应用、JEE协议实现等等),会因为不同而造成webapp确实无法跑起来~但这些都跟JVM无关,真正跟JVM有关的就是class文件,如果在编译成class文件的过程中使用了特定的一些配置,如:指定了java版本、对其进行增强混淆,就会使得class文件中的一些JVM弱规范部分不一致,导致不同的JVM在解析时出现各种问题。
所以,我现在要做的,并不想改变class内容,我只想能不能让这个内容不会让人知道,只让JVM知道~
望多讨论~
5 楼 wwwcomy 2015-06-11  
有些奇怪的混淆方式(包括改classloader以及那块之下的内容)很容易造成jvm或web容器不兼容的情况。

比如Oracle的JDK环境Tomcat里跑的好好的webapp,拿到WebSphere就部署不上。

鱼与熊掌不可兼得啊。。
4 楼 whywen_MoJian 2015-06-11  
不错,顶一个。
3 楼 near_sun 2015-06-11  
改完之后就不是java。
改完 比较大的问题 就是日志问题,还有异常定位问题
2 楼 hellohank 2015-06-11  
luhantu 写道
里面的图片貌似没有了……非常遗憾啊

已经处理过了。
这个文章,我是先在word中写的,所以有些图片在复制时会丢失,有些格式也有点乱,今天会完善一下。
1 楼 luhantu 2015-06-10  
里面的图片貌似没有了……非常遗憾啊

相关推荐

    Java防反编译技术研究.pdf

    为了应对这一问题,Java防反编译技术成为了开发过程中的一个重要领域。在这篇论文中,作者探讨了反编译技术的发展,并提出了新的方法以提高Java程序的安全性。 首先,作者提到了反编译技术的起源。Java之所以能够跨...

    JAVA反编译技术和代码安全.pdf

    本篇文章旨在深入探讨JAVA反编译技术及其对代码安全性的影响,并提出有效的防护策略。 #### 二、JAVA反编译技术概述 ##### 1. 反编译的概念 反编译技术是指将目标代码转换回源代码的过程。这里的“目标代码”指的...

    java反编译(附源代码)

    Java反编译是Java开发中一个重要的技术领域,它涉及到对已编译的Java字节码(.class文件)进行逆向工程,以获取接近原始的源代码。这对于理解库函数、研究开源软件或者调试不可获得源代码的二进制程序非常有用。本文...

    java 反编译 反编译软件

    Java反编译是一种技术,它允许开发者查看Java字节码(.class文件)背后的源代码。这在多种情况下非常有用,比如分析已有的库、学习别人的实现或者在没有源码的情况下调试二进制代码。本篇文章将深入探讨Java反编译的...

    防止java反编译的一些方法

    ### 防止Java反编译的策略与技术解析 #### 概述 在软件开发领域,保护代码免受逆向工程(反编译)的威胁是至关重要的,尤其是在Java编程语言中,因其字节码的特性使得其相对易于被反编译。本文将深入探讨几种常用...

    java 反编译软件

    本文将深入探讨Java反编译的概念、原理以及如何使用jad反编译工具。 一、Java反编译概念 反编译是将已编译的二进制代码转换回源代码的过程。对于Java来说,这个过程主要是将.class文件转换成.java文件。由于Java的...

    java反编译工具

    本文将深入探讨Java反编译的相关知识点,以及如何使用这样的工具将一个jar包工程直接转换为完整的Java工程。 Java是一种高级编程语言,其源代码被编译成字节码(.class文件),这些字节码可以在Java虚拟机(JVM)上...

    Android防反编译工具

    本篇文章将深入探讨Android防反编译的概念、方法以及如何使用"apk_anti_decompile"这样的工具来增强应用的安全性。 首先,我们需要理解什么是Android反编译。反编译是指将已编译的二进制代码转换回接近原始源代码的...

    利用混淆器ProGuard混淆java类,防止反编译

    在Java开发中,保护代码安全是一项重要的任务,尤其是在发布应用或库时,因为恶意用户可能会尝试反编译你的代码以获取敏感信息。本篇将详细讲解如何使用混淆器ProGuard来混淆Java类,以增加反编译的难度,从而保护你...

    java反编译

    Java反编译是Java开发中一个重要的技术环节,它允许开发者查看Java字节码(.class文件)的源代码,即使原始的.java文件已丢失或不在手边。这对于理解库函数的工作原理、学习他人代码、调试和逆向工程等场景非常有用...

    Java反编译工具.rar

    在本讨论中,我们将深入探讨Java反编译的概念、用途以及一些常用的反编译工具。 Java是一种高级编程语言,它的源代码首先被编译成字节码,然后由Java虚拟机(JVM)执行。字节码是平台无关的,这使得Java应用程序...

    Android-DecompileApk-一键反编译APK

    开发者可能通过混淆、加密、添加防反编译机制等方式来保护代码不被轻易逆向工程。 8. **混淆技术**:ProGuard 和 R8 是常用的Java代码混淆工具,它们通过重命名类和方法、删除未使用的代码、优化代码等方式,使反...

    android反编译.zip

    "android反编译.zip"这个压缩包提供了实现这一目标所需的工具和步骤。下面,我们将深入探讨这些知识点。 首先,APK文件是Android应用的打包格式,包含了 Dex(Dalvik Executable)文件,这是Java字节码的优化形式,...

    C#程序反编译保护 教程

    本教程将深入探讨如何保护C#程序不被轻易反编译。 首先,我们需要理解什么是反编译。反编译是将已编译的二进制代码转换回高级语言的过程,如C#、Java等。常见的C#反编译工具有ILSpy、Reflector和dotPeek等。这些...

    反编译与二次打包

    反编译的过程并不简单,因为编译后的代码通常失去了原始的结构和注释,而且为了保护知识产权,开发者可能使用了混淆技术,使得反编译的结果难以理解。因此,反编译者需要具备深厚的编程基础和逆向工程技能,才能从反...

    反编译class.dex

    本篇文章将深入探讨如何对`class.dex`进行反编译,以及相关的工具和流程。 首先,我们要了解反编译的概念。反编译是将已编译的二进制代码转换回人类可读的源代码的过程。对于Android的`class.dex`文件,我们通常...

    代码混淆—关于android被反编译的两种解决方案

    本文将深入探讨两种防止Android应用被反编译的策略:代码混淆和使用安全工具。 首先,我们来了解一下什么是代码混淆。代码混淆是一种通过改变代码的可读性来增加其复杂性的技术,主要是通过对变量名、函数名和类名...

    classloader 加密解密应用程序 ,反编译class

    同时,掌握加密解密和反编译防御技术对于开发安全的Java应用至关重要。 总结来说,`ClassLoader`在Java中扮演着核心角色,负责加载和管理类。通过自定义`ClassLoader`,我们可以实现加密解密应用程序,提升代码的...

    Android系统安全和反编译实战学习下载

    本篇将深入探讨Android系统的安全机制以及如何进行反编译实战,以提高应用的安全防护能力。 首先,Android系统的安全模型基于Linux内核,采用了权限管理系统,每个应用都有独立的用户ID和权限集。这种沙箱机制使得...

    android反编译工具

    - 防反编译技术:许多应用会使用混淆、加密或自定义指令集来保护代码,使得反编译结果难以理解。 - 法律问题:反编译他人的应用可能涉及到版权和隐私法律,必须确保合法使用。 - 动态加载:部分代码可能在运行时...

Global site tag (gtag.js) - Google Analytics