- 浏览: 295760 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (155)
- Liferay portal研究 (23)
- spring研究 (7)
- Displaytag (2)
- Flash Builder (0)
- 搜索引擎 (12)
- 杂项 (17)
- SCM管理 (7)
- Jquery (5)
- Linux (7)
- Oracle (10)
- httpd集成 (3)
- Maven2 (5)
- 企业管理 (1)
- tomcat高级 (4)
- dos命令 (1)
- ldap (2)
- Java (8)
- webservice (1)
- jetty代码研究 (3)
- OpenCMS (1)
- JMX (2)
- hibernate (5)
- Ant (1)
- js tree (4)
- Quartz (0)
- CMS (1)
- springside (1)
- proxool (1)
- freemarker (1)
- Cookie (1)
- CAS SSO (4)
- mysql (1)
- php (1)
- js (2)
- Asset (1)
- openmeeting (1)
- h2数据库 (2)
- wcf vs java ws (1)
最新评论
-
22199143:
...
当在重启Tomcat容器时 Exception in Thread "HouseKeeper" java.lang.NullPointerException -
liuqq:
一直用Oracle开发,几乎没有接触过其他数据库。使用Mysq ...
The Nested Set Model -
yjsxxgm:
yjsxxgm 写道FFFFFFFFFFFFFFFWWW
java 访问wcf -
yjsxxgm:
FFFFFFFFFFFFFFF
java 访问wcf -
hjp222:
scanIntervalSeconds 是重新启动,并非真正的 ...
Jetty 热部署
现在的JDK都是1.4/1.5用比较老的JAD和ECLIPSE的JODE进行反编译,出来的代码的可读性比较差,而且比较多错误.
以下是同一CLASS文件反编译出来的代码:
可以看出:
1、JODE出来的代码的可读性最好,不过有CLASS文件代码用JODE是反编译不出来出现异常;
2、JAD出来的代码经常要进行大量整理;
3、JODE和JAD对混混淆过的代码,变量的顺序可能会不一样,自变量的命名,JODE会好一些。
4、对于PUSH和POP,左修整时候,可以自己加自变量,临时存储;
5、JAVA对于表达式或函数参数,是从右到左进行解释的。函数参数,最后PUSH的,是最右边的参数;对于
等号赋值也是先右后左进行出栈。
/**
* jode
* @param i
* @param i_1_
* @param graphics
*/
private void b(int i, int i_1_, Graphics graphics) {
graphics.setColor(0);
if (((h) this).e.f == null)
graphics.setColor(6710886);
else {
int tmp=0;
if (((h) this).e.f.size() == 1) {
PUSH g.c;
PUSH = 64;
} else {
PUSH g.c;
PUSH = 80;
}
g.a(POP, POP, 0, 16, 16, i, i_1_, graphics);
}
StringBuffer stringbuffer = new StringBuffer();
if (((h) this).e.e > 0) {
graphics.setColor(16711680);
stringbuffer.append('[');
stringbuffer.append(((h) this).e.e);
stringbuffer.append("\u65b0\u6d88\u606f"); //新消息
stringbuffer.append(']');
}
if (((h) this).f)
graphics.setColor(16777215);
stringbuffer.append(((h) this).e.a());
graphics.drawString(a(stringbuffer.toString(), 158), i + 16 + 1,
i_1_ + 1, 20);
}
/**
* jad
* @param i
* @param j
* @param g1
*/
private void b(int i, int j, Graphics g1)
{
g1.setColor(0);
if(e.f != null) goto _L2; else goto _L1
_L1:
g1.setColor(0x666666);
goto _L3
_L2:
if(e.f.size() != 1) goto _L5; else goto _L4
_L4:
g.c;
76;
goto _L6
_L5:
g.c;
95;
_L6:
0;
19;
19;
i;
j;
g1;
g.a();
_L3:
StringBuffer stringbuffer = new StringBuffer();
if(e.e > 0)
{
g1.setColor(0xff0000);
stringbuffer.append('[');
stringbuffer.append(e.e);
stringbuffer.append("\u65B0\u6D88\u606F");
stringbuffer.append(']');
}
if(f)
g1.setColor(0xffffff);
stringbuffer.append(e.a());
g1.drawString(a(stringbuffer.toString(), 219), i + 19 + 1, j + 1, 20);
return;
}
// public final void a(boolean bool) {
// if (bool) {
// PUSH this;
// PUSH "BD";
// } else {
// PUSH this;
// PUSH "AA";
// }
// ((n) POP).d = POP;
// }
//
public final void a(boolean flag)
{
if(!flag){
this.d="AA";
}else{
this.d="BD";
}
// if(!flag) goto _L2; else goto _L1
//_L1:
// this;
// "BD";
// goto _L3
//_L2:
// this;
// "AA";
//_L3:
// d;
}
再加几个用例:
一般情况下Java应用的开发者为了保护代码不被别人抄袭,在生成class文件的时候都java文件进行了混淆,这种class文件用反编译工具得到的结果很难看懂,并且不能进行编译。本文从研究的角度,浅析如何读懂这种反编译过来的文件。
例子一:赋值
反编译过来的代码如下:
Node node;
Node node1 = _$3.getChildNodes().item(0);
node1;
node1;
JVM INSTR swap ;
node;
getChildNodes();
0;
item();
getChildNodes();
0;
item();
getNodeValue();
String s;
s;
原始语句:
Node node;
Node node1 = currDocument.getChildNodes().item(0);
node = node1;
String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
注解:
JVM INSTR swap ; //赋值语句
练习:
String s1;
String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
s8;
s8;
JVM INSTR swap ;
s1;
10;
Integer.parseInt();
int i;
i;
例子二:不带参数创建对象
反编译过来的代码如下:
JVM INSTR new #244 <Class CrossTable>;
JVM INSTR dup ;
JVM INSTR swap ;
CrossTable();
CrossTable crosstable;
crosstable;
原始语句:
CrossTable crosstable = new CrossTable();
注解:
练习:
JVM INSTR new #246 <Class Database>;
JVM INSTR dup ;
JVM INSTR swap ;
Database();
Object obj;
obj;
例子三:带参数创建对象
反编译过来的代码如下:
JVM INSTR new #262 <Class StringBuffer>;
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s2);
StringBuffer();
s.substring(j, i);
append();
s6;
append();
toString();
s2;
原始语句:
s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();
注解:
此语句实际上是:s2 += s.substring(j, i) + s6;
练习:
例子四:for循环
反编译过来的代码如下:
int k = 0;
goto _L4
_L8:
...
k++;
_L4:
if(k < as.length) goto _L8; else goto _L7
原始语句:
for(int k=0;k < as.length;k++)
{
...
}
注解:
例子五:while循环
反编译过来的代码如下:
String s1 = "";
goto _L1
_L3:
JVM INSTR new #262 <Class StringBuffer>;
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s1);
StringBuffer();
_$2(resultset, s, l);
append();
toString();
s1;
_L1:
if(resultset.next()) goto _L3; else goto _L2
原始语句:
String s1 = "";
while(resultset.next())
{
s1 = s1 + resultSetToString(resultset, s, l);
}
注解:
欢迎有此兴趣的朋友和我交流。
以下是同一CLASS文件反编译出来的代码:
可以看出:
1、JODE出来的代码的可读性最好,不过有CLASS文件代码用JODE是反编译不出来出现异常;
2、JAD出来的代码经常要进行大量整理;
3、JODE和JAD对混混淆过的代码,变量的顺序可能会不一样,自变量的命名,JODE会好一些。
4、对于PUSH和POP,左修整时候,可以自己加自变量,临时存储;
5、JAVA对于表达式或函数参数,是从右到左进行解释的。函数参数,最后PUSH的,是最右边的参数;对于
等号赋值也是先右后左进行出栈。
/**
* jode
* @param i
* @param i_1_
* @param graphics
*/
private void b(int i, int i_1_, Graphics graphics) {
graphics.setColor(0);
if (((h) this).e.f == null)
graphics.setColor(6710886);
else {
int tmp=0;
if (((h) this).e.f.size() == 1) {
PUSH g.c;
PUSH = 64;
} else {
PUSH g.c;
PUSH = 80;
}
g.a(POP, POP, 0, 16, 16, i, i_1_, graphics);
}
StringBuffer stringbuffer = new StringBuffer();
if (((h) this).e.e > 0) {
graphics.setColor(16711680);
stringbuffer.append('[');
stringbuffer.append(((h) this).e.e);
stringbuffer.append("\u65b0\u6d88\u606f"); //新消息
stringbuffer.append(']');
}
if (((h) this).f)
graphics.setColor(16777215);
stringbuffer.append(((h) this).e.a());
graphics.drawString(a(stringbuffer.toString(), 158), i + 16 + 1,
i_1_ + 1, 20);
}
/**
* jad
* @param i
* @param j
* @param g1
*/
private void b(int i, int j, Graphics g1)
{
g1.setColor(0);
if(e.f != null) goto _L2; else goto _L1
_L1:
g1.setColor(0x666666);
goto _L3
_L2:
if(e.f.size() != 1) goto _L5; else goto _L4
_L4:
g.c;
76;
goto _L6
_L5:
g.c;
95;
_L6:
0;
19;
19;
i;
j;
g1;
g.a();
_L3:
StringBuffer stringbuffer = new StringBuffer();
if(e.e > 0)
{
g1.setColor(0xff0000);
stringbuffer.append('[');
stringbuffer.append(e.e);
stringbuffer.append("\u65B0\u6D88\u606F");
stringbuffer.append(']');
}
if(f)
g1.setColor(0xffffff);
stringbuffer.append(e.a());
g1.drawString(a(stringbuffer.toString(), 219), i + 19 + 1, j + 1, 20);
return;
}
// public final void a(boolean bool) {
// if (bool) {
// PUSH this;
// PUSH "BD";
// } else {
// PUSH this;
// PUSH "AA";
// }
// ((n) POP).d = POP;
// }
//
public final void a(boolean flag)
{
if(!flag){
this.d="AA";
}else{
this.d="BD";
}
// if(!flag) goto _L2; else goto _L1
//_L1:
// this;
// "BD";
// goto _L3
//_L2:
// this;
// "AA";
//_L3:
// d;
}
再加几个用例:
一般情况下Java应用的开发者为了保护代码不被别人抄袭,在生成class文件的时候都java文件进行了混淆,这种class文件用反编译工具得到的结果很难看懂,并且不能进行编译。本文从研究的角度,浅析如何读懂这种反编译过来的文件。
例子一:赋值
反编译过来的代码如下:
Node node;
Node node1 = _$3.getChildNodes().item(0);
node1;
node1;
JVM INSTR swap ;
node;
getChildNodes();
0;
item();
getChildNodes();
0;
item();
getNodeValue();
String s;
s;
原始语句:
Node node;
Node node1 = currDocument.getChildNodes().item(0);
node = node1;
String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
注解:
JVM INSTR swap ; //赋值语句
练习:
String s1;
String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
s8;
s8;
JVM INSTR swap ;
s1;
10;
Integer.parseInt();
int i;
i;
例子二:不带参数创建对象
反编译过来的代码如下:
JVM INSTR new #244 <Class CrossTable>;
JVM INSTR dup ;
JVM INSTR swap ;
CrossTable();
CrossTable crosstable;
crosstable;
原始语句:
CrossTable crosstable = new CrossTable();
注解:
练习:
JVM INSTR new #246 <Class Database>;
JVM INSTR dup ;
JVM INSTR swap ;
Database();
Object obj;
obj;
例子三:带参数创建对象
反编译过来的代码如下:
JVM INSTR new #262 <Class StringBuffer>;
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s2);
StringBuffer();
s.substring(j, i);
append();
s6;
append();
toString();
s2;
原始语句:
s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();
注解:
此语句实际上是:s2 += s.substring(j, i) + s6;
练习:
例子四:for循环
反编译过来的代码如下:
int k = 0;
goto _L4
_L8:
...
k++;
_L4:
if(k < as.length) goto _L8; else goto _L7
原始语句:
for(int k=0;k < as.length;k++)
{
...
}
注解:
例子五:while循环
反编译过来的代码如下:
String s1 = "";
goto _L1
_L3:
JVM INSTR new #262 <Class StringBuffer>;
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s1);
StringBuffer();
_$2(resultset, s, l);
append();
toString();
s1;
_L1:
if(resultset.next()) goto _L3; else goto _L2
原始语句:
String s1 = "";
while(resultset.next())
{
s1 = s1 + resultSetToString(resultset, s, l);
}
注解:
欢迎有此兴趣的朋友和我交流。
发表评论
-
Eclipse
2010-05-26 08:39 1243Eclipse 快捷键(1) Ctrl+1 快 ... -
A bridge method
2010-04-08 21:37 180213 A bridge method ... -
struts2原理分析
2010-04-01 10:23 5795读者如果曾经学习过Struts1.x或者有过Struts1.x ... -
1,失血模型2,贫血模型3,充血模型4,胀血模型
2010-03-25 20:34 3251为了补大家的遗憾,在此总结下ROBBIN的领域模型的一些观点和 ... -
myeclipse 启动优化
2010-01-25 21:10 1825解决MyEclipse吃内存,让MyE ... -
ca 证书
2010-01-21 12:21 945http://jeffyyko.blog.51cto.com/ ... -
jpolite2
2010-01-19 20:15 1856http://www.trilancer.com/jpolit ... -
p3p iframe session共享及其它
2009-12-22 08:27 3464IE浏览器iframe跨域丢失Session问题 在开发中, ... -
摩斯密码
2009-12-11 21:45 1358突然对密斯密码很感兴趣,所以在网上找了一些有关的资料,供大家参 ... -
Win2003环境下用Apache整合Tomcat6和IIS服务器共用80端口
2009-12-03 10:15 3880Win2003环境下用Apache整合Tomcat6和I ... -
好的网址wiget
2009-09-30 10:47 912tree outlook style webfxtree:ht ... -
比较好的博客
2009-09-29 22:03 837一些通用模块:www.faqee.com 一些通用模块的作者: ... -
vm 修改磁盘大小
2009-09-26 09:33 1369成功检核过的: vmware-vdiskmanager -x ... -
vmtools 安装
2009-09-19 21:42 1560、VMware Tools安装手记(For Linux Gue ... -
vm被打开问题
2009-09-19 21:09 827启动系统报告This virtual machine appe ... -
搭手架项目
2009-09-16 21:50 10211.Appfuse[java] 2.rapid-framewo ...
相关推荐
描述中提到的链接指向了一个ITEYE博客,虽然具体内容未给出,但可以推测博主分享了关于Java反编译工具的使用经验和心得。通常,这类工具可以帮助开发者了解无法获得源代码的库或框架的工作原理,甚至可能用于修复bug...
Java反编译工具JD-GUI是一款非常实用的软件,它允许开发者查看并理解Java字节码,将已编译的.class文件转换回可读的Java源代码。在软件开发过程中,有时我们需要查看或分析已有的Java类文件,而原始的源代码不再可用...
(注:如果使用Eclipse插件,则很容易得到包中的某个类的反编译代码) 3.当有标签块,嵌套循环中有break/continue,有goto语句的时候,会提示信息“Couldn't fully decompile method ”;当有try-catch-finally语句...
** Jadclipse:Java 反编译利器** Jadclipse 是一款专门为 Eclipse 集成开发环境设计的反编译插件,它使得开发者能够在 Eclipse 中方便地查看 Java 类的源代码,即使这些类没有原始的 .java 文件。Jadclipse 的核心...
### Java入门缓冲区溢出编程心得 #### 缓冲区溢出原理与实践 缓冲区溢出是一种常见的安全漏洞,通常发生在程序试图将过多的数据写入一个固定大小的内存区域时。这种行为可能会覆盖相邻的内存空间,从而导致程序...
在刚开始的第一章就详细地讲解了Java开发环境的搭建、反编译工具的使用、JDK文档资料的查阅,Java程序的编译、运行过程。在第二章中,全面地讲解Java的基本语法知识,对基本语法的讲解也不是泛泛而谈,而是在其中...
首先,视频从基础开始,详细介绍了Java开发环境的配置,包括JDK的安装和设置,以及如何使用反编译工具以理解已编译的Java代码。此外,还教授了如何查阅JDK文档,这是开发者自我学习和解决问题的重要工具。接着,教程...
在刚开始的第一章就详细地讲解了Java开发环境的搭建、反编译工具的使用、JDK文档资料的查阅,Java程序的编译、运行过程。在第二章中,全面地讲解Java的基本语法知识,对基本语法的讲解也不是泛泛而谈,而是在其中...
"jd-gui.exe" 是一个Java反编译工具,主要用于查看和分析Java字节码,帮助开发者理解已编译的.class文件内部结构。这个工具在软件开发过程中,尤其是在逆向工程、代码调试或者学习第三方库的工作中非常有用。它提供...
这篇“多年Java精华积累”文档很可能是作者多年深入学习和实践Java的心得总结,对于初学者和有经验的开发者来说,都是一个宝贵的资源。下面,我们将根据这个主题,探讨一些重要的Java知识点。 1. **Java基础** - ...
aspose-words 替换文本代码,报告引擎
- **javap**:Java反汇编器,可以用来查看类文件中的字节码。 #### 技术支持与社区参与 JDK提供了多种技术支持和反馈渠道,如官方论坛、邮件列表和bug跟踪系统等,以便用户报告问题并获取帮助。此外,还鼓励用户...
- **使用工具**:如dex2jar、JD-GUI、apktool等,可以将APK文件反编译为Java源码或XML布局文件。 - **分析代码**:通过对反编译出的代码进行分析,可以了解应用的内部实现细节。 ### 十四、如何进行Android单元测试...
12. **XML解析:** DOM和SAX两种解析方式,以及使用JAXB进行对象与XML之间的序列化和反序列化。 13. **JDBC:** 数据库连接、事务处理、预编译语句、批处理操作,以及结果集的处理。 14. **设计模式:** 常见的...
2. Java Decompiler:如JD-GUI、Procyon等反编译工具,用于查看未包含源码的类。 3. Git:版本控制工具,可以帮助追踪源码的修改历史,理解代码的演变过程。 五、源码阅读的实践与应用 将源码阅读与实际项目结合,...
在CTF挑战中,Java可能涉及到的方面包括代码审计、漏洞利用、反编译和逆向工程等。理解类、对象、继承、多态性、异常处理、IO流、网络编程等核心概念是解决Java相关问题的基础。 2. **Java安全**:在HSCTF 2015中,...
在这里,我们可以深入理解恶意软件的工作原理,学习如何反编译、重构恶意代码,甚至可以在此基础上创造新的恶意软件样本,以提升对抗网络威胁的能力。 逆向工程是网络安全领域的一项关键技能,它涉及将已执行的代码...