看雪论坛
发新帖

[原创]安卓改机技术揭秘(一) 工具篇

ckis 2016-10-2 00:25 16264

  目前 市面上你能买到的一些安卓刷量变机工具例如 008K、变机宝等等 使用的都是XPOSED框架来修改手机的机型。这种修改方式目前是一种主流技术,主流技术的优点就是兼容性好、开发(包括文档支持、社区支持、第三方模块)成本低、稳定性高等特点。但对于当前项目来说,主流技术并不是一个好的解决办法,因为主流技术不光你了解,APP的厂商的技术人员也很了解,而且一般规律来看,厂商的技术实力、人力、财力以及这三方面的积累,不是一个小团队的作者可以对抗的。

目前改机软件所实现的修改机型项目汇总起来分为以下几类
1:手机唯一身份标志
这个很好理解,主要包括 IMEI IMSI ICCID 等等这些全球唯一的身份标志,来表示这台手机的独立性,另外要实现一些编号的校验位运算,一般情况下,这些标志身份的序号都有校验位和一些固定的格式和算法,这里有很多渠道和积分墙是对这些序号的合法性有检测的。
2 : 唯一标志衍生信息
这个衍生信息就有很多项了,例如一些改机软件 随便的把某个厂商的型号和一个合法的IMEI结合在一起,殊不知IMEI的前6位为TAC,是每个机型独有的身份标志,随便搭配后,一定会被检测出来的。再例如联通的IMSI是46001开头,移动和电信的就不一样,IMSI,ICCID,NUMBER,运营商,网络制式,mnc,mcc这些信息最起码是要匹配的。
3:环境信息
环境信息分为两部分 ①:手机内部环境 包括你的系统特定信息,用户特定信息。②:手机外部环境:基站信息、GPS信息、WIFI信息等等。

本文中所有的操作都基于Android Studio环境。下面进入实战操作环节!

1 首先创建一个APP,并配置XPOSED的开发环境,配置过程可以参考以下两篇文章,此处不再重复。
http://www.cnblogs.com/csonezp/p/5177928.html
http://www.open-open.com/lib/view/open1451364108964.html

2 配置好XPOSED环境后,在该APP中创建HOOK类 本文为MainHook,该类必须继承IXposedHookLoadPackage

public class MainHook implements IXposedHookLoadPackage
{
	@Override
	public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable
	{
		//xposed程序入口 do something...
	}
}



3 实际修改项

目前市面上的很多改机软件都没有修改第二处的IMEI
另外一个位置是在com.android.internal.telephony.PhoneSubInfo类中,
导致有些反作弊系统读取这个位置的IMEI值后不会下分

HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getDeviceId", GetCatValue("imei"));
HTool.XHookMethod("com.android.internal.telephony.PhoneSubInfo",mLpp.classLoader, "getDeviceId", GetCatValue("imei"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSubscriberId", GetCatValue("imsi"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getLine1Number", GetCatValue("number"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimSerialNumber", GetCatValue("simserial"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimCountryIso", GetCatValue("simcountryiso"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimOperator", GetCatValue("simoperator"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimOperatorName", GetCatValue("simoperatorname"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkCountryIso", GetCatValue("networkcountryiso"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkOperator", GetCatValue("networkoperator"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkOperatorName", GetCatValue("networkoperatorname"));

//WIFI信息
HTool.XHookMethod(android.net.wifi.WifiInfo.class.getName(),mLpp.classLoader, "getMacAddress", GetCatValue("wifimac"));
HTool.XHookMethod(android.net.wifi.WifiInfo.class.getName(),mLpp.classLoader, "getBSSID", GetCatValue("bssid"));
HTool.XHookMethod(android.net.wifi.WifiInfo.class.getName(),mLpp.classLoader, "getSSID", "\""+GetCatValue("ssid")+"\"");
XposedHelpers.findAndHookMethod(java.net.NetworkInterface.class.getName(),mLpp.classLoader, "getHardwareAddress", new Object[] {
		new XC_MethodHook()
		{
			protected void afterHookedMethod(MethodHookParam param) throws Throwable
			{
				//每个安卓系统中 至少存在5个以上的MAC地址 
				//但大多数软件只修改了MAC和BSSID 
				//真正的MAC修改是在此处理函数中监听每次访问.
			}
		}});
		
//蓝牙信息
HTool.XHookMethod(BluetoothAdapter.class.getName(),mLpp.classLoader,"getAddress", GetCatValue("bluemac"));
HTool.XHookMethod(BluetoothAdapter.class.getName(),mLpp.classLoader, "getName", GetCatValue("bluename"));

//设置手机信息 无论手机是否插入了sim卡 都会模拟出SIM卡的信息 APP获得SIM卡消息时返回该手机已有SIM卡
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getPhoneType", TelephonyManager.PHONE_TYPE_GSM);
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkType", TelephonyManager.NETWORK_TYPE_HSPAP);
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimState", TelephonyManager.SIM_STATE_READY);
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "hasIccCard", true);

	
//修改手机系统信息 此处是手机的基本信息 包括厂商 信号 ROM版本 安卓版本 主板 设备名 指纹名称等信息
XposedHelpers.setStaticObjectField(android.os.Build.class, "MODEL", GetCatValue("model"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "MANUFACTURER", GetCatValue("manufacturer"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "BRAND", GetCatValue("brand"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "HARDWARE", GetCatValue("hardware"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "BOARD", GetCatValue("board"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "SERIAL", GetCatValue("serial"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "DEVICE", GetCatValue("device"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "ID", GetCatValue("id"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "PRODUCT", GetCatValue("product"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "DISPLAY", GetCatValue("display"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "FINGERPRINT", GetCatValue("fingerprint"));

XposedHelpers.findAndHookMethod("android.os.SystemProperties",mLpp.classLoader, "native_get", new Object[] {String.class,String.class,
		new XC_MethodHook()
		{
			//为了防止某些APP跳过Build类 而直接使用SystemProperties.native_get获得参数
		}});
//修改系统版本 我看到世面上的软件基本上都是不能修改系统版本的 从而造成了刷量后 很多渠道最终会显示你的APP用户全部使用的某一系统版本
//这样的话数据就太假了.
XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "RELEASE", GetCatValue("version"));
XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "SDK", GetCatValue("apilevel"));

HTool.XHookMethod(android.os.Build.class.getName(),mLpp.classLoader, "getRadioVersion", GetCatValue("radioversion"));

//修改为指定的运营商mnc mcc信息
XposedHelpers.findAndHookMethod(android.content.res.Resources.class.getName(),mLpp.classLoader, "getConfiguration", new Object[] {
		new XC_MethodHook()
		{
			...........................
			//此处的mnc和mcc必须和系统中其他关于运营商的数据对应!
		}});

//修改ANDROID_ID
XposedHelpers.findAndHookMethod(android.provider.Settings.Secure.class.getName(),mLpp.classLoader, "getString",
new Object[] {ContentResolver.class,String.class,
		new XC_MethodHook()
		{
			...............................
			//此处会根据传入的String参数 判断返回值 其中包括比较关键的数据就是android_id
		}});

//防止APP使用Runtime.exec方式获取一些特定的系统属性
XposedHelpers.findAndHookMethod(Runtime.class.getName(),mLpp.classLoader, "exec",new Object[] {String.class,String[].class, File.class,
		new XC_MethodHook()
		{
			//一些APP从JAVA层获得到了数据 还会从shell(native)层获得一些更底层的数据 来判断用户的合法性
			//经常用到的有 cat、getprop、ifconfig等等命令,当exec执行这些命令后 往往会返回一些手机的真实信息
			//因为框架和处理方式不同,...部分此处根据自己需求,编写重定向返回值的过程...
		}});

//修改位置信息
XposedHelpers.findAndHookMethod(LocationManager.class.getName(),mLpp.classLoader, "getLastKnownLocation",
	new Object[] {String.class,
			new XC_MethodHook()
			{
				..........................
				//返回预先设置好的经纬度信息以伪装地理位置
			}});

HTool.XHookMethod(Location.class.getName(),mLpp.classLoader, "getLatitude", latitude);
HTool.XHookMethod(Location.class.getName(),mLpp.classLoader, "getLongitude", longitude);


//修改GSM制式手机的基站信息
HTool.XHookMethod(android.telephony.gsm.GsmCellLocation.class.getName(),mLpp.classLoader, "getLac", GsmLac);
HTool.XHookMethod(android.telephony.gsm.GsmCellLocation.class.getName(),mLpp.classLoader, "getCid", GsmCid);


//修改CDMA制式手机的基站信息
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getBaseStationLatitude", CdmaLatitude);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getBaseStationLongitude", CdmaLongitude);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getBaseStationId", CdmaBid);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getSystemId", CdmaSid);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getNetworkId", CdmaNid);


//模拟手机的APP列表
XposedHelpers.findAndHookMethod("android.app.ApplicationPackageManager",mLpp.classLoader, "getInstalledPackages",new Object[] {int.class,
		new XC_MethodHook()
		{
			//此处模拟正常用户的APP列表 其中随机的增加和删除一些常用APP 以达到每个手机的APP有很大的随意性和合理性
		}});

XposedHelpers.findAndHookMethod("android.app.ApplicationPackageManager",mLpp.classLoader, "getInstalledApplications",new Object[] {int.class,
		new XC_MethodHook()
		{
			//此处模拟正常用户的APP列表 其中随机的增加和删除一些常用APP 以达到每个手机的APP有很大的随意性和合理性
		}});
		
//防止APP的VPN SOCK5 HTTP代理检测
XposedHelpers.findAndHookMethod(java.net.NetworkInterface.class.getName(),mLpp.classLoader, "getNetworkInterfacesList",new Object[] {
		new XC_MethodHook()
		{
			........................................
			//此处对于一些连接信息 对JAVA做了隐藏处理 但对于系统和Native层依然是可见的 所以APP不会检测到代理 但代理却可以正常的运行...
		}});



       
以上这些做下来 从信息采集上基本可以过市面上70%的系统了 对于某些系统的高级检测,则需要我们采用更高级的处理方式才能攻破对方的防线,这些处理方式我们随后会讲到。
但目前推广市场上 不光是采用技术手段 还采取大数据分析等方式判断你的数据是否合格 所以想把这个作为一个项目来做 从技术方面解决工具问题只是刚刚开始。


欢迎讨论 QQ 586593

本主题帖已收到 0 次赞赏,累计¥0.00
最新回复 (49)
fujing 2016-10-2 00:35
2
谢谢分享
铭天星 2016-10-2 03:38
3
感谢分享
影子不寂寞 2016-10-2 09:23
4
支持一个
8
kanxue 2016-10-2 09:36
5
2008年的老会员了,感谢分享!
诗函 2016-10-2 18:13
6
感谢分享,正好把自己的工具增加一些数据
junkboy 2016-10-2 20:23
7
厉害~~~
无边 2016-10-2 20:35
8
我自己做了一年,结果还没lz全
小豆芽 2016-10-2 22:03
9
感谢分享~
fanweiriu 2016-10-4 06:01
10
刷量有市场才好啊
Loopher 2016-10-8 09:22
11
感谢分享~
1
koflfy 2016-10-8 10:27
12
mark
chmlqw 2016-10-9 13:50
13
做协议版......
1
张jialin 2016-10-9 17:56
14
感谢分享,写的很全面。

仔细研究了几天发现了一点遗漏的地方,这里贴个代码:(这段代码手机上执行不会调用TelephonyManager.getDeviceId,没有调用shell,没有jni,但是确实能获取到imei)

TelephonyManager tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

  Method TelephonyManager_private_getSubscriberInfo = tel.getClass().getDeclaredMethod("getSubscriberInfo");
            TelephonyManager_private_getSubscriberInfo.setAccessible(true);

            Object iphonesubinfo = TelephonyManager_private_getSubscriberInfo.invoke(tel);
            log(iphonesubinfo.toString());

            Method getDeviceId = iphonesubinfo.getClass().getDeclaredMethod("getDeviceId");
            log(getDeviceId.toString());
            getDeviceId.setAccessible(true);

            Object deviceid = getDeviceId.invoke(iphonesubinfo);
            log("deviceid:" + deviceid.toString());
ckis 2016-10-10 02:41
15
针对imei的部分 我有特意强调 你的这种方式在我顶楼的代码中 是可以被hook到的
ckis 2016-10-10 02:46
16
其实关于安卓值得写的东西很多 但模块都很杂 很分散 不太好把这些东西整理成一个文章 安卓刷量里面需要解决的技术问题太多了 我干了将近一年 才把这里面的很多环节理顺 回头有空慢慢写吧
AqCxBoM 2016-10-10 10:47
17
这玩意貌似挺合适我某位友人,@他
1
张jialin 2016-10-10 10:49
18
我在4.2.2的模拟器上测试确实没有hook到,不过模拟器内核和framework是被修改过的,可能有点问题,但是手机上又没装xposed。

你是指com.android.internal.telephony.PhoneSubInfo.getDeviceId这个,在手机上是能hook到我前面那段代码吗?PhoneSubInfo应该就是接口IphoneSubInfo的一个实现吧。
1
张jialin 2016-10-10 10:52
19
我也是在研究安卓反刷量~,多到论坛交流,我研究还不久,没太多心得,不过也有点想法想写点东西,再研究一段时间。
2
光棍节 2016-10-10 14:11
20
感谢分享
ckis 2016-10-11 06:03
21
我是研究刷量的
cindaralle 2016-11-9 14:32
22
但是请求IP不会变啊,如果上万个量都是一个IP岂不是很假,就比如移动广告平台,服务器不检测IP吗??
lisit 2016-11-19 15:07
23
vpn。
cindaralle 2016-11-19 21:52
24
这方法不现实
王小东 2016-11-21 08:11
25
谢谢分享
ckis 2016-11-23 13:42
26
淘宝搜索全国混拨pptp 你会发现这很现实
cindaralle 2016-11-26 20:16
27
我的天啊,爱死你了
northunion 2016-11-30 15:28
28
感谢分享~
1
学编程 2017-1-12 20:08
29
经过实测4.4,也是不行的。
狂奔的鸡骨架 2017-1-13 14:09
30
mark
gaosha 2017-1-28 23:21
31
有没有不用xposed就伪装imei的方法,或者说安卓7.0可以用的伪装imei的方法
ckis 2017-2-11 13:29
32
如果有特殊的rom版本修改了PhoneSubInfo.class是有可能HOOK失败的

我在GOOGLE NEXUS4/5原生ROM 4.4.4下 测试成功

另附api level 19的PhoneSubInfo.class源文件
上传的附件:
ckis 2017-2-11 13:30
33
自己写JAVA环境的inject和HOOK就可以
Yecate 2017-2-11 13:35
34
看看 感谢分享
moria 2017-2-11 17:12
35
厉害~~~
1
学编程 2017-2-12 21:03
36
测试的是哪个APK?
kingyangcn 2017-2-14 09:27
37
感谢,学习了。
骂了隔壁 2017-2-14 10:16
38
写的好全面都,基本上市面上的作弊工具都覆盖掉了。这里说下自己做识别的时候一些体验
1.目前市面上作弊工具都是根据官方api写的,但是国内很多手机都是双卡的,如果通过研究双卡API,其实是可以获取到原始值。
2.xposed是基于Java层hook,通过jni开发也能获取到一些原始参数
3.通过xposed源码研究可以发现他将hook的插件和方法都保存在内存中了,通过这个特征可以非常准确的识别xposed
zoukaiping 2017-2-14 16:53
39
楼上的,可以具体的列出来实际的代码吗?
1. 双卡的API也是可以被HOOK的。
2. XOPSED无法对JNI进行HOOK,但是也可以通过第三方的源代码HOOK SO, LIBC。
3. 具体不是很明白?show me code..
骂了隔壁 2017-2-14 22:37
40
因为做的是防作弊,所以关注点可能有点不一样
1. 是的。常见的双卡api有 展讯、mtk、高通 ,只要知道了API接口就可以hook。但是市面的作弊工具很少有针对双卡做处理,所以这可以作为防作弊识别的一个点。
2. xposed 无法hook native 代码,但是实现市面是最常见的hook工具就是xposed了,想 Cydia 用的就比较少,所以和上面类似这也可以作为一个识别点。另外像got表hook 或者inline hook 也可以通过jni识别。
3. 不好意思公司代码可能不能贴出来。说下思路吧,通过ClassLoader 识别Loader进来的xposed插件,通过放射调用xposed保存插件和插件hook函数的属性
heartbeast 2017-3-7 15:12
41
收藏了再学习
dongdongdong 2017-3-20 19:07
42
有没有源码?
安卓逆向狗 2017-3-20 23:14
43
我的天啊 我只会用不会整
hapiant 2017-4-1 13:11
44
楼主能分享源代码么?
llancer 2017-4-19 17:45
45
发现一个获取wifi信息没有hook到的地方
NetworkInfo  networkInfo  =  ((ConnectivityManager)  this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
//获取ssid
networkInfo.getExtraInfo()
有点萌 2017-4-19 20:11
46
mark
ArcherJohn 2017-5-29 02:21
47
nice!
orayer 2017-6-3 17:55
48
感谢,学习了
vurtneye 2017-6-23 20:28
49
骂了隔壁 因为做的是防作弊,所以关注点可能有点不一样 1. 是的。常见的双卡api有 展讯、mtk、高通 ,只要知道了API接口就可以hook。但是市面的作弊工具很少有针对双卡做处理,所以这可以作为防作弊识别 ...
你好,请教下,xpose我修改了包名和jar名称,类名和一些常见的名称都修改了,还是被检查出来我使用了xpose
alexzy 2017-6-27 14:21
50
获取SDK  用的是Build.VERSION.SDK_INT,这个怎么HOOK呢?
返回



©2000-2017 看雪学院 | Based on Xiuno BBS | 知道创宇带宽支持 | 微信公众号:ikanxue
Time: 0.018, SQL: 11 / 京ICP备10040895号-17