165 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Smali - デコンパイル/[修正]/コンパイル
{{#include ../../banners/hacktricks-training.md}}
時には、隠された情報おそらくよく難読化されたパスワードやフラグにアクセスするためにアプリケーションコードを修正することが興味深い場合があります。そのため、apkをデコンパイルし、コードを修正して再コンパイルすることが興味深いかもしれません。
**オペコードリファレンス:** [http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html)
## 簡単な方法
**Visual Studio Code**と[APKLab](https://github.com/APKLab/APKLab)拡張機能を使用すると、コマンドを実行することなく、アプリケーションを**自動的にデコンパイル**、修正、**再コンパイル**、署名&インストールできます。
この作業を大いに簡素化する**スクリプト**は[**https://github.com/ax/apk.sh**](https://github.com/ax/apk.sh)です。
## APKをデコンパイルする
APKToolを使用すると、**smaliコードとリソース**にアクセスできます:
```bash
apktool d APP.apk
```
もし**apktool**がエラーを出した場合は、[**最新バージョン**](https://ibotpeaches.github.io/Apktool/install/)をインストールしてみてください。
あなたが見るべき**興味深いファイルは**次の通りです:
- _res/values/strings.xml_およびres/values/\*内のすべてのxml
- _AndroidManifest.xml_
- 拡張子が_.sqlite_または_.db_のファイル
もし`apktool`が**アプリケーションのデコードに問題がある**場合は、[https://ibotpeaches.github.io/Apktool/documentation/#framework-files](https://ibotpeaches.github.io/Apktool/documentation/#framework-files)を確認するか、**`-r`**(リソースをデコードしない)という引数を使用してみてください。その後、問題がリソースにあり、ソースコードにない場合は、問題が発生しません(リソースもデコンパイルされません)。
## Smaliコードの変更
あなたは**命令を変更**したり、いくつかの変数の**値を変更**したり、新しい命令を**追加**することができます。私は[**VS Code**](https://code.visualstudio.com)を使用してSmaliコードを変更します。その後、**smalise拡張機能**をインストールすると、エディタが**命令が不正確である**かどうかを教えてくれます。\
いくつかの**例**はここにあります:
- [Smali変更の例](smali-changes.md)
- [Google CTF 2018 - Shall We Play a Game?](google-ctf-2018-shall-we-play-a-game.md)
または、[**以下のSmali変更の説明を確認することができます**](smali-changes.md#modifying-smali)。
## APKの再コンパイル
コードを修正した後、次のコマンドを使用して**再コンパイル**できます:
```bash
apktool b . #In the folder generated when you decompiled the application
```
新しいAPKは_**dist**_フォルダーの**内部**で**コンパイル**されます。
もし**apktool**が**エラー**を投げた場合は、[**最新バージョン**をインストール](https://ibotpeaches.github.io/Apktool/install/)してみてください。
### **新しいAPKに署名する**
次に、**キーを生成**する必要があります(パスワードといくつかの情報をランダムに入力するよう求められます):
```bash
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
```
最後に、新しいAPKに**署名**します:
```bash
jarsigner -keystore key.jks path/to/dist/* <your-alias>
```
### 新しいアプリケーションの最適化
**zipalign** は、Android アプリケーション (APK) ファイルに重要な最適化を提供するアーカイブ整列ツールです。[More information here](https://developer.android.com/studio/command-line/zipalign).
```bash
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
```
### **新しいAPKに署名する再度**
もしあなたが**apksigner**を使用することを**好む**場合、**最適化を適用した後にapkに署名する必要があります**。ただし、**アプリケーションには一度だけ署名する必要があることに注意してください**。jarsignerzipalignの前またはaspsignerzipalignの後で署名してください。
```bash
apksigner sign --ks key.jks ./dist/mycompiled.apk
```
## Smaliの変更
次のHello World Javaコードについて:
```java
public static void printHelloWorld() {
System.out.println("Hello World")
}
```
Smaliコードは次のようになります
```java
.method public static printHelloWorld()V
.registers 2
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello World"
invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
.end method
```
The Smali instruction set is available [here](https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions).
### Light Changes
### 関数内の変数の初期値を変更する
いくつかの変数は、オペコード _const_ を使用して関数の最初に定義されており、その値を変更することができます。または、新しい値を定義することもできます:
```bash
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
```
### 基本操作
```bash
#Math
add-int/lit8 v0, v2, 0x1 #v2 + 0x1 and save it in v0
mul-int v0,v2,0x2 #v2*0x2 and save in v0
#Move the value of one object into another
move v1,v2
#Condtions
if-ge #Greater or equals
if-le #Less or equals
if-eq #Equals
#Get/Save attributes of an object
iget v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save this.o inside v0
iput v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save v0 inside this.o
#goto
:goto_6 #Declare this where you want to start a loop
if-ne v0, v9, :goto_6 #If not equals, go to: :goto_6
goto :goto_6 #Always go to: :goto_6
```
### より大きな変更
### ロギング
```bash
#Log win: <number>
iget v5, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Get this.o inside v5
invoke-static {v5}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; #Transform number to String
move-result-object v1 #Move to v1
const-string v5, "wins" #Save "win" inside v5
invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I #Logging "Wins: <num>"
```
推奨事項:
- 関数内で宣言された変数v0、v1、v2...)を使用する場合は、これらの行を _.local \<number>_ と変数の宣言 (_const v0, 0x1_) の間に置いてください。
- 関数のコードの中間にログ記録コードを挿入したい場合:
- 宣言された変数の数に2を加えます_.locals 10_ から _.locals 12_
- 新しい変数は、すでに宣言された変数の次の番号である必要があります(この例では _v10__v11_ で、v0から始まることを忘れないでください
- ログ記録関数のコードを変更し、_v5_ と _v1_ の代わりに _v10__v11_ を使用します。
### トースティング
関数の最初に _.locals_ の数に3を加えることを忘れないでください。
このコードは **関数の中間に挿入する** ために準備されています(**必要に応じて** **変数****番号** を変更してください)。これは **this.o****値** を取得し、**String** に **変換** し、その値で **トースト****作成** します。
```bash
const/4 v10, 0x1
const/4 v11, 0x1
const/4 v12, 0x1
iget v10, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I
invoke-static {v10}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v11
invoke-static {p0, v11, v12}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v12
invoke-virtual {v12}, Landroid/widget/Toast;->show()V
```
{{#include ../../banners/hacktricks-training.md}}