国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
MIUI ROM適配之旅第三天——反編譯
首先說(shuō)句抱歉,今天事情比較多,教程出來(lái)的比較晚,請(qǐng)包含。今后幾天也會(huì)稍晚一點(diǎn),但是我會(huì)每天更新的。

    今天我們來(lái)詳細(xì)的看看反編譯,想要修改一個(gè)系統(tǒng)自帶的應(yīng)用程序和它的代碼,在沒(méi)有源碼的情況下,我們就不得不用反編譯來(lái)修改。

    和很多書(shū)籍一樣,為了向經(jīng)典的"Hello, World"致敬,我們也從一個(gè)簡(jiǎn)單的程序開(kāi)始HelloActivity.apk。當(dāng)你把這個(gè)APK安裝到手機(jī)上運(yùn)行后,在屏幕上就顯示一行文字"Hello, World!"(世界我來(lái)了!是的,兄弟姐妹們,從今天起我們真正進(jìn)入反編譯的世界,我們來(lái)了?。?br>
1. 反編譯
    為了介紹方便,從現(xiàn)在起,我會(huì)用cracker~$作為命令提示符,其后的文字表示我們需要運(yùn)行的命令。如果其后有斜體字,表示命令的輸出結(jié)果。

cracker~$ apktool d HelloActivity.apk
這條命令運(yùn)行完后,在當(dāng)前目錄下會(huì)生成一個(gè)名為HelloActivity的目錄。
該目錄的結(jié)構(gòu)為(名稱后跟/表示這是一個(gè)目錄):
HelloActivity/
       |--------------AndroidManifest.xml
       |--------------apktool.yml
       |--------------res/
       |--------------smali/
apktool.yml是apktool生成的一個(gè)配置文件,基本上你不需要修改這個(gè)文件。下面的章節(jié)我們逐個(gè)介紹剩下的AndroidManifest.xml文件和res, smali目錄。

2. AndroidManifest.xml
    要想完全理解這個(gè)文件,你得對(duì)Android的內(nèi)部運(yùn)作機(jī)制非常清楚。幸好我們修改一個(gè)APK的時(shí)候基本上不改這個(gè)文件。這里幫助你有個(gè)大致的了解。
   
    Android安裝程序一般叫apk文件(apk是Android Package的縮寫(xiě),表示Android安裝包)。一般來(lái)說(shuō),程序都會(huì)有一個(gè)或多個(gè)Activity, Activity是什么呢,從概念說(shuō)它是一個(gè)和用戶交互的窗口,你每天使用Android手機(jī)的時(shí)候基本上你打交道的每個(gè)界面都是一個(gè)Activity。AndroidManifest.xml是一個(gè)xml格式的清單文件,就像你去超市買(mǎi)東西會(huì)打印出一個(gè)購(gòu)物清單,AndroidManifest.xml也起著一個(gè)清單的作用,它告訴系統(tǒng),我有這些Activity。(實(shí)際情況遠(yuǎn)比這復(fù)雜,想學(xué)Android編程的同學(xué)請(qǐng)看這個(gè)http://developer.android.com/guide/index.html,好好學(xué)習(xí)其中的內(nèi)容)。
   
    具體到HelloActivity下的AndroidManifest.xml文件,大家可以找到如下內(nèi)容:
    <application
    android:label="@string/app_name" android:icon="@drawable/ic_launcher_hello">
            <activity android:name="HelloActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    其中有一行<category android:name="android.intent.category.LAUNCHER" />,包含這一行的Activity會(huì)顯示在桌面中,就是說(shuō)你可以通過(guò)桌面顯示的圖標(biāo)啟動(dòng)這個(gè)Activity。里面還有android:label="@string/app_name" android:icon="@drawable/ic_launcher_hello"。這兩個(gè)屬性是做什么的呢,android:label表示程序顯示在桌面上的名字,android:icon表示程序顯示在桌面上的圖標(biāo)。如果想要改顯示的名字和圖標(biāo),修改其后的兩個(gè)資源,如何修改資源,下一節(jié)詳細(xì)介紹。

3. 資源
    res目錄下放置了程序所需要的所有資源。資源是什么呢,一般來(lái)說(shuō),一個(gè)圖形用戶界面(GUI)程序總是會(huì)使用一些圖片,或者顯示的文字的大小和顏色等?;蛘呓缑娴牟季?,比如顯示的界面上面是文字,下面是兩個(gè)按鈕等等。這些程序的一個(gè)重要特點(diǎn)就是用戶界面和代碼邏輯的分離。當(dāng)我們需要替換圖片或者簡(jiǎn)單修改界面布局的時(shí)候,不需要改變代碼。而Android程序會(huì)將這些代碼中需要用到的文件都放在res目錄下,稱之為資源。

    可以看到res目錄的內(nèi)容為:
res/
|--------drawable-hdpi/
             |-----------ic_launcher_hello.png
|--------layout/
         |---------hello_activity.xml
|--------values/
         |---------ids.xml
         |---------public.xml
         |---------strings.xml
    對(duì)于HelloActivity來(lái)說(shuō),res目錄下有三個(gè)子目錄drawable-hdpi, layout, values。由于HelloActivity比較簡(jiǎn)單,因此res下內(nèi)容不多,但是一個(gè)復(fù)雜的程序res目錄下內(nèi)容相應(yīng)的也會(huì)比較多,但是基本原理都是一樣的。
   
    res下面的子目錄基本上是按照資源類(lèi)型來(lái)分類(lèi)組織的,以drawable開(kāi)頭的表示圖片資源,大家可能會(huì)看到drawable-hdpi, drawable-mdpi, drawable-ldpi等,這些hdpi,mdpi,lpid分別表示高/中/低分辨率,會(huì)根據(jù)不同的屏幕分辨率選擇不同的圖片。要想替換圖片,替換這些目錄下的圖片就可以了。(替換圖片比這稍復(fù)雜點(diǎn),一般替換圖片,最好保持和原圖片兼容,比如說(shuō)色系,尺寸以及點(diǎn)9圖片的一些參數(shù)等)。
   
    以layout開(kāi)頭的表示布局文件,用來(lái)描述程序的界面。anim子目錄存放程序使用到的動(dòng)畫(huà),xml開(kāi)頭的目錄存放程序用到的一些xml文件等。
   
    values開(kāi)頭的目錄下面存放一些我們稱之為基本元素的定義,比如說(shuō)colors.xml給出顏色值的定義,dimens.xml給出一些大小的定義。strings.xml是一些字符串的定義。我們看看HellloActivity的strings.xml文件。

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="hello_activity_text_text">Hello, World!</string>
        <string name="app_name">HelloWorld</string>
    </resources>
   
    其中的以<string開(kāi)頭便是這是一個(gè)字符串,name是給這個(gè)資源起一個(gè)名字,后面的字符串表示這個(gè)字符串的值。Android的資源大致按這種形式來(lái)組織的,先將資源分成幾種類(lèi)型,然后每一種類(lèi)型的所有資源取一個(gè)名字,這個(gè)名字對(duì)應(yīng)了這個(gè)資源的值/內(nèi)容。
   
    我們一般修改資源通常情況下是修改圖片或者漢化。漢化比較簡(jiǎn)單,values/strings.xml文件存放程序用到的所有英文字符串值。要漢化,首先在values下建立一個(gè)目錄values-zh-rCN。然后將values/strings.xml拷貝到該目錄中,將每一個(gè)字符串翻譯成中文。我們現(xiàn)在將strings.xml拷貝到values-zh-rCN目錄下,并將文件內(nèi)容改為:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="hello_activity_text_text">你好,世界!</string>
        <string name="app_name">你好世界</string>
    </resources>
   
    現(xiàn)在我們需要把修改后的文件在編回apk文件,運(yùn)行如下命令:
    cracker~$ apktool b HelloActivity HelloActivity.apk
    這條命令表示編譯HelloActivity目錄的內(nèi)容,輸出文件為HelloActivity.apk,如果你不想覆蓋原有的文件,可以換一個(gè)名字或者放在另外一個(gè)目錄下。
   
    接下來(lái)我們需要對(duì)生成的APK進(jìn)行簽名,下載附件中的壓縮包sign.zip, 解壓后有一個(gè)腳本sign.sh。假定你把解壓后的文件都放在/home/cracker/tools目錄中。運(yùn)行如下命令:
    cracker~$ export KEY_PATH=/home/cracker/tools
    cracker~$ /home/cracker/tools/sign.sh HelloActivity.apk
    cracker~$ adb install -r HelloActivity.apk.signed.aligned
注意最后一條命令如果失敗,如果你不是用我們提供的HelloActivity做實(shí)驗(yàn)的話,會(huì)發(fā)生簽名不一致的錯(cuò)誤,這個(gè)時(shí)候先卸載原來(lái)的,再安裝。運(yùn)行看看,對(duì)的,現(xiàn)在顯示在你面前的是“你好,世界!”

    漢化成功了,是的,漢化就這么簡(jiǎn)單。如果你只想停留在漢化或者替換圖片這個(gè)階段,從這里開(kāi)始以后的文章不用看了。如果你沒(méi)有Android編程基礎(chǔ),從這里開(kāi)始以后的文章也不用看了。
   
    到底發(fā)生了什么魔法,為什么這樣替換一下圖片或者改字符串就能改變程序最終運(yùn)行的結(jié)果呢,想要理解這個(gè),我們就的大致的了解一下資源的編譯過(guò)程。首先我們看看values目錄下一個(gè)有意思的文件publics.xml,它的內(nèi)容如下:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <public type="drawable" name="ic_launcher_hello" id="0x7f020000" />
        <public type="layout" name="hello_activity" id="0x7f030000" />
        <public type="string" name="hello_activity_text_text" id="0x7f040000" />
        <public type="string" name="app_name" id="0x7f040001" />
        <public type="id" name="text" id="0x7f050000" />
    </resources>
每一行的id后面都有一個(gè)看起來(lái)很奇怪的數(shù)字,這個(gè)數(shù)字是干嘛的呢?Android下有一個(gè)資源編譯器會(huì)編譯res目錄下的所有文件,它為每一個(gè)資源名字分配一個(gè)數(shù)字標(biāo)識(shí)符,這個(gè)標(biāo)識(shí)符分成3個(gè)部分,最前面的1個(gè)字節(jié)表示包名,所有的apk這個(gè)字節(jié)都是7f。表示這些資源是非共享的,其它APK訪問(wèn)不到。所有那些可以共享的資源放在system/framework/framework-res.apk下。/system/framework往往還有其它共享的資源包。這些共享的資源包前面的1個(gè)字節(jié)從0x1開(kāi)始,依次增加。中間的一個(gè)字節(jié)表示資源的類(lèi)型,每一個(gè)類(lèi)型的數(shù)字標(biāo)識(shí)符是不一樣的,最后的2個(gè)字節(jié)是資源的序號(hào),統(tǒng)一類(lèi)型的資源序號(hào)從0依次往上遞增。一般來(lái)說(shuō),資源id是由資源編譯器(aapt)自動(dòng)產(chǎn)生的,但是定義在publics.xml中的值告訴編譯器,你必須為這個(gè)id使用這個(gè)值。apktool會(huì)為所有的資源名稱定義這個(gè)值在publics.xml里,這樣可以保證替換資源后資源的id不會(huì)變化。

    為啥資源的id這么重要,如果變了,會(huì)怎么樣呢,這得結(jié)合代碼理解。我們?cè)贘ava代碼里通常這樣引用資源,比如R.string.app_name。這個(gè)Java代碼經(jīng)過(guò)編譯后,這條引用直接變成了資源id,即0x7f040001,所以你在下面反編譯后的smali代碼里面是看不到R.string.app_name這個(gè)東西的,只能看到0x7f040001。資源編譯器會(huì)生成一個(gè)查找表,對(duì)于每一個(gè)id,查找表中保存了這個(gè)id對(duì)應(yīng)的名字和值(如果是文件,則為文件所在路徑)。程序在運(yùn)行的時(shí)候,會(huì)根據(jù)id去查詢這個(gè)查找表找到對(duì)應(yīng)的資源的值或文件。
   
    最后說(shuō)一句,資源的ID非常重要,運(yùn)行adb pull /system/framework/framework-res.apk反編譯這個(gè)文件,好好的消化一下這一節(jié)的內(nèi)容吧。

4. smali
    終于迎來(lái)我們最重要的部分了smali目錄,smali目錄存放的是反編譯后的Java代碼,文件名以smali結(jié)尾,故稱作smali文件。這些代碼比一般的Java代碼可讀性差太多了,但是和傳統(tǒng)的x86或者其他體系結(jié)構(gòu)下的匯編文件那又是好讀多了。雖然有工具可以直接把這些反匯編成java代碼,單是好不了太多,我們還是直接讀取修改smali文件。從這里我們才真正的開(kāi)始是一名程序員。
   
    我們來(lái)看一下反編譯后的smali目錄下的HelloActivity.smali文件,和Java組織源代碼的方式一樣,smali目錄下的文件也是按文件包的包名結(jié)構(gòu)組織目錄結(jié)構(gòu)的,文件的內(nèi)容如下:
   
    .class public Lcom/example/android/helloactivity/HelloActivity;
    .super Landroid/app/Activity;
    .source "HelloActivity.java"
   
    # direct methods
    .method public constructor <init>()V
        .locals 0
   
        .prologue
        .line 27
        invoke-direct {p0}, Landroid/app/Activity;-><init>()V
   
        return-void
    .end method

    # virtual methods
    .method public onCreate(Landroid/os/Bundle;)V
        .locals 2
        .parameter "savedInstanceState"
   
        .prologue
        .line 33
        invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
   
        .line 37
        const/high16 v1, 0x7f03
   
        invoke-virtual {p0, v1},
    Lcom/example/android/helloactivity/HelloActivity;->setContentView(I)V
   
        .line 38
        const/high16 v1, 0x7f05
   
        invoke-virtual {p0, v1},
     Lcom/example/android/helloactivity/HelloActivity;->findViewById(I)Landroid/view/View;
   
        move-result-object v0
   
        check-cast v0, Landroid/widget/TextView;
   
        .line 39
        .local v0, txtView:android/widget/TextView;
        const/high16 v1, 0x7f04
   
        invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(I)V
   
        .line 40
        return-void
    .end method
   
    文件中的以#開(kāi)頭的文字表示注釋, 以.開(kāi)頭的叫做annotations,其中的.line表示對(duì)應(yīng)的源代碼的行號(hào),這個(gè)對(duì)調(diào)試很重要。.metho和.end method表示一個(gè)方法定義的開(kāi)始和結(jié)束。Smali文件中的這些指令的功能請(qǐng)參照http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html,有一些不懂沒(méi)關(guān)系,在接下來(lái)得兩章我們會(huì)接觸到大部分指令。
   
    其中.line 39的代碼對(duì)應(yīng)的源代碼是
    txtView.setText(R.string.hello_activity_text_text)
   
    我們現(xiàn)在想將這行代碼改成txtView.setText("Happy, Cracker!"),將.line 39到.line 40行的代碼改為:
     .line 39
     .local v0, txtView:android/widget/TextView;
     const-string v1, "Happy, Cracker!"
     invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
再按照上一節(jié)所說(shuō)得重新編譯,簽名,安裝運(yùn)行,好了,現(xiàn)在出現(xiàn)在你面前的是Happy, Cracker!了,真happy!

    接下來(lái)的兩章我們都會(huì)介紹如何直接修改smali代碼從而改變程序的功能,這種方法我們叫做代碼插樁,接下來(lái)的兩章我們將會(huì)用代碼插樁的方法將MIUI的功能加到原生ROM中去。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Android開(kāi)發(fā)學(xué)習(xí)筆記(三)——基于Eclipse開(kāi)發(fā)環(huán)境的搭建及HelloAndroid示例程序的創(chuàng)建
andriod的apk文件相關(guān)的編譯反編譯工具
手把手教你逆向分析 Android 程序
Android逆向之旅---反編譯利器Apktool和Jadx源碼分析以及錯(cuò)誤糾正
Android安全攻防戰(zhàn),反編譯與混淆技術(shù)完全解析(上)
破解驗(yàn)證,讓爬取更隨心所欲!
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服