Android設備的唯一標識符
1.IMEI (手機的身份證號碼)
IMEI(International Mobile Equipment Identity)是國際移動設備身份碼的縮寫,國際移動裝備辨識碼,是由15位數字組成的”電子串號”,它與每台移動電話機一一對應,而且該碼是全世界唯一的。每一只移動電話機在組裝完成后都將被賦予一個全球唯一的一組號碼,這個號碼從生產到交付使用都將被制造生產的廠商所記錄。
有些設備的IMEI有兩個,可以在撥號鍵盤輸入“*#06#”查看。普通APP獲取需要申請權限():
//權限 <uses-permissionandroid:name="android.permission.READ_PHONE_STATE" />
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
//獲取IMEI號
String imei = telephonyManager.getDeviceId();
2.IMSI (SIM卡的身份證號碼)
IMSI是區別移動用戶的標志,儲存在SIM卡中,可用於區別移動用戶的有效信息。其總長度不超過15位,同樣使用0~9的數字,例如460010280100023。其中MCC是移動用戶所屬國家代號,占3位數字,中國的MCC規定為460;MNC是移動網號碼,最多由兩位數字組成,用於識別移動用戶所歸屬的移動通信網;MSIN是移動用戶識別碼,用以識別某一移動通信網中的移動用戶,
IMSI與IMEI權限相同,獲取代碼:
//權限 <uses-permissionandroid:name="android.permission.READ_PHONE_STATE" />
TelephonyManager telephonyManager=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//獲取IMSI號
String imsi=telephonyManager.getSubscriberId();
3.ANDROID_ID
ANDROID_ID 是一串64位的數字,並以16進制字符串的形式保存下來,是設備首次啟動時隨機生成的設備的第一個引導,其記錄着一個固定值,通過它可以知道設備的壽命。ANDROID_ID也可視為作為唯一設備標識號的一個好選擇,當設備沒有手機號時,例如平板設備等,可以采用ANDROID_ID作為標識。
需要注意:
android_id在設備恢復出廠設置后,該值會改變
部分定制手機獲取到的android_id為null
由於定制問題,不同的設備可能會產生相同的ANDROID_ID
Android 8.0后不同應用獲得的值不同
應用簽署密鑰、用戶和設備的每個組合都具有唯一的 ANDROID_ID 值。因此,在相同設備上運行但具有不同簽署密鑰的應用將不會再看到相同的 Android ID(即使對於同一用戶來說,也是如此)參考https://developer.android.com/about/versions/oreo/android-8.0-changes?hl=zh-cn
android_id獲取方式:
import android.provider.Settings;
String ANDROID_ID =Settings.System.getString(getContentResolver(),Settings.System.ANDROID_ID);
4.設備序列號(Serial Number 或 SN)
SN碼是Serial Number的縮寫,有時也叫SerialNo,也就是產品序列號,產品序列是為了驗證“產品的合法身份”而引入的一個概念,它是用來保障用戶的正版權益,享受合法服務的;一套正版的產品只對應一組產品序列號。別稱:機器碼、認證碼、注冊申請碼等。
獲取方式:
1.adb shell
adb shell getprop ro.serialno
2.android.os.Build
String SerialNumber = android.os.Build.SERIAL;
3.android.os.SystemProperties.get
此API為hidden API,需要反射獲取
ClassLoader cl = context.getClassLoader();
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//參數類型
Class[] paramTypes= new Class[2];
paramTypes[0]= String.class;
paramTypes[1]= String.class;
Method get = SystemProperties.getMethod("get", paramTypes);
//參數
Object[] params= new Object[2];
params[0]= new String(key);
params[1]= new String(def);
ret= (String) get.invoke(SystemProperties, params);
除了SN號,還有制造商、品牌、型號、設備名等其他信息和SN的獲取方式相同
android.os.Build.BRAND:獲取設備品牌
android.os.Build.MODEL :獲取手機的型號 設備名稱。
android.os.Build.MANUFACTURER:獲取設備制造商
android.os.Build.BOARD:獲取設備基板名稱
android.os.Build.BOOTLOADER:獲取設備引導程序版本號
android.os.Build.CPU_ABI:獲取設備指令集名稱(CPU的類型)
android.os.Build.CPU_ABI2:獲取第二個指令集名稱
android.os.Build.DEVICE:獲取設備驅動名稱
android.os.Build.DISPLAY:獲取設備顯示的版本包(在系統設置中顯示為版本號)和ID一樣
android.os.Build.FINGERPRINT:設備的唯一標識。由設備的多個信息拼接合成。
android.os.Build.HARDWARE:設備硬件名稱,一般和基板名稱一樣(BOARD)
android.os.Build.HOST:設備主機地址
android.os.Build.ID:設備版本號。
android:os.Build.PRODUCT:整個產品的名稱
android:os.Build.RADIO:無線電固件版本號,通常是不可用的 顯示unknown
android.os.Build.TAGS:設備標簽。如release-keys 或測試的 test-keys
android.os.Build.TIME:時間
android.os.Build.TYPE:設備版本類型 主要為"user" 或"eng".
android.os.Build.USER:設備用戶名 基本上都為android-build
android.os.Build.VERSION.RELEASE:獲取系統版本字符串。如4.1.2 或2.2 或2.3等
android.os.Build.VERSION.CODENAME:設備當前的系統開發代號,一般使用REL代替
android.os.Build.VERSION.INCREMENTAL:系統源代碼控制值,一個數字或者git hash值
android.os.Build.VERSION.SDK:系統的API級別 一般使用下面大的SDK_INT 來查看
android.os.Build.VERSION.SDK_INT:系統的API級別 數字表示
5.MAC地址
android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) context.getSystemService(Context.WIFI_SERVICE);
String macAddress = wifi.getConnectionInfo().getMacAddress();
沒有 WiFi 硬件或者 WiFi 不可用的設備可能返回 null 或空
Android 6.0開始,谷歌為保護用戶數據,用此方法獲取到的 Wi-Fi mac 地址都為02:00:00:00:00:00
需要 ACCESS_WIFI_STATE 權限
Frida hook代碼
Java.perform(function() { var TelephonyManager = Java.use("android.telephony.TelephonyManager"); //IMEI hook TelephonyManager.getDeviceId.overload().implementation = function () { console.log("[*]Called - getDeviceId()"); var temp = this.getDeviceId(); console.log("real IMEI: "+temp); return "867979021642856"; }; // muti IMEI TelephonyManager.getDeviceId.overload('int').implementation = function (p) { console.log("[*]Called - getDeviceId(int) param is"+p); var temp = this.getDeviceId(p); console.log("real IMEI "+p+": "+temp); return "867979021642856"; }; //IMSI hook TelephonyManager.getSimSerialNumber.overload().implementation = function () { console.log("[*]Called - getSimSerialNumber(String)"); var temp = this.getSimSerialNumber(); console.log("real IMSI: "+temp); return "123456789"; }; ////////////////////////////////////// //ANDOID_ID hook var Secure = Java.use("android.provider.Settings$Secure"); Secure.getString.implementation = function (p1,p2) { if(p2.indexOf("android_id")<0) return this.getString(p1,p2); console.log("[*]Called - get android_ID, param is:"+p2); var temp = this.getString(p1,p2); console.log("real Android_ID: "+temp); return "844de23bfcf93801"; } //android的hidden API,需要通過反射調用 var SP = Java.use("android.os.SystemProperties"); SP.get.overload('java.lang.String').implementation = function (p1) { var tmp = this.get(p1); console.log("[*]"+p1+" : "+tmp); return tmp; } SP.get.overload('java.lang.String', 'java.lang.String').implementation = function (p1,p2) { var tmp = this.get(p1,p2) console.log("[*]"+p1+","+p2+" : "+tmp); return tmp; } // hook MAC var wifi = Java.use("android.net.wifi.WifiInfo"); wifi.getMacAddress.implementation = function () { var tmp = this.getMacAddress(); console.log("[*]real MAC: "+tmp); return tmp; } })