一,用jd-gui.exe等工具查看源代码。如何你不会,能够参看此文章:java
http://blog.csdn.net/hp_2008/article/details/8207879ide
能够到如下链接下载可视化反编译工具:工具
http://download.csdn.net/detail/hp_2008/5099046ui
二,反编译后的源代码,是乱的,看不太懂。这是由于开发者在发布APK时,通常都会用代码混淆器将原始的源代码打乱,
这也是防盗的一种方法。可是再怎样防,道高一尺,魔高一丈,用反编译工具很轻松的就可反编译成源码。要想作到反编译成一点也看不懂的代码,这很难,
在Android Java开源的世界里就更难作到了。固然你能够把核心的放到中间层,用C/C++封装成库,经过JNI调用,这样要想反编译库就有难度了。this
用混淆器打乱的代码,反编译后,要想看懂也不是一件容易的事。由于大部人都会用免费的混淆器来混淆源代码,大部份反编译过来的代码就有必定的规则可寻:spa
(本人水平有限,若有什么不对的地方,还请指教,很是感谢).net
反编译后的代码通常会产生如下结构的代码,(代码结构是我的总结的,若有雷同,纯属巧合)比较难看懂,本文章根据实现状况对这几种结构作个简单说明。3d
1,反编译后的代码:if while结构
if (BTActivity.access$2300(this.this$0))
{
int i = BTActivity.access$700(this.this$0).sendCommand(1028, 4, paramInt);
BTActivity.access$2500(this.this$0).notifyDataSetChanged();
}
while (true)
{
return;
Bluetooth localBt = BTActivity.access$700(this.this$0);
int k = BTActivity.access$600(this.this$0);
int l = localBt.sendCommand(1026, paramInt, k);
}code
(1)只分析逻辑
很显然上面的代码也不是原始的源代码,可是很接近了,若是要想完成还原,还得本身改。
分析上面的代码:这里应该有一个if else的逻辑。从上面的代码分析,return下的代码
应该是永远不会被执行,但这是不可能的。因此上面的代码逻辑(咱们先不看语句)应该是这样的,
去掉while和return,加上else,修改后以下:
if (BTActivity.access$2300(this.this$0))
{
int i = BTActivity.access$700(this.this$0).sendCommand(1028, 4, paramInt);
BTActivity.access$2500(this.this$0).notifyDataSetChanged();
}
else
{
Bluetooth localBt = BTActivity.access$700(this.this$0);
int k = BTActivity.access$600(this.this$0);
int l = localBt.sendCommand(1026, paramInt, k);
}
这样的逻辑才是做者的本意。对象
(2)逻辑分析完了,应该分析语句.
A,这个真的很难看懂。像这句:int i = BTActivity.access$700(this.this$0).sendCommand(1028, 4, paramInt);
很显然,这个是引用外部的一个类中的一个方法。而后返回整类,从下面的语句能够得知,这个返回值是用不到的。因此这句可去掉int i
还原上面的语句应该是这样的:
BTActivity.access$700(this.this$0).sendCommand(1028, 4, paramInt);
B,access$700是什么意思呢。这个应该是BTActivity类中的一个对像,而后这个对象有sendCommand方法。这样你就能够去查这个BTActivity类定义的哪一个对象
有这样一个方法了,这好理解。
很差理解的是这句:int k = BTActivity.access$600(this.this$0); 这句初步还原就是去掉int k。
而后是这个access$600,它对应的是BTActivity中的哪一个方法呢。这很难肯定,因此我说要猜,那有没有方法呢。固然有:
1,看这个类中有多少个方法,若是只有一个,那指定就是它了。
2,若是有多个,那就要看参数。若是只有一个方法的参数与之相对应,那必定是它。
3,若是参数同样的也有多个。那看逻辑。若是看不出来,只有猜:)。或参加本身的逻辑。
(3)为何会出现像access$700(方法不同,后面的数字也不同)这样的方法名呢,缘由是,调用者和被调者不在同一个类中。内部类也不行,若是
二者在同一个类中,好比同类的方法调用,那反编译后的名字必定是可看懂的。不会是有数字的名字。
(4) 再举一个更简单的if else例
反编译后的代码:
if (paramBoolean)
paramTextView.setTextColor(-16727809);
while (true)
{
return;
paramTextView.setTextColor(-1315861);
}
还原成真正的原始代码,按我上面说的应该是:
if (paramBoolean)
{
paramTextView.setTextColor(-16727809);
}
else
{
paramTextView.setTextColor(-1315861);
}
之后碰到这样的if while还原就应该是上面的样子。
2, 反编译后的代码:switch case while结构
switch (this.mBand)
{
default:
case 0:
case 1:
case 2:
}
while (true)
{
return;
this.mBand.setText("FM1");
continue;
this.mBand.setText("FM2");
continue;
this.mBand.setText("AM");
}
(1)分析逻辑:根据mBand的不一样值,设置文本的显示内容。
这个很好看懂,再也不多说,还原成原始代码:
switch (mBand)
{
case 0:
mBand.setText("FM1");
break;
case 1:
mBand.setText("FM2");
break;
case 2:
mBand.setText("AM");
break;
default:
}
(2)这里关键的地方是:一个continue对你应着一个case的结束;。
3,反编译后代码以下:if for while结构
int i15 = this.freq;
int i16 = this.rmin;
if (i15 < i16)
i17 = this.min;
int i29;
for (this.freq = i17; ; this.freq = i29)
{
int i27;
int i28;
do
{
this.x = getWidth();
this.y = -1;
break label32:
i27 = this.freq;
i28 = this.max;
}
while (i27 <= i28);
i29 = this.max;
}
this.y = 0;
invalidate();
(1)代码逻辑分析:保证freq的值在min和max之间。
分析后获得的原始源代码:
if (freq < min)
{
freq = min;
}
if (freq <= max)
{
x = getWidth();
y = -1;
}
else
{
freq = max;
y = 0;
invalidate();
}
(2)获得上面的源代码关键在于,按反编译后的代码走一遍。
4, 解析switch for while结构代码
PowerManager localPowerManager = (PowerManager)getSystemService("power");
switch (paramInt)
{
default:
case 0:
case 1:
}
for (String str = "on"; ; str = "other")
while (true)
{
PowerManager.WakeLock localWakeLock = localPowerManager.newWakeLock(6, str);
localWakeLock.acquire();
localWakeLock.release();
return;
str = "off";
}
还原原始源代码:
PowerManager localPowerManager = (PowerManager)getSystemService("power");
String str = null;
switch (paramInt)
{
case 0:
str = "on";
break;
case 1:
str = "off";
break;
default:
str = "other";
break;
}
PowerManager.WakeLock localWakeLock = localPowerManager.newWakeLock(6, str);
localWakeLock.acquire();
localWakeLock.release();
5, 分析返编译后的代码(if while结构)
例1:
if (paramInt1 == 0)
this.mMessage.setText("");
while (true)
{
this.mAdditionalMessage.setVisibility(8);
int i = this.mLevel.getMax();
if (paramInt2 != i)
this.mLevel.setMax(paramInt2);
Toast localToast = this.mToast;
......
return;
TextView localTextView = this.mMessage;
String str = "" + paramInt1;
localTextView.setText(str);
}
分析:1,先去掉“this"
2,看返编译后的按顺序逻辑走一遍。能够看出while到return这段代码,无论怎么样都会执行的。因此原始代码应该是这样的:
setSmallIcon(paramInt1);
paramInt1 &= 2147483647;
if (paramInt1 == 0)
{
mMessage.setText("");
}
else
{
String str = "" + paramInt1;
mMessage.setText(str);
}
mAdditionalMessage.setVisibility(8);
if (paramInt2 != mLevel.getMax())
{
mLevel.setMax(paramInt2);
}
mToast.setView(mView);
......
6,一个continue对应一个back原则(switch while结构)
在这种形式中,一个contiune必定是对应一个back,但一个case不必定只对应一个contiune,也有一个case对应两个或多个contiune(即back).
如如下反编译后的代码:
1 switch (getId()) 2 { 3 case 2131034119: 4 case 2131034120: 5 case 2131034121: 6 case 2131034122: 7 case 2131034123: 8 case 2131034124: 9 case 2131034125: 10 case 2131034126: 11 case 2131034127: 12 case 2131034128: 13 default: 14 case 2131034129: 15 case 2131034130: 16 case 2131034131: 17 case 2131034132: 18 case 2131034133: 19 case 2131034134: 20 case 2131034117: 21 case 2131034118: 22 } 23 while (true) 24 { 25 return; 26 int i = paramVerticalSeekBar.getProgress() * 14; 27 int j = paramVerticalSeekBar.getMax(); 28 int k = i / j; 29 if (APPActivity.access$200(this.this$0) == k) 30 continue; 31 int l = APPActivity.access$202(this.this$0, k); 32 int i1 = APPActivity.access$200(this.this$0); 33 continue; 34 int i3 = paramVerticalSeekBar.getProgress() * 14; 35 int i4 = paramVerticalSeekBar.getMax(); 36 k = i3 / i4; 37 if (APPActivity.access$400(this.this$0) == k) 38 continue; 39 int i5 = APPActivity.access$402(this.this$0, k); 40 EQ localEQ2 = APPActivity.access$1400(this.this$0); 41 int i6 = APPActivity.access$400(this.this$0); 42 int i7 = localEQ2.sendCommand(257, 2, i6); 43 continue; 44 int i8 = paramVerticalSeekBar.getProgress() * 14; 45 int i9 = paramVerticalSeekBar.getMax(); 46 k = i8 / i9; 47 if (APPActivity.access$500(this.this$0) == k) 48 continue; 49 int i10 = APPActivity.access$502(this.this$0, k); 50 int i11 = APPActivity.access$500(this.this$0); 51 continue; 52 int i13 = paramVerticalSeekBar.getProgress() * 3; 53 int i14 = paramVerticalSeekBar.getMax(); 54 k = i13 / i14; 55 if (APPActivity.access$600(this.this$0) == k) 56 continue; 57 int i15 = APPActivity.access$602(this.this$0, k); 58 EQ localEQ4 = APPActivity.access$1400(this.this$0); 59 int i16 = APPActivity.access$600(this.this$0); 60 int i17 = localEQ4.sendCommand(257, 8, i16); 61 continue; 62 int i18 = paramVerticalSeekBar.getProgress() * 3; 63 int i19 = paramVerticalSeekBar.getMax(); 64 k = i18 / i19; 65 if (EQActivity.access$700(this.this$0) == k) 66 continue; 67 int i20 = APPActivity.access$702(this.this$0, k); 68 EQ localEQ5 = APPActivity.access$1400(this.this$0); 69 int i21 = APPActivity.access$700(this.this$0); 70 continue; 71 int i23 = paramVerticalSeekBar.getProgress() * 3; 72 int i24 = paramVerticalSeekBar.getMax(); 73 k = i23 / i24; 74 if (APPActivity.access$800(this.this$0) == k) 75 continue; 76 int i25 = APPActivity.access$802(this.this$0, k); 77 EQ localEQ6 = APPActivity.access$1400(this.this$0); 78 int i26 = APPActivity.access$800(this.this$0); 79 continue; 80 int i28 = paramVerticalSeekBar.getProgress() * 14; 81 int i29 = paramVerticalSeekBar.getMax(); 82 k = i28 / i29; 83 if (APPActivity.access$900(this.this$0) == k) 84 continue; 85 int i30 = APPActivity.access$902(this.this$0, k); 86 EQ localEQ7 = APPActivity.access$1400(this.this$0); 87 int i31 = APPActivityvity.access$900(this.this$0); 88 continue; 89 int i33 = paramVerticalSeekBar.getProgress() * 3; 90 int i34 = paramVerticalSeekBar.getMax(); 91 k = i33 / i34; 92 if (APPActivity.access$1000(this.this$0) == k) 93 continue; 94 int i35 = APPActivity.access$1002(this.this$0, k); 95 EQ localEQ8 = APPActivity.access$1400(this.this$0); 96 int i36 = APPActivity.access$1000(this.this$0); 97 }
分析代码:
1),上遍已对这种形式有讲过,一个continue对应一个case,可是你数一数会发现,对不上号,明显case多于contiune,缘由是什么呢?其实switch里的default对应的是while中的return,在switch中default以上的case是用不着,是没有用的。
2),若是default上面的case没有用,聪明的你能够可能会问两个问题?A,default上面的case没有用,为何还会有呢?缘由很简单,由于反编译器也不是全智能的总会有不对的(可是执行逻辑是不会有错),呵呵真正的缘由固然不会是这样,你能够本身去分析一下,从整个程序分析就能够得出结论来。B,那按一个continue对应一个back的原则不是有错吗? 固然没有。一个continue仍是对应一个back, 聪明的你必定看懂了,每两个continue中间还有一个if语句,对,没错,你理解是对的,就是在这中间知足条件时就会back,因此就会有一个continue与之相对应。 所这里每一个if + continue + continue的形式对应一个case。3),恢复原代码结构就变的简单,这里就再敖叙了