APK反编译后代码分析
来源:互联网 发布:spring cloud 打印sql 编辑:程序博客网 时间:2024/05/29 02:29
一,用jd-gui.exe等工具查看源代码。如何你不会,可以参看此文章:
http://blog.csdn.net/hp_2008/article/details/8207879
可以到以下连接下载可视化反编译工具:
http://download.csdn.net/detail/hp_2008/5099046
二,反编译后的源代码,是乱的,看不太懂。这是因为开发者在发布APK时,一般都会用代码混淆器将原始的源代码打乱,这也是防盗的一种方法。但是再怎样防,道高一尺,魔高一丈,用反编译工具很轻松的就可反编译成源码。要想做到反编译成一点也看不懂的代码,这很难,
在Android Java开源的世界里就更难做到了。当然你可以把核心的放到中间层,用C/C++封装成库,通过JNI调用,这样要想反编译库就有难度了。
用混淆器打乱的代码,反编译后,要想看懂也不是一件容易的事。因为大部人都会用免费的混淆器来混淆源代码,大部份反编译过来的代码就有一定的规则可寻:
(本人水平有限,如有什么不对的地方,还请指教,非常感谢)
反编译后的代码一般会产生以下结构的代码,(代码结构是个人总结的,如有雷同,纯属巧合)比较难看懂,本文章根据实现情况对这几种结构做个简单说明。
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); }
(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).
如以下反编译后的代码:
switch (getId()) { case 2131034119: case 2131034120: case 2131034121: case 2131034122: case 2131034123: case 2131034124: case 2131034125: case 2131034126: case 2131034127: case 2131034128: default: case 2131034129: case 2131034130: case 2131034131: case 2131034132: case 2131034133: case 2131034134: case 2131034117: case 2131034118: } while (true) { return; int i = paramVerticalSeekBar.getProgress() * 14; int j = paramVerticalSeekBar.getMax(); int k = i / j; if (APPActivity.access$200(this.this$0) == k) continue; int l = APPActivity.access$202(this.this$0, k); int i1 = APPActivity.access$200(this.this$0); continue; int i3 = paramVerticalSeekBar.getProgress() * 14; int i4 = paramVerticalSeekBar.getMax(); k = i3 / i4; if (APPActivity.access$400(this.this$0) == k) continue; int i5 = APPActivity.access$402(this.this$0, k); EQ localEQ2 = APPActivity.access$1400(this.this$0); int i6 = APPActivity.access$400(this.this$0); int i7 = localEQ2.sendCommand(257, 2, i6); continue; int i8 = paramVerticalSeekBar.getProgress() * 14; int i9 = paramVerticalSeekBar.getMax(); k = i8 / i9; if (APPActivity.access$500(this.this$0) == k) continue; int i10 = APPActivity.access$502(this.this$0, k); int i11 = APPActivity.access$500(this.this$0); continue; int i13 = paramVerticalSeekBar.getProgress() * 3; int i14 = paramVerticalSeekBar.getMax(); k = i13 / i14; if (APPActivity.access$600(this.this$0) == k) continue; int i15 = APPActivity.access$602(this.this$0, k); EQ localEQ4 = APPActivity.access$1400(this.this$0); int i16 = APPActivity.access$600(this.this$0); int i17 = localEQ4.sendCommand(257, 8, i16); continue; int i18 = paramVerticalSeekBar.getProgress() * 3; int i19 = paramVerticalSeekBar.getMax(); k = i18 / i19; if (EQActivity.access$700(this.this$0) == k) continue; int i20 = APPActivity.access$702(this.this$0, k); EQ localEQ5 = APPActivity.access$1400(this.this$0); int i21 = APPActivity.access$700(this.this$0); continue; int i23 = paramVerticalSeekBar.getProgress() * 3; int i24 = paramVerticalSeekBar.getMax(); k = i23 / i24; if (APPActivity.access$800(this.this$0) == k) continue; int i25 = APPActivity.access$802(this.this$0, k); EQ localEQ6 = APPActivity.access$1400(this.this$0); int i26 = APPActivity.access$800(this.this$0); continue; int i28 = paramVerticalSeekBar.getProgress() * 14; int i29 = paramVerticalSeekBar.getMax(); k = i28 / i29; if (APPActivity.access$900(this.this$0) == k) continue; int i30 = APPActivity.access$902(this.this$0, k); EQ localEQ7 = APPActivity.access$1400(this.this$0); int i31 = APPActivityvity.access$900(this.this$0); continue; int i33 = paramVerticalSeekBar.getProgress() * 3; int i34 = paramVerticalSeekBar.getMax(); k = i33 / i34; if (APPActivity.access$1000(this.this$0) == k) continue; int i35 = APPActivity.access$1002(this.this$0, k); EQ localEQ8 = APPActivity.access$1400(this.this$0); int i36 = APPActivity.access$1000(this.this$0); } }分析代码:
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),恢复原代码结构就变的简单,这里就再敖叙了。
转载自:http://blog.csdn.net/ordinaryjoe/article/details/8626010
- APK反编译后代码分析
- APK反编译后代码分析(一)
- APK反编译后代码分析(二)
- APK反编译后代码分析(二)
- APK反编译后代码分析(一)
- APK反编译后代码分析(一)
- 分析APK反编译后的代码 (转载)
- APK反编译后插入代码
- JD-GUI反编译后代码逻辑分析
- JD-GUI反编译后代码逻辑分析
- JD-GUI反编译后代码逻辑分析
- JD-GUI反编译后代码逻辑分析
- 反编译后代码混淆问题小分析
- JD-GUI反编译后代码逻辑分析
- android Apk 代码反编译
- apk反编译后创建项目
- apk反编译后重新打包
- 反编译apk,查看java代码
- 提高Android App性能的技巧(转载)
- java异常
- 移动硬盘质量比较
- (k倍动态减法游戏)zoj 3599 hdu 2486
- CAlayer的一些基本属性应用
- APK反编译后代码分析
- 新手选车系列之(七): 没有绝对好坏,只有相对适合
- C++中引用作为形参的作用
- 浅谈Android数据加载 —— Loader
- Android开发系列(二十九):使用ContextMenu创建上下文菜单
- 安卓透明颜色设置说明
- 线程
- 职责链模式(chain of responsibility)
- [Erlang]如何遍历当前目录?