Android getDeviceId 底层源码分析,一键新机

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 callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(int subId,
422            String callingPackage, String message, CallPhoneMethodHelper 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 callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(int phoneId,
465            String callingPackage, String message, CallPhoneMethodHelper 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 > [email protected]::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("[email protected]::IRadio", serviceName, retry));
    }

你可能感兴趣的:(Android getDeviceId 底层源码分析,一键新机)