抖音device_register设备注册分析学习

抓包可得:https://log.snssdk.com/service/2/device_register/

数据的大致是如下数据,然后将数据进行压缩加密就可以了

{“header”:{“magic_tag”:”ss_app_log”,””build_serial”:”*”,”version_code”:*,”timezone”:8,” +
“”mc”:”” + * + “”,”sim_serial_number”:[{“sim_serial_number”:”*”}],” +”sim_region”:”CN”,”region”:”CN”,”package”:”com.ss.android.ugc.aweme”,”        “”appkey”:”*”,”app_version”:”*”,”resolution”:”1280×720″,”aid”:1128,”  “”display_density”:”hdpi”,”sig_hash”:”*”,” +  “”not_request_sender”:0,”openudid”:””+ sOpenId +”*”,release_build”:”*”,”tz_offset”:*,”rom_version”:”*”,” +
“”rom”:”*”,”clientudid”:”” +*+ “”,”os_api”:*,”mcc_mnc”:”*”,” +
“”sdk_version”:”*”,”device_id”:””+ sDeviceId+””,”*”:””+ * +””,”device_brand”:”*”,” +
“manifest_version_code”:*,”serial_number”:”*”,”os_version”:”*”,” +
“”display_name”:”抖音短视频”,”cpu_abi”:”armeabi-v7a”,”update_version_code”:*,”language”:”zh”,” +
“”channel”:”*”,”tz_name”:”Asia\\/Shanghai”,”density_dpi”:240},”_gen_time”:”” “” +””}

包含了各种设备的一些消息,首先使用标准Gzip压缩参数然后调AES进行加密

以上是百度搜索的前辈的结果,可以得知具体的流程,对我们分析起来会有很大的帮助。

分析笔记

版本10.5.0

拖入JADX搜索文本device_register定位到com.ss.android.c.b;类的c方法

  1. private boolean c(String str) {
  2. StringBuilder stringBuilder;
  3. String stringBuilder2;
  4. byte[] bytes = str.getBytes("UTF-8");
  5. if (m.a(a.a)) {
  6. stringBuilder = new StringBuilder("http://");
  7. stringBuilder.append(a.c);
  8. stringBuilder.append("/service/2/device_register/");
  9. stringBuilder2 = stringBuilder.toString();
  10. } else {
  11. stringBuilder2 = a.a;
  12. }
  13. String d = u.d(f.b(b.this.i, stringBuilder2), true);
  14. long currentTimeMillis = System.currentTimeMillis();
  15. boolean z = currentTimeMillis - b.this.o < 600000;
  16. b.this.o = currentTimeMillis;
  17. byte[] bArr = (byte[]) bytes.clone();
  18. if (a.b != null ? a.b.a() : true) {
  19. try {
  20. stringBuilder2 = u.h(d, bArr, b.this.i, z);//////提交加密
  21. } catch (RuntimeException e) {
  22. if (z) {
  23. stringBuilder = new StringBuilder();
  24. stringBuilder.append(d);
  25. stringBuilder.append("&config_retry=b");
  26. d = stringBuilder.toString();
  27. }
  28. stringBuilder2 = h.d.g(d, bytes, "application/json; charset=utf-8");
  29. }
  30. } else {
  31. if (z) {
  32. stringBuilder = new StringBuilder();
  33. stringBuilder.append(d);
  34. stringBuilder.append("&config_retry=b");
  35. stringBuilder2 = stringBuilder.toString();
  36. } else {
  37. stringBuilder2 = d;
  38. }
  39. stringBuilder2 = h.d.g(stringBuilder2, bytes, "application/json; charset=utf-8");
  40. }
  41. if (stringBuilder2 == null) {
  42. return false;
  43. }
  44. if (stringBuilder2.length() == 0) {
  45. return false;
  46. }
  47. boolean z2;
  48. JSONObject jSONObject = new JSONObject(stringBuilder2);
  49. b.this.m = System.currentTimeMillis();
  50. b.this.g = c.e;
  51. Editor edit = b.this.j.edit();
  52. edit.putLong("last_config_time", b.this.m);
  53. edit.putInt("last_config_version", b.this.g);
  54. stringBuilder2 = b.this.p;
  55. String g = b.this.h.g(null);
  56. boolean a = m.a(g);
  57. String optString = jSONObject.optString("install_id", null);
  58. d = jSONObject.optString("device_id", null);
  59. if (m.a(optString) || optString.equals(b.this.p) || optString.equalsIgnoreCase("0") || optString.equalsIgnoreCase("None")) {
  60. z2 = false;
  61. } else {
  62. b.this.p = optString;
  63. if (!m.a(stringBuilder2)) {
  64. try {
  65. JSONObject jSONObject2 = new JSONObject();
  66. jSONObject2.put("old_id", stringBuilder2);
  67. jSONObject2.put("new_id", optString);
  68. b.y("umeng", "iid_change", jSONObject2);
  69. } catch (Exception e2) {
  70. }
  71. }
  72. z2 = true;
  73. }
  74. try {
  75. if (!(m.a(d) || d.equals(g) || d.equalsIgnoreCase("0") || d.equalsIgnoreCase("None"))) {
  76. if (!m.a(g)) {
  77. try {
  78. stringBuilder2 = b.this.h.b();
  79. optString = b.this.h.f();
  80. String c = b.this.h.c();
  81. String d2 = b.this.h.d();
  82. String[] e3 = b.this.h.e();
  83. JSONObject jSONObject3 = new JSONObject();
  84. jSONObject3.put("old_id", g);
  85. jSONObject3.put("new_id", d);
  86. jSONObject3.put("openudid", stringBuilder2);
  87. jSONObject3.put("clientudid", c);
  88. if (!m.a(optString)) {
  89. jSONObject3.put("udid", optString);
  90. }
  91. if (!m.a(d2)) {
  92. jSONObject3.put("serial_number", d2);
  93. }
  94. if (e3 != null && e3.length > 0) {
  95. jSONObject3.put("sim_serial_number", Arrays.toString(e3));
  96. }
  97. b.y("umeng", "did_change", jSONObject3);
  98. } catch (Exception e4) {
  99. }
  100. }
  101. z2 = true;
  102. }
  103. if (!(m.a(d) || d.equalsIgnoreCase("0"))) {
  104. d.equalsIgnoreCase("None");
  105. }
  106. if (z2) {
  107. try {
  108. b.this.k.put("install_id", b.this.p);
  109. b.this.k.put("device_id", d);
  110. edit.putString("install_id", b.this.p);
  111. edit.putString("device_id", d);
  112. } catch (Exception e5) {
  113. }
  114. }
  115. edit.commit();
  116. if (z2) {
  117. b.this.h.g(b.this.j);
  118. b.this.x();
  119. }
  120. b.z(true, a);
  121. return true;
  122. } catch (Exception e6) {
  123. e6.printStackTrace();
  124. return false;
  125. }
  126. }

之后 package com.ss.android.common.applog.u类的h方法

  1. public static String h(String str, byte[] bArr, Context context, boolean z) {
  2. Throwable th = true;
  3. if (m.a(str) || bArr == null || bArr.length <= 0) {
  4. return null;
  5. }
  6. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(8192);
  7. GZIPOutputStream gZIPOutputStream = new GZIPOutputStream(byteArrayOutputStream);
  8. try {
  9. Editor edit;
  10. gZIPOutputStream.write(bArr);
  11. byte[] toByteArray = byteArrayOutputStream.toByteArray();
  12. if (!i) {
  13. synchronized (l) {
  14. try {
  15. SharedPreferences sharedPreferences = context.getSharedPreferences(m, 0);
  16. k = sharedPreferences.getInt("app_log_encrypt_faild_count", 0);
  17. edit = sharedPreferences.edit();
  18. edit.putInt("app_log_encrypt_faild_count", k + 1);
  19. edit.apply();
  20. i = true;
  21. } catch (Throwable th2) {
  22. }
  23. }
  24. }
  25. Throwable th3;
  26. if (k < 3) {
  27. byte[] a = EncryptorUtil.a(toByteArray, toByteArray.length);///////NATIVE层SO方法
  28. if (j) {
  29. th3 = th;
  30. toByteArray = a;
  31. } else {
  32. synchronized (l) {
  33. try {
  34. edit = context.getSharedPreferences(m, 0).edit();
  35. if (k > 2) {
  36. k -= 2;
  37. } else {
  38. k = 0;
  39. }
  40. edit.putInt("app_log_encrypt_faild_count", k);
  41. edit.apply();
  42. j = true;
  43. } catch (Throwable th4) {
  44. }
  45. }
  46. th3 = th;
  47. toByteArray = a;
  48. }
  49. } else {
  50. th3 = null;
  51. }
  52. if (toByteArray == null || th3 == null) {
  53. throw new RuntimeException("encrypt failed");
  54. }
  55. StringBuilder stringBuilder = new StringBuilder();
  56. stringBuilder.append(str);
  57. stringBuilder.append("&tt_data=a");
  58. String stringBuilder2 = stringBuilder.toString();
  59. if (z) {
  60. StringBuilder stringBuilder3 = new StringBuilder();
  61. stringBuilder3.append(stringBuilder2);
  62. stringBuilder3.append("&config_retry=b");
  63. stringBuilder2 = stringBuilder3.toString();
  64. }
  65. HashMap hashMap = new HashMap();
  66. hashMap.put("Content-Type", "application/octet-stream;tt-data=a");
  67. return com.bytedance.a.c.h.d.c(stringBuilder2, toByteArray, hashMap);
  68. } catch (Throwable th5) {
  69. th = th5;
  70. return null;
  71. } finally {
  72. gZIPOutputStream.close();
  73. }
  74. }

package com.bytedance.frameworks.encryptor.EncryptorUtil类

  1. public class EncryptorUtil {
  2. private static native byte[] ttEncrypt(byte[] bArr, int i);
  3.  
  4. static {
  5. try {
  6. System.loadLibrary("Encryptor");
  7. } catch (UnsatisfiedLinkError e) {
  8. e.printStackTrace();
  9. }
  10. }
  11.  
  12. public static byte[] a(byte[] bArr, int i) {
  13. if (bArr != null && i > 0) {
  14. try {
  15. if (bArr.length == i) {
  16. return ttEncrypt(bArr, i);
  17. }
  18. } catch (Throwable unused) {
  19. return null;
  20. }
  21. }
  22. return null;
  23. }
  24. }

具体需要什么参数,后面需要HOOK抖音接口得出具体数据。时间有限,暂时到这。

发表评论

邮箱地址不会被公开。 必填项已用*标注