1、概述
目前市面上的一面新机,基本都是Hook到TelephonyManager getDeviceId 方法,如何绕过?
getDeviceId 底层实现:
Android 获取Imei 接口主要由 TelephonyManager getDeviceId 来获取。
在Java层通过RILJ 和 RILD建立通讯socket,来和modem(基带芯片)建立沟通 获取返回值。
和RILD建立链接需要有Root系统权限,所以,如果获取了root权限,可以绕过系统的Api来获取IMEI,如果没有Root权限,或者是系统uid的话 基本没办法绕过getDeviceId
很多境外电商亚马逊刷单的方案已经过时,一键新机只有从底层定制才靠谱的。这个有研究的可以和我沟通交流。
2、源码,基于android10.0
主要做权限的检测
PhoneSubInfoController
51 public PhoneSubInfoController(Context context, Phone[] phone) {
52 mPhone = phone;
53 if (ServiceManager.getService("iphonesubinfo") == null) {
54 ServiceManager.addService("iphonesubinfo", this);
55 }
56 mContext = context;
57 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
58 }
59
PhoneSubInfoController phone = Handler (com.android.internal.telephony.GsmCdmaPhone) {df44a64}
75 public String getImeiForSubscriber(int subId, String callingPackage) {
76 return callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(subId, callingPackage,
77 "getImei", (phone)-> phone.getImei());
78 }
79
421 private <T> T callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(int subId,
422 String callingPackage, String message, CallPhoneMethodHelper<T> callMethodHelper) {
423 return callPhoneMethodWithPermissionCheck(subId, callingPackage, message, callMethodHelper,
424 (aContext, aSubId, aCallingPackage, aMessage)->
425 TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(
426 aContext, aSubId, aCallingPackage, aMessage));
427 }
60 public String getDeviceId(String callingPackage) {
61 return getDeviceIdForPhone(SubscriptionManager.getPhoneId(getDefaultSubscription()),
62 callingPackage);
63 }
65 public String getDeviceIdForPhone(int phoneId, String callingPackage) {
66 return callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(phoneId, callingPackage,
67 "getDeviceId", (phone)-> phone.getDeviceId());
68 }
69
464 private <T> T callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(int phoneId,
465 String callingPackage, String message, CallPhoneMethodHelper<T> callMethodHelper) {
466 // Getting subId before doing permission check.
467 if (!SubscriptionManager.isValidPhoneId(phoneId)) {
468 phoneId = 0;
469 }
470 final Phone phone = mPhone[phoneId];
471 if (phone == null) {
472 return null;
473 }
474 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
475 phone.getSubId(), callingPackage, message)) {
476 return null;
477 }
478
479 final long identity = Binder.clearCallingIdentity();
480 try {
481 return callMethodHelper.callMethod(phone);
482 } finally {
483 Binder.restoreCallingIdentity(identity);
484 }
485 }
通过RIL获取EVENT_GET_DEVICE_IDENTITY
/frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaPhone.java
2350 private void handleRadioAvailable() {
2351 mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
2352
2353 mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
2354 mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
2355 startLceAfterRadioIsAvailable();
2356 }
F:\android-10.0.0_r41\frameworks\opt\telephony\src\java\com\android\internal\telephony\RIL.java
public class RIL extends BaseCommands implements CommandsInterface
@Override
public void getDeviceIdentity(Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
RILRequest rr = obtainRequest(RIL_REQUEST_DEVICE_IDENTITY, result,
mRILDefaultWorkSource);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
try {
radioProxy.getDeviceIdentity(rr.mSerial);
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "getDeviceIdentity", e);
}
}
}
D/xyh: xyh radioProxy > android.hardware.radio@1.3::IRadio@Proxy
if (mRadioProxy == null) {
try {
mRadioProxy = android.hardware.radio.V1_3.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
mRadioVersion = RADIO_HAL_VERSION_1_3;
} catch (NoSuchElementException e) {
}
}
//获取硬件层 服务service dev/hwbinder HIDL
/hardware/interfaces/radio/1.3/IRadio.hal
具体hidl参考文章 https://blog.csdn.net/xiaosayidao/article/details/75577940
/**
* This will invoke the equivalent of the C++ getService(std::string) if retry is
* true or tryGetService(std::string) if retry is false. If the service is
* available on the device and retry is true, this will wait for the service to
* start. Otherwise, it will return immediately even if the service is null.
*/
public static IRadio getService(String serviceName, boolean retry) throws android.os.RemoteException {
return IRadio.asInterface(android.os.HwBinder.getService("android.hardware.radio@1.3::IRadio", serviceName, retry));
}