a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 177|回复: 1

[专业语言] JAVA认证:防止JAVA程序源代码被反编译

[复制链接]
发表于 2012-8-4 12:44:44 | 显示全部楼层 |阅读模式
我们都知道JAVA是一种解析型说话,这就抉择JAVA文件编译后不是机械码,而是一个字节码文件,也就是CLASS文件。而这样的文件是存在纪律的,经由反编译工具是可以还原回来的。例如Decafe、FrontEnd,YingJAD和Jode等等软件。下面是《Nokia中Short数组转换算法》   类中Main函数的ByteCode:7 ?0 B8 F& K- ?
  0 ldc #16. o/ r4 U1 p; L* n1 s7 g8 h
  2 invokestatic #181 V$ i+ N8 C! ?7 D7 D
  5 astore_1) }2 e% {- \: P' x$ V# O8 ^8 J
  6 return4 p( h7 F' Z5 E/ @
  其源代码是:short [] pixels = parseImage("/ef1s.png");; d& J, o, q) ?) d+ L4 A
  我们经由过程反编译工具是可以还原出以上源代码的。而经由过程简单的剖析,我们也能自己写出源代码的。" y1 D& ^0 z' Q$ Y  S
  第一行:ldc #16, W; K9 a, F% Q" d: @$ F7 k
  ldc为虚拟机的指令,浸染是:压入常量池的项,形式如下
# `; G: _$ y* n7 g  ldc index: h2 S' x) a, d( o" O, i  H# e1 c! O: ^) K
  这个index就是膳缦沔的16,也就是在常量池中的有用索引,当我们去看常量池的时辰,我们就会找到index为16的值为String_info,琅缦沔存了/ef1s.png.
/ I0 t# J7 U+ _1 O% G$ V1 C" {5 {  所以这行的意思就是把/ef1s.pn作为一个String存在常量池中,其有用索引为16。
* b: v" s5 V; g  第二行:2 invokestatic #18/ Q' Y/ ]/ P; \! N4 h/ V
  invokestatic为虚拟机指令,浸染是:挪用类(static)体例,形式如下& t# u+ v4 Z; s5 J
  invokestatic indexbyte1 indexbyte2
# _7 k! |" o' N" H* L# T4 b  其中indexbyte1和indexbyte2必需是在常量池中的有用索引,而是指向的类型必需有Methodref标识表记标帜,对类名,体例名和体例的描述符的引用。* ?6 ^) K  y7 s3 p
  所以当我们看常量池中索引为18的处所,我们就会获得以下信息:
9 N" S: f- H5 V% F8 _- B% c" }  Class Name : cp_info#1* w% c& o% i- \: p: _, |) P
  Name Type : cp_info#19
$ D" \* [; A3 A7 T  1 和19都是常量池中的有用索引,值就是右边中的值,再往下跟踪我就不多说了,有乐趣的伴侣可以去JAVA虚拟机规范。0 c" @! G  r: C& y3 A
  这里我简单介绍一下parseImage(Ljava/lang/String;)[S 的意思。' g" y# x- m6 R; Z- Z7 b$ I/ ?
  这就是parseImage这个函数的运行,我们反过来看看parseImage的原型就年夜白了
; Z# N# h% N$ `! c9 Y, E0 o. Z  short [] parseImage(String)# X7 N. v% F& t5 @2 m9 g
& l. t. y9 Z) c) |' w
  那么Ljava/lang/String;就是说需要传入一个String对象,而为什么前面要有一个L呢,这是JAVA虚拟机用来暗示这是一个Object。如不美观是根基类型,这里就不需要有L了。然后返回为short的一维数组,也就是对应的[S。是不是很有意思,S对应着Short类型,而 “[”对应一维数组,那有些伴侣要问了,两维呢,那就“[[”,呵呵,是不是很有意思。
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:44:45 | 显示全部楼层

JAVA认证:防止JAVA程序源代码被反编译

</p>  好了,挪用了函数,返回的值要保留下来吧。那么就是第三行要做的工作了。
! s) c0 X( v. ~% u! N6 H  第三行:5 astore_1: d5 @1 g  k8 B
  呵呵,很简单的。可是饶暌剐文章,也是斗劲轻易杂乱的处所。
: o" z  ?2 [: c% i, L! `* {* z$ [* L  astore_为虚拟机指令,浸染为:将当前reference存储到局部变量中去。而必需是对当前框架的局部变量的有用索引。打个例如,可能我们这个函数中可能还要用到这个局部变量,我们可以经由过程来找到它。例如挪用虚拟机指令:
+ Q* ]5 R5 U' o7 p3 A8 F  aload_1,就能获得该值。
0 G  n0 t" I5 _% a. I  第四行:6 return
1 u6 F6 L4 b2 r; S/ {" x- |3 K  同样的,return也是虚拟机指令了,它的浸染为:细腻式返回void。
* @" d% m6 x8 o' u% E  这里也就是退出main函数。9 H$ ~/ v$ d9 P/ X3 V4 M1 A5 F
  ----------------------------------------------------------------------------0 h/ F% W' B! L0 v
  ok,终于烦琐完毕了。有些伴侣可能要问,这么复杂,才四行就嗣魅这么多,呵呵,可能是我这人废话过多,当然如不美观你熟悉了,一点就能看懂了。经由过程肉眼就可以反编译轨范了。今朝所有的反编译工具都无法做到完美反编译,在有问题的处所还需要人去批改。3 e- U+ A, Y% h
  好了,说了半天若何反编译,我们就来看看如不美观在你的轨范如不美观防止别人来反编译。十分困难写好的轨范被人反编译了,多郁闷。哈哈。工欲善其事,必先利其器,这句话用对了吗?
4 B* X: M% O. [% K8 B  什么同化等等的体例,我就不说了,我这里主若是要说一种经由过程添加代码来在某种水平来避免当前风行的反编译工具对你的代码进行反编译。
6 b, A; i' p0 c  E  方案一。. v! o( ]1 U/ z. q/ H7 N
  1,首先要添加一个参数为Exception类型的函数,例如这样。
; o; R, X9 i& U* T  public static void Fake(Exception e)2 O, q: V* E& j: ]$ T5 T* q
  {8 S+ R) M# d3 a0 e
  e.toString();
- S) P3 U9 J9 d- I7 s1 u  }# i. ]8 M6 f/ C( \9 W( F
  必然要有e.toString();,因为要防止你的同化器把无用的代码过滤。
- p+ a, @2 z% g, T7 t! G! P  2,然后在每个类中挪用这个函数,放在try...catch(Exception e)..中的catch琅缦沔,例如:1 {; m8 u" ~; [
  try
. p; K. f, ?0 T/ ~4 C# j( f: Z4 D  {
% j8 x  F6 r5 Q: Z0 [7 X+ @4 [" x  t  ...$ I! F) ?! p9 G/ d1 n+ X
  }9 Z* {" \$ y9 i. [7 i) \+ C
  catch (Exception e)
1 h. C0 U' b. M8 L' A# s5 I4 A+ J  {
( Y( |5 ?* E3 O- w. j1 J  @  Fake(e);$ W6 P3 Y  M8 z9 H) [
  }
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-7 14:16 , Processed in 0.234862 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表