dy设备deviceid iid注册分析

article/2025/10/14 2:56:33

清楚缓存,重新打开app, 点击同意按钮,会触发设备注册;

在这里插入图片描述
很明显是一个post包,device_register
可以看到请求体加密了 那么 请求体是什么呢?

很老版本思路:都是直接明文注册
较老版本思路:在反编译后请求体通过一个bool来判断,是否走,ttencrypt;
这个地方可以hook明文也可以直接修改bool值,让抓包直接抓到明文;

正常情况下,是将请求体压缩后,走ttencrypt,进行密文注册;

我们接着往下走,看新版是否有变化;


看下params参数:

cdid:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
只找到个从SharedPreferences xml拿,没有就uuid;

openudid:

在这里插入图片描述


x_ss_stub:

这个值就很普通了,java层,post包的时候会把data转成字符串进行md5的一个值;

在这里插入图片描述


搜出来个这玩意,兄弟们想想这是干啥,注册,激活。。
在这里插入图片描述

ttencrypt:

搜一下:/service/2/device_register/

在这里插入图片描述

private boolean LIZ(String str, JSONObject jSONObject) {String[] strArr;boolean z;Throwable th;ChangeQuickRedirect changeQuickRedirect;String str2;ChangeQuickRedirect changeQuickRedirect2;ChangeQuickRedirect changeQuickRedirect3;l4Z l4z;String C;boolean z2;ChangeQuickRedirect changeQuickRedirect4 = LIZ;if (PatchProxy.isEnable(changeQuickRedirect4)) {PatchProxyResult proxy = PatchProxy.proxy(new Object[]{str, jSONObject}, this, changeQuickRedirect4, false, 5);if (proxy.isSupported) {return ((Boolean) proxy.result).booleanValue();}}try {byte[] bytes = str.getBytes("UTF-8");System.currentTimeMillis();ChangeQuickRedirect changeQuickRedirect5 = l5V.LIZ;if (PatchProxy.isEnable(changeQuickRedirect5)) {PatchProxyResult proxy2 = PatchProxy.proxy(PatchProxy.getEmptyArgs(), null, changeQuickRedirect5, true, 1);if (proxy2.isSupported) {strArr = (String[]) proxy2.result;if (strArr == null) {for (String str3 : strArr) {byte[] bArr = (byte[]) bytes.clone();if (!StringUtils.isEmpty(str3)) {Logger.debug();if (TextUtils.isEmpty(jSONObject.optString("device_id")) || TextUtils.isEmpty(jSONObject.optString("install_id"))) {z = true;} else {z = false;}try {ChangeQuickRedirect changeQuickRedirect6 = LIZ;if (PatchProxy.isEnable(changeQuickRedirect6)) {PatchProxyResult proxy3 = PatchProxy.proxy(PatchProxy.getEmptyArgs(), this, changeQuickRedirect6, false, 7);if (proxy3.isSupported) {z2 = ((Boolean) proxy3.result).booleanValue();}}ChangeQuickRedirect changeQuickRedirect7 = l5V.LIZ;if (PatchProxy.isEnable(changeQuickRedirect7)) {PatchProxyResult proxy4 = PatchProxy.proxy(PatchProxy.getEmptyArgs(), null, changeQuickRedirect7, true, 4);if (proxy4.isSupported) {z2 = ((Boolean) proxy4.result).booleanValue();}}if (l5V.LIZJ != null) {z2 = l5V.LIZJ.LIZ();}try {if (str3.indexOf(63) < 0) {new StringBuilder();C = O.C(str3, "?");} else {new StringBuilder();C = O.C(str3, "&");}str2 = NetUtil.sendEncryptLog(C, bArr, this.LIZJ.LJIILL, false, (String[]) null, (Map) null, (String) null, z, false);} catch (RuntimeException unused) {l4Q.LIZ(Monitor.Key.register, Monitor.State.f_to_bytes);try {str2 = NetUtil.doPost(str3, bytes, true, "application/json; charset=utf-8", false, (Map) null, z, false);String C2 = O.C("device_register response: ", str2);changeQuickRedirect2 = l4T.LIZ;if (PatchProxy.isEnable(changeQuickRedirect2)) {}changeQuickRedirect3 = l4T.LIZ;if (PatchProxy.isEnable(changeQuickRedirect3)) {}l4z = l4T.LIZIZ;if (l4z != null) {}if (str2 != null) {}l4Q.LIZ(Monitor.Key.register, Monitor.State.f_resp_error);} catch (Throwable th2) {th = th2;l4Q.LIZ(Monitor.Key.register, Monitor.State.f_net);l5O l5o = this.LIZJ;changeQuickRedirect = l5O.LIZIZ;if (PatchProxy.isEnable(changeQuickRedirect)) {}if (th instanceof CommonHttpException) {}}}String C22 = O.C("device_register response: ", str2);changeQuickRedirect2 = l4T.LIZ;if (PatchProxy.isEnable(changeQuickRedirect2) || !PatchProxy.proxy(new Object[]{C22}, null, changeQuickRedirect2, true, 1).isSupported) {changeQuickRedirect3 = l4T.LIZ;if (PatchProxy.isEnable(changeQuickRedirect3)) {try {} catch (Throwable th3) {th = th3;l4Q.LIZ(Monitor.Key.register, Monitor.State.f_net);l5O l5o2 = this.LIZJ;changeQuickRedirect = l5O.LIZIZ;if (PatchProxy.isEnable(changeQuickRedirect)) {PatchProxyResult proxy5 = PatchProxy.proxy(new Object[]{th}, l5o2, changeQuickRedirect, false, 21);if (proxy5.isSupported) {if (!((Boolean) proxy5.result).booleanValue()) {throw th;}}}if (th instanceof CommonHttpException) {int responseCode = ((CommonHttpException) th).getResponseCode();if (l5o2.LJJIIJ) {continue;} else if (responseCode < 200) {continue;} else if (responseCode == 301) {continue;} else if (responseCode != 302) {throw th;}} else {continue;}}}l4z = l4T.LIZIZ;if (l4z != null) {l4z.LIZ(C22, null);}}if (str2 != null || str2.length() == 0) {l4Q.LIZ(Monitor.Key.register, Monitor.State.f_resp_error);} else if (LIZ(new JSONObject(str2))) {return true;}} catch (Throwable th4) {th = th4;l4Q.LIZ(Monitor.Key.register, Monitor.State.f_net);l5O l5o22 = this.LIZJ;changeQuickRedirect = l5O.LIZIZ;if (PatchProxy.isEnable(changeQuickRedirect)) {}if (th instanceof CommonHttpException) {}}}}return false;}throw new IllegalArgumentException("url is null");}}strArr = (l5V.LIZIZ == null || l5V.LIZIZ.length <= 0 || StringUtils.isEmpty(l5V.LIZIZ[0])) ? new String[]{O.C("https://", l5V.LIZLLL, "/service/2/device_register/"), O.C("https://", l5V.LIZLLL, "/service/2/device_register/")} : l5V.LIZIZ;if (strArr == null) {}} catch (Throwable unused2) {l4Q.LIZ(Monitor.Key.register, Monitor.State.f_exception);return false;}}

可以看到整个注册这个接口的流程;
在这里插入图片描述
这一段代码是核心,看到是发请求去了;

import com.ss.android.common.applog.NetUtil;

str2 = NetUtil.sendEncryptLog(C, bArr, this.LIZJ.LJIILL, false, (String[]) null, (Map) null, (String) null, z, false);str2 = NetUtil.doPost(str3, bytes, true, "application/json; charset=utf-8", false, (Map) null, z, false);

这个时候,我们看出来已经和老版本有区别了,没有一个bool值来控制是否请求加密,而是直接去加密,若报错才会进行明文注册; 这是一点不同的地方;

doPost: 确实没啥东西;
在这里插入图片描述

sendEncryptLog:
在这里插入图片描述
在这里插入图片描述
如果包含str.contains(“/service/2/app_log/”)就去走ttEncrypt 加密,目前走else
在这里插入图片描述
else: 也是压缩 ttEncrypt 加密
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

ttEncrypt 该加密方式so层,libEncryptor.so

我们在看下,整体接口:
在这里插入图片描述
看到确实是发了很多接口,注册,激活,日志包等等;而且必须是六神注册,密文注册,这样设备才可用;

很明显的,device_register,app_alert ,app_log等等

为了权重更好,甚至注册完之后还需要发一些日志包,过一些验证码,提高设备权重;


http://chatgpt.dhexx.cn/article/TKkMly0I.shtml

相关文章

Redis 设计与实现: redisObject 数据结构,以及 Redis 的数据类型

redisObject 数据结构&#xff0c;以及 Redis 的数据类型 redisObject 是 Redis 类型系统的核心&#xff0c; 数据库中的每个键、值&#xff0c;以及 Redis 本身处理的参数&#xff0c; 都表示为这种数据类型。 redisObject 的定义位于 redis.h &#xff1a; /** Redis 对象…

(五)、Redis的RDB持久化---Redis设计与实现读书笔记

两个用于生成RDB文件的命令 save&#xff1a;会阻塞Redis服务器进程&#xff0c;直到RDB文件创建完毕&#xff0c;在阻塞期间&#xff0c;服务器不能处理任何命令请求bgsave&#xff1a;会派生出一个子进程&#xff0c;然后由子进程负责创建RDB文件&#xff0c;服务器经常(父进…

《redis设计与实现》 读书笔记

《redis设计与实现》 作者&#xff1a;黄健宏 读书笔记 一、前言 什么是redis&#xff1a; Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。简而言之redis就是放在远程网络上的一个key-va…

《Redis设计与实现》阅读:Redis底层研究之简单动态字符串SDS

除仅用于字符串字面量的情况外&#xff0c;对于可以被修改值的字符串的表示&#xff0c;Redis底层并没有采用C语言传统的字符串表示&#xff0c;即以空字符结尾的字符数组&#xff0c;而是采用专门为其设计的简单动态字符串作为其默认字符串表示&#xff0c;其英文全称为Simple…

Redis秒杀功能设计与实现

前言 抢购问题不仅是电商类项目中一个重要的业务,也是许多开发人员在进阶过程中绕不开的问题,关于抢购,如果理清了前后的逻辑和里面涉及到的几个关键性的问题,问题就迎刃而解了 抢购中的几个常见问题 如何设计抢购功能?(表结构,以及整体的抢购思路)不借助中间件如何实…

Redis设计与实现阅读总结(一)数据结构和对象

Redis设计与实现阅读总结&#xff08;一&#xff09;数据结构和对象 最近团队几个人和我聊了下&#xff0c;加上我自己平时的反思&#xff0c;我发现自己问题确实很多 其中一个问题就是&#xff0c;自己学习东西没有系统性&#xff0c;没有总结 这次的博客算是一个总结的开始。…

(六)、Redis的AOF持久化---Redis设计与实现读书笔记

redisServer关于AOF的数据结构 /***Redis 服务器类*/ struct redisServer{...//AOF缓存区sds aof_buf;... }当服务器执行完一个写命令后&#xff0c;会一协议格式将被执行的写命令追加到服务器类的aof_buf缓存区的末尾。 AOF文件的写入、同步 写入、同步概念 写入&#xff…

Redis | 第8章 发布订阅与事务《Redis设计与实现》

第8章 发布订阅与事务 前言1. 发布订阅1.1 频道的订阅与退订1.2 模式的订阅与退订1.3 发送消息1.4 查看订阅消息 2. 事务2.1 事务的实现2.2 WATCH 命令的实现2.3 事务的 ACID 性质 最后 前言 参考资料&#xff1a;《Redis设计与实现 第二版》&#xff1b; 第三部分为独立功能…

AOF -- Redis 设计与实现

Redis 分别提供了 RDB 和 AOF 两种持久化机制&#xff1a; RDB 将数据库的快照&#xff08;snapshot&#xff09;以二进制的方式保存到磁盘中。AOF 则以协议文本的方式&#xff0c;将所有对数据库进行过写入的命令&#xff08;及其参数&#xff09;记录到 AOF 文件&#xff0c…

Redis设计与实现学习总结

Redis设计与实现学习总结 本文主要对Redis的设计和实现原理做了一个介绍很总结&#xff0c;有些东西我也介绍的不是很详细准确&#xff0c;尽量在自己的理解范围内把一些知识点和关键性技术做一个描述。如有错误&#xff0c;还望见谅&#xff0c;欢迎指出。 这篇文章主要还是参…

Redis的设计与实现(1):5种基本数据结构的底层实现

一、简单的动态字符串&#xff08;SDS) Redis没有直接使用C语言传统的字符串表示&#xff0c;而是自己构建了一种名为简单动态字符串&#xff08;simple dynamic string,SDS&#xff09;的抽象类型&#xff0c;并将SDS作为Redis默认的字符串表示。 在Redis里&#xff0c;C字符…

Redis设计与实现总结

本文总结自《Redis设计与实现》一书&#xff0c;只打算总结Redis底层数据结构的实现。Redis的使用参考我的另一篇笔记Redis操作指南。 1 Redis概览 Redis是一个C语言编写的开源、非关系型内存数据库。它底层属于单线程、全内存操作&#xff0c;提供对象共享、引用计数和对象回…

Redis设计与实现

文章目录 第一部分&#xff1a;内部数据结构简单动态字符串(simple dynamic string)双端链表字典跳跃表 第二部分&#xff1a;内存映射数据结构整数集合intset压缩列表 redis数据类型对象处理机制(redisObject)字符串string哈希表hash列表list集合set有续集zset 第四部分&#…

redis的设计与实现

redis的设计和实现 第一部分、数据结构与对象 一、简单动态字符串&#xff1a; 在大多数情况下redis只会使用c字符串作为字面量&#xff0c;在大多情况下&#xff0c;redis使用SDS作为字符串表示。 比起C字符串&#xff0c;SDS具有五种优点&#xff1a; SDS结构里面会有一…

虚拟IP注册Nacos的问题

虚拟IP注册Nacos的问题 问题&#xff1a; A服务器有两个网卡&#xff0c;网卡 lo 绑定了 127.0.0.1 和一个虚拟IP&#xff0c;网卡 eth0 绑定了本地公网IP和一个虚拟IP。同样B服务器的网卡也是相同的配置&#xff0c;A、B服务器拥有的虚拟IP都是同一个地址。 当将A、B服务器部…

天翼云高可用虚拟IP(HAVIP)实践

产品概述 天翼云高可用虚拟IP&#xff08;High-Availability Virtual IP Address&#xff0c;简称HAVIP&#xff09;是一种可用独立创建和删除的私有网络IP地址资源。通过在VIP CIDR中申请一个私有网络IP地址&#xff0c;然后与高可用软件&#xff08;如高可用软件Keepalived&…

云服务器虚拟ip绑定主机,如何在云平台上给云主机中的Keepalived的虚拟IP绑定弹性IP?...

1、 查看Keepalived和网卡配置文件中虚拟IP地址 查看虚拟机keepalived.config配置文件可以看到本地IP地址为172.16.100.109&#xff0c;虚拟IP地址为172.16.100.104。 (图1 Keepalived配置文件) 查看虚拟机网卡的IP地址情况&#xff0c;可以看到本地IP和虚拟IP。 (图2 查看虚拟…

EasyConnect虚拟IP地址未分配

工作中遇到EasyConnect虚拟IP地址未分配&#xff0c;导致无法正常连接服务器进行调测工作。 检查是否安装成功

蒲公英联机平台的服务器虚拟IP,蒲公英客户端如何使用固定虚拟IP管理虚拟局域网的步骤是什么?...

蒲公英异地组网分为路由器成员与客户端成员两种。其中路由器成员下的电脑&#xff0c;可通过本地连接获取的局域网IP进行组网通信访问&#xff1b;而安装并登录了蒲公英客户端成员&#xff0c;则是通过系统随机分配的临时虚拟IP&#xff0c;来进行组网成员的通讯。当成员移除原…

服务器怎么做虚拟ip,如何在服务器上添加虚拟IP?看完原来如此简单!!

写在前面最近&#xff0c;有位小伙伴为了实现Nginx的高可用&#xff0c;在自己的服务器上搭建了一套Nginx集群&#xff0c;Nginx节点的服务器总共有3台。那么问题来了&#xff1a;如何对外只使用一个IP地址&#xff0c;通过某种策略来访问三个服务器节点上的Nginx&#xff1f;答…