Android - 反编译android apk文件

  • 主要目的: 学习优秀的软件设计,解决封闭包特定问题
  • 邪恶的做法:去除广告,修改别人的软件包名,重新打包发布。
  • 有争议的: 中文汉化

注意 请遵循Google相关协议和相关法律法规

反编译apk工具

目前有几种工具:

关于smali的使用,请参考jserv的http://jserv.blogspot.com/2010/05/android.html

dexdump功能比较弱,且麻烦,就不讨论介绍了。

解压apk

这里拿com.himsn.apk 做例子,apk包其实是一个zip文件,直接解压

$ unzip com.himsn.apk

得到一驼的东西:

.  ├── AndroidManifest.xml  程序全局配置文件  ├── classes.dex Dalvik 字节码  ├── META-INF  │   ├── ALIAS_NA.RSA  │   ├── ALIAS_NA.SF  │   └── MANIFEST.MF  ├── res 存放资源文件的目录  │   ├── anim  │   │   ├── cycle_7.xml  │   │   └── shake.xml  │   ├── drawable  │   │   ├── avatar_unknown.png  │   │   ├── ...  │   │   ├── button_choose_contact.xml  │   │   ├── typing4.png  │   │   └── typing.xml  │   ├── layout  │   │   ├── add_contact.xml  │   │   ├── ...  │   │   └── two_line_list_item.xml  │   ├── menu  │   │   ├── choose_contact_offline.xml  │   │   ├── choose_contact.xml  │   │   └── main.xml  │   ├── raw  │   │   ├── key_char.jpg  │   │   ├── key_num.jpg  │   │   ├── ...  │   │   ├── key_pressed_right.png  │   │   └── winks.png  │   └── xml  │       └── preferences.xml  └── resources.arsc 编译后的二进制资源文件  

目录下三个文件两个文件夹,一一来说

[deli@athena himsn]$ ls -p  AndroidManifest.xml  classes.dex  META-INF/  res/  resources.arsc  

AndroidManifest.xml

用vim打开,都是乱码,看看这是什么文件类型的:

[deli@athena himsn]$ file AndroidManifest.xml  AndroidManifest.xml: DBase 3 data file (4256 records)  

除了这个,还有layout目录下的二进制xml文件,可以使用AXMLPrinter工具将其转换为可读的xml文件,工具下载地址:http://code.google.com/p/android4me/downloads/list, 使用很简单:

$ java -jar AXMLPrinter2.jar AndroidManifest.xml AndroidManifest2.xml

很多xml一个个转化很麻烦,这样的工作,当然是用shell完成了。

$ cd res  $  for file in */*.xml; do java -jar AXMLPrinter2.jar $file > temp; echo $file; mv temp $file -f; done  

AndroidManifest2.xml的内容如下:(省略一部分)

<?xml version="1.0" encoding="utf-8"?>  <manifest   xmlns:android="http://schemas.android.com/apk/res/android"   android:versionCode="210"   android:versionName="2.1.0"   package="com.himsn"   >   <uses-sdk    android:minSdkVersion="2"    >   </uses-sdk>   <uses-permission    android:name="android.permission.READ_PHONE_STATE"    >   </uses-permission>   <application    android:label="@7F080000"    android:icon="@7F02002A"    >    <activity     android:label="@7F080000"     android:name=".ChooseContactActivity"     android:launchMode="2"     android:configChanges="0x000000E0"     >     <intent-filter      >      <action       android:name="android.intent.action.MAIN"       >      </action>      <category       android:name="android.intent.category.LAUNCHER"       >      </category>     </intent-filter>    </activity>    <activity     android:theme="@7F090001"     android:label="@7F080004"     android:name=".AuthReqActivity"     android:configChanges="0x000000E0"     >    </activity>    <meta-data     android:name="ADMOB_PUBLISHER_ID"     android:value="a149c8f51949be3"     >    </meta-data>   </application>  </manifest>  

感觉还行,但是像 android:label="@7F080000" android:icon="@7F02002A"

@7F080000这个神秘的东西,是什么意思呢? 下面会有提到。

classes.dex

目前反编译classes.dex比较好的工具是 Dedexer,可以下载已经编译好的jar文件ddx1.11.jar.

mkdir src  java -jar ddx1.11.jar --help  java -jar ddx1.11.jar -o -D -r -d src classes.dex  

然后在src目录下,又生成一坨东西。

注意: ddx1.11.jar 对应java 1.6版本,我用 1.5.0_18,就会遇到

[deli@athena tools-common]$ java -jar ddx1.11.jar  Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file  

也可以下载源代码自行编译。

进入 src/com/himsn 目录

[deli@athena himsn]$ grep -i 7F080000 *

R$string.ddx:.field public static final app_name I = 2131230720 ; 0x7f080000

好家伙,回前面提到的 @7F080000,原来在 R$string。其他xml文件出现神秘的字符,grep 一下,就出来了。 xml还有其他神秘数字, 比如

<ImageView>  android:scaleType="3"  

这个3是啥意思? 开始我是用最原始的方式,我深信,一切尽在ApiDemos中,结果在ApiDemos的反编译文件里grep,一般80%都可以找到,然后跟源代码对比,就出来了。

android:scaleType="3" 就是android:scaleType="fitCenter" 类似的

| android:scaleType="7"| android:scaleType="centerInside"

android:scaleType="6" android:scaleType="centerCrop"
android:ellipsize="4" android:ellipsize="marquee"
android:ellipsize="3" android:ellipsize="end"

后面发现用eclipse打开xml layout文件,在属性选项里,点击,在下拉菜单,都有相应的数字,从0开始,那么就好办多了。

还有一些情况,比如

android:textColor="?android:01010036" android:textColor="?android:01010212"

这个比较好办,看到有android字样,就知道是系统定义的常量,在android sdk Reference android.R.xxx 页面搜索01010036,找到:

"?android:01010036" 对应 "?android:attr/textColorSecondary" "?android:01010212" 对应 "?android:attr/textColorTertiary"

反编译过两个apk,我都能把xml文件100%还原出来。

解读ddx格式

挑个src/com/himsn/HiMSN.ddx 看看吧。

.class public com/himsn/HiMSN  .super android/app/Activity  .source HiMSN.java    .field public static final ACTIVITY_ONGOING_CONTACTS I = 112 ; 0x70  .field public static final ACTIVITY_WINKS I = 113 ; 0x71  .field private static final TAG Ljava/lang/String; = "IMEasy"  .field private final mFilter Landroid/content/IntentFilter;  .field private mManager Lcom/shiyansucks/imeasy/manager/IMMgr;  .field mMenu Landroid/view/Menu;  .field private final mReceiver Landroid/content/BroadcastReceiver;    .method public <init>()V  .limit registers 3    .line 41   invoke-direct {v2},android/app/Activity/<init> ; <init>()V    .line 43   new-instance v0,com/himsn/HiMSN$1    ....    

真是难懂! 没关系,Gabor Paller为我们整理好了 Dalvik opcodes 文档,对照一下,记住常用的,慢慢研读,会有一番风景,enjoy!

读ddx,或多或少做一些笔记,零零散散,再补充一下。

行首为 ".field" 字段的,是类变量。 grep "\.field" xxx.ddx ,列出所有的变量。

行首为 ".method " 字段的,是成员函数 grep "\..method " xxx.ddx ,列出所有的成员函数。

 88     if-eqz  v1,l2d9da   89 ; v1 : single-length   90 .line 482   91     new-instance    v0,android/content/Intent   92 ; v0 : Landroid/content/Intent;   93     invoke-direct   {v0},android/content/Intent/<init>  ; <init>()V   94 ; v0 : Landroid/content/Intent;   95 l2d9ca:  

上面的条件是这样的:

 if (v != 0) {    intent = new Intent(); // intent 在该代码段上边有定义过。   } else {    // l2d9ca:   }  

if 里的判断顺序正好相反。

基本的数据类型

 Long => Long   J => long   I => int   V => void   Z => boolean   D => double  

apktool

目前最好的Android反编译工具,可以修改并重新打包.输出文件格式smail,与ddx类似。用法:

 apktool d your.apk  

apktool可以很完美的把xml文件还原出来,比 AXMLPrinter2.jar 做得更彻底。不过AXMLPrinter2.jar还对xml格式化,看来美观一些。

最佳实践

用dedexer反编译出来的ddx文件,参数名没显示出来,可读性强.

.method public static getSearchQueryForPublisher(Ljava/lang/String;)Ljava/lang/String;  .limit registers 3    

apktool 反编译出来的smali文件,参数名都列出来

.method public static getSearchQueryForPublisher(Ljava/lang/String;)Ljava/lang/String;      .locals 2      .parameter "publisher"  

加上 dex2jar + jd-gui ,多个工具一起用,互相验证,会有意想不到的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值