安卓逆向 - 使用ApkTool进行逆向
ApkTool简介
APKTool 是一种常用的逆向工程工具,专门用于处理 Android APK 文件(Android应用安装包)。它的主要功能是将 APK 文件进行反编译(Decompile)和重新打包(Recompile),以便开发者或研究人员分析和修改 Android 应用程序。
ApkTool工作原理
-
解包过程:
- APKTool 使用 aapt(Android Asset Packaging Tool)解析 APK 的资源和 XML 文件。
- 将 APK 文件的内容分解为:
- AndroidManifest.xml:包含应用的基本配置信息。
- res/:应用的界面资源(如图片、布局文件)。
- smali/:反编译后的代码。
-
重新打包过程:
- APKTool 会将修改后的资源和代码重新组合为 APK 文件,保持原始结构。
ApkTool常用命令
apktool --version (查看版本)
apktool d app.apk -o output_folder (反编译APK :d表示解包)
apktool b output_folder -o new_app.apk (重新打包apk: b 表示打包)
apktool if app.apk (仅解包资源文件: 用于解包需要特定资源框架的应用)
apktool d app.apk -p custom_framework_path (指定系统框架: 对于依赖特定系统框架的应用,必须先安装相关框架文件)
apktool d app.apk --force (强制解包: 如果同名目录已经存在,默认情况下 APKTool 会提示错误,使用此选项可以覆盖输出)
apktool b output_folder --ignore-res (忽略错误继续打包: 用于资源文件可能损坏但希望完成打包的场景)
apktool b output_folder --copy-original (添加自定义配置: 用于保留未修改的资源文件或代码部分)
apktool b output_folder --use-aapt2 (自定义压缩选项: 适用于需要支持新版 Android 特性的场景)
apktool clean (清除缓存)
ApkTool解包后目录解析
- assets(存放应用的静态资源文件,这里的文件通常是开发者自己添加的静态资源)
- lib (存放应用的本地库文件,以 .so 结尾的文件,通常用 C/C++ 编写并通过 JNI 调用,按照 CPU 架构分为不同文件夹)
- META-INF (存放签名相关的信息,MANIFEST.MF:描述文件内容的元数据,CERT.RSA 和 CERT.SF:APK 的数字签名和校验文件)
- original (通常存放反编译过程中的临时文件,或者一些特殊框架信息, 如果为空,说明当前解包的 APK 不依赖额外框架)
- res (存放资源文件(资源文件夹),)
- smali (存放反编译后的代码,每个类一个 .smali 文件,文件内容是 Android 的中间语言)
- unknown (存放 APKTool 无法识别的文件或特殊资源)
- AndroidManifest.xml (应用的核心配置文件,应用的包名、权限、组件(Activity、Service、Receiver 等),启动 Activity、权限声明、Intent 过滤器)
- apktool.yml (APKTool 的配置文件,记录解包过程中的元信息,例如版本号、框架依赖,配置项用于控制重新打包时的行为)
实战
编写app,功能是需要邀请码才能进行注册,代码参考《Android 软件安全权威指南》
要点:要编译release的,不然代码不全
对apk进行解包
查看解包后的文件
随便输入注册信息,提示 Registration failed!
分析smail语法,在MainActivity$1.smali 中
.class Lcom/example/crame0201/MainActivity$1;
.super Ljava/lang/Object;
.source "MainActivity.java"
# interfaces
.implements Landroid/view/View$OnClickListener;
# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
value = Lcom/example/crame0201/MainActivity;->onCreate(Landroid/os/Bundle;)V
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x0
name = null
.end annotation
# instance fields
.field final synthetic this$0:Lcom/example/crame0201/MainActivity;
# direct methods
.method constructor <init>(Lcom/example/crame0201/MainActivity;)V
.locals 0
.annotation system Ldalvik/annotation/MethodParameters;
accessFlags = {
0x8010
}
names = {
null
}
.end annotation
.line 70
iput-object p1, p0, Lcom/example/crame0201/MainActivity$1;->this$0:Lcom/example/crame0201/MainActivity;
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public onClick(Landroid/view/View;)V
.locals 2
.line 73
iget-object p1, p0, Lcom/example/crame0201/MainActivity$1;->this$0:Lcom/example/crame0201/MainActivity;
invoke-static {p1}, Lcom/example/crame0201/MainActivity;->-$$Nest$fgetedit_userName(Lcom/example/crame0201/MainActivity;)Landroid/widget/EditText;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/String;->trim()Ljava/lang/String;
move-result-object v0
iget-object v1, p0, Lcom/example/crame0201/MainActivity$1;->this$0:Lcom/example/crame0201/MainActivity;
invoke-static {v1}, Lcom/example/crame0201/MainActivity;->-$$Nest$fgetedit_sn(Lcom/example/crame0201/MainActivity;)Landroid/widget/EditText;
move-result-object v1
.line 74
invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/String;->trim()Ljava/lang/String;
move-result-object v1
.line 73
invoke-static {p1, v0, v1}, Lcom/example/crame0201/MainActivity;->-$$Nest$mcheckSN(Lcom/example/crame0201/MainActivity;Ljava/lang/String;Ljava/lang/String;)Z
move-result p1
const/4 v0, 0x0
if-eqz p1, :cond_0
.line 75
iget-object p1, p0, Lcom/example/crame0201/MainActivity$1;->this$0:Lcom/example/crame0201/MainActivity;
sget v1, Lcom/example/crame0201/R$string;->unsuccessed:I
invoke-static {p1, v1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object p1
.line 76
invoke-virtual {p1}, Landroid/widget/Toast;->show()V
goto :goto_0
.line 78
:cond_0
iget-object p1, p0, Lcom/example/crame0201/MainActivity$1;->this$0:Lcom/example/crame0201/MainActivity;
sget v1, Lcom/example/crame0201/R$string;->successed:I
invoke-static {p1, v1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;
move-result-object p1
.line 79
invoke-virtual {p1}, Landroid/widget/Toast;->show()V
.line 80
iget-object p1, p0, Lcom/example/crame0201/MainActivity$1;->this$0:Lcom/example/crame0201/MainActivity;
invoke-static {p1}, Lcom/example/crame0201/MainActivity;->-$$Nest$fgetbtn_register(Lcom/example/crame0201/MainActivity;)Landroid/widget/Button;
move-result-object p1
invoke-virtual {p1, v0}, Landroid/widget/Button;->setEnabled(Z)V
.line 81
iget-object p1, p0, Lcom/example/crame0201/MainActivity$1;->this$0:Lcom/example/crame0201/MainActivity;
sget v0, Lcom/example/crame0201/R$string;->register:I
invoke-virtual {p1, v0}, Lcom/example/crame0201/MainActivity;->setTitle(I)V
:goto_0
return-void
.end method
核心的验证逻辑在下面的这段代码中
1、作用:调用 checkSN 方法。
2、参数说明:
p1:可能是当前 Activity 的实例。
v0:第一个字符串(通常是用户名,edit_userName 的值)。
v1:第二个字符串(通常是注册码,edit_sn 的值)。
返回值:该方法返回一个布尔值(true 或 false),结果被存储在寄存器 p1 中。
invoke-static {p1, v0, v1}, Lcom/example/crame0201/MainActivity;->-$$Nest$mcheckSN(Lcom/example/crame0201/MainActivity;Ljava/lang/String;Ljava/lang/String;)Z
move-result p1
if-nez p1, :cond_0
所以修改的就是 if-nez p1, :cond_0
这个逻辑,让它为false
if-eqz p1, :cond_0
重新打包apk,并使用编写apk时生成的as签名加上
java -jar apktool_2.10.0.jar b app-release (打包)
apksigner sign --ks keys_stores.jks --out a.apk app-release.apk (加上签名,要输入签名时填入的密码)
版权所有:Ljierui'Blog
文章标题:安卓逆向 - 使用ApkTool进行逆向
文章链接:https://fuckdog.org/post-55.html
本站文章均为原创,未经授权请勿用于任何商业用途
文章标题:安卓逆向 - 使用ApkTool进行逆向
文章链接:https://fuckdog.org/post-55.html
本站文章均为原创,未经授权请勿用于任何商业用途