本帖最后由 qintangtao 于 2017-12-16 09:51 编辑
严重声明
本文的意图只有一个就是通过分析学习更多的逆向技术,如果有人利用本文知识和技术进行非法操作进行牟利,带来的任何法律责任都将由操作者本人承担,和本文作者无任何关系,最终还是希望大家能够秉着学习的心态阅读此文。
MIUI9绕开联网和插卡打开未知来源
最新MIUI9的设备通过PC手机助手安装APK,需要在设备上打开未知来源。
发现最新的MIUI9打开未知来源需要联网和插入SIM卡后才能打开。
* 用命令打开“未知来源”
在MIUI9中加了权限,打开失败。因此需要手动打开
* 设置->更多设置->系统安全->未知来源
提示需要联网,联网后再次打开,又提示需要插入SIM卡
看来是进行了网络检测和SIM卡检测
看来只有老老实实的联网和插卡后才能打开未知来源了
会不会有其它方式可以绕开呢?不能把,本地检测了网络和插卡,绕不过吧
* pull“com.android.settings”
* jadx查看下
拖进去居然没有反应,看来反编译失败了
解开apk后发现没有classes.dex
经过一番搜索,dex被提取并转换成oat了
* pull oat
虽然是.odex结尾的,但其实是oat格式的文件
* oat转dex
oat是elf格式的文件并且包含了一个完整的dex
用ExtractDexFromOat把oat转换成dex
* jadx 打开 .dex
居然还是打开失败
经过一番折腾,是因为dex头中的035改成了037导致反编译失败
把037改成035即可用jadx打开了
我是把jadx解析dex用到的lib包dx-1.10.jar反编译后去掉了对035的校验
* apktool 反编译资源文件
* 搜索“未知来源”
“install_applications”可疑
* 继续搜索“install_applications”看在那个布局文件中出现
出现在security_settings_misc.xml
[XML] 纯文本查看 复制代码 <com.android.settings.MiuiRestrictedSwitchPreference android:persistent="false" android:title="@string/install_applications" android:key="toggle_install_applications" android:summaryOn="@string/install_unknown_applications" android:summaryOff="@string/install_unknown_applications" style="?android:attr/preferenceScreenStyle" />
可以看出com.android.settings.MiuiRestrictedSwitchPreference是小米自定义的没有android:id,可以看到有android:key有可能是根据这个key在程序中操作的
* jadx搜索“toggle_install_applications”
在com.android.settings.SecuritySettings找到2处
this.bGg = (MiuiRestrictedSwitchPreference) findPreference("toggle_install_applications");
正如上面的猜想是通过key来获取MiuiRestrictedSwitchPreference对象
[Java] 纯文本查看 复制代码 public boolean onPreferenceChange(Preference preference, Object obj) { String key = preference.getKey(); if ("toggle_install_applications".equals(key)) { if (((Boolean) obj).booleanValue()) { this.bGg.setChecked(false); bsN(); z = false; } else { bsI(false); } } return z;}
在onPreferenceChange中响应事件
打开时调用bsN();
关闭时调用bsI(false);
* 跟踪bsN()
弹出确认框 可以看到上面关闭时也是调用的bsI
* 跟踪bsI()
关闭:
[Java] 纯文本查看 复制代码 Global.putInt(blI(), "install_non_market_apps", z ? 1 : 0);
打开:
[Java] 纯文本查看 复制代码 Intent intent = new Intent("com.miui.securitycenter.action.UNKNOWN_SOURCE_VERIFY");
intent.setPackage("com.miui.securitycenter");
startActivityForResult(intent, 1004);
startActivityForResult的第二个参数是请求码1044
应该是在onActivityResul中根据"com.miui.securitycenter"中设置的返回码来确定是否打开“未知来源”
* 跟踪onActivityResul()
第一个参数是请求码,第二个参数是返回码
可以看出当请求码=1004时,返回码=-1时打开“未知来源”
看看“com.miui.securitycenter”中做了什么
* pull“com.miui.securitycenter”包才能继续跟踪了
* pull “com.miui.securitycenter”的oat文件
* 同样把oat转dex
* apktool 反编译资源文件
* 在AndroidManifest.xml搜索com.miui.securitycenter.action.UNKNOWN_SOURCE_VERIFY
找到相关activity “com.miui.permcenter.install.UnknownSourceVerifyActivity”
* 用修改过的jadx打开SecurityCenter.dex(不校验dex头的035)
找到UnknownSourceVerifyActivity
可以看到V()把返回码设置成了-1
1、VERSION.SDK_INT == 24 && !"mido".equals(str)
2、VERSION.SDK_INT == 25 && new ArrayList().contains(str)
3、T()
Build.DEVICE=tiffany,VERSION.SDK_INT=25
前面两个条件满足就可以,但是在我测试的设备上不满足前面两个条件
继续看T()
* 跟踪T(), 父类AdbInstallVerifyActivity的方法
* 跟踪W()
此处判断了是否联网,没有联网则提示并finish掉
* 跟踪m
* 跟踪 a.a(this.R.getApplicationContext(), hashMap));
* 跟踪 com.miui.securityscan.utils.a.Jr(arg3);
获取android_id
* 跟踪 ((Map)v4).put("sim", a.b(arg3));
可以看到没有插卡返回“off”
* 跟踪 new i().al(jSONObject2.toString())
请求数据加密
* 跟踪 a.c()
post请求
Url是this.R.s
在子类UnknownSourceVerifyActivity中s赋值为“http://srv.sec.miui.com/data/unknownSources”
* 用Fiddler看一下
HTTP/1.1 200 OK
Server: Server/2.1.1
Date: Fri, 08 Dec 2017 06:41:22 GMT
Content-Length: 29
Connection: keep-alive
x-host-name: c00.bj
x-sec-s: qXjqQ8Kf7TcFT2R9C6E3CxcbkG5L7a1H1jAH9co1OPbJ3Ciy5P68qznvRwOnr/AL5qVW6BddwZV6fG1zE0sxJT20EKWH+6B/vdzTXVBLFX3zic+CJvwOwQCGNHyGQmZ6Gd41xq1Mt3Izthve+0HQM/3TkFDkmUbLqrELpOGtut0=
{"status":"0","message":"ok"}
向"http://srv.sec.miui.com/data/unknownSources"请求数据
当没有插入SIM卡的时候,则请求数据中sim=off时返回的status!=0并且message提示需要插卡
* 根据返回的数据
return jSONObject.optInt("status", -1) == 0 ? null : jSONObject.optString("message");
Status=0时返回null,否则返回message
* 跟踪au(String str)
可以看到当str=null时调用了V() 将返回码设置成-1后并finish掉
* 根据上面的跟踪,看来并不是在本地校验sim卡是否存在而是在服务器端校验的
既然如此我们是否可以拦截求情返回status=0的数据呢?
当然是可以的
我们可以开启一个热点,并开启一个webserver,让手机连接这个热点,把相关请求转到webserver上并返回自定义的数据即可
* 开启热点并把“srv.sec.miui.com”添加到host
* 使用QtWebServer 开发一个小的webserver
* 断开热点机器上的外网
设备就不会联网激活
* 连接该热点
就可以把srv.sec.miui.com的请求转到QtWebServer 上
请求路径是“/data/unknownSources”则返回{"status":"0","message":"ok"} |