9

Android 反编译、修改、重打包与签名

 3 years ago
source link: https://blog.andiedie.cn/posts/552a/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这篇博客主要介绍如何使用 Apktool、dex2jar、jd-gui等工具反编译 Android APP、修改源码、重新打包并签名。

1. 工具安装

1.1. Apktool

Apktool 主要用于反编译和重编译 APK 文件。

Windows 和 Linux 安装方法参照:官方指南

macOS 安装方法如下:

  • 右键保存启动脚本,命名为 apktool
  • 下载最新版本的 Apktool,命名为 apktool.jar
  • apktoolapktool.jar 移动到 /usr/local/bin 目录下
  • 使用 chmod +x apktoolchmod +x apktool.jar 添加运行权限
  • 在命令行直接运行命令 apktool 即可,安装完成

1.2. dex2jar

dex2jar 主要用于将 dex 文件转为 jar 文件

GitHub 下载最新版本,并解压。运行解压后目录下的 d2j-dex2jar.shd2j-dex2jar.bat 即可。

1.3. jd-gui

jd-gui 主要用来可视化 jar 文件。

GitHub 下载最新版本,并解压。运行解压后目录下的 JD-GUI 即可。

macOS 下注意

如果 jd-gui 无法打开,编辑 JD-GUI.app/Contents/MacOS/universalJavaApplicationStub.sh

exec "$JAVACMD" \
-cp "${JVMClassPath}" \
-Xdock:icon="${ResourcesFolder}/${CFBundleIconFile}" \
-Xdock:name="${CFBundleName}" \
## ----- 添加这两行 -----
--add-opens java.base/jdk.internal.loader=ALL-UNNAMED \
--add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED \
## --------------------
${JVMOptions:+$JVMOptions }\
${JVMDefaultOptions:+$JVMDefaultOptions }\
${JVMMainClass}\
${JVMArguments:+ $JVMArguments}

详见 issue

2. 查看源码

以小米投屏神器 APP 为例。

运行 d2j-dex2jar.sh 将 APK 中的 dex 文件转为 jar 文件:

$ ./d2j-dex2jar.sh mi.apk
dex2jar mi.apk -> ./mi-dex2jar.jar

打开 jd-gui,将 mi-dex2jar.jar 拖进去,即可看到反编译后的源码。

image-20190211172815715

3. 修改源码

这里以增加 Log 为修改源码的例子。

jd-gui 只能查看源码,但是无法修改。要修改源码,只能修改 smali 文件,它类似于汇编,但是要简单很多。

首先得使用 apktool 进行反编译:

apktool d mi.apk -o mi

这里将 mi.apk 进行反编译并将结果放到 mi 目录中。

首先找到需要添加 Log 的位置,建议在 jd-gui 中寻找,然后在 mi 目录中定位。

例如以下 classsmali 的对应关系

  • mi-dex2jar.jar!/com/xiaomi/mitv/phone/tvassistant/b/a.class
  • mi/smali/com/xiaomi/mitv/phone/tvassistant/b/a.smali

打开 a.classa.smali,首先看 java

public void a(int paramInt)
{
String str1 = String.valueOf(System.currentTimeMillis());
String str2 = a(String.valueOf(paramInt), this.b, str1);
new c(this.d, String.format("http://%s:6095/general?action=setVolum&volum=%d&ts=%s&sign=%s", new Object[] { this.a, Integer.valueOf(paramInt), str1, str2 }), new c.a()
{
public void a(int paramAnonymousInt, String paramAnonymousString) {}
}).d();
}

对应的 smali 文件内容,为了简单,我只提取了部分内容。

.method public a(I)V
# a 是方法,p0 = this
# a 接收一个参数, p1 = paramInt'

# 定义了 8 个寄存器
.locals 8

.prologue
.line 55
# 获取系统当前时间
invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
# 结果赋值给 v0
move-result-wide v0
# 调用 String.valueOf 方法,将 v0 转为字符串
invoke-static {v0, v1}, Ljava/lang/String;->valueOf(J)Ljava/lang/String;
# 结果赋值给 v0
move-result-object v0
# 到这一步
# String str1 = String.valueOf(System.currentTimeMillis());
# 执行完了

.line 57
# 调用 String.valueOf 方法 p1 转为字符串
invoke-static {p1}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
# 结果赋值给 v1
move-result-object v1
# 获取 this.b,也就是从 p1 中获取 b,并赋值给 v2
iget-object v2, p0, Lcom/xiaomi/mitv/phone/tvassistant/b/a;->b:Ljava/lang/String;
# 将 v1,v2,v0 作为参数调用方法 a,并传递 p0 作为 this
invoke-direct {p0, v1, v2, v0}, Lcom/xiaomi/mitv/phone/tvassistant/b/a;->a(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
# 将结果赋值给 v1
move-result-object v1
# 到这一步
# String str2 = a(String.valueOf(paramInt), this.b, str1);
# 执行完了

...

假设我们想要得知其中 this.b 的值,可以这样添加 Log:

.method public a(I)V
# 额外定义 4 个寄存器用于存储 TAG
.locals 12

.prologue
.line 55

# 设置初始化TAG
const-string v8, "AndiedieHack.currentTimeMillis"

const-string v9, "AndiedieHack.param"

const-string v10, "AndiedieHack.b"

const-string v11, "AndiedieHack.result"

invoke-static {}, Ljava/lang/System;->currentTimeMillis()J

move-result-wide v0

invoke-static {v0, v1}, Ljava/lang/String;->valueOf(J)Ljava/lang/String;

move-result-object v0
# 第一个 Log,使用 v8 作为 TAG,输出 v0 的值,即系统当前时间
invoke-static {v8, v0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

.line 57
invoke-static {p1}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;

move-result-object v1
# 第二个 Log,使用 v9 作为 TAG,输出 v1 的值
# v1 是 p1 的字符串形式,p1 是函数参数
invoke-static {v9, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

iget-object v2, p0, Lcom/xiaomi/mitv/phone/tvassistant/b/a;->b:Ljava/lang/String;
# 第三个 Log,使用 v10 作为 TAG,输出 v2 的值,即 this.b
invoke-static {v10, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

invoke-direct {p0, v1, v2, v0}, Lcom/xiaomi/mitv/phone/tvassistant/b/a;->a(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

move-result-object v1
# 第四个 Log,使用 v11 作为 TAG,输出 v1 的值,即 str2
invoke-static {v11, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

到这一步,源码修改完成。接下来进行重新打包。

3. 重新打包与签名

将修改后的内容重新打包为 APK:

apktool b mi -o unsigned.apk

打包之后的 unsigned.apk 是没有签名的,无法安装。

签名需要使用一个 keystore,可以直接使用 Android Studio 为我们生成的 debug 用 keystore。

位置在 用户目录/.android/debug.keystorealiasandroiddebugkey,密码是 android

签名命令:

jarsigner -keystore debug.keystore -signedjar signed.apk  unsigned.apk  androiddebugkey

输入密码即可。

在手机上安装 signed.apk,注意如果之前已经安装了投屏神器,需要先卸载,因为两者的签名不一致。

运行 APP,调整音量,可以看到以下 Log:

image-20190211175802805


Recommend

  • 98
    • www.cocoachina.com 6 years ago
    • Cache

    重组 IPA (打包再签名)

    一、IPA 的简单认识 首先有一个这样的 ipa 包文件: 直接修改文件后缀为: IPADev.zip , 然后解压,是这...

  • 65
    • www.cocoachina.com 6 years ago
    • Cache

    iOS自动签名打包(xcodebuild)

    iOS自动打包主要用xcodebuild命令, 在终端输入xcodebuild --help可以查看xcodebuild的参数。

  • 44
    • blog.poetries.top 6 years ago
    • Cache

    dll预编译提高webpack打包速度

    我们构建前端项目的时候,往往希望第三方库( vendors )和自己写的代码可以分开打包,因为第三方库往往不需要经常打包更新。对此 Webpack 的文档建议用 CommonsChunkPlugin 来单独打包第三方库...

  • 14
    • gameinstitute.qq.com 4 years ago
    • Cache

    APK资源修改与重签名打包

    APK资源修改与重签名打包 发表于2020-08-10 评论0 2.9k浏览 想免费获取内部独家PPT资料库?观...

  • 8
    • www.techug.com 3 years ago
    • Cache

    iOS 打包签名,你真的懂吗

    iOS 打包签名,你真的懂吗 2 导语:iOS 签名类型有 Development、AD-Hoc、In-House、App Store,而打包过程中又涉及到各种证书、Provision Profile、entitlements、CertificateSigningRequest、p12、A...

  • 8
    • segmentfault.com 3 years ago
    • Cache

    Maven: 让你的编译和打包自动化

    Maven: 让你的编译和打包自动化发布于 53 分钟前工具与资源中心帮助开发者更加高效的工作,提供围绕开发者全生命周期的工具与资源

  • 3
    • segmentfault.com 3 years ago
    • Cache

    Taro编译打包优化实践

    Taro编译打包优化实践发布于 11 月 26 日随着项目越来越大,编译的耗时也在默默地不断增加。无论是开发阶段还是生产集成,编译耗时都成为了一个不容小觑的痛点。

  • 7
    • www.androidchina.net 3 years ago
    • Cache

    Android 编译打包的那些疑问

    我们平时都是用 AS 进行打包,这就造成了很多盲点,我们就来看看究竟是咋回事,提前声明这篇文章讲的不全,只讲一些疑惑盲点,需要全面学习的,看老罗的吧,详细的令人发指。 我们从结果入手,看看打包完毕的apk里面是啥模样,把.apk 修改成 .zip...

  • 8
    • blog.51cto.com 2 years ago
    • Cache

    apktool 反编译 apk 修改后打包

    apktool 反编译 apk 修改后打包 原创 no_shutdown_ 2022-06-07 11:31:40

  • 7
    • www.fly63.com 2 years ago
    • Cache

    webpack打包时如何修改文件名

    在使用webpack进行项目打包的时候,我们可通过以下方式对不同类型的资源,进行文件名或文件路径的修改1、使用copy-webpack-plugin插件复制的文件,这个就是配置from和tone...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK