說說APK反編譯(代碼插入)的那點事


http://shazhuzhu1.iteye.com/blog/1415328

很多人熱衷於逆向工程,其過程中既可以學習作者的思路,又可以鍛鍊自己的能力,可謂是一舉多得今天我來給大傢伙介紹介紹我所瞭解的apk反編譯的相關技術,和大家一起來做一個逆向工程.

         提醒:未經授權而逆向別人的程序是違法行爲在此,我們只做學術研究,不搞破壞~

 

知識鋪墊:

1.反編譯的結果有兩種,一種是smali (java機器碼),還有一種是大家喜聞樂見的java代碼形式.

2.apk文件其實是一個zip壓縮包,裏面的目錄結構與android工程的結構很類似,其中我們的java源碼(包括R.java)classes.dex文件中.

3.期間的工具大部分是java寫的,運行時需要具備java環境!

我先介紹大家喜聞樂見的形式吧,哈哈

 

apk反編譯爲源碼.

需要的工具:

1.dex2jar. dex2jar-0.0.7.10-SNAPSHOT.zip (590.31 KB, 下載次數: 44)

 

2.Jd-gui. jd-gui-0.3.3.osx.i686.zip (689.59 KB, 下載次數: 39)

 

3.AXMLPrinter2. AXMLPrinter2.zip (38.76 KB, 下載次數: 34)

 

 

逆向目標是前陣子懸賞區發過的一個demo,正好是我寫的,我授權給所有cmd100用戶,歡迎逆向,不追任何究法律責任..

源碼:http://www.cmd100.com/bbs/forum- ... 052-pid-173308.html

Apk文件CMD100.demo.slipButton.rar (18.74 KB, 下載次數: 19)

 

 

方法:

既然是一個zip壓縮包,那就先把apk包解壓出來吧!

可以看到解壓出來的文件如下:

1.PNG

 

先處理xml 文件.. 你可能想直接打開xml文件,但其實xml文件被加密過了,打開只會是一堆你讀不懂的東西,這需要用工具解碼一下用到AXMLPrinter2.

打開CMD切換到AXMLPrinter2目錄.

命令: Java –jar axmlprinter2.jar [路徑]\AndroidManifest.xml >輸出文件名.xml

2.PNG

 

打開生成的這個文件,看看Manifest.xml是不是出來了?

反編譯結果:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:versionCode="1"
  5. android:versionName="1.0"
  6. package="CMD100.demo.slipButton"
  7. >
  8. <application
  9.   android:label="@7F040001"
  10.   android:icon="@7F020000"
  11.   android:debuggable="true"
  12.   >
  13.   <activity
  14.    android:label="@7F040001"
  15.    android:name=".Main"
  16.    >
  17.    <intent-filter
  18.     >
  19.     <action
  20.      android:name="android.intent.action.MAIN"
  21.      >
  22.     </action>
  23.     <category
  24.      android:name="android.intent.category.LAUNCHER"
  25.      >
  26.     </category>
  27.    </intent-filter>
  28.   </activity>
  29. </application>
  30. <uses-sdk
  31.   android:minSdkVersion="4"
  32.   >
  33. </uses-sdk>
  34. </manifest>
複製代碼

源文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3.       package="CMD100.demo.slipButton"
  4.       android:versionCode="1"
  5.       android:versionName="1.0">
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">
  7.         <activity android:name=".Main"
  8.                   android:label="@string/app_name">
  9.             <intent-filter>
  10.                 <action android:name="android.intent.action.MAIN" />
  11.                 <category android:name="android.intent.category.LAUNCHER" />
  12.             </intent-filter>
  13.         </activity>
  14.     </application>
  15.     <uses-sdk android:minSdkVersion="4" />
  16. </manifest>
複製代碼

 

使用同樣的方法把res/layout/目錄下的佈局文件也解碼一下~在此我就不再贅述了.

 

接下來是dex文件的處理,需要用dex2jar工具處理轉換一下.

先把工具解壓出來,然後CMD切換到指定目錄,運行如下命令:

dex2jar.bat [目錄]\classes.dex

3.PNG

 

執行完畢後,classes.dex所在目錄下便生成了一個名爲classes.dex.dex2jar.jar的文件!

jd-gui打開這個生成的jar試試!代碼就在裏面了有沒有?!

4.PNG

 

對比一下main.java.

反編譯:

  1. public class Main extends Activity
  2.   implements OnChangedListener
  3. {
  4.   public void OnChanged(boolean paramBoolean)
  5.   {
  6.     if (paramBoolean)
  7.     {
  8.       Toast.makeText(this, "打開了...", 0).show();
  9.       return;
  10.     }
  11.     Toast.makeText(this, "關閉了...", 0).show();
  12.   }
  13.   public void onCreate(Bundle paramBundle)
  14.   {
  15.     super.onCreate(paramBundle);
  16.     setContentView(2130903040);
  17.     ((SlipButton)findViewById(2131034112)).SetOnChangedListener(this);
  18.   }
  19. }
複製代碼

源文件:

  1. public class Main extends Activity implements OnChangedListener {
  2.     /** Called when the activity is first created. */
  3.     @Override
  4.     public void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         setContentView(R.layout.main);
  7.         
  8.         SlipButton myBtn =(SlipButton) findViewById(R.id.slipBtn);//獲得指定控件
  9.         myBtn.SetOnChangedListener(this);//爲控件設置監聽器
  10.     }
  11. @Override
  12. public void OnChanged(boolean CheckState) {//當按鈕狀態被改變時
  13.   // TODO Auto-generated method stub
  14.   if(CheckState)
  15.    Toast.makeText(this,"打開了..." , Toast.LENGTH_SHORT).show();
  16.   else
  17.    Toast.makeText(this,"關閉了..." , Toast.LENGTH_SHORT).show();
  18. }
  19. }
複製代碼

 

 

 

P.S.其實這樣獲得的源碼還是有一部分會出現錯誤啊~

 

=================分割線========================

 

apk反編譯爲smali並插入自己的代碼

用到的工具:

1.apktool.jar (smali-1.2.6.jar & baksmali-1.2.6.jar) Apktool.zip (2.01 MB, 下載次數: 27)

 

2.auto-sign. APK-sign.rar (1.66 MB, 下載次數: 33)

 

 

這些工具都是google的開源項目

 

主要流程:

1.反編譯

2.插入代碼

3.重新打包

 

方法:

有了前面的鋪墊,我就不再囉嗦了.

命令:java -jar apktool.jar d 目標文件.apk

5.PNG

 

apktool.jar所在目錄下就生成了這個apk反編譯後的文件夾,打開看看!

包括xml在內的文件都被解碼了!

 

不過我們關注的是smali文件夾,打開看看,裏面的目錄結構和源碼的目錄結構是一致的!

找到要修改的地方.在這個例子裏,就在Main.java(第一個載入的activity)OnCreate方法裏插入一段代碼吧!

打開 Main.smali

  1. .class public LCMD100/demo/slipButton/Main;
  2. .super Landroid/app/Activity;
  3. .source "Main.java"
  4. # interfaces
  5. .implements LCMD100/demo/slipButton/OnChangedListener;

  6. # direct methods
  7. .method public constructor <init>()V
  8.     .locals 0
  9.     .prologue
  10.     .line 14
  11.     invoke-direct {p0}, Landroid/app/Activity;-><init>()V
  12.     return-void
  13. .end method

  14. # virtual methods
  15. .method public OnChanged(Z)V
  16.     .locals 2
  17.     .parameter "CheckState"
  18.     .prologue
  19.     const/4 v1, 0x0
  20.     .line 28
  21.     if-eqz p1, :cond_0
  22.     .line 29
  23.     const-string v0, "\u6253\u5f00\u4e86..."
  24.     invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
  25.     move-result-object v0
  26.     invoke-virtual {v0}, Landroid/widget/Toast;->show()V
  27.     .line 32
  28.     :goto_0
  29.     return-void
  30.     .line 31
  31.     :cond_0
  32.     const-string v0, "\u5173\u95ed\u4e86..."
  33.     invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
  34.     move-result-object v0
  35.     invoke-virtual {v0}, Landroid/widget/Toast;->show()V
  36.     goto :goto_0
  37. .end method
  38. .method public onCreate(Landroid/os/Bundle;)V
  39.     .locals 2
  40.     .parameter "savedInstanceState"
  41.     .prologue
  42.     .line 18
  43.     invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
  44.     .line 19
  45.     const/high16 v1, 0x7f03
  46.     invoke-virtual {p0, v1}, LCMD100/demo/slipButton/Main;->setContentView(I)V
  47.     .line 21
  48.     const/high16 v1, 0x7f05
  49.     invoke-virtual {p0, v1}, LCMD100/demo/slipButton/Main;->findViewById(I)Landroid/view/View;
  50.     move-result-object v0
  51.     check-cast v0, LCMD100/demo/slipButton/SlipButton;
  52.     .line 22
  53.     .local v0, myBtn:LCMD100/demo/slipButton/SlipButton;
  54.     invoke-virtual {v0, p0}, LCMD100/demo/slipButton/SlipButton;->SetOnChangedListener(LCMD100/demo/slipButton/OnChangedListener;)V
  55.     .line 23
  56.     return-void
  57. .end method
複製代碼


你發現裏頭的代碼是見都沒見過的格式,這就是java的彙編代碼了

學過80x86彙編的同學看着這些代碼是不是也覺得陌生?

沒事,我們可以對照前面介紹的那種方法查看源碼,然後尋找修改的位置!

 

找到這一行:

.method public onCreate(Landroid/os/Bundle;)V

 

這就是OnCreate方法的代碼起始了,

.line 23

return-void

 

之前插入如下代碼: (效果是Toast彈出一句話.)

  1. const-string v0, "Hey,dude.This program has been fucked!"
  2. const/4 v1, 0x0

  3. invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

  4. move-result-object v0
  5. invoke-virtual {v0}, Landroid/widget/Toast;->show()V
複製代碼

 

 

 

 

爲什麼是這個,其實我也不懂smali,但是可以把自己要的功能寫出來,再反彙編然後copy到這來

好吧,我們來分析一下這段代碼,前面是類似申明瞭兩個變量,v0,v1,然後調用了ToastmakeText方法(列出了參數),再然後調用了其show方法

看吧,其實我們是能大概看懂smali的內容,只是不懂語法而已!

 

好吧,廢話不多說.

現在改好了,apktool重新打包~

命令: java -jar apktool.jar b 目標文件夾

6.PNG

 

執行完後,就在這個目錄裏生成了兩個目錄,分別是build,dist

Build下是中間文件,dist下則是apk文件(但是這個apk文件未簽名)

 

下面就是重新簽名.

先解壓auto-sign

我們進入Build文件夾,複製apk文件夾到auto-sign文件夾下,然後執行命令:

sign_pack.bat apk

 

稍等片刻,你會發現文件夾下生成了對應的目錄,進入這個目錄,apk靜靜地躺在那

趕緊,裝到手機上看看,是不是改成了?

device.png

 

成功彈出,哈哈...

 

至此,apk的反編譯和代碼插入就結束了.

藉此方法,我們可以輕鬆的對apk進行DIY...

 

歡迎轉載,,轉載請註明出處!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章