165 lines
6.6 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**](https://developer.android.com/studio/command-line/) 而不是 jarsigner**您应该在应用** zipalign **优化后签署apk**。但请注意,您只需**使用 jarsigner 签署应用一次**(在 zipalign 之前)或使用 aspsigner在 zipalign 之后)。
```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
```
Smali 指令集可在 [这里](https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions) 获取。
### 轻微更改
### 修改函数内部变量的初始值
某些变量在函数开始时使用操作码 _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 开始)。
- 更改日志记录函数的代码,并使用 _v10__v11_ 代替 _v5__v1_
### Toasting
请记得在函数开始时将 _.locals 的数量加 3。
此代码准备插入到 **函数的中间****根据需要更改** **变量****数量**)。它将获取 **this.o****值****转换** 为 **String**,然后 **制作** 一个 **toast** 以显示其值。
```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}}