缘由:做ROM的搭档找到我说客户的一款App,在某一个盒子上无法运转,点击就闪退了,在其他盒子上均没有出现这样的状况,看我能不能分析出什么原因。
反编译部分的介绍在文章结尾
排查原因
依据现象来看,这程序要嘛崩溃了,要嘛该App不适配此款盒子(比方ABI不支持、Target SDK Version等问题)
minSdkVersion体系版别不支持?
可是搭档告诉我这款盒子是Android9,在其他的Android9和Android 4.4盒子上都跑过,没问题,排除了minSdkVersion的问题
ABI不支持?
不太或许,先不想这个
ADB才是王道
但凡遇到问题,只需设备能够adb,起码问题就处理了一半,但一问,说这盒子好像不能Adb,,鹅鹅鹅饿~~
后来凭借adbhelper发现,此款盒子仍是能adb,仅仅惯例状况下adb的端口是60001,连上之后履行adb root的话,又会换回默认端口,这个状况我也是活久见。。
说正题,连上adb之后,通过抓日志,发现了如下问题:Permission denial: writing to settings requires:android.permission.WRITE_SECURE_SETTINGS
,依据错误仓库信息,大致是app调用了wifimanager.setWifiEnabled(true)
这个办法引起的
处理
权限思路
因为自己对android.permission.WRITE_SECURE_SETTINGS
这个权限并不太了解,所以从反常的字面意思了解,我认为是权限不可,所以我测验让app拥有权限来确保其正常运转。
办法1:adb shell pm grant {包名} {权限内容}
履行指令,赋予该程序权限adb shell pm grant {packagename} android.permission.WRITE_SECURE_SETTINGS
,履行指令之后,提示java.lang.SecurityException: Package xxxx has not requested permission android.permission.WRITE_SECURE_SETTINGS
意思说该程序不需求这个权限,这个问题的原因是因为app并没有在清单文件中声明这个权限,这就有意思了,这个app操作需求这个权限却没有请求权限,或许主要原因是因为曾经的低版别不需求,Android9需求吧,所以咱们得先给他添加这个声明,然后再赋予这个权限。
通过apktool反编译,然后修正清单文件添加这个权限,再从头打包(后面再说具体得反编译重打包的步骤),一切稳当之后再次履行上面指令,果然老天是不会让我舒坦的,履行后出现反常:java.lang.SecurityException: Package android does not belong to 10034
,触发问题的调用仓库仍是之前那个办法引起的。(⊙﹏⊙),思考半天,看了下它的清单文件,并没有声明targetSdkVersion,这有点怪哦,也是活久见,莫非游戏apk就能够这么无视规则?那我要不给他添加上,,,嗯能够一试,仍是相同的配方,给清单文件添加如下代码:
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="22" />
然后从头打包,再来,没错,仍是相同的滋味,相同的问题,我认为修正来低于23,权限能够就自动答应了,现在想起来真是too young to simple。。
东搜搜西搜搜,想测验下是不是因为这个程序不是体系app,后来将程序放在system/app下作为体系程序,仍是相同问题,所以很明显,权限这条路行不通。
所以这个问题的处理办法应该参阅如下内容:
这个错误是因为你的运用试图调用setWifiEnabled办法,这个办法在Android 9(API级别28)及以上版别现已被弃用。在这些版别中,只要体系运用才干调用setWifiEnabled办法。
即便你的运用现已被装置为体系运用,并且现已获得了WRITE_SECURE_SETTINGS权限,它依然不能调用setWifiEnabled办法。这是因为这个办法现在只能被体系UI调用,其他运用,包括体系运用,都不能调用这个办法。
你能够考虑运用WifiNetworkSuggestionAPI来提示用户连接到特定的Wi-Fi网络,或许运用Settings.Panel.ACTION_WIFI来引导用户到Wi-Fi设置页面。
以下是如何运用Settings.Panel.ACTION_WIFI的示例:
valintent=Intent(Settings.Panel.ACTION_WIFI)
startActivity(intent)
这段代码会打开Wi-Fi设置页面,让用户自己开启或封闭Wi-Fi。
修正程序源代码
权限的路行不通,那咱们只能想办法修复app这段逻辑代码了,可是他人的apk,明显不是那么简略让人想改就改撒,提出是这儿的问题,他人也不必定信啊,所以我打算自己改这个apk的编译后的源代码,让他不要触发引起反常的那个逻辑,绕过看程序能不能正常跑起来,这一步就需求懂得起smali,还好这个问题比较简略,定位到代码改了之后,从头打包,这下消停了,程序很好正常的运转。
反编译
反编译这一块触及许多概念,曾经大约接触过,都仅仅看,没有实际操作,有些时候操作也仅仅简略的反编译看下源码,但总体东西和触及的概念主要有ApkTool、dex2jar-2.1、jarsigner、jd-gui,还有些文章提到SignApk.jar、jax-gui等;
说下自己的了解,假如咱们需求从头打包一个apk,那么咱们肯定要从这个apk得到咱们能够修正的文件进行修正,修正后再从头打包,这是咱们需求的核心流程;
反编译APK
ApkTool,具体的效果自己查,大致意思是假如咱们想看清单文件内容,资源文件之类的,咱们就能够通过这个东西进行反编译,因为前面我需求给源程序在清单文件中新增权限声明,所以咱们就需求先得到反编译的工程,然后直接修正清单文件即可(把AndroidManifest拖动到Android Studio或许其他文本修正东西中直接修正然后保存即可)
-
反编译apk :先在终端将当前位置定位到ApkTool的目录,然后履行指令
apktool d {xxx.apk:你的apk名称}
,该指令会将apk反编译后保存在apktool所在目录下。也能够运用如下指令指定反编译后工程的存储途径apktool d -o {反编译后的存储目录} {xxx.apk}
,其实只需求知道反编译apk是运用的apktool d即可,查一下文档了解更详细的用法。 -
从头编译:修正之后咱们需求从头打包成apk,运用指令
apk b {反编译后的存储目录}
,编译成功之后,会保存在指定目录下的dist文件夹中。也能够用-o 指定存储的目录。
重签名
apk反编译修正了,也从头编译成了新的apk,但此刻这个apk是没有签名的,直接拿到设备上装置是不可的,所以咱们需求签名。
这儿就需求用到jarsign,这个应该是jdk内自带的jarsigner -verbose -keystore {签名文件途径:也便是keystore、jks文件} -signedjar {签名后的apk途径} {没有签名的apk途径} {运用的签名文件别号,也便是keyalias}
假如没出错,则咱们就拥有了现已签名的被修正正的apk了,能够去运转验证了。可是因为咱们是用的自己签名文件签名的,是不能掩盖装置本来的apk的,两者签名不一致。
运用体系签名
这块我没测验过,需求的自行检查搜索检查,附带个链接Android运用程序签名体系的签名(SignApk.jar)_新根的博客-CSDN博客
修正源码
跟直接修正清单文件的原理差不多,都是直接修正,可是因为是smali,就需求做必定的语法了解才干改了。也有东西能够将smali转换成java的,比方运用skylot/jadx: Dex to Java decompiler (github.com)东西,不过这个办法仅仅将smali转换成java来查阅,假如咱们想从头打包,那仍是有必要修正smali文件才行的。
关于这一节主张参阅:Android App 逆向入門之二:修正 smali 程式碼 (cymetrics.io)
额定说的:其实上面整个进程咱们没用到dex2jar-2.1、jd-gui之类的,其实效果不同,dex2jar的效果是将apk的后缀改成zip解压出来会得到许多dex文件,咱们通过dex2jar能够让这些dex转换成jar文件,jar文件便是惯例生成的java class文件了,可是jar文件无法直接打开检查,就需求凭借jd-gui之类的东西。。所以的目的是说咱们想看看他人程序的代码的时候用的吧。
就到这吧,做个记录。。