反编译APK替换中文文案为其他语言

反编译安卓应用以实现文案语言转换的工程实践。

Views: 290
1 0
Read Time:2 Minute, 48 Second

在近期某个项目中,接收到一个比较奇葩的需求,需要在不修改源码的情况下替换所有的文案为俄文。

接到该需求时,第一反应便是需要修改资源包,通常而言每个应用的所有文本内容都会放到res目录下对应的资源文件夹内,如下所示:

values-zh-rCN //中国大陆地区
values-zh-rHK //中国香港地区
values-zh-rTW //中国台湾地区

正向思维来看,我们需要新增对应地区的语言资源文件夹,将相应的文案进行对应翻译,放入该文件夹,之后重新进行编译打包,再进行签名,后续进行安装就能看到效果了。

以上建立在我们拥有源码工程及对应的签名文件的情况下,如果没有源码去实现这个需求,就只能通过反编译的手段来实现了。

此时我们需要借助apktool这个工具,apktool 是一个非常常用的Android 逆向工程工具,主要用于反编译 APK(Android 应用安装包),以便查看、修改、重新打包和调试应用资源及 Smali 代码。它常被用于分析 APK 的结构、修改界面文字、多语言适配、甚至研究某些应用的实现逻辑。

总的来说,要实现这个目的需要经历如下步骤:

1.首先确定需要进行文案替换的应用具体是哪一个,此时我们可以先打开该应用,使其位于前台,再通过如下命令确认位于前台的应用所对应的包名:

adb shell dumpsys activity activities | grep mResumedActivity

//获取当前出于Resume状态的应用
pissarropro:/ $ dumpsys activity activities | grep mResumedActivity
    mResumedActivity: ActivityRecord{dc6c83a u0 com.android.chrome/com.google.android.apps.chrome.Main t8188}
pissarropro:/ $

2.根据前述步骤拿到的包名,找到系统内对应的APK路径,通过ADB工具拉取该APK

//找到APK对应的路径
pissarropro:/ $ pm list packages -f | grep "com.android.chrome"
package:/data/app/~~rf1cFFBb7xWuaYGMDZ2S_w==/com.android.chrome-CarZF9ibWgDes2CEjGjyXA==/base.apk=com.android.chrome
pissarropro:/ $

//拉取该APK
adb pull /data/app/~~rf1cFFBb7xWuaYGMDZ2S_w==/com.android.chrome-CarZF9ibWgDes2CEjGjyXA==/base.apk

3.通过apk tool对拉取出来的APK进行反编译:

apktool d CarControl.apk -o OUTPUT

如果在执行上述命令的过程中出现如下错误:

Can't find framework resources for package of id: 2. You must install proper framework files

出现该错误的原因是因为APK本身依赖了一些系统资源,APKTool在解析这些资源时,找不到对应的framework资源文件,此时我们就需要从系统中找到这些资源文件并进行安装,以便APKTool进行解析。

通常而言,framework的资源文件位于framework-res.apk内,我们可以通过如下命令进行拉取:

adb pull /system/framework/framework-res.apk

对于不同的厂商而言,每个厂商还有自己定制的framework资源文件,这些资源文件也需要拉取:

//华为
adb pull /system/framework/hwext-res.apk
//小米
adb pull /system/framework/miui-framework-res.apk

拿到上述资源后,我们再进行安装:

apktool if framework-res.apk
apktool if framework-res-ext.apk

安装完成之后我们再进行反编译,得到如下内容:

AndroidManifest.xml
apktool.yml
assets/
original/
res/
unknown/

之后我们找到res/values-zh-rCN/strings.xml文件,将该文件内的中文内容进行翻译修改,直接将其修改为对应的语言文本即可。

修改完成之后,我们需要使用apktool重新进行打包,使用如下命令进行打包:

Apktool b OUTPUT -o  CarControl_New.apk

这样我们就得到了新的APK,接下来我们需要注意,如果直接重新安装应用,大概率是会安装失败的,因为我们并没有原始的签名,所以这里只能是将新生成的APK进行推入。之后我们重新启动应用,就可以看到效果了。

更进一步,我们来了解一下apktool的具体工作原理,apktool其实是一个工具的组合,可以对APK进行解包与打包操作。在解包操作中,apktool会进行如下步骤:

  1. 解压APK文件:将*.apk解压为文件结构,classe.dex、resources.arsc、AndroidManifest.xml以及res资源等
  2. 加载framework资源:如果应用依赖系统资源(@android: 前缀的),apktool 会加载之前通过 apktool if framework-res.apk 安装的系统资源包
  3. 反编译二进制资源:将二进制的 resources.arsc 和 AndroidManifest.xml 通过 aapt的逆过程转为可读 XML
  4. 反汇编dex字节码:使用 baksmali 将 classes.dex 转换为 .smali 文件
  5. 输出结果:最终生成一个结构化目录,可以直接编辑

在经过上述步骤后,我们可以拿到AndroidManifest.xml,修改权限申请、入口Activity等内容;同时也拿到了res资源文件,我们可以修改对应的资源文件,实现不同的文案显示、颜色样式等;更进一步我们可以直接修改smali文件,实现逻辑修改、去广告等操作。

后记

在解决该问题的过程中,除了apktool,我们还可以用APKEditor。相对于apktool,APKEditor更适合这种简单的文案修改工作,使用起来也会更得心应手。

除了使用这种反编译的方式修改APK资源,我们还可以用Overlay的方法实现该需求,这种方式更为合理,对系统的侵入修改会更小。对于Overlay的具体原理可以参考我的另一篇文章,此处不做过多赘述,这里只列举一下大概的流程:

1.新建APK,无需Activity、Service等内容,只需将values-zh-rCN/strings.xml内容放置于res目录

2.配置AndroidManifest.xml,内容可参考如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.seres.settings.overlay">

    <overlay
        android:targetPackage="com.android.settings"
        android:priority="999"
        android:isStatic="true" />
</manifest>

3.打包APK,无Root情况下需要同样的系统签名;Root情况下可以手动推入系统

4.使用adb shell cmd overlay list查看是否生效:

franzkafka@franzkafka:~$ adb shell cmd overlay list
com.android.uwb.resources
[x] com.android.uwb.resources.cuttlefish.overlay

com.android.connectivity.resources
[x] com.android.connectivity.resources.cuttlefish.overlay

android
[x] android.cuttlefish.overlay
[x] android.cuttlefish.phone.overlay
[ ] com.android.internal.display.cutout.emulation.corner
[ ] com.android.internal.display.cutout.emulation.double
[ ] com.android.internal.systemui.navbar.gestural_wide_back
[ ] com.android.internal.display.cutout.emulation.hole
[ ] com.android.internal.display.cutout.emulation.tall
[ ] com.android.internal.systemui.navbar.threebutton
[ ] com.android.internal.systemui.navbar.gestural_extra_wide_back
[ ] com.android.theme.font.notoserifsource
[ ] com.android.internal.display.cutout.emulation.waterfall
[ ] com.android.internal.systemui.navbar.transparent
[ ] com.android.role.notes.enabled
[ ] com.android.internal.systemui.navbar.gestural
[ ] com.android.internal.systemui.navbar.gestural_narrow_back
[x] com.android.systemui:neutral
[x] com.android.systemui:accent
[x] com.android.systemui:dynamic

com.android.nfc
[x] com.android.nfc.cuttlefish.overlay

com.android.providers.settings
[x] com.android.providers.settings.cuttlefish.overlay

com.android.wifi.resources
[x] com.android.wifi.resources.cf

com.android.networkstack.tethering
[x] com.android.networkstack.tethering.cuttlefishoverlay

com.android.systemui
[x] com.android.systemui.auto_generated_rro_vendor__
Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
FranzKafka95
FranzKafka95

极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。

Articles: 97

Leave a Reply

Your email address will not be published. Required fields are marked *

en_USEN