本文目标:
- 大致了解Java byte code以及Assembly.
- 简单概述如何反编译Java Class
- 二进制文件的反编译
- 回答“难道真的不能保护程序源码吗?”
Java Byte Code:
- 使用命令javap -c <ClassName>来把Java源代码编译为Java Byte Code
- 要编译Java源代码必须保证所在机器上有JVM环境
- 不同的操作系统必须安装相应的JVM环境
Java Byte Code的简单语法:
- iconst_0 : push 0 onto the stack
- istore_1: pop the top of the stack as variable 1
- goto: jump to line
- iload_1: push variable 1 onto the stack
- bipush, ldc: push value onto stack
- if_icmplt: if 1St item on stack > 2nd jump to line
- Ifeq: if 1st item on stack > 2nd jump to line
更多语法请自己Google.
反编译:
反编译通常执行编译器的相反动作 —---- 即把含有相对抽象的底层代码(通常指那些被设计用来给计算机读取的语言)转化为高级语言代码(我们经常使用并能简单看懂的语言)。
这里以JD-GUI来说明,它本身是一款Java发编译软件,即把Java Byte Code转化为Java 源代码。
图1. 使用JD-GUI来查看一个可运行的JAR文件,源文件是一个软件需要注册码的例子。
上述例子有什么用处?
- 反编译可以让我们看明白整个程序的运行过程 并且可以了解一些软件的内部算法
- 反编译可以更好的更改和重新编译程序
- 所有被用来保护软件核心机制的代码都可以被移除,比如破解软件等
当然反编译不是万能的,只能编译出大概,并不能保证百分百的正确。例如,true在Byte Code中的显示和1是一样的。因此反编译并不能分辨1和true, 0和false。(不过相差不会太多。)
Binaries:
- 即汇编语言
- 相对于 Java Byte Code 更加底层
- 不同的 OS 需要使用不同的编译器,当然原理是一样的
汇编语法:
- PUSH: add to top of stack
- CALL: execute a function
- RET, RETN, RETF: end a function and restart calling code
更多信息依旧请自己查阅Google
图2. Windows中最经典的调试程序ollydbg。说明一下上述两个软件都是Free的。
原理解析:上图中被选中的那行执行了StrCmp这个函数,事实上就是比对两个String,也就是通常程序用来验证密码的最基本方式。这一行的上面两行则是提取了2个密码,一个是Built-in的,一个一般是用户输入的。只要在调试器中更改ECX为EDX即可让程序比对密码时,提取同一个密码,也就是说讲永远为True。值得说明,下一句的TEST即是比对。
Ollydbg在破解中的作用是什么:
- 可以搜索内存中的String,初级软件,比如教学视频一般会把密码直接藏在内存中。
- 可以查看Register中的Key和Value。
- 可以通过调换JEQ和JNEQ来绕过IF语句。
- ……
如何防御反编译或者调试程序探查:
- 动态生成 Key – 但是黑客可以运行程序
- 加密程序或者加壳 – 但是程序中其实依旧有相对应用来解密的 Key 能被黑客发现
- 混编数据和代码,甚至加入无用信息 – 能够拖延黑客破解所用的时间,数月甚至几年,例如 Skype
- 现实中真正有用的防御手段 - 部分或者全部数据存放在网络服务器上,例如 WoW, BlueRay 或者 硬件级别的保护措施
End:
结尾送大家两句话,是我对互联网以及安全领域的真正理解。写完了才发现貌似和开源没关系T.T
- Attackers own the internet.
- Good protection tends to slow down this decryption, not stop it.
本文为原创,转载请注明出处Oschina。
来源:oschina
链接:https://my.oschina.net/u/212915/blog/101773