透视JAVA——反编译、修补和逆向工程技术 读书笔记

1、  Java source is not compiled to binary machine code like C/C++ source is.

2、  Because the bytecode does not represent the lowest-level machine language, the format of the code closely resembles the source code.

3、public String getDisplayName() {

return getUserName() + “ (“ + getHostName() + “)”;

}

is represented by the following bytecode:

0 new #4 <java/lang/StringBuffer>

3 dup

4 aload_0

5 invokevirtual #5 <covertjava/decompile/MessageInfoComplex.getUserName>

8 invokestatic #6 <java/lang/String.valueOf>

11 invokestatic #6 <java/lang/String.valueOf>

14 invokespecial #7 <java/lang/StringBuffer.<init>>

17 ldc #8 < (>

19 invokevirtual #9 <java/lang/StringBuffer.append>

22 aload_0

23 invokevirtual #10 <covertjava/decompile/MessageInfoComplex.getHostName>

26 invokevirtual #9 <java/lang/StringBuffer.append>

29 ldc #11 <)>

31 invokevirtual #9 <java/lang/StringBuffer.append>

34 invokestatic #6 <java/lang/String.valueOf>

37 invokestatic #6 <java/lang/String.valueOf>

40 areturn

3、  Potential Problems with Decompiled Code(混淆器)

Most of the time, decompiling produces a readable file that can be changed and recompiled.However, on some occasions decompiling does not render a file that can be compiled again.

Reason: This can happen if the bytecode was obfuscated, and the names given by the obfuscator result in ambiguity at the compilation. The bytecode is verified when loaded, but the verifications assume that the compiler has checked for a number of errors.

obfuscated by the Zelix ClassMaster obfuscator.

static class c

implements Runnable

{

public void run()

{

boolean flag = a.b;

System.out.println(a(“*4%p\002\026&kj\016\0135”));

b b1 = new b(a(“2\000\006_\”;\0”), a(“3 ‘w\005\02778u\022”));

System.out.println(a(“5$8m\n\037$kw\017X|k”).concat(String.valueOf

➥(String.valueOf(b1.d()))));

b1 = new b(null, a(“2\000\006_\”;\0”));

System.out.println(a(“5$8m\n\037$kw\017X|k”).concat(String.valueOf

➥(String.valueOf(b1.d()))));

if(flag)

b.c = !b.c;

}

private static String a(String s)

{

char ac[];

int i;

int j;

ac = s.toCharArray();

i = ac.length;

j = 0;

if(i > 1) goto _L2; else goto _L1

_L1:

ac;

j;

_L10:

JVM INSTR dup2 ;

JVM INSTR caload ;

j % 5;

JVM INSTR tableswitch 0 3: default 72

//                       0 52

//                       1 57

//                       2 62

//                       3 67;

goto _L3 _L4 _L5 _L6 _L7

_L4:

0x78;

goto _L8

_L5:

65;

goto _L8

_L6:

75;

goto _L8

_L7:

30;

goto _L8

_L3:

107;

_L8:

JVM INSTR ixor ;

(char);

JVM INSTR castore ;

j++;

if(i != 0) goto _L2; else goto _L9

_L9:

ac;

i;

goto _L10

_L2:

if(j >= i)

return new String(ac);

if(true) goto _L1; else goto _L11

_L11:

}

}

很多商业项目会用这招,为了保护代码。

即使使用了混淆器,可以保证源代码不会被反编译以后直接运用,但是我们可以通过反编译找出你源代码的逻辑或者创新点。这对研发代码的开发很不公平,那么像保护它,只能应用Patents(专利)。

Advanced obfuscators go further and change the control flow of Java code by restructuring the existing logic and inserting bogus code that will not execute.

Debug information is not needed to run the class but is used by debuggers to associate the bytecode with the source code.

When the debug information is stripped out, the names that were stored are lost, so decom-pilers have to generate their own names. In our case, after the stripping, sendMessage para-meter names would appear as s1and s2instead of  host and message.

^*^

Encoding Java Strings

Even if class and method names are changed, the strings written by methods to a log file or console can betray the method purpose.In our case, ChatServer.sendMessageoutputs a trace message using the following:

System.out.println(“Sending message to host “ + host + “: “ + message);

String encoding is a powerful feature that should be provided by a commercial-strength obfuscator.

The best obfuscators are capable of transforming the execution flow of bytecode by inserting bogus conditional and  goto statements. This can slow down the execution somewhat, but it might be a small price to pay for the increased protection of the IP. Listing 3.3 shows what sendMessage has become after all the transformations discussed earlier have been applied.

混淆前后比照

混淆前:

public void a(String s, String s1)

throws Exception

{

if(s == null || s.trim().length() == 0)

{

throw new Exception(“Please specify host name”);

} else

{

System.out.println(String.valueOf(String.valueOf((

new StringBuffer(“Sending message to host “)

).append(s).append(“: “).append(s1))));

String s2 = String.valueOf(String.valueOf((

new StringBuffer(“//”)).append(s).append(“:”)

.append(b).append(“/chatserver”)));

b b1 = (b)Naming.lookup(s2);

MessageInfo messageinfo = new MessageInfo(e, f);

b1.receiveMessage(s1, messageinfo);

System.out.println(“Message sent to host “.concat(

String.valueOf(String.valueOf(s))));

return;

}

}

混淆后:public void a(String s, String s1)

throws Exception

{

boolean flag = MessageInfo.c;

s;

if(flag) goto _L2; else goto _L1

_L1:

JVM INSTR ifnull 29;

goto _L3 _L4

_L3:

s.trim();

_L2:

if(flag) goto _L6; else goto _L5

_L5:

length();

JVM INSTR ifne 42;

goto _L4 _L7

_L4:

throw new Exception(a(“\002)qUe7egDs1,rM6:*g@6<$yQ”));

_L7:

System.out.println(String.valueOf(String.valueOf((

new StringBuffer(a(“\001 zP\177<\”4Ys!6uSsr1{\024~=6`\024”))

).append(s).append(a(“he”)).append(s1))));

String.valueOf(String.valueOf(

(new StringBuffer(a(“}j”))).append(s).append(“:”)

.append(b).append(a(“}&|Ub! fBs “))));

_L6:

String s2;

s2;

covertjava.chat.b b1 = (covertjava.chat.b)Naming.lookup(s2);

MessageInfo messageinfo = new MessageInfo(e, f);

b1.receiveMessage(s1, messageinfo);

System.out.println(a(“\037 gGw5 4Gs<14@yr-{Gbr”).concat(String.valueOf

➥(String.valueOf(s))));

if(flag)

b.c = !b.c;

return;

}

Inserting Corrupt Code

Inserting corrupt code is a somewhat dubious technique used by some obfuscators to prevent obfuscated classes from decompiling. The technique is based on a loose interpretation of the Java bytecode specification by the Java Runtime. JRE does not strictly enforce all the rules of bytecode format verification, and that allows obfuscators to introduce incorrect bytecode into the class files. The introduced code does not prevent the original code from executing, but an attempt to decompile the class file results in a failure—or at best in confusing source code full

of JVM INSTR keywords.

Eliminating Unused Code (Shrinking)

As an added benefit, most obfuscators remove unused code, which results in application size reduction. For example, if a class called  A has a method called  m() that is never called by any class, the code for  m() is stripped out of A’s   bytecode. This feature is especially useful for code that is downloaded via the Internet or installed in unsecured environments.

Optimizing Bytecode

Another added benefit touted by obfuscators is potential code optimization. The vendors claim that declaring nonfinal methods as final where possible and performing minor code improvements can help speed up execution. It is hard to assess the real performance gains,and most vendors do not publish the metrics. What is worth noting here is that, with every new release, JIT compilers are becoming more powerful. Therefore, features such as method finalization and dead code elimination are most likely performed by it anyway.

For commercial applications that contain intellectual property, I recommend Zelix

KlassMaster primarily because of its unique control flow obfuscation.

 
 

Java之逆向工程(1) - 反编译、修补和逆向工程技术 读书笔记的更多相关文章

  1. 如何保护java程序不被反编译

    Java是一种 跨平台的.解释型语言 Java 源代码编译中间“字节码”存储于class文件中.Class文件是一种字节码形式的中间代码,该字节码中包括了很多源代码的信息,例如变量名.方法名 等.因此 ...

  2. Java逆向武器库_反编译工具

    1.反编译工具之_jd-gui 官网下载地址:http://java-decompiler.github.io/#jd-gui-download 使用: 下载后解压直接使用即可. jd-gui的优势是 ...

  3. Java代码加密与反编译(二):用加密算法DES修改classLoader实现对.class文件加密

    Java代码加密与反编译(二):用加密算法DES修改classLoader实现对.class文件加密 二.利用加密算法DES实现java代码加密 传统的C/C++自动带有保护机制,但java不同,只要 ...

  4. Java Jar源码反编译工具那家强

    本文介绍下Java Jar常见的反编译工具,并给出使用感受. 反编译JAR能干什么: 排查问题.分析商业软件代码逻辑,学习优秀的源码思路. JD-GUI 下载地址:http://java-decomp ...

  5. 《Java编程思想》——初始化与清理(一)读书笔记

    第一次写这个,这一章都用word写的,结果复制过来没图片....只能上传word文档了.以后改用markdown比较好 word文档地址:<Java编程思想>--初始化与清理(一)读书笔记

  6. Java .class文件的反编译与反汇编

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10840818.html 一:反编译 通常用于第三方JAR包的逆向工程. 一般我们拿到的jar包都是经过编译后 ...

  7. Java代码加密与反编译(一):利用混淆器工具proGuard对jar包加密

    Java 代码编译后生成的 .class 中包含有源代码中的所有信息(不包括注释),尤其是在其中保存有调试信息的时候.所以一个按照正常方式编译的 Java .class 文件可以非常轻易地被反编译.通 ...

  8. 《深入理解Java虚拟机:JVM高级特性与最佳实践》读书笔记

    第一部分 走进Java 一.走进Java 1.概述 java广泛应用于嵌入式系统.移动终端.企业服务器.大型机等各种场合,摆脱了硬件平台的束缚,实现了“一次编写,到处运行”的理想 2.java技术体系 ...

  9. 《疯狂Java:突破程序员基本功的16课》读书笔记-第一章 数组与内存控制

    很早以前就听过李刚老师的疯狂java系列很不错,所以最近找一本拿来拜读,再此做下读书笔记,促进更好的消化. 使用Java数组之前必须先对数组对象进行初始化.当数组的所有元素都被分配了合适的内存空间,并 ...

随机推荐

  1. [CF226E]Noble Knight's Path

    [CF226E]Noble Knight's Path 题目大意: 一棵\(n(n\le10^5)\)个结点的树,初始时所有结点都是白色.\(m(m\le10^5)\)次操作,操作包含以下两种: 将点 ...

  2. 区间DP--凸多边形三角剖分

    给定一个具有N(N<50)个顶点(从1到N编号)的凸多边形,每个顶点的权均已知.问如何把这个凸多边形划分成N-2个互不相交的三角形,使得这些三角形顶点的权的乘积之和最小? 输入文件:第一行 顶点 ...

  3. c# -- Form1_Load()不被执行的三个解决方法

    我的第一个c#练习程序,果然又出现问题了...在Form1_Load() not work.估计我的人品又出现问题了. 下面实现的功能很简单,就是声明一个label1然后,把它初始化赋值为hello, ...

  4. CAShapeLayer实现音量大小动态改变

    我是效果图 实现如图这效果一般会直接通过多张图进行切换进行完成.但这样的处理,会浪费App的资源存储空间,而且效率也不高.那么今天我们用CAShapeLayer实现以下吧. 拆分: 1.一个椭圆 2. ...

  5. Java过滤任意(script,html,style)标签符,返回纯文本--封装类

     import java.util.regex.Pattern;   /**  * 过滤标签字符串,返回纯文本  *  */ public class ChangePlainText {        ...

  6. 一些值得学习的Unity教程 (很实用的包括源码)

    ***********************项目源码******************************** 1. 降临 2. 沉睡缤纷乐 3. 千炮捕鱼 4. Photon官方FSP示例 ...

  7. infor系统日常问题解决笔记

    1.问题:结算单核准时候显示订单XXX的状态为已修改. 解决方法:在采购订单状态栏重新核准订单,采购订单状态不影响发票核准,结算后不允许再新增采购订单行,否则仍然会提示采购订单状态为已修改,且无法进行 ...

  8. appium+python自动化26-模拟手势点击坐标(tap)

    ​# 前言: 有时候定位元素的时候,你使出了十八班武艺还是定位不到,怎么办呢?(面试经常会问) 那就拿出绝招:点元素所在位置的坐标 tap用法 1.tap是模拟手指点击,一般页面上元素 的语法有两个参 ...

  9. Combogrid的onChange和onSelect

    这里只作记录一下 在easyui开发过程中遇到下边两个事儿 combogrid/combotree做级联: $("#" + deptId).combotree( { url : u ...

  10. 仿LOL项目开发第一天

    ---恢复内容开始--- 仿LOL项目开发第一天 by---草帽 项目源码研究群:539117825 最近看了一个类似LOL的源码,颇有心得,所以今天呢,我们就来自己开发一个类似于LOL的游戏demo ...