# Smali - 反编译/【修改】/编译
☁️ HackTricks 云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥 * 你在一家**网络安全公司**工作吗?你想在 HackTricks 中看到你的**公司广告**吗?或者你想获得**PEASS 的最新版本或下载 HackTricks 的 PDF**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! * 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品——[**The PEASS Family**](https://opensea.io/collection/the-peass-family) * 获取[**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com) * **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram 群组**](https://t.me/peass),或者**关注**我在**推特**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。** * **通过向**[**hacktricks 仓库**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud 仓库**](https://github.com/carlospolop/hacktricks-cloud) **提交 PR 来分享你的黑客技巧。**
有时候,修改应用程序代码以访问隐藏信息可能是有趣的(也许是混淆良好的密码或标志)。然后,反编译 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 代码和资源**: ``` 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 ``` 它将在_dist_文件夹中**编译**新的APK。 如果**apktool**出现错误,请尝试[安装**最新版本**](https://ibotpeaches.github.io/Apktool/install/) ### **签署新的APK** 然后,您需要**生成一个密钥**(将要求您输入密码和一些可以随机填写的信息): ```bash keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias ``` 最后,对新的APK进行**签名**: ```bash jarsigner -keystore key.jks path/to/dist/* ``` ### 优化新应用程序 **zipalign** 是一个归档对齐工具,为 Android 应用程序(APK)文件提供重要的优化。[更多信息请参考这里](https://developer.android.com/studio/command-line/zipalign)。 ```bash zipalign [-f] [-v] infile.apk outfile.apk zipalign -v 4 infile.apk ``` ### **签署新的APK(再次?)** 如果您更喜欢使用\[**apksigner**]\([**https://developer.android.com/studio/command-line/apksigner**](https://developer.android.com/studio/command-line/apksigner))\*\*而不是jarsigner,**您应该在使用zipalign进行优化后签署apk**。但请注意,您只需要使用jarsigner(在zipalign之前)或aspsigner(在zipalign之后)对应用程序进行一次签署。 ```bash apksigner sign --ks key.jks ./dist/mycompiled.apk ``` ## 修改 Smali 对于以下的 Hello World Java 代码: ``` public static void printHelloWorld() { System.out.println("Hello World") } ``` Smali 代码如下: ``` .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_操作码定义,您可以修改它们的值,或者您可以定义新的变量: ``` #Number const v9, 0xf4240 const/4 v8, 0x1 #Strings const-string v5, "wins" ``` ### 基本操作 In this section, we will cover some basic operations that can be performed on Smali code. 在本节中,我们将介绍一些可以在Smali代码上执行的基本操作。 #### Modifying Constants #### 修改常量 To modify a constant value in Smali code, you need to locate the instruction that loads the constant value onto the stack and replace it with a new value. 要修改Smali代码中的常量值,您需要找到将常量值加载到堆栈上的指令,并将其替换为新值。 For example, if you want to change the constant value `123` to `456`, you would locate the instruction `const/16 v0, 123` and replace `123` with `456`. 例如,如果您想将常量值`123`更改为`456`,您需要找到指令`const/16 v0, 123`并将`123`替换为`456`。 #### Modifying Method Calls #### 修改方法调用 To modify a method call in Smali code, you need to locate the instruction that invokes the method and replace it with a new method call. 要修改Smali代码中的方法调用,您需要找到调用方法的指令,并将其替换为新的方法调用。 For example, if you want to change the method call `invoke-virtual {v0, v1}, Lcom/example/Class;->method()V` to `invoke-static {v0, v1}, Lcom/example/Class;->method()V`, you would locate the instruction `invoke-virtual {v0, v1}, Lcom/example/Class;->method()V` and replace `invoke-virtual` with `invoke-static`. 例如,如果您想将方法调用`invoke-virtual {v0, v1}, Lcom/example/Class;->method()V`更改为`invoke-static {v0, v1}, Lcom/example/Class;->method()V`,您需要找到指令`invoke-virtual {v0, v1}, Lcom/example/Class;->method()V`并将`invoke-virtual`替换为`invoke-static`。 #### Modifying Field Access #### 修改字段访问 To modify a field access in Smali code, you need to locate the instruction that accesses the field and replace it with a new field access. 要修改Smali代码中的字段访问,您需要找到访问字段的指令,并将其替换为新的字段访问。 For example, if you want to change the field access `iget-object v0, v1, Lcom/example/Class;->field:Landroid/widget/TextView;` to `sget-object v0, Lcom/example/Class;->field:Landroid/widget/TextView;`, you would locate the instruction `iget-object v0, v1, Lcom/example/Class;->field:Landroid/widget/TextView;` and replace `iget-object` with `sget-object`. 例如,如果您想将字段访问`iget-object v0, v1, Lcom/example/Class;->field:Landroid/widget/TextView;`更改为`sget-object v0, Lcom/example/Class;->field:Landroid/widget/TextView;`,您需要找到指令`iget-object v0, v1, Lcom/example/Class;->field:Landroid/widget/TextView;`并将`iget-object`替换为`sget-object`。 #### Modifying Control Flow #### 修改控制流 To modify the control flow in Smali code, you need to locate the instructions that define the control flow and modify them accordingly. 要修改Smali代码中的控制流,您需要找到定义控制流的指令并相应地进行修改。 For example, if you want to change the condition for a branch instruction, you would locate the instruction `if-eqz v0, :label` and modify the condition `if-eqz` to `if-nez`. 例如,如果您想更改分支指令的条件,您需要找到指令`if-eqz v0, :label`并将条件`if-eqz`修改为`if-nez`。 #### Modifying Exception Handling #### 修改异常处理 To modify exception handling in Smali code, you need to locate the instructions that define the exception handling and modify them accordingly. 要修改Smali代码中的异常处理,您需要找到定义异常处理的指令并相应地进行修改。 For example, if you want to change the catch type for an exception handler, you would locate the instruction `.catch Ljava/lang/Exception;` and modify `Ljava/lang/Exception;` to the desired catch type. 例如,如果您想更改异常处理程序的catch类型,您需要找到指令`.catch Ljava/lang/Exception;`并将`Ljava/lang/Exception;`修改为所需的catch类型。 #### Modifying Local Variables #### 修改局部变量 To modify local variables in Smali code, you need to locate the instructions that define the local variables and modify them accordingly. 要修改Smali代码中的局部变量,您需要找到定义局部变量的指令并相应地进行修改。 For example, if you want to change the value of a local variable `v0` to `123`, you would locate the instruction `const/16 v0, 0` and replace `0` with `123`. 例如,如果您想将局部变量`v0`的值更改为`123`,您需要找到指令`const/16 v0, 0`并将`0`替换为`123`。 #### Modifying Method Parameters #### 修改方法参数 To modify method parameters in Smali code, you need to locate the instructions that define the method parameters and modify them accordingly. 要修改Smali代码中的方法参数,您需要找到定义方法参数的指令并相应地进行修改。 For example, if you want to change the value of a method parameter `p0` to `456`, you would locate the instruction `const/16 p0, 0` and replace `0` with `456`. 例如,如果您想将方法参数`p0`的值更改为`456`,您需要找到指令`const/16 p0, 0`并将`0`替换为`456`。 ``` #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 ``` ### 较大的更改 ### 日志记录 ``` #Log win: 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: " ``` 推荐: * 如果你要在函数内使用已声明的变量(声明为v0、v1、v2...),请将这些行放在_.local \_和变量声明(_const v0, 0x1_)之间。 * 如果你想在函数的代码中间插入日志代码: * 将已声明变量的数量增加2:例如,从_.locals 10_变为_.locals 12_。 * 新的变量应该是已声明变量的下一个数字(在这个例子中应该是_v10_和_v11_,记住它从v0开始)。 * 更改日志函数的代码,并使用_v10_和_v11_代替_v5_和_v1_。 ### Toasting 记得在函数开头的_.locals_数量上加3。 这段代码准备好了可以插入到**函数的中间**(根据需要**更改**变量的**数量**)。它将获取**this.o**的**值**,将其转换为**字符串**,然后用其值**制作**一个**toast**。 ``` 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 ```
☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * 你在一家**网络安全公司**工作吗?想要在HackTricks中看到你的**公司广告**吗?或者你想要**获取PEASS的最新版本或下载HackTricks的PDF**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! * 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品——[**The PEASS Family**](https://opensea.io/collection/the-peass-family) * 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com) * **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f) 或者 [**Telegram群组**](https://t.me/peass),或者**关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。** * **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**