Android進階知識樹——應用安全基礎篇

1、Smile語法入門

Smali是Java虛擬機中的一種.dex格式文件彙編器,它採用一種寬鬆式的Jasmin/dedexer的語法,表達了.dex格式所有功能和信息,如果瞭解Smali語言基礎,在我們反編譯程序時就可以看出程序的大致代碼,這對於分析競品可能有所幫助,下面一起學習下Smali基礎知識

  • 原始類型映射關係:這裏的映射關係和JNI中一致
  1. v :void ()
  2. Z:boolean
  3. B:byte
  4. S:short
  5. C:char
  6. I:int
  7. J:long
  8. F:float
  9. D:double
  • 類的表示:smile中採用全路徑的方式進行展示,如:Ljava/lang/String;
  1. L:表明此處表示類
  2. java/lang/String:類的全路徑名稱
  3. ;:類聲明結束符號
  • 數組表示:數組採用[+元素類型的方式,如[I 、[Ljava/lang/String
  1. [:表示聲明數組
  2. I:表示數組的類型
  3. [[I:表示二維數組
  • 對象的表示:對象的表示分爲兩部分,一部分是持有此對象類型的表示,第二部分是變量展示即變量名+變量類型,如: Ljava/lang/String; ——> FieldName : Ljava/lang/String;
  1. Ljava/lang/String;:類的全路徑
  2. FieldName:對象名稱
  3. Ljava/lang/String;:對象類型
  • 方法表示:使用方法的所在類、方法名、方法簽名表示,如 Ljava/lang/String; ——> method(III)V
  1. Ljava/lang/String;:類的全路徑
  2. method:方法名稱
  3. III:方法的傳參類型,傳入3個Int類型數據
  4. V :方法返回類型
  • 方法參數:.param p1, “savedInstanceState” # Landroid/os/Bundle;
  1. .param:表示參數
  2. p1:寄存器
  3. “savedInstanceState":參數名稱
  4. # Landroid/os/Bundle;:參數類型
  • 寄存器:表示此方法在執行中需要的存儲空間個位置
  1. 方法中聲明使用寄存器個數
    .registers 指令指定了方法中寄存器的總數
    .locals 指令表明了方法中非參寄存器的總數,出現在方法中的第一行
  2. 方法的參數被放在最後幾個寄存器中
1.1、Smile實戰示例
public class MainActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      TextView textView = findViewById(R.id.textView);
   }
   @Subscribe
   public void action(TypeEvent event) {
   }
   @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
   public void actionTwo(TypeEvent event) {
   }
}
  1. 查看生成的smali代碼
.class public Lcom/alex/kotlin/jniapplication/MainActivity;  //表明類文件的路徑和名稱
.super Landroid/support/v7/app/AppCompatActivity;  //繼承的父類
.source "MainActivity.java" //當前類的名稱
# direct methods //聲明方法開始
.method public constructor <init>()V  //構造函數
    .locals 0 
    .line 10  //代碼行數
    invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V
    return-void
.end method  //聲明方法結束
# virtual methods
.method public action(Lcom/alex/kotlin/jniapplication/TypeEvent;)V //action()標明瞭方法名、參數、返回類型
    .locals 0
    .param p1, "event"    # Lcom/alex/kotlin/jniapplication/TypeEvent; //參數 
    .annotation runtime Lorg/greenrobot/eventbus/Subscribe;  //方法註解
    .end annotation
    .line 22
    return-void
.end method
.method public actionTwo(Lcom/alex/kotlin/jniapplication/TypeEvent;)V //actionTwo()
    .locals 0
    .param p1, "event"    # Lcom/alex/kotlin/jniapplication/TypeEvent;
    .annotation runtime Lorg/greenrobot/eventbus/Subscribe;
        sticky = true
        threadMode = .enum Lorg/greenrobot/eventbus/ThreadMode;->MAIN:Lorg/greenrobot/eventbus/ThreadMode;
    .end annotation
    .line 27
    return-void
.end method
.method protected onCreate(Landroid/os/Bundle;)V  //create()
    .locals 1  //聲明寄存器個數
    .param p1, "savedInstanceState"    # Landroid/os/Bundle; //聲明參數
    .line 14
    invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V //代碼語句
    .line 15
    const v0, 0x7f09001c
    invoke-virtual {p0, v0}, Lcom/alex/kotlin/jniapplication/MainActivity;->setContentView(I)V //代碼語句
    .line 16
    const v0, 0x7f070087
    invoke-virtual {p0, v0}, Lcom/alex/kotlin/jniapplication/MainActivity;->findViewById(I)Landroid/view/View;//代碼語句
    move-result-object v0
    .line 17
    .local v0, "textView":Landroid/widget/TextView;
    return-void
.end method

從上面示例編譯後的smile語言中,根據smile的語句特性可以清晰閱讀到整個代碼的內容,相比之下還是很清晰的,具體細節見代碼註釋;

2、ApkTool反編譯

  • 反編譯APK

在開發中使用發編譯的場景不多,但如果想查看某些產品的實現和代碼,就要先將產品反編譯出來,反編譯的過程也很簡單,下面一起使用ApkTool反編譯一個apk,直接命令行工具反編譯現有的apk

apktool d app-debug.apk   //編譯解析出資源文件,但會將Class文件解析成smali文件
apktool d -s app.apk  //編譯解析出資源文件,但會將Class文件解析成dex文件
  1. 編譯結果——smile語言
    在這裏插入圖片描述
  2. 反編譯dex語言
    在這裏插入圖片描述
  • 將dex編譯爲Jar包
  1. 將上面編譯的classes.dex文件複製到dexjar文件夾下,執行命令語句
sh d2j-dex2jar.sh classes.dex
sudo chmod +x d2j_invoke.sh //處理文件權限
  1. 文件夾下會自動生成classes-dex2jar.jar
  • JD-GUI查看生成的代碼
  1. 打開GUI將第二部生成的classes-dex2jar.jar包拖入即可查看生成對應的Java代碼
    在這裏插入圖片描述

3、Jadx反編譯

  • 配置導入工具
git clone https://github.com/skylot/jadx.git  //先下載jadx文件
cd jadx
./gradlew dist //編譯
  • jadx使用
  1. 雙擊bin/jadx-gui運行程序,此時會啓動操作界面和terminal(顯示操作日誌)
  2. 將要反編譯的APK拖進窗口即可自動編譯
  3. 反編譯的代碼可以在Java 和 Smali之間切換
    在這裏插入圖片描述
  • 代碼搜索功能
  1. Navigation -> Text Search 或者 Navigation -> Class Search啓動代碼搜索功能
  2. jadx支持 Class、Method、Field、Code四個維度的搜索
  3. 在代碼中可以直接右鍵 -> Find Usage 查找代碼
    在這裏插入圖片描述
  • deobfuscation
  1. 對於代碼混淆的APK,點擊 “ 工具 -> 反混淆 “會自動爲每個類創建別名方便查看和查找
    在這裏插入圖片描述在這裏插入圖片描述
  • 導出Gradle工程
  1. 點擊“File -> 導出Gradle工程 “
  • 反編譯出現卡頓
  1. 針對出現的卡頓修改併發線程:File -> 首選項 ->. 並行線程數 (默認爲4)
    在這裏插入圖片描述

4、二次打包

關於二次打包主要是修改編譯後smaile代碼,然後重新打包簽名即可,這裏就是要看懂smile代碼,另外保證修改後的smile代碼不衝突即可,詳細參見Android反編譯和二次打包實戰

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