手把手教你逆向高德车机7.5.0制作共存版
前言
很多车机上自带的高德都比较老,而且不允许更新和卸载。
这就需要一个制作另一个高德
。
在安卓上,所有app并不是根据名字来区分唯一性的,而是包名package
。
也就是说我们把app安装包(apk)里的package设置成一个新的即可达到成功安装与官方版并存。
那怎么改apk呢?
这就用到了反编译也叫做逆向工程技术。
正好借此契机,大家跟着我学习一下安卓的反逆向工程技术,以后自己给软件换个图标、改个名称、破解个vip起步手到擒来。
前提工作
电脑下载并安装好一下几个软件
apktool
apktool用于对apk进行反编译及重新打包的工具
官方地址:https://apktool.org
这里建议配置成环境变量,方便后边使用(方然你觉得麻烦 不配置也行 非必须)
打开终端,输入apktool -version
出现版本号,既为成功
C:\Users\Administrator> apktool -version
2.9.3
Press any key to continue . . .
dex-tools
apktool反编译后,安卓的所有代码逻辑文件都在编译文件夹里的classes.dex
中。
此文件原本为java或kotlin所编写,后被打包加密而成,很难直接读取里边的代码逻辑。
dex-tools工具则用于将此dex文件转换为可读的jar(java)格式。
官方地址:https://github.com/pxb1988/dex2jar
这里建议配置成环境变量,方便后边使用(方然你觉得麻烦 不配置也行 非必须)
打开终端,输入d2j-dex2jar
出现以下,既为成功
C:\Users\Administrator> d2j-dex2jar
d2j-dex2jar -- convert dex to jar
usage: d2j-dex2jar [options] <file0> [file1 ... fileN]
options:
--skip-exceptions skip-exceptions
-d,--debug-info translate debug info
-e,--exception-file <file> detail exception file, default is $current_dir/[fi
le-name]-error.zip
-f,--force force overwrite
-h,--help Print this help message
-n,--not-handle-exception not handle any exceptions thrown by dex2jar
-nc,--no-code
-o,--output <out-jar-file> output .jar file, default is $current_dir/[file-na
me]-dex2jar.jar
-os,--optmize-synchronized optimize-synchronized
-p,--print-ir print ir to System.out
-r,--reuse-reg reuse register while generate java .class file
-s same with --topological-sort/-ts
-ts,--topological-sort sort block by topological, that will generate more
readable code, default enabled
version: reader-v2.4, translator-v2.4, ir-v2.4
jd-gui
用于读取dex-tools生成jar文件的工具。
以便于分析安卓的代码逻辑。
官方地址:https://github.com/java-decompiler/jd-gui
如果是widnows,下载对应版本即可
开始反编译
去官网下载车机版本的高德,为方便好记 我将其改名为 gaode.apk
对其执行反编译的命令 apktool d .\gaode.apk
D:\app> apktool d .\gaode.apk
I: Using Apktool 2.9.3 on gaode.apk
I: Loading resource table...
I: Decoding file-resources...
I: Loading resource table from file: C:\Users\Administrator\AppData\Local\apktool\framework\1.apk
S: Could not decode file, replacing by FALSE value: anim/abc_slide_in_top.xml
S: Could not decode file, replacing by FALSE value: anim/activity_enter.xml
S: Could not decode file, replacing by FALSE value: anim/abc_slide_out_bottom.xml
S: Could not decode file, replacing by FALSE value: anim/abc_slide_out_top.xml
S: Could not decode file, replacing by FALSE value: anim/activity_exit.xml
S: Could not decode file, replacing by FALSE value: anim/abc_slide_in_bottom.xml
S: Could not decode file, replacing by FALSE value: anim/abc_fade_in.xml
S: Could not decode file, replacing by FALSE value: anim/abc_fade_out.xml
I: Decoding values */* XMLs...
I: Decoding AndroidManifest.xml with resources...
I: Regular manifest package...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
Press any key to continue . . .
如果你要是不修改反编译的代码 只是替换下图标静态资源啥的,可以apktool -r d .\gaode.apk
进行反编译,这样就不会报错了,但是反编译的代码内容是无法修改的
失败
看到一堆Could not decode file
的报错提示了吗?
原因是因为反编译的时候去提取它(反编译工具apktool)认为一些必要资源的时候 没找到而报错 既资源文件误报错。
这会导致我们在回编打包的时候报错,不信你试试,在不做任何修改情况下尝试一下在打包回去 apktool b .\gaode\
D:\app> apktool b .\gaode\
I: Using Apktool 2.9.3
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
W: D:\app\.\gaode\res\values\anims.xml:3: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml:4: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml:5: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml:6: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml:7: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml:8: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml:9: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml:10: error: invalid value for type 'anim'. Expected a reference.
W: D:\app\.\gaode\res\values\anims.xml: error: file failed to compile.
brut.androlib.exceptions.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\ADMINI~1\AppData\Local\Temp\brut_util_Jar_12222067369825036268574268945791329902.tmp, compile, --dir, D:\app\.\gaode\res, --legacy, -o, D:\app\.\gaode\build\resources.zip]
Press any key to continue . . .
看提示大概也能明白 在anims.xml
引用的这些资源不存在,刚好对应到反编译时候提示的问题。
那我们将报错的地方注释即可(因为这些资源在项目中真的没有用到,否则可不能随意注释)。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- <item type="anim" name="abc_fade_in">false</item>
<item type="anim" name="abc_fade_out">false</item>
<item type="anim" name="abc_slide_in_bottom">false</item>
<item type="anim" name="abc_slide_in_top">false</item>
<item type="anim" name="abc_slide_out_bottom">false</item>
<item type="anim" name="abc_slide_out_top">false</item>
<item type="anim" name="activity_enter">false</item>
<item type="anim" name="activity_exit">false</item> -->
</resources>
失败
再次打包,依然报错
D:\app> apktool b .\gaode\
I: Using Apktool 2.9.3
I: Checking whether sources has changed...
I: Checking whether resources has changed...
I: Building resources...
W: D:\app\.\gaode\res\values\public.xml:3: error: no definition for declared symbol 'com.autonavi.amapauto:anim/abc_fade_in'.
W: D:\app\.\gaode\res\values\public.xml:4: error: no definition for declared symbol 'com.autonavi.amapauto:anim/abc_fade_out'.
W: D:\app\.\gaode\res\values\public.xml:9: error: no definition for declared symbol 'com.autonavi.amapauto:anim/abc_slide_in_bottom'.
W: D:\app\.\gaode\res\values\public.xml:10: error: no definition for declared symbol 'com.autonavi.amapauto:anim/abc_slide_in_top'.
W: D:\app\.\gaode\res\values\public.xml:11: error: no definition for declared symbol 'com.autonavi.amapauto:anim/abc_slide_out_bottom'.
W: D:\app\.\gaode\res\values\public.xml:12: error: no definition for declared symbol 'com.autonavi.amapauto:anim/abc_slide_out_top'.
W: D:\app\.\gaode\res\values\public.xml:15: error: no definition for declared symbol 'com.autonavi.amapauto:anim/activity_enter'.
W: D:\app\.\gaode\res\values\public.xml:16: error: no definition for declared symbol 'com.autonavi.amapauto:anim/activity_exit'.
W: error: failed linking references.
brut.androlib.exceptions.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\ADMINI~1\AppData\Local\Temp\brut_util_Jar_73040750885300977133450964023895867926.tmp, link, -o, C:\Users\ADMINI~1\AppData\Local\Temp\APKTOOL12512811945052100666.tmp, --package-id, 127, --min-sdk-version, 15, --target-sdk-version, 23, --version-code, 21000001, --version-name, 7.5.0.600064, --no-auto-version, --no-version-vectors, --no-version-transitions, --no-resource-deduping, --allow-reserved-package-id, --no-compile-sdk-metadata, --warn-manifest-validation, -e, C:\Users\ADMINI~1\AppData\Local\Temp\APKTOOL12300926364868950439.tmp, -0, arsc, -I, C:\Users\Administrator\AppData\Local\apktool\framework\1.apk, --manifest, D:\app\.\gaode\AndroidManifest.xml, D:\app\.\gaode\build\resources.zip]
Press any key to continue . . .
说明这些不存在的文件, 不但anims.xml
用了,public.xml
也用了。
那就好办了,同上,我们将其对应使用的到的地方注释即可
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- <public type="anim" name="abc_fade_in" id="0x7f010000" />
<public type="anim" name="abc_fade_out" id="0x7f010001" /> -->
<public type="anim" name="abc_grow_fade_in_from_bottom" id="0x7f010002" />
<public type="anim" name="abc_popup_enter" id="0x7f010003" />
<public type="anim" name="abc_popup_exit" id="0x7f010004" />
<public type="anim" name="abc_shrink_fade_out_from_bottom" id="0x7f010005" />
<!-- <public type="anim" name="abc_slide_in_bottom" id="0x7f010006" />
<public type="anim" name="abc_slide_in_top" id="0x7f010007" />
<public type="anim" name="abc_slide_out_bottom" id="0x7f010008" />
<public type="anim" name="abc_slide_out_top" id="0x7f010009" /> -->
<public type="anim" name="abc_tooltip_enter" id="0x7f01000a" />
<public type="anim" name="abc_tooltip_exit" id="0x7f01000b" />
<!-- <public type="anim" name="activity_enter" id="0x7f01000c" />
<public type="anim" name="activity_exit" id="0x7f01000d" /> -->
<public type="anim" name="btn_checkbox_to_checked_box_inner_merged_animation" id="0x7f01000e" />
<public type="anim" name="btn_checkbox_to_checked_box_outer_merged_animation" id="0x7f01000f" />
...
成功
再次尝试打包,即可看到成功了
D:\app> apktool b .\gaode\
I: Using Apktool 2.9.3
I: Checking whether sources has changed...
I: Checking whether resources has changed...
I: Building resources...
I: Copying libs... (/lib)
I: Copying libs... (/kotlin)
I: Building apk file...
I: Copying unknown files/dir...
I: Built apk into: .\gaode\dist\gaode.apk
Press any key to continue . . .
修改应用逻辑代码
如上,将打包好的apk签名(在网上找找教程 简单)后安装到手机,会发现无法使用app
这个是高德地图启动的时候做了签名相关的校验,我们修改了包名及签名,所以无法通过校验。
我们来定位和分析下 这个猥琐的检验检查在代码哪儿!
通过解读AndroidManifest.xml
,在其中搜索 android.intent.category.LAUNCHER
,其所在 Activity 就是启动界面。
...
<activity android:configChanges="fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:exported="true" android:icon="@drawable/v3_icon" android:launchMode="singleTask" android:name="com.autonavi.auto.remote.fill.UsbFillActivity" android:relinquishTaskIdentity="false" android:screenOrientation="user">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.APP_MAPS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
...
通过此代码我们可以得知,这个启动页面对应的包逻辑代码文件为 com.autonavi.auto.remote.fill.UsbFillActivity
然后我们就可以按照这个包路径,通过以下步骤查看启动也里边的逻辑
1、将安装包 gaode.apk
作为压缩包解压,后拿到里边的classes.dex
。
2、使用dex-tools
将classes.dex
转换为能看懂的jar文件: d2j-dex2jar .\classes.dex
3、打开jd-gui
,将转换的jar文件拖入其中查看并分析代码
结合错误错误提示文字搜索,很快就能定位到 校验逻辑处
找到方法 g() 的调用地点,可以看到当l90.d(ee.A().f())
为false
会弹出异常提示,并阻止进入程序。
好了,截止目前,我们已经知道了 只要让l90的d方法返回true即可。
我们找到进入编译后的文件 gaode\smali\l90.smali
,编辑此文件的d方法,将返回值改为true
smali 语法和 Java 还是有很大差别的,但是我们不需要精通,对应这个校验方法看上去很复杂,但是我们的需求只不过是让这个方法返回 true 即可,因此修改如下:
...
.method public static d(Landroid/content/Context;)Z
.locals 1
.line 1
const/4 p0, 0x1
return p0
.end method
最后的检验,我们再次打包并签名,就可以看到可以成功的安装并使用了
修改包名
要想制作共存,必须使得包名和原版不同。
打开安卓的项目配置文件 AndroidManifest.xml
搜索 package="com.autonavi.amapauto"
讲起替换为你想要的包名即可 比如package="com.baidu"
修改应用名称
默认的应用名称为高德地图
, 那么我们在反编译的项目中全局搜索这几个字,最终定位到是在res\values-zh\strings.xml
找到<string name="app_name">高德地图</string>
讲起改为你想要的名字 比如 <string name="app_name">高德车机</string>
修改应用图标
使用图标生成网站,生成应用图标(安卓app图标自己做的话麻烦 需要适配不同分辨率,此网站可以帮你做),复制到res
目录中。
打开安卓的项目配置文件 AndroidManifest.xml
搜索 android:icon=@drawable/v3_icon
全部替换为android:icon="@mipmap/ic_launcher"
。
其它
什么都不改的情况下,反编译再打包就会资源错误的问题,是apktool高版本的问题,我随便选了一个低点的版本就可以了
D:\app> apktool d .\gaode.apk
I: Using Apktool 2.6.0 on gaode.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: C:\Users\Administrator\AppData\Local\apktool\framework\1.apk
I: Regular manifest package...
I: Decoding file-resources...
S: Could not decode file, replacing by FALSE value: anim/activity_exit.xml
S: Could not decode file, replacing by FALSE value: anim/abc_slide_in_top.xml
S: Could not decode file, replacing by FALSE value: anim/abc_slide_in_bottom.xml
S: Could not decode file, replacing by FALSE value: anim/abc_slide_out_top.xml
S: Could not decode file, replacing by FALSE value: anim/abc_fade_out.xml
S: Could not decode file, replacing by FALSE value: anim/abc_fade_in.xml
S: Could not decode file, replacing by FALSE value: anim/activity_enter.xml
S: Could not decode file, replacing by FALSE value: anim/abc_slide_out_bottom.xml
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
Press any key to continue . . .
D:\app> apktool b .\gaode\
I: Using Apktool 2.6.0
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
I: Copying libs... (/lib)
I: Copying libs... (/kotlin)
I: Building apk file...
I: Copying unknown files/dir...
I: Built apk...
Press any key to continue . . .
后来经过验证只要不超过2.8.1以上就可以, 最后一个能用就是2.8.1!
不过如果你若将apktool降级到低版本,那很多新apk或许解包签名就可能存在问题了,比如via在apltool2.8下解包后在打包签名就会安装失败。
所以结合情况,根据需要考虑
手机上使用mt管理器 或np管理器或Apktool M修改包名更简单,也没发现问题,可能是内置的apktool低版本原因吧。
电脑端也有很多好用的软件,比如我才知道的 安卓修改大师
不过这些底层都是基于apktool
感兴趣的可以试试
更多请加群