首页
论坛
专栏
课程

Android改机系列:一.Android一键新机原理剖析

2019-7-22 21:48 8393

Android改机系列:一.Android一键新机原理剖析

2019-7-22 21:48
8393

声明:本帖只作为技术分享,切勿用于非法用途,如果用于其他用途,本贴概不负责,如果有侵权,请管理员删除。

一个改机案例

6月份拿到一个口碑不错的商业改机案例,该案例只能运行在指定的手机,指定的rom,号称各大app无法检测,免root的改机框架。

 

我手上只有nexus6p,安装到手机上跑了一下,瞬间闪退,没有任何崩溃日志。但是这条日志出卖了它:

 

这明显是调用System.exit(0)主动退出。

静态分析

 

通过图片可以看到dex被混淆,字符串也被加密

解密字符串重打包

字符串解密往往是固定的smali格式:

    const-string vX, "加密后的字符串"
    invoke-static {vX}, Lcom/test/decString(Ljava/lang/String;)Ljava/lang/String;
    move-result-object vX

这个案例也不例外,所以编写一个脚本去匹配以上代码,然后调用解密代码(自己去源码里扣)解密字符串,然后把解密之后的字符串替换加密的字符串,然后再删除const-string vX, "解密之后字符串"以下两条指令,然后重打包即可(各位大佬若有更好的方案请告知)。当然我这里还加上了hook系统签名校验:

    private void hook(Context context) {
        try {
            DataInputStream is = new DataInputStream(new ByteArrayInputStream(Base64.decode(oriSign, 0)));
            byte[][] sign2 = new byte[(is.read() & 255)][];
            for (int i = 0; i < sign2.length; i++) {
                sign2[i] = new byte[is.readInt()];
                is.readFully(sign2[i]);
            }
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Object currentActivityThread = activityThreadClass.getDeclaredMethod("currentActivityThread", new Class[0]).invoke(null, new Object[0]);
            Field sPackageManagerField = activityThreadClass.getDeclaredField("sPackageManager");
            sPackageManagerField.setAccessible(true);
            Object sPackageManager = sPackageManagerField.get(currentActivityThread);
            Class<?> iPackageManagerInterface = Class.forName("android.content.pm.IPackageManager");
            this.base = sPackageManager;
            this.sign = sign2;
            this.appPkgName = context.getPackageName();
            Object proxy = Proxy.newProxyInstance(iPackageManagerInterface.getClassLoader(), new Class[]{iPackageManagerInterface}, this);
            sPackageManagerField.set(currentActivityThread, proxy);
            PackageManager pm = context.getPackageManager();
            Field mPmField = pm.getClass().getDeclaredField("mPM");
            mPmField.setAccessible(true);
            mPmField.set(pm, proxy);
            Log.i(TAG,"PmsHook success.");
        } catch (Exception e) {
            Log.e(TAG,"PmsHook failed.");
            e.printStackTrace();
        }
    }

这是jadx反混淆和解密字符串之后的效果,这下代码阅读性高了很多:

过授权、签名校验、系统认证、登录

这是一个厮杀的过程,本案例检验之处有非常多,so中也存在字符串加密和检验。当然这不是本篇文章重点,具体厮杀过程就不过多赘述。最后庐山真面目出现了:

新机原理

绝杀技一:免root Hook

此案例通过编译xposed源码并且修改特征码,把Xposed相关名称改为系统名称,例如camera、email、phone。然后hook堆栈信息,把hook框架的堆栈过滤掉。然后把改名字的xposed集成至LineageOs源码中。然后通过魔改后的XposedBridge.jar编写Hook模块,这样就实现了免root集成hook框架。这样子真的可以为所欲为。

绝杀技二:全面Hook Android设备信息接口

这个不用多说,全面的Hook了java层所有获取设备信息的有关函数,包括文件读取的io重定向,附件中是我整理的Hook相关接口。

绝杀技三:伪造真实用户活动

各大厂商都在做风控,IP画像、设备画像、用户画像、手机号画像...,没用用户行为的设备,必然是非正常用户,肯定是过不了风控的,通过hook相关接口,每次新机填充不同的短信,通话记录,联系人,照片,启动时间,周边蓝牙、wifi,sensor的值随机化...

绝杀技四:基站、gps、ip位置一致

目前获取位置信息主要有基站、gps、ip位置,三个维度。改机必然是通过链接代理(vpn)来生成不同ip,这里就要保证每次基站和gps的位置要和IP的位置信息相差不大,这样每次新机都是一个新的地理位置。

绝杀技五:SysPropertyHook

Xposed只是java层的Hook,现在大多数设备指纹sdk都是native获取或者native和java层都获取,然后进行对比。这里通过Hook SystemProperties.set、Settings.System.put、Settings.Secure.put、Settings.Global.put。保证改机后/system/build.porp、System.xml、Secure.xml、Global.xml文件真实改变,保证native层通过getProp时候和java层获取的是一致的

新机流程

准备新机设备信息PhoneInfo

通过读取/assets目录下的设备信息集,随机生成一个设备信息,然后通过当前ip获取基带和gps的位置,并且生成用户信息。把这些信息全部写入到sdcard中的phoneInfo.json中。

完成Hook

通过读取sdcard中的phoneInfo.json的设备信息完成Hook,自此新机已经完成。

由于版权原因,案例就不放出来了

下篇预告

Android改机系列:二.全息备份原理刨析



[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最后于 2019-7-30 19:28 被seandong编辑 ,原因:
上传的附件:
最新回复 (34)
小黄鸭爱学习 2019-7-22 23:29
2
0
我也在分析一个改机软件,功能号称最牛逼。过了他的付费之后发现改完设备连不上WIFI了
seandong 2019-7-23 00:05
3
0
小黄鸭爱学习 我也在分析一个改机软件,功能号称最牛逼。过了他的付费之后发现改完设备连不上WIFI了
什么改机?有样本吗
香风一族 2019-7-23 00:50
4
0
apk样本?
yy虫子yy 2019-7-23 01:35
5
0
貌似改机都需要hook
bluth 2019-7-23 10:05
6
0
能过数盟检测吗
最后于 2019-7-23 10:05 被bluth编辑 ,原因:
duoduo231 2019-7-23 10:09
7
0
样本不发一下吗
芃杉 2019-7-23 10:23
8
0
mark
koflfy 1 2019-7-23 10:56
9
0
mark
seandong 2019-7-23 11:21
10
0
bluth 能过数盟检测吗
这个不太清楚
seandong 2019-7-23 11:21
11
0
duoduo231 样本不发一下吗
私我拿样本
litaomn 2019-7-23 12:33
12
0
坐等第二篇
Superoot 2019-7-23 14:48
13
0
感谢分享
夜迷人 2019-7-23 15:51
14
0
优秀!在来个纯rom的改机
miyuecao 2019-7-23 15:56
15
0
感谢分享
seandong 2019-7-23 20:32
16
0
原版在这https://www.lanzous.com/i5489ri
密码:Dalvik   ,要的自己取,私信太多,回不过来
最后于 2019-7-23 20:34 被seandong编辑 ,原因:
Jack飞 2019-7-24 14:02
17
0
mark
bunnyrene 2019-7-25 13:10
18
0
非常强
hzzheyang 2019-7-25 15:04
19
0
感觉像完全进入了一个新世界
东方红太阳升 2019-7-25 22:57
20
0
小黄鸭爱学习 我也在分析一个改机软件,功能号称最牛逼。过了他的付费之后发现改完设备连不上WIFI了
可以加个联系方式吗?扣4320+1090
wx_DD强哥 2019-7-26 10:09
21
0
怎么联系你?可以合作一下么
小堆 1 2019-7-26 14:55
22
0
这个改机的作者还是有点儿东西的。由于我这边没有真机,一直在模拟器上进行分析。其中,该APP分析完毕。我直接采用了hook的方法对所有的字符串进行了解密操作,发现调用exit和检测xposed函数,采用hook过掉相关函数以及网络检测等函数,忘记是哪一处了,调用到了一个用户信息,这儿也需要hook给属性赋值一下。总得来说,这一块儿其实不难。随后对框架进行了分析,从rom中提取到了框架以及相关文件,结果发现框架也混淆了,模拟器有闪退现象,太恶心了。。遂没有继续进行分析这儿。深入对bridge进行了分析,将hook相关的文件全部复制到模拟器中,机型不对,导致失败。最后自己尝试根据对方的bridge文件编写对方框架的hook模块。可以修改对方的bridge文件  强制加载我们编写的模块
hhhhhhhhhh
最后于 2019-7-26 14:57 被小堆编辑 ,原因:
seandong 2019-7-26 16:20
23
0
小堆 这个改机的作者还是有点儿东西的。由于我这边没有真机,一直在模拟器上进行分析。其中,该APP分析完毕。我直接采用了hook的方法对所有的字符串进行了解密操作,发现调用exit和检测xposed函数,采用 ...
rom也做了校验,提一个点 sevice.jar。CameraView干掉。签名校验过掉。
seandong 2019-7-26 16:20
24
0
wx_DD强哥 怎么联系你?可以合作一下么
17727858071
小堆 1 2019-7-26 17:21
25
0
seandong rom也做了校验,提一个点 sevice.jar。CameraView干掉。签名校验过掉。
rom没有详细看,混淆和字符串加密实在不想搞了。还不如自己依赖他的框架写一个hook快。hhh
冒险岛mxd 2019-7-27 13:57
26
0
膜拜大佬
樊辉 2019-7-30 17:31
27
0
擎天柱
Lupinus 2019-8-8 14:39
28
1
"然后再删除const-string vX, "解密之后字符串"以下两条指令,然后重打包即可",实际操作中,删后面两条指令还是麻烦了一点。我觉得可以直接替换,把加密前的字符串直接替换解密后的,然后修改一下Lcom/test/decString(Ljava/lang/String;)Ljava/lang/String;的返回值,直接返回参数就好了。
学编程 1 2019-8-9 11:49
29
0
这个案例也不例外,所以编写一个脚本去匹配以上代码,然后调用解密代码(自己去源码里扣)解密字符串,然后把解密之后的字符串替换加密的字符串,然后再删除const-string vX, "解密之后字符串"以下两条指令,然后重打包即可(各位大佬若有更好的方案请告知)
这个脚本可以共享吗
放猪bayiliu 2019-8-24 22:12
30
0
样本失效了?
a小天 2019-8-26 19:43
31
0
该案例只能运行在指定的手机,指定的rom
请问这个指定手机是哪个手机 指定的rom包哪里弄。求教
iceway 6天前
32
0
大神,问一个mtpd的问题,我在安卓root的状态下运行
mtpd wlan0 pptp xxxxx.com 1723 name xxxxxxx password xxxxxxx linkname vpn refuse-eap nodefaultroute usepeerdns idle 1800 mtu 1400 mru 1400 nomppe
09-10 14:21:10.298 12357 12357 I mtpd    : Using protocol pptp
09-10 14:21:10.298 12357 12357 I mtpd    : Connecting to yhtip.com port 1723 via wlan0
09-10 14:21:10.334 12357 12357 I mtpd    : Connection established (socket = 7)
09-10 14:21:10.334 12357 12357 D mtpd    : Sending SCCRQ
09-10 14:21:10.362 12357 12357 D mtpd    : Received SCCRP -> Sending OCRQ (local = 18894)
09-10 14:21:10.362 12357 12357 I mtpd    : Tunnel established
09-10 14:21:10.395 12357 12357 D mtpd    : Received OCRQ (remote = 19230)
09-10 14:21:10.396 12357 12357 I mtpd    : Session established
09-10 14:21:10.396 12357 12357 I mtpd    : Creating PPPoX socket
09-10 14:21:10.397 12357 12357 I mtpd    : Starting pppd (pppox = 8)
09-10 14:21:10.399 12357 12357 I mtpd    : Pppd started (pid = 12359)
09-10 14:21:10.446 12359 12359 I pppd    : Using PPPoX (socket = 8)
09-10 14:21:10.449 12359 12359 I pppd    : pppd 2.4.7 started by root, uid 0
09-10 14:21:10.450 12359 12359 I pppd    : Using interface ppp0
09-10 14:21:10.450 12359 12359 I pppd    : Connect: ppp0 <-->
09-10 14:21:11.623 12359 12359 I pppd    : type=1400 audit(0.0:3068): avc: denied { ioctl } for path="socket:[7386867]" dev="sockfs" ino=7386867 ioctlcmd=8922 scontext=u:r:magisk:s0 tcontext=u:r:magisk:s0 tclass=udp_socket permissive=1
09-10 14:21:11.774 12359 12359 I pppd    : CHAP authentication succeeded
09-10 14:21:11.840 12359 12359 I pppd    : CCP terminated by peer (No compression negotiated)
09-10 14:21:11.841 12359 12359 I pppd    : Compression disabled by peer.
09-10 14:21:11.873 12359 12359 I pppd    : type=1400 audit(0.0:3069): avc: denied { ioctl } for path="socket:[7386867]" dev="sockfs" ino=7386867 ioctlcmd=8918 scontext=u:r:magisk:s0 tcontext=u:r:magisk:s0 tclass=udp_socket permissive=1
09-10 14:21:11.887 12359 12359 I pppd    : type=1400 audit(0.0:3070): avc: denied { ioctl } for path="socket:[7386867]" dev="sockfs" ino=7386867 ioctlcmd=891c scontext=u:r:magisk:s0 tcontext=u:r:magisk:s0 tclass=udp_socket permissive=1
09-10 14:21:11.896 12359 12359 I pppd    : local  IP address 10.61.231.48
09-10 14:21:11.897 12359 12359 I pppd    : remote IP address 10.255.255.254
09-10 14:21:11.898 12359 12359 I pppd    : primary   DNS address 114.114.114.114
09-10 14:21:11.899 12359 12359 I pppd    : secondary DNS address 223.5.5.5


显示连接成功,但是访问ip138.com,还是自己的电脑IP,并不是代理的IP,但是我手动设置V.P.N就可以,为啥呢
seandong 1天前
33
0
iceway 大神,问一个mtpd的问题,我在安卓root的状态下运行mtpd wlan0 pptp xxxxx.com 1723 name xxxxxxx password xxxxxxx linkname vp ...
这应该是没设置成功吧
iceway 20小时前
34
0
seandong 这应该是没设置成功吧
大神,怎么样才是正确的设置办法呢
miyuecao 5分钟前
35
0
iceway 大神,问一个mtpd的问题,我在安卓root的状态下运行mtpd wlan0 pptp xxxxx.com 1723 name xxxxxxx password xxxxxxx linkname vp ...
看日志连接没有问题,估计是你默认路由的问题,mtpd命令后应该是需要手动指定默认路由
游客
登录 | 注册 方可回帖
返回