您的位置:首页 > 移动开发 > Android开发

Android apk反编译基础(apktoos)图文教程

2014-12-25 12:37 357 查看
本文主要介绍了Androidapk反编译基础,使用的工具是apktoos,我们将用图文的方式说明apktoos工具的使用方式,你可以参考这个方法反编译其它APK试试看了
很久有写过一个广工图书馆主页一个类爬虫的demo(因为没接口,只能扒取静态网页),实现一些图书馆系统的一些功能。但最近发现图书馆系统在html页面上做了手脚,一页html页面中嵌入了几千行的注释,并有了自己的App,应该是为了增加扒取的流量成本来防止别人去扒取网页,不过加注释这手段就不敢恭维了,内网访问速度还行,但外网访问的话体验很差的。

如下图:一堆注释,导致一个网页要2MB









主页上的APP,必然是用了图书馆的后台接口和服务器交互的,从而想试试用反编译的手段来看看APP使用了什么接口。(另外更简单可以通过tcpdump来给Android手机抓包分析其接口,再用Wireshark来分析tcp包,不过你想要知道全部接口的话,可能需要一个个接口去调用,会比较麻烦,采用反编译,可能集中在一个类中找到这些接口)。

首先要准备的工具:(了解更多反编译工具可以去看雪论坛下载或者学习-Link)

APKTool是GOOGLE提供的APK编译工具,需要JAVA运行环境。可以对APK进行反编译,使用它可以将其反编译成非常接近打包前的原始格式。逆向AndroidManifest.xml、资源文件resources.arsc以及将dex文件反编译成可以调试的smali文件。修改后,可以将其编译回apk文件。APKTool也可以用来汉化Android软件然后重新打包发布。
官方:http://code.google.com/p/android-apktool/

解压缩APKTool,并把要反编译的APK放入目录中



反编译:

通过CMD进入上面的目录,执行命令:apktooldecodeZhaoBenShu.apkoutdir

稍等片刻完成反编译,反编译后的文件会在outdir目录下。



---outdir目录结构



res:资源文件,跟adnroid工程目录下的res基本一样,各种UI图片XML布局文件valuesxml文件(多了一个public.xml,有各个资源的id号(R.java中的id))
smail:这个是重点文件夹,里面都是smail格式文件,是Dalvik虚拟机执行的操作码(Dalvikopcodes),这些操作吗有自己的语法,如果有学过JNI的话,这些语法还是比较容易看懂和理解的。AndroidManifest.xml:Android工程下的AndroidManifest.xml
apktool.yml:用于重打包。

smail语法:(全部语法请link)

smail中的数据类型签名跟java中的是一样的,如下。

B---byteC---charD---doubleF---floatI---intJ---longS---shortV---voidZ---boolean[XXX---arrayLxxx/yyy---object

smail代码例子:



初看smail文件,可能会觉得有一些凌乱。不过只要把几种语法弄懂了,就可以很好地阅读smail文件。
smail比较常用语法(非全部)分为:赋值,取值,函数调用,if语句,返回值等。

赋值取值:


例子:
iget-objectv6,p0,Lcom/zbsh/code/clas/ClassSystem$9;->val$vBarCodes:Ljava/util/ArrayList;

分析:

iget个取值操作,i=instance,是用来instancefiled(实例变量),object是类的意思。v6是本地寄存器,p0在这里是代表this(在非static函数正代表this,在static函数中代表第一个参数)。Lcom/zbsh/code/clas/ClassSystem是表示包路径为Lcom/zbsh/code/clas下的ClassSystem类,->相当于C/C++的箭头操作符,后面是类中的变量或者方法vBarCodes是ClassSystem中的一个变量,Ljava/util/ArrayList是vBarCodes这个变量的类型(是java中类的签名)

作用:

把ClassSystem中vBarCodes的值存放在寄存器v6中,vBarCodes的类型必须是对象,且是实例变量非静态变量。
其中object可以是替换成基本数据类型:iget-booleaniget-byteiget-chariget-short等等。

同样的

sget-[type]用来获取static变量。(少了一个p0,因为静态变量是没有this的)

aget-[type]用来获取array类型。

[x]getvx,vy,把寄存器vy中的值赋给vx。

赋值:

同样都有以下几种:
iput-[type]
sput-[type]
aput-[type]

也支持寄存器和寄存器之间的赋值,寄存器和变量之间的赋值。

函数调用

invoke-direct调用private函数
invoke-super调用父类函数
invoke-static调用静态函数
invoke-virtual用于调用protected或public函数(相当于C++的虚函数,java的重载函数,只有protect和public能够重载)
还有一种比较特殊的:invoke-xxxxx/range:参数多于5个的时候,要加/rang

例子:

invoke-virtual{v4,v1},Ljava/lang/String;->equals(Ljava/lang/Object;)Z

v4是this,代表Ljava/lang/String的一个实例,v1是函数的第一个参数,在这里是调用放在V4寄存器中类型为Ljava/lang/String的实例的equal()方法,并传入参数v1,返回的结果是Z类型,也就是boolean类型。

如果是invoke-static{v4,v1},不同遇在于invoke-virtual{v4,v1}的是v4不是this,而是第一个参数。v1是第二个参数,所调用的方法需要两个参数。

返回值:

获取返回值:

move-resultvx:把上一个方法返回的值,存在寄存器vx中。

返回返回值:

return-void没返回。
returnvx返回寄存器中vx的值。

if语句:

if-eqvx,vy,target:eq:equal如果vx==xy跳转到target目标代码,否则执行顺序执行下一句代码
if-nevx,vy,target:nq:notequal如果vx!=xy跳转到target目标代码,否则执行顺序执行下一句代码
if-eqzvx,target:eqz:equalzero如果vx==0跳转到target目标代码,否则执行顺序执行下一句代码
if-nezvx,target:nez:notequalzero如果vx!=0跳转到target目标代码,否则执行顺序执行下一句代码

读[b]smail,找接口:
[/b]
以搜索接口为例子:
根据文件命名找到GropZbshFind.smali这个文件,应该就是搜索Activity。

在其中有一段代码:

复制代码

代码如下:

#virtualmethods
.methodpubliconCreate(Landroid/os/Bundle;)V
.locals3
.parameter"savedInstanceState"</font></p><p><fontface="CourierNew">.prologue
.line13
invoke-super{p0,p1},Lcom/zbsh/code/thrd/GroupActivity;->onCreate(Landroid/os/Bundle;)V</font></p><p><fontface="CourierNew">.line14
const-classv0,Lcom/zbsh/code/ZbshFindMain;</font></p><p><fontface="CourierNew">invoke-virtual{v0},Ljava/lang/Class;->getName()Ljava/lang/String;</font></p><p><fontface="CourierNew">move-result-objectv0</font></p><p><fontface="CourierNew">new-instancev1,Landroid/content/Intent;</font></p><p><fontface="CourierNew">const-classv2,Lcom/zbsh/code/ZbshFindMain;</font></p><p><fontface="CourierNew">invoke-direct{v1,p0,v2},Landroid/content/Intent;->(Landroid/content/Context;Ljava/lang/Class;)V</font></p><p><fontface="CourierNew">invoke-virtual{p0,v0,v1},Lcom/zbsh/code/GropZbshFind;->startChildActivity(Ljava/lang/String;Landroid/content/Intent;)V</font></p><p><fontface="CourierNew">.line15
return-void
.endmethod

很明显是通过startActivity来启动ZbshFindMain这个Activity,

在ZbshFindMain中找到Onclick方法。



复制代码
代码如下:

#virtualmethods
.methodpubliconClick(Landroid/view/View;)V
.........省略一坨代码...........
iget-objectv0,v5,Lcom/zbsh/code/clas/ClassSystem;->ipAddress:Ljava/lang/String;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">.line199
.localv0,ipAddress:Ljava/lang/String;
new-instancev5,Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-static{v0},Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv6</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-direct{v5,v6},Ljava/lang/StringBuilder;->(Ljava/lang/String;)V</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">const-stringv6,"Find/GetBookList.aspx?a="</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">const-stringv6,"gdut"</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">const-stringv6,"&b="</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv6</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv5,p0,Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5},Lcom/zbsh/code/ZbshFindMain;->getApplication()Landroid/app/Application;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">check-castv5,Lcom/zbsh/code/clas/ApplZbsh;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv5,v5,Lcom/zbsh/code/clas/ApplZbsh;->iSystem:Lcom/zbsh/code/clas/ClassSystem;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv5,v5,Lcom/zbsh/code/clas/ClassSystem;->searchType:Ljava/lang/String;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v6,v5},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">const-stringv6,"&c="</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv6</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv5,p0,Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5},Lcom/zbsh/code/ZbshFindMain;->getApplication()Landroid/app/Application;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">check-castv5,Lcom/zbsh/code/clas/ApplZbsh;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv5,v5,Lcom/zbsh/code/clas/ApplZbsh;->iSystem:Lcom/zbsh/code/clas/ClassSystem;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv5,v5,Lcom/zbsh/code/clas/ClassSystem;->inputKeywords:Ljava/lang/String;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v6,v5},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">const-stringv6,"&d="</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">sgetv6,Lcom/zbsh/code/clas/ClassDataParameter;->count:I</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">const-stringv6,"&e="</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">sgetv6,Lcom/zbsh/code/clas/ClassDataParameter;->page:I</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v6},Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5},Ljava/lang/StringBuilder;->toString()Ljava/lang/String;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv3</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">.line201
.localv3,urlPath:Ljava/lang/String;
iget-objectv5,p0,Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5},Lcom/zbsh/code/ZbshFindMain;->getApplication()Landroid/app/Application;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">move-result-objectv5</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">check-castv5,Lcom/zbsh/code/clas/ApplZbsh;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv5,v5,Lcom/zbsh/code/clas/ApplZbsh;->iSystem:Lcom/zbsh/code/clas/ClassSystem;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv6,p0,Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">iget-objectv6,v6,Lcom/zbsh/code/ZbshFindMain;->mUIHandler:Landroid/os/Handler;</font></pre>
<preclass="brush:php;highlight:[5,15];html-script:true"><fontface="">invoke-virtual{v5,v0,v3,v6},Lcom/zbsh/code/clas/ClassSystem;->GetFindOnThread(Ljava/lang/String;Ljava/lang/String;Landroid/os/Handler;)V
上面这段代码,实现的是通过StringBuilder,通过append方法,拼成一个地址出来,再调用ClassSystem;->GetFindOnThread这个方法,传入参数,进行一个异步图书搜索的任务。

再从ClassDataParameter.smali中找到一些定义host地址常量。

复制代码

代码如下:

.line20
const-stringv0,"<ahref="http://59.41.253.11:7778/">http://59.41.253.11:7778/</a>"</p><p>sput-objectv0,Lcom/zbsh/code/clas/ClassDataParameter;->IPADDRESS_TEL:Ljava/lang/String;</p><p>.line21
const-stringv0,"<ahref="http://222.200.98.173:7778/">http://222.200.98.173:7778/</a>"</p><psput-objectv0,Lcom/zbsh/code/clas/ClassDataParameter;->IPADDRESS_EDU:Ljava/lang/String

我们可以拼出图书搜索的接口是:http://222.200.98.173:7778/Find/GetBookList.aspx?a=&b=1&c=java&d=40&e=100

返回的是Json数据格式化下:

复制代码

代码如下:

{
"error":"0",
"findtotal":"1612",
"findcache":"20131124024041.htm",
"find_list":[
{
"CtrlNo":"70658",
"Isbn":"7-301-03477-6",
"Title":"Java教程(Internet面向对象程序设计)",
"Author":"MaryCampione",
"Edition":"",
"Publisher":"北大版",
"PubDate":"97.12"
},
{
"CtrlNo":"70657",
"Isbn":"7-301-03476-8",
"Title":"Java类手册",
"Author":"PatrickChan",
"Edition":"",
"Publisher":"北大版",
"PubDate":"97.12"
},
{
"CtrlNo":"605337",
"Isbn":"978-7-115-30271-7",
"Title":"Java7基础教程=Java7forabsolutebeginners",
"Author":"(美)JayBryant著;李鹏,韩智译",
"Edition":"",
"Publisher":"人民邮电出版社",
"PubDate":"2013.01"
},
{
"CtrlNo":"604835",
"Isbn":"978-7-302-30346-6",
"Title":"Java改错学习法[专著]",
"Author":"朱福喜编著",
"Edition":"",
"Publisher":"清华大学出版社",
"PubDate":"2013"
}
]
}

其次:
还可以通过反编译更强大的用处是用来修改smali代码,再重打包apk,来破解一些收费软件,去除广告之类,或者了解一些优秀软件的实现逻辑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: