免责声明

  1. 本博客所涉及的 爬虫技术、逆向分析方法 仅用于 学习、研究和技术交流
  2. 文中所有示例代码、工具和方法,均不得用于以下行为:
    • 未经授权的数据采集
    • 侵犯他人知识产权
    • 干扰或破坏正常业务系统
    • 任何违反国家法律法规的行为
  1. 因读者将本教程内容用于 非法用途 而产生的一切后果,由读者本人承担,本博客作者不承担任何法律及连带责任。
  2. 请在学习和实践过程中 遵守相关法律法规、网站/平台的服务协议及 robots 协议,合理合规地使用所学技术。

device-id

这其实就是设备id,可以直接随机生成就行,这里还是带着看一下

String a4 = com.bilibili.api.e.a();
if (!TextUtils.isEmpty(a4)) {aVar.h("Device-ID", a4);
}

直接看com.bilibili.api.e.a吧:

public class e {private static String a;public static String a() {return a;}public static void b(String str) {a = str;}
}

一样的也是b函数调用,可以用hook也可以直接查找用例,这里就不带大家找了:

public void run() {if (!j.a) {com.bilibili.api.d.b(j.c(this.a));}// 这是加密值com.bilibili.api.e.b(com.bilibili.lib.biliid.utils.f.a.c(this.a));
}

先找this.a:

a(Context context) {this.a = context;
}

context 上下文环境 —— 管理资源

Context 就是应用在 Android 系统中的运行环境,提供了操作资源、启动组件、获取系统服务的能力。

那么这里就不用管,直接看com.bilibili.lib.biliid.utils.f.a.c

public static String c(@Nullable Context context) {// 如果之前已经有缓存的 f13193c,就直接返回,避免重复计算if (!TextUtils.isEmpty(f13193c)) {return f13193c;}// 如果 context 是 null,啥也没法干,直接返回空字符串if (context == null) {return "";}// 从 e.k().f(context) 获取一个值(可能是存储的 ID)String f = c2.f.b0.c.a.e.k().f(context);f13193c = f;// 如果获取到的值非空,就直接返回if (!TextUtils.isEmpty(f)) {return f13193c;}// 如果还是没拿到,就调用 g(context) 生成一个新的 IDf13193c = g(context);// 把新生成的 ID 存起来(持久化到本地,比如 SharedPreferences)c2.f.b0.c.a.e.k().x(f13193c, context);// 返回最终的 IDreturn f13193c;
}// 前面很多都是从之前所说的存储中拿,重点看g函数
static String g(Context context) {// 1. 先调用 f(context) 获取一个基础值(可能是之前存储的 ID 或默认值)String f = f(context);// 2. 如果 f 太短(小于 4 个字符),说明无效,需要生成一个新的if (f.length() < 4) {// a. 获取 Android 系统 ID(每台设备唯一)String androidId = Settings.Secure.getString(context.getContentResolver(), "android_id");// b. 获取设备型号并进行处理(g.g(Build.MODEL))String modelHash = g.g(Build.MODEL);// c. 拼接 Android ID 和设备型号,形成一个新的字符串f = androidId + "@" + modelHash;}// 3. 对最终的字符串做进一步处理(b(f)return b(f);
}// 主要
String androidId = Settings.Secure.getString(context.getContentResolver(), "android_id"); // 之前获取过
// b. 获取设备型号并进行处理(g.g(Build.MODEL) 清除空格)
String modelHash = g.g(Build.MODEL);  // Build.MODEL:设备型号// c. 拼接 Android ID 和设备型号,形成一个新的字符串
f = androidId + "@" + modelHash;// b(f) : 自定义算法
public static String b(String str) {// 1. 将字符串转换成字节数组byte[] bytes = str.getBytes();// 2. 对第一个字节做异或运算,增加混淆性// bytes[0] = bytes[0] ^ (bytes.length & 255)bytes[0] = (byte) (bytes[0] ^ ((byte) (bytes.length & 255)));// 3. 从第二个字节开始,每个字节都和前一个字节异或for (int i = 1; i < bytes.length; i++) {bytes[i] = (byte) ((bytes[i - 1] ^ bytes[i]) & 255);}try {// 4. 将处理后的字节数组进行 Base64 编码(flags = 11)return new String(Base64.encode(bytes, 11));} catch (Exception unused) {// 5. 编码失败时,返回原始字符串return str;}
}

梳理好之后,就可以直接模拟出python代码(经过校验,是一致的):

def obfuscate_string(s: str) -> str:"""型号加密,不补 Base64 '='"""# 1. 将字符串转换成字节数组bytes_arr = bytearray(s.encode('utf-8'))if not bytes_arr:return s# 2. 对第一个字节做异或运算bytes_arr[0] = bytes_arr[0] ^ (len(bytes_arr) & 0xFF)# 3. 从第二个字节开始,每个字节都和前一个字节异或for i in range(1, len(bytes_arr)):bytes_arr[i] = (bytes_arr[i - 1] ^ bytes_arr[i]) & 0xFFtry:# 4. Base64 编码,URL-safe,并去掉结尾 '='encoded = base64.urlsafe_b64encode(bytes_arr)return encoded.decode('utf-8').rstrip('=')except Exception:# 5. 编码失败时返回原始字符串return sdef get_device_id():"""获取device_id"""androidId = '5d01aa95f9aca38c'models = ["Pixel 7", "Redmi K50", "ONEPLUS 9 Pro", "Vivo V23", "MI 12X","SM-G998B", "Xiaomi 11T", "OPPO Reno8", "Pixel 7 Pro", "Lenovo Legion Y90","Realme GT Neo3", "MI 11 Ultra", "Redmi Note 11", "ONEPLUS A6013", "VOG-L29","P50 Pro", "OPPO Find X5", "Vivo X80", "Pixel 6a", "Redmi K40","SM-G991U", "Xiaomi 12S", "Realme GT", "ONEPLUS 8T", "Vivo Y76","OPPO Reno7", "MI 10 Pro", "Pixel 5", "Lenovo K12 Pro", "Redmi Note 10","SM-G990F"]model = random.choice(models)modelHash = model.replace(' ', '').strip()return obfuscate_string(androidId + "@" + modelHash)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/96676.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/96676.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/96676.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C++数据结构之循环链表

概述循环链表本质上也是一个单向或双向链表&#xff0c;但其最后一个节点的指针并不指向NULL&#xff0c;而是指向链表的第一个节点&#xff0c;从而形成一个闭合的环。这种结构使得在遍历链表时&#xff0c;可以从任意一个节点开始&#xff0c;并最终回到起始点。音乐播放软件…

Mongodb的教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、mongodb是什么&#xff1f; 二、mongodb的下载与安装教程 三、mongodb的常见操作 总结 前言 在当今数据驱动的世界中&#xff0c;数据库技术是构建高效…

MySQL视图有什么用?一文读懂虚拟表的六大核心价值

引言 在数据库开发中&#xff0c;你是否遇到过这样的困境&#xff1a;业务人员需要查看复杂关联数据却难以理解多表JOIN&#xff0c;或需要限制某些用户只能访问特定字段&#xff1f;MySQL视图正是为此设计的"数据透视镜"。本文将通过官方定义、典型场景和最佳实践&a…

ubuntu24.04 frps服务器端自动启动设置【2025-08-20】

Ubuntu 24.04采用systemd作为默认的init系统&#xff0c;我们可以通过创建systemd服务单元文件来实现开机自启动。以下是具体实施步骤&#xff1a;创建服务文件使用文本编辑器创建服务配置文件&#xff1a;sudo nano /etc/systemd/system/frps.service编写服务配置内容在文件中…

数据结构与算法-字符串、数组和广义表(String Array List)

3 字符串、数组和广义表&#xff08;String Array List&#xff09; 3.1 字符串&#xff08;String&#xff09; 3.1.1 串的顺序存储 a. 定长顺序&#xff1a; #define MAXLEN 255 // 串的定长顺序存储结构 typedef struct {char ch[MAXLEN 1]; // 字符串数据&#xff0c;…

【网络运维】Shell 脚本编程:if 条件语句

Shell 脚本编程&#xff1a;if 条件语句 if 条件语句概述 if 条件语句是 Linux Shell 脚本编程中最基础且使用频率最高的控制结构之一&#xff0c;其语义类似于自然语言中的“如果…那么…”。熟练掌握 if 语句的用法&#xff0c;是成为一名合格运维工程师的基本要求。 if 语句…

浮点型的位结构和表示的值

位结构float 各部分的含义 符号位&#xff1a; 为 0 表示正数&#xff0c;为 1 表示负数。 指数部分&#xff1a; 指数部分是一个移码。指数部分有 8 位&#xff0c;首先当成无符号整型&#xff0c;则值域是 [0, 255] .因为是移码&#xff0c;所以 移码值 无符号整型值 - 127 …

39_基于深度学习的行人摔倒检测识别系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)

目录 项目介绍&#x1f3af; 功能展示&#x1f31f; 一、环境安装&#x1f386; 环境配置说明&#x1f4d8; 安装指南说明&#x1f3a5; 环境安装教学视频 &#x1f31f; 二、数据集介绍&#x1f31f; 三、系统环境&#xff08;框架/依赖库&#xff09;说明&#x1f9f1; 系统环…

【系统分析师】高分论文:论企业数据治理

【摘要】 2022年3月&#xff0c;我作为系统分析师及IT 负责人&#xff0c;参加了我司的企业级数据平台建设项目&#xff0c;该项目作为我司在企业数字化转型过程中重要的里程碑&#xff0c;在我司数字化运营中扮演着关键的角色。该项目主要包含企业级数据仓库&#xff0c;数据治…

Seata原理分析

简介Apache Seata™ (incubating) 是什么&#xff1f;Seata 是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。在 Seata 开源之前&#xff0c;其内部版本在阿里系内部一直扮演着应用架构层数据一致性的中间件角色&#x…

力扣 30 天 JavaScript 挑战 第38天 (第九题)学习了 语句表达式的区别 高级函数 promise async await 节流

开始答题 版本一&#xff1a; /*** param {Function} fn* return {Function}*/ var once function(fn) {let runCount0return function(...args){runCountrunCount 1 ? return fn(...args) :return undefined} };/*** let fn (a,b,c) > (a b c)* let onceFn once(fn)…

25年八月份宁德时代社招部分岗位入职Verify测评演绎数字推理SHL题型变更、题库使用说明

开始测评前&#xff0c;请注意:1、挑选一个安静的环境&#xff0c;选择一台网速正常且无任何网络端口限制的电脑进行测评;2、移动设备无法兼容远程监考功能&#xff0c;请使用配备有可正常运作的摄像头的台式机或笔记本电脑&#xff0c;建议使用最新版本的Chrome&#xff0c;Fi…

【KO】前端面试四

以下是剩余题目的详细解答,结合前端知识体系和实际应用场景展开: 91. JS 放在 head 里和放在 body 里有什么区别? 对比维度 放在 <head> 放在 <body> 加载阻塞性 会阻塞页面渲染,需等待 JS 下载/执行完成后,才继续渲染页面 一般放在 </body> 前,页面渲…

[Vid-LLM] 数据集 | 基准测试

第5章&#xff1a;数据集与基准测试 在前一章中&#xff0c;我们探讨了**视频大语言模型(Vid-LLMs)**能够执行的各种"工作"或"功能"&#xff0c;从视频总结到充当智能代理。 我们了解了它们的构建方式和扮演的角色。 但这里有个关键问题&#xff1a;这些惊…

34、扩展仓储管理系统 (跨境汽车零部件模拟) - /物流与仓储组件/extended-warehouse-management

76个工业组件库示例汇总 扩展仓储管理系统 (跨境汽车零部件模拟) 概述 这是一个高级的仓储管理系统 (WMS) 模拟组件&#xff0c;专为展示跨境汽车零部件的复杂物流场景而设计。它模拟了从海外供应商发货&#xff0c;经过海运/空运、清关、质检&#xff0c;到最终入库上架&am…

nodejs koa留言板案例开发

包含功能 登录注册(不开放注册只是用固定的账号信息) 查看列表 查看详情 发布信息 编辑信息 删除信息 项目接口 npm init -y npm install koa --save npm istall koa-router --save (旧版本) 或者 npm install koa/router --save &#xff08;新版本&#xff09; npm instal…

4+ 图论高级算法

强连通分量 基础概念 强连通&#xff1a;在有向图 GGG 中&#xff0c;如果两个点 uuu 和 vvv 是互相可达的&#xff0c;即从 uuu 出发可以到达 vvv , 从 vvv 也可以到达 uuu , 则称 uuu 和 vvv 是强连通的。如果 GGG 中任意两个点都是互相可达的&#xff0c;则称 GGG 是强连通图…

从罗永浩访谈李想中学习现代家庭教育智慧

引言 在这个信息爆炸的时代&#xff0c;每个父母都在寻找培养孩子的最佳方式。在罗永浩与理想汽车创始人李想的深度访谈中&#xff0c;我们看到了一个成功企业家童年成长的真实样本。李想的成长经历为现代家庭教育提供了许多值得深思的启示。 一、正义感与乐观精神的种子 李想回…

AI实现超级客户端打印 支持APP 网页 小程序 调用本地客户端打印

核心思路都是&#xff1a;需要一个安装在用户电脑上的“中间人”程序&#xff08;本地客户端&#xff09;来接管打印任务&#xff0c;然后通过某种通信方式命令这个客户端进行打印。下面我将分平台详细阐述各种实现思路、优缺点和适用场景。一、核心思路与公共组件&#xff1a;…

Java集合(Collection、Map、转换)

✅ 推荐使用 ❌ 已过时 1. Collection Collection 是集合框架的根接口之一&#xff0c;它是所有单列集合&#xff08;如 List、Set、Queue 等&#xff09;的公共父接口。Collection 接口定义了集合的基本操作&#xff0c;比如添加、删除、遍历等。 Collection ├── List │ …