最近再研究設備唯一碼的問題,發現Huluwa的獲取機制有點意思,就稍微研究了下,
先貼出其獲取唯一碼代碼邏輯:
具體類名為
com.common.use.util.UCodeUtil
類中代碼
public class UCodeUtil {
public static String getLocalUUID(Context context) {
File file = new File(PathUtils.getExternalStoragePath() + File.separator + ".h/ucode.bat");
if (!file.exists()) {
String trim = getUniqueCode(context).trim();
if (!writeLocalUUID(trim)) {
return trim;
}
}
String readFile2String = FileIOUtils.readFile2String(file);
if (StringUtils.isEmpty(readFile2String)) {
return getUniqueCode(context).trim();
}
return StringUtils.replaceBlank(readFile2String);
}
private static boolean writeLocalUUID(String str) {
if (StringUtils.isEmpty(str)) {
return false;
}
String str2 = PathUtils.getExternalStoragePath() + File.separator + ".h/ucode.bat";
if (!FileUtils.createOrExistsFile(str2)) {
return false;
}
FileIOUtils.writeFileFromBytesByChannel(str2, str.getBytes(), true);
return true;
}
public static String getUniqueCode(Context context) {
StringBuilder sb = new StringBuilder();
String model = getModel();
if (StringUtils.isNotEmpty(model)) {
sb.append(model);
sb.append(":");
Log.e("UniqueCode", "model:" + model);
}
String imei = getImei(context);
if (StringUtils.isNotEmpty(imei)) {
sb.append(imei);
sb.append(":");
Log.e("UniqueCode", "imei:" + imei);
}
String macAddress = getMacAddress(context);
if (StringUtils.isNotEmpty(macAddress)) {
sb.append(macAddress);
sb.append(":");
Log.e("UniqueCode", "macAddress:" + macAddress);
}
String serialNo = getSerialNo(context);
if (StringUtils.isNotEmpty(serialNo)) {
sb.append(serialNo);
Log.e("UniqueCode", "serialNo:" + serialNo);
}
if (StringUtils.isEmpty(imei) && StringUtils.isEmpty(macAddress) && StringUtils.isEmpty(serialNo)) {
String uuid = UUID.randomUUID().toString();
Log.e("UniqueCode", "strUUid:" + uuid);
sb.append(uuid);
}
return EncryptUtils.encryptMD5ToString(sb.toString());
}
private static String getModel() {
return Build.MODEL;
}
private static String getImei(Context context) {
try {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService("phone");
if (ContextCompat.checkSelfPermission(context, "android.permission.READ_PHONE_STATE") != 0) {
return "";
}
if (Build.VERSION.SDK_INT >= 26) {
return telephonyManager.getImei();
}
return telephonyManager.getDeviceId();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
private static String getMacAddress(Context context) {
WifiInfo connectionInfo = ((WifiManager) context.getApplicationContext().getSystemService("wifi")).getConnectionInfo();
if (connectionInfo != null && !connectionInfo.getMacAddress().equals("02:00:00:00:00:00")) {
return connectionInfo.getMacAddress();
}
try {
for (T t : Collections.list(NetworkInterface.getNetworkInterfaces())) {
if (t.getName().equalsIgnoreCase("wlan0")) {
byte[] hardwareAddress = t.getHardwareAddress();
if (hardwareAddress == null) {
return "";
}
StringBuilder sb = new StringBuilder();
int length = hardwareAddress.length;
for (int i = 0; i < length; i++) {
sb.append(String.format("%02X:", new Object[]{Byte.valueOf(hardwareAddress[i])}));
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
private static String getSerialNo(Context context) {
if (Build.VERSION.SDK_INT < 26) {
return Build.SERIAL;
}
if (ContextCompat.checkSelfPermission(context, "android.permission.READ_PHONE_STATE") != 0) {
return Build.SERIAL;
}
return Build.getSerial();
}
}
核心獲取唯一碼函式就是getLocalUUID函式,具體獲取邏輯就是先讀取/sdcard/.h/ucode.bat內容,其內容就是當前設備唯一碼,若是讀取不到就開始獲取設備資訊,獲取的設備資訊有MODEL,IMEI,MAC,SERIAL,然后拼接后獲取其MD5的哈希值就是設備唯一碼,然后存盤在ucode.bat檔案中,
不過經測驗應該在其內部資料里也存了一份,先獲取那一份,若是不存在,則再獲取ucode.bat內容,
因此,有心人只要修改了ucode.bat內容,然后清除軟體資料再重新打開,就可以再次獲取試用資格了,
建議其增強檢測機制,比如檢測IP,地理位置,或者把獲取設備資訊的邏輯放在so層,增加so層混淆,還有最好不要把設備唯一碼放在外部存盤,不過最好還是取消試用機制,可以嘗試下試看機制,這樣就杜絕了可以獲取整個視頻資料的可能,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/242474.html
標籤:其他
