替换未加固 APK 中的特定字符串

同步来源:树洞剪藏 源站剪藏 ID:159 原文地址:https://mp.weixin.qq.com/s/bH1DMLxjkgxjTYCu1PqywA
替换未加固 APK 中的特定字符串
替换未加固 APK 中的特定字符串
原创
杨浦老苏
各种折腾
2024年11月06日 19:00 上海
各种折腾 聚沙成塔,集腋成裘 764篇原创内容
公众号 ,
本文纯粹是为了弥补缺憾,而做的技术可行性验证,但如果对你有所启发,老苏会觉得非常欣慰,不感兴趣的朋友可以忽略 前言 2023 的最后一天,老苏发了一篇《将群晖IPTV后台管理套件docker化》,原本是想着通过 docker ,让其他平台的用户也能使用,结果只存活了几个小时就挂了 当时只完成了后台部分,配套的 Android 客户端还需要用户自己用 MT 管理器来修改 apk 中的后台地址。修改方法网上能找到教程,不过对于大部分用户来说,还是有门槛的。 而原本的套件安装完成时,会自动生成对应后台地址的安卓客户端文件。原理老苏大概是明白的,只是因为文章被下架,所以也就没了心情。 最近有点闲,重新研究了一下 Apktool 的编译和反编译,为了不搞乱环境,老苏还是习惯性的封装成了镜像。 原理 其实原理不复杂,第一步将未加固的 apk 文件进行反编译,第二步进行字符串替换,第三步重新编译,第四步重新签名。 思路理顺了,能少走点弯路。一开始老苏忘记了给编译出来的 apk 重新签名,结果导致生成的 apk 不能安装。加入了 Apksigner 之后, Dockerfile 几乎又重新重写了一遍,白白浪费了好几个小时。 构建镜像
如果你不想自己构建,可以跳过,直接阅读下一章节 先要准备三个文件,分别是 Dockerfile 、 entrypoint.sh 和 generate-keystore.sh ,这三个文件放在同一个目录中,用于镜像的构建
文件都放在 Github 上,地址:https://github.com/wbsu2003/Dockerfile/tree/main/apktool generate-keystore.sh generate-keystore.sh 是用于生成签名证书的脚本
生成私钥
openssl genrsa -out my-release-key.pem 2048
生成自签名证书
openssl req -new -x509 -key my-release-key.pem -out my-release-cert.pem -days 365 -subj "/CN=MyApp/C=US"
将私钥和证书合并为 PKCS#12 文件
openssl pkcs12 - export -out " $KEYSTORE_PATH " -inkey my-release-key.pem - in my-release-cert.pem -name "my-key-alias" -passout pass: " $KEYSTORE_PASSWORD "
检查生成的 keystore 文件
if [ -f $KEYSTORE_PATH ]; then echo "Keystore successfully created at $KEYSTORE_PATH " else echo "Failed to create keystore." fi
清理临时文件
rm my-release-key.pem my-release-cert.pem
entrypoint.sh entrypoint.sh 则完成了整个原理中描述的的 4 步流程
!/bin/bash
生成证书
if [ "$GENERATE_KEYSTORE" = "true" ]; then echo "生成 keystore..." if [ -z "$KEYSTORE_PASSWORD" ]; then echo "请设置 KEYSTORE_PASSWORD 环境变量。" exit 1 fi /usr/local/bin/generate-keystore.sh fi
检查 keystore 文件是否存在
if [ ! -f "$KEYSTORE_PATH" ]; then echo "Error: Keystore file $KEYSTORE_PATH does not exist." exit 1 else echo "Keystore file found: $KEYSTORE_PATH" fi
检查 apksigner 是否可用
if ! command -v apksigner &> /dev/null; then echo "apksigner 未找到,请检查 Android SDK 是否正确安装。" exit 1 fi
检查环境变量是否设置
if [[ -z "$APP_URL" || -z "$NEW_APP_URL" || -z "$ORIGINAL_APK_NAME" ]]; then echo "请设置环境变量 APP_URL、NEW_APP_URL 和 ORIGINAL_APK_NAME" exit 1 fi
定义输入和输出路径
INPUT_DIR="/app/input" OUTPUT_DIR="/app/output" ORIGINAL_APK="$INPUT_DIR/$ORIGINAL_APK_NAME"
创建 decompiled 目录
DECOMPILED_DIR="/app/decompiled" if [ -d "$DECOMPILED_DIR" ]; then rm -rf "$DECOMPILED_DIR" fi
提取原 APK 的签名信息
SIGNATURE_INFO=$(apksigner verify --print-signature "$ORIGINAL_APK") echo "原 APK 签名信息:" echo "$SIGNATURE_INFO"
反编译 APK
apktool d "$ORIGINAL_APK" -o "$DECOMPILED_DIR"
替换字符串
find "$DECOMPILED_DIR" -type f -exec sed -i "s|$APP_URL|$NEW_APP_URL|g" {} +
重新编译 APK
apktool b "$DECOMPILED_DIR" -o "$OUTPUT_DIR/${ORIGINAL_APK_NAME%.apk}_new.apk"
使用 PKCS #12 keystore 对新 APK 进行签名
if apksigner sign --ks "$KEYSTORE_PATH" --ks-type PKCS12 --ks-pass pass:"$KEYSTORE_PASSWORD" --key-pass pass:"$KEYSTORE_PASSWORD" --out "$OUTPUT_DIR/${ORIGINAL_APK_NAME%.apk}_new_signed.apk" "$OUTPUT_DIR/${ORIGINAL_APK_NAME%.apk}_new.apk"; then echo "新 APK 已生成并输出到 $OUTPUT_DIR/${ORIGINAL_APK_NAME%.apk}_new_signed.apk" else echo "签名失败,未生成新 APK。" exit 1 fi
Dockerfile Dockerfile 完成整个运行环境的搭建
使用基础镜像
FROM openjdk: 8 -jdk-slim
安装必要的工具
RUN apt-get update && apt-get install -y
wget
unzip
openssl
&& apt-get clean
下载并安装 Android SDK
RUN wget -q https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip -O sdk-tools.zip
&& unzip sdk-tools.zip -d /android-sdk
&& rm sdk-tools.zip
设置环境变量
ENV ANDROID_SDK_ROOT=/android-sdk ENV PATH=$PATH:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/build-tools/ 29.0 . 3
设置 keystore 别名和密码
ENV GENERATE_KEYSTORE= "true" ENV KEY_ALIAS= "my-key-alias" ENV KEYSTORE_PASSWORD= "123456" ENV KEYSTORE_PATH= "/app/my-release-key.keystore"
安装 Android SDK Build Tools 和 Platform Tools
RUN yes | /android-sdk/tools/bin/sdkmanager --licenses
&& /android-sdk/tools/bin/sdkmanager "build-tools;29.0.3" "platform-tools"
&& apt-get remove --purge -y wget unzip
&& apt-get autoremove -y
&& rm -rf /var/lib/apt/lists/*
将 apktool.jar 复制到容器中
COPY apktool_2.10.0.jar /usr/local/bin/apktool.jar
在线下载 apktool
#RUN wget -q https://github.com/iBotPeaches/Apktool/releases/download/v2.10.0/apktool_2.10.0.jar -O /usr/local/bin/apktool.jar \
RUN apt-get update && apt-get install -y curl
&& curl -L -o /usr/ local /bin/apktool.jar https://github.com/iBotPeaches/Apktool/releases/download/v2.10.0/apktool_2.10.0.jar
&& echo -e '#!/bin/sh
exec java -jar /usr/local/bin/apktool.jar "$@"' > /usr/ local /bin/apktool
&& chmod +x /usr/ local /bin/apktool
设置工作目录
WORKDIR /app
复制证书生成脚本
COPY generate-keystore.sh /usr/ local /bin/generate-keystore.sh RUN chmod +x /usr/ local /bin/generate-keystore.sh
复制 entrypoint 脚本
COPY entrypoint.sh /usr/ local /bin/entrypoint.sh RUN chmod +x /usr/ local /bin/entrypoint.sh
设置默认命令
ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]
构建镜像和容器运行的基本命令如下👇
新建文件夹 apktool
mkdir -p apktool
进入 apktool 目录
cd apktool
将 Dockerfile、entrypoint.sh 和 generate-keystore.sh 放入目录
构建镜像
docker build -t wbsu2003/apktool:v1 .
使用
这个镜像是命令行运行的,没有 Web 界面 还是以在群晖上运行为例 在 docker 文件夹中,创建一个新文件夹 apktool ,并在其中建两个子文件夹 input 和 output
文件夹 装载路径 说明 docker/apktool/input /app/input 存放待处理的 apk 文件 docker/apktool/output /app/output 存放处理之后的 apk 文件
新建文件夹 apktool 和 子目录
mkdir -p /volume1/docker/apktool/{input,output}
进入 apktool 目录
cd /volume1/docker/apktool
将需要处理的 apk 文件放入到 input 目录中
示例文件老苏放在了:https://github.com/wbsu2003/Dockerfile/raw/refs/heads/main/apktool/QHTV.apk,用手机安装会提示风险,可能是因为签名是 V1 的缘故; 现在可以在当前目录中执行下面的命令了
运行容器(全部参数)
docker run --rm
-v $( pwd )/input:/app/input
-v $( pwd )/output:/app/output
-e APP_URL= "http://192.168.0.199/iptv"
-e NEW_APP_URL= "http://192.168.0.197:3332"
-e ORIGINAL_APK_NAME= "QHTV.apk"
-e GENERATE_KEYSTORE= "true"
-e KEYSTORE_PASSWORD= "123456"
-e KEYSTORE_PATH= "/app/my-release-key.keystore"
wbsu2003/apktool
第一次运行,会需要下载镜像
可变 值 APP_URL 指程序中原来的后台地址 NEW_APP_URL 指用于替换的新的后台地址 ORIGINAL_APK_NAME 指需要替换的 apk 的文件名,该文件应该被放在 input 目录中 GENERATE_KEYSTORE 是否要生成证书,默认为 true KEYSTORE_PASSWORD 用于保护 keystore 的密码,脚本会使用这个密码生成和访问 keystore KEYSTORE_PATH 证书的路径,默认为 /app/my-release-key.keystore ,不建议改
前 3 个为必填项,后 3 个为可选项 当然也可以省掉 KEYSTORE 相关的三个变量,因为老苏在 Dockerfile 中赋了默认值
运行容器(必要参数)
docker run --rm
-v $( pwd )/input:/app/input
-v $( pwd )/output:/app/output
-e APP_URL= "http://192.168.0.199/iptv"
-e NEW_APP_URL= "http://192.168.0.197:3332"
-e ORIGINAL_APK_NAME= "QHTV.apk"
wbsu2003/apktool
但 GENERATE_KEYSTORE 如果赋值为 false ,是不会往下执行的
运行容器(错误示例)
docker run --rm
-v $( pwd )/input:/app/input
-v $( pwd )/output:/app/output
-e APP_URL= "http://192.168.0.199/iptv"
-e NEW_APP_URL= "http://192.168.0.197:3332"
-e ORIGINAL_APK_NAME= "QHTV.apk"
-e GENERATE_KEYSTORE= "false"
wbsu2003/apktool
如果没有出错的话 可以在 output 目录看到两个文件 其中 QHTV_new_signed.apk 就是我们用来安装的文件,它的签名状态已经改为了 V1+V2+V3 其他 目前老苏发现的问题:
如果你先安装了 QHTV.apk 文件,再安装 QHTV_new_signed.apk 会提示安装不了,必须先卸载 QHTV.apk 才行,这是因为签名文件变了。老苏采用的是动态生成签名,所以每次执行,签名都是不一样的;
生成的 QHTV_new_signed.apk 在 HarmonyOS 2.0.0 和电视盒子上运行正常,但是在另一台 Android 14 上,则卡在首界面,后台授权中查不到上线信息,因此也就无法授权,这个已经超出了本文的范围; 另外请不要问关于 《将群晖IPTV后台管理套件docker化》的问题,当时就是为了不想做技术支持,专门设置成了付费文章,谢谢~ 参考文档
Apktool | Apktool 地址:https://apktool.org/ iBotPeaches/Apktool: A tool for reverse engineering Android apk files 地址:https://github.com/iBotPeaches/Apktool 群晖NAS安装IPTV管理系统套件 图文教程 – WANG 地址:https://www.oureiq.top:8812/2023/01/29/群晖nas安装iptv管理系统套件-图文教程/
各种折腾 聚沙成塔,集腋成裘 764篇原创内容
公众号 , @所有人:写文不易,如果你都看到了这里,请点个 赞 和 在看 ,分享给更多的朋友;为确保你能收到每一篇文章,请主页右上角设置星标。
预览时标签不可点
群晖 668 docker 675 工具 33 字符串 1
群晖 · 目录
上一篇 Docker可视化管理面板DPanel的安装 下一篇 IPTV直播源自动检测和更新工具
阅读原文 修改于 2024年12月01日
关闭
更多
小程序 广告
搜索「undefined」网络结果
微信扫一扫 关注该公众号
当前内容可能存在未经审核的第三方商业营销信息,请确认是否继续访问。
继续访问 取消 微信公众平台广告规范指引
: , 。
视频 小程序 赞 ,轻点两下取消赞 在看 ,轻点两下取消在看 分享 留言 收藏