Androidapk反编译基础(apktoos)图⽂教程
很久有写过⼀个⼴⼯图书馆主页⼀个类爬⾍的demo(因为没接⼝,只能扒取静态⽹页),实现⼀些图书馆系统的⼀些功能。但最近发现图书馆系统在html页⾯上做了⼿脚,⼀页html 页⾯中嵌⼊了⼏千⾏的注释,并有了⾃⼰的App,应该是为了增加扒取的流量成本来防⽌别⼈去扒取⽹页,不过加注释这⼿段就不敢恭维了,内⽹访问速度还⾏,但外⽹访问的话体验很差的。
如下图:⼀堆注释,导致⼀个⽹页要2MB
主页上的APP,必然是⽤了图书馆的后台接⼝和服务器交互的,从⽽想试试⽤反编译的⼿段来看看APP使⽤了什么接⼝。(另外更简单可以通过来给Android⼿机抓包分析其接⼝,再⽤Wireshark来分析tcp包,不过你想要知道全部接⼝的话,可能需要⼀个个接⼝去调⽤,会⽐较⿇烦,采⽤反编译,可能集中在⼀个类中到这些接⼝)。
解压缩APKTool,并把要反编译的APK放⼊⽬录中
反编译:
通过CMD进⼊上⾯的⽬录,执⾏命令: apktool decode ZhaoBenShu.apk outdir
稍等⽚刻完成反编译,反编译后的⽂件会在outdir⽬录下。
---outdir⽬录结构
res :资源⽂件,跟adnroid⼯程⽬录下的res基本⼀样,各种UI图⽚  XML布局⽂件  values xml⽂件(多了⼀个l,有各个资源的id号(R.java中的id))
smail:这个是重点⽂件夹,⾥⾯都是smail格式⽂件,是Dalvik虚拟机执⾏的操作码(Dalvik opcodes),这些操作吗有⾃⼰的语法,如果有学过JNI的话,这些语法还是⽐较容易看懂和理解的。l:Android⼯程下的l
smail语法:(全部语法请)
smail中的数据类型签名跟java中的是⼀样的,如下。
B---byteC---charD---doubleF---floatI---intJ---longS---shortV---voidZ---boolean[XXX---arrayLxxx/yyy---object
smail代码例⼦:
初看smail⽂件,可能会觉得有⼀些凌乱。不过只要把⼏种语法弄懂了,就可以很好地阅读smail⽂件。
smail⽐较常⽤语法 ( ⾮全部)分为:赋值,取值,函数调⽤,if语句,返回值等。
赋值取值:
例⼦: iget-object v6, p0, Lcom/zbsh/code/clas/ClassSystem$9;->val$vBarCodes:Ljava/util/ArrayList;
分析:
iget个取值操作,i=instance,是⽤来instance filed(实例变量),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-boolean  iget-byte  iget-char  iget-short等等。
同样的:
sget- [type]⽤来获取static变量。(少了⼀个p0,因为静态变量是没有this的)
aget-[type]⽤来获取array类型。
[x]get vx, 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-result vx :把上⼀个⽅法返回的值,存在寄存器 vx中。
返回返回值:
return-void  没返回。
return vx      返回寄存器中vx的值。
if语句:
if-eq vx,vy,target:eq:equal  如果vx==xy 跳转到target⽬标代码,否则执⾏顺序执⾏下⼀句代码
if-ne vx,vy,target:nq :not equal  如果vx!=xy 跳转到target⽬标代码,否则执⾏顺序执⾏下⼀句代码
if-eqz vx,target:eqz : equal zero  如果vx==0 跳转到target⽬标代码,否则执⾏顺序执⾏下⼀句代码
if-nez vx,target:nez :not equal zero  如果vx!=0 跳转到target⽬标代码,否则执⾏顺序执⾏下⼀句代码
读smail,接⼝:
以搜索接⼝为例⼦:
根据⽂件命名到GropZbshFind.smali这个⽂件,应该就是搜索Activity。
在其中有⼀段代码:
复制代码
代码如下:
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
.locals 3
.parameter "savedInstanceState"</font></p> <p><font face="Courier New"> .prologue
.line 13
invoke-super {p0, p1}, Lcom/zbsh/code/thrd/GroupActivity;->onCreate(Landroid/os/Bundle;)V</font></p> <p><font face="Courier New"> .line 14
const-class v0, Lcom/zbsh/code/ZbshFindMain;</font></p> <p><font face="Courier New"> invoke-virtual {v0}, Ljava/lang/Class;->getName()Ljava/lang/String;</font></p> <p><font face="Courier New"> move-result-object v0</font></p> <p><font face="Courier New"> new-instance v1, Landroid/content/Intent;</font></p> <p><font face="Courier New"> const-class v2, Lcom/zbsh/code/ZbshFindMain;</font></p> <p><font face="Courier New"> invoke-direct {v1, p0, v2}, Landroid/content/Intent;->
(Landroid/content/Context;Ljava/lang/Class;)V</font></p> <p><font face="Courier New"> invoke-virtual {p0, v0, v1}, Lcom/zbsh/code/GropZbshFind;-
>startChildActivity(Ljava/lang/String;Landroid/content/Intent;)V</font></p> <p><font face="Courier New"> .line 15
return-void
.
end method
很明显是通过startActivity来启动ZbshFindMain这个Activity,
在ZbshFindMain中到Onclick⽅法。
复制代码
代码如下:
# virtual methods
.method public onClick(Landroid/view/View;)V
.........省略⼀坨代码...........
iget-object v0, v5, Lcom/zbsh/code/clas/ClassSystem;->ipAddress:Ljava/lang/String;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    .line 199
.local v0, ipAddress:Ljava/lang/String;
new-instance v5, Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-static {v0}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v6</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-direct {v5, v6}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    const-string v6, "Find/GetBookList.aspx?a="</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    const-string v6, "gdut"</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    const-string v6, "&b="</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v6</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v5, p0, Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5}, Lcom/zbsh/code/ZbshFindMain;->getApplication()Landroid/app/Application;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    check-cast v5, Lcom/zbsh/code/clas/ApplZbsh;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v5, v5, Lcom/zbsh/code/clas/ApplZbsh;->iSystem:Lcom/zbsh/code/clas/ClassSystem;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v5, v5, Lcom/zbsh/code/clas/ClassSystem;->searchType:Ljava/lang/String;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v6, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    const-string v6, "&c="</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v6</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v5, p0, Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5}, Lcom/zbsh/code/ZbshFindMain;->getApplication()Landroid/app/Application;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    check-cast v5, Lcom/zbsh/code/clas/ApplZbsh;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v5, v5, Lcom/zbsh/code/clas/ApplZbsh;->iSystem:Lcom/zbsh/code/clas/ClassSystem;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v5, v5, Lcom/zbsh/code/clas/ClassSystem;->inputKeywords:Ljava/lang/String;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v6, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    const-string v6, "&d="</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    sget v6, Lcom/zbsh/code/clas/ClassDataParameter;->count:I</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    const-string v6, "&e="</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    sget v6, Lcom/zbsh/code/clas/ClassDataParameter;->page:I</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v3</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    .line 201
.local v3, urlPath:Ljava/lang/String;
iget-object v5, p0, Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    invoke-virtual {v5}, Lcom/zbsh/code/ZbshFindMain;->getApplication()Landroid/app/Application;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    move-result-object v5</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    check-cast v5, Lcom/zbsh/code/clas/ApplZbsh;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v5, v5, Lcom/zbsh/code/clas/ApplZbsh;->iSystem:Lcom/zbsh/code/clas/ClassSystem;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v6, p0, Lcom/zbsh/code/ZbshFindMain$4;->this$0:Lcom/zbsh/code/ZbshFindMain;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    iget-object v6, v6, Lcom/zbsh/code/ZbshFindMain;->mUIHandler:Landroid/os/Handler;</font></pre>
<pre class="brush: php; highlight: [5, 15]; html-script: true"><font face="">    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地址常量。
复制代码
代码如下:
.line 20
const-string v0, "<a href="59.41.253.11:7778/">59.41.253.11:7778/</a>"</p> <p> sput-object v0, Lcom/zbsh/code/clas/ClassDataParameter;-
>IPADDRESS_TEL:Ljava/lang/String;</p> <p> .line 21
const-string v0, "<a href="222.200.98.173:7778/">222.200.98.173:7778/</a>"</p> <p> sput-object v0, Lcom/zbsh/code/clas/ClassDataParameter;-
>IPADDRESS_EDU:Ljava/lang/String
返回的是Json数据格式化下:
复制代码
代码如下:
{
"error": "0",
"findtotal": "1612",
"findcache": "20131124024041.htm",
"find_list": [
{
"CtrlNo": "70658",
"Isbn": "7-301-03477-6 ",
"Title": "Java教程(Internet⾯向对象程序设计)",
"Author": "Mary Campione",
"Edition": " ",
"Publisher": "北⼤版",
"PubDate": "97.12"
},
{
"CtrlNo": "70657",
"Isbn": "7-301-03476-8 ",
"Title": "Java类⼿册",
"Author": "Patrick Chan",
"Edition": " ",
"Publisher": "北⼤版",
"PubDate": "97.12"
},
{
"CtrlNo": "605337",
"Isbn": "978-7-115-30271-7 ",
"Title": "Java 7基础教程= Java 7 for absolute beginners",
"Author": "(美) Jay Bryant著;, 韩智译",
"Edition": " ",
"Publisher": "⼈民邮电出版社",
"PubDate": "2013.01"
},
{
"CtrlNo": "604835",
"Isbn": "978-7-302-30346-6 ",
"Title": "Java改错学习法 [专著]",
"Author": "朱福喜编著",
"Edition": " ",
"Publisher": "清华⼤学出版社",
"PubDate": "2013"
}
]
}
其次:
网页app
还可以通过反编译更强⼤的⽤处是⽤来修改smali代码,再重打包apk,来破解⼀些收费软件,去除⼴告之类,或者了解⼀些优秀软件的实现逻辑。