当前位置: 首页 > news >正文

JS逆向:由 words 、sigBytes 引发的一系列思考与实践

【作者主页】:小鱼神1024

【擅长领域】:JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等

在做JS逆向时,你是否经常看到 wordssigBytes 这两个属性呢,比如:

{words: [2003644449, 1081552243, 594308145, 1718382376], sigBytes: 16
}

如果发现了它们的踪迹,那恭喜你了。基本可以确定,网站是使用 crypto-js 库中某一个加密算法实现加密的。

words 、sigBytes 它们是什么

crypto-js 这个流行的 JavaScript 加密库中,wordssigBytesCryptoJS.lib.WordArray 对象的两个重要属性。

words 数组是 WordArray 对象的主体,它用于存储加密数据。在 crypto-js 中,一个 word 是由32位(或者说是4个字节)组成的,因此每个元素在 words 数组中实际上可以表示4个字节的数据。

在计算机系统中,一个32位的整数可以存储从-2,147,483,648到2,147,483,647的整数值(如果是有符号整数),或者从0到4,294,967,295(如果是无符号整数)。这种表示范围是因为32位可以表示2^32(即4,294,967,296)个不同的值。

补充

在计算机和信息技术中,32位(4字节)是一个常用的数据大小单位,用来表示数据的存储或处理容量。具体来讲:

  • 1位(bit):是计算机数据的最基本单位,代表一个二进制数字,即0或1。
  • 1字节(Byte):通常由8位组成,是基本的数据存储单位。1字节可以表示0到255(或者在二进制中是00000000到11111111)之间的一个数值。
  • 32位:则相当于4字节(4 Bytes),因为1字节是8位,所以4字节就是4 * 8 = 32位。

如何生成 WordArray 对象

两种解决办法:

通过 CryptoJS.enc.Utf8.parse 生成

如果已知utf8编码的明文,则可以使用 CryptoJS.enc.Utf8.parse 方法生成 WordArray 对象。

const CryptoJS = require("crypto-js");// 生成 WordArray 对象
const keyWordArray = CryptoJS.enc.Utf8.parse("wm0!@w-s#ll1flo(");
console.log(keyWordArray);
通过 CryptoJS.lib.WordArray.create 生成
const CryptoJS = require("crypto-js");
const words = [2003644449, 1081552243, 594308145, 1718382376]; // 32位整数数组(words数组)
const sigBytes = 16;// 使用 CryptoJS 转换字节数组到 WordArray
const keyWordArray = CryptoJS.lib.WordArray.create(words, sigBytes);console.log(keyWordArray);

如何将 WordArray 转化为 UTF-8 字符串

const CryptoJS = require("crypto-js");
const wordArrayBytes = {words: [ 2003644449, 1081552243, 594308145, 1718382376 ],sigBytes: 16
};// 将 WordArray 转换为 UTF-8 字符串
const key = CryptoJS.enc.Utf8.stringify(wordArrayBytes);
console.log(key);// wm0!@w-s#ll1flo(

如何将 WordArray 转化为十六进制Hex

const CryptoJS = require("crypto-js");
const wordArrayBytes = {words: [ 2003644449, 1081552243, 594308145, 1718382376 ],sigBytes: 16
};// 将 WordArray 转换为十六进制Hex
const key = CryptoJS.enc.Hex.stringify(wordArrayBytes);
console.log(key);// 776d302140772d73236c6c31666c6f28

那如何判断一个字符串是否为有效的十六进制字符串,可以检查以下几点:

  • 字符串长度:十六进制字符串的长度应该是偶数。

  • 字符范围:十六进制字符串只能包含 0-9 以及 a-f 和 A-F 这些字符。

可以编写一个函数来实现这个逻辑:

// 判断一个字符串是否为十六进制字符串的函数
function isHexString(str) {// 检查长度是否为偶数if (str.length % 2 !== 0) {return false;}// 使用正则表达式检查字符串是否只包含合法的十六进制字符(0-9, a-f, A-f)const hexRegex = /^[0-9a-fA-F]+$/;return hexRegex.test(str);
}// 示例测试
const testHexString1 = "776d302140772d73236c6c31666c6f28";
const testHexString2 = "1a2b3g4d5e"; // 包含非法字符 'g'
const testHexString3 = "123";        // 长度为奇数console.log(isHexString(testHexString1)); // 输出:true
console.log(isHexString(testHexString2)); // 输出:false
console.log(isHexString(testHexString3)); // 输出:false

WordArray整数数组、Hex十六进制、ByteArray字节数组、UTF-8字符串之间的相互转换

// 判断一个数组是否为字节数组(每个元素为0到255之间的整数)
function isByteArray(arr) {// 首先检查是否为数组if (!Array.isArray(arr)) {return false;}// 检查每个元素是否为0到255之间的整数for (let i = 0; i < arr.length; i++) {if (typeof arr[i] !== 'number' || arr[i] < 0 || arr[i] > 255 || !Number.isInteger(arr[i])) {return false;}}return true;
}// 将字节数组转换为十六进制字符串的函数
function bytesToHex(bytes) {if (!isByteArray(bytes)) {throw new Error('输入必须是字节数组');}return bytes.map(byte => byte.toString(16).padStart(2, '0')).join('');
}// 将十六进制字符串转换为字节数组的函数
function hexToBytes(hex) {let bytes = [];for (let c = 0; c < hex.length; c += 2) {bytes.push(parseInt(hex.substr(c, 2), 16));}return bytes;
}// 将32位整数数组(words数组)转换为字节数组的函数
function wordsToBytes(words) {let bytes = [];for (let i = 0; i < words.length; i++) {let word = words[i];bytes.push((word >> 24) & 0xFF);bytes.push((word >> 16) & 0xFF);bytes.push((word >> 8) & 0xFF);bytes.push(word & 0xFF);}return bytes;
}// 将字节数组转换为UTF-8字符串的函数
function bytesToStringUTF8(bytes) {if (!isByteArray(bytes)) {throw new Error('输入必须是字节数组');}return new TextDecoder('utf-8').decode(new Uint8Array(bytes));
}let key = { words: [2003644449, 1081552243, 594308145, 1718382376], sigBytes: 16 };// 将key的words数组转换为字节数组
let keyBytes = wordsToBytes(key.words);// 将字节数组转换为十六进制字符串,测试使用
let keyHex = bytesToHex(keyBytes);// 打印key和iv的十六进制字符串
console.log("十六进制Hex:", keyHex);// 将十六进制字符串还原为字节数组,以确保转换过程的无损失和准确性,测试使用
let keyBytesFromHex = hexToBytes(keyHex);// 将字节数组转换为UTF-8字符串,得到最终的字符串表示
let keyString = bytesToStringUTF8(keyBytes);// 打印key和iv的UTF-8字符串表示
console.log("字符串UTF-8:", keyString);

用 Uint8Array 生成字节数组

Uint8Array 的特点包括以下几点:

  • 无符号整数:Uint8Array 存储的是无符号的 8 位整数(0 到 255),因此每个元素的取值范围是从 0 到 255。这意味着每个元素可以表示一个字节的数据,适用于处理字节数据和二进制数据。

  • 定长数组:Uint8Array 是一种定长数组,它的长度在创建时就已经确定,并且不能动态改变。这有助于提高操作效率和性能,尤其在处理大量数据时非常有用。

// 用 Uint8Array 生成字节数组
const uint8Array = Uint8Array.from([119, 109, 48, 33, 64,119, 45, 115, 35, 108,108, 49, 102, 108, 111,40
]);// 使用 TextDecoder 将 bytes 转换为字符串
const textDecoder = new TextDecoder();
const decodedString = textDecoder.decode(uint8Array);console.log(decodedString);// wm0!@w-s#ll1flo(

为什么 AES、DES等加密时,要先转化 WrodArray

// AES 加密
function encrypt(word) {// 转化为 WordArrayconst iv = CryptoJS.enc.Utf8.parse("0102030405060708");// 转化为 WordArrayconst key = CryptoJS.enc.Utf8.parse('wm0!@w-s#ll1flo(');const encrypted = CryptoJS.AES.encrypt(word, key, {iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7})return encrypted.toString();
}

转化为32位二进制数据再进行加密是出于以下几个主要原因:

  • 加密算法的要求:几乎所有的现代加密算法,包括对称加密(如AES)和非对称加密(如RSA),在底层操作时都是以二进制数据形式工作的。这是因为加密算法在设计时需要操作位(bit)和字节(byte),而不是高级语言中的文本或数字等类型。因此,将数据转换为二进制形式是执行这些算法的必要步骤。

  • 安全性增强:通过转换为二进制数据,可以确保在加密过程中原始数据的内容不会因其格式或结构而泄露信息。此外,某些加密方式(如块加密)要求数据以特定大小的块来处理。将数据预先转化为二进制形式,可以更容易地按块对数据进行操作和填充。

  • 性能优化:直接对二进制数据进行操作比对高级数据类型(如字符串或对象)进行操作要有效率得多。加密和解密操作通常需要大量的数据处理工作,特别是在数据量大或需求高性能的应用场景中。预先将数据转换为二进制格式,可以最大限度地减少处理时间和资源消耗。

创作不易,动动您发财的小手,点赞关注一波,支持我创作更多对您有帮助的文章!

相关文章:

JS逆向:由 words 、sigBytes 引发的一系列思考与实践

【作者主页】&#xff1a;小鱼神1024 【擅长领域】&#xff1a;JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 在做JS逆向时&#xff0c;你是否经常看到 words 和 sigBytes 这两个属性呢&#xff0c;比如&#xff…...

计算机的错误计算(十五)

摘要 介绍历史上由于计算精度问题引起的灾难或事件。 今天换个话题&#xff0c;说说历史上曾经发生过的一些事件。 1961 年 , 美国麻省理工学院气象学家洛伦兹在仿真天气预报时 , 将 0.506127 舍入到 0.506 , 所得计算结果大相径庭 ! 这种“差之毫厘 , 谬以千里”的现象…...

制作img文件

安装软件包 sudo apt-get install dosfstools dump parted kpartx 创建空白img文件 sudo dd if/dev/zero ofraspberrypi.img bs1M count4000 给img文件分区 sudo parted raspberrypi.img --script -- mklabel msdos sudo parted raspberrypi.img --script -- mkpart primar…...

GB28181视频汇聚平台EasyCVR接入Ehome设备视频播放出现异常是什么原因?

多协议接入视频汇聚平台EasyCVR视频监控系统采用了开放式的架构&#xff0c;系统可兼容多协议接入&#xff0c;包括市场标准协议&#xff1a;国标GB/T 28181协议、GA/T 1400协议、JT808、RTMP、RTSP/Onvif协议&#xff1b;以及主流厂家私有协议及SDK&#xff0c;如&#xff1a;…...

Java利用poi实现word,excel,ppt,pdf等各类型文档密码检测

介绍 最近工作上需要对word,excel,ppt,pdf等各类型文档密码检测&#xff0c;对文件进行分类&#xff0c;有密码的和没密码的做区分。查了一堆资料和GPT都不是很满意&#xff0c;最后东拼西凑搞了个相对全面的检测工具代码类&#xff0c;希望能给需要的人带来帮助。 说明 这段…...

顺序表与链表学习笔记

顺序表及其结构定义 &#xff08;1&#xff09;结构定义 顺序存储&#xff1a; 顺序表的元素按顺序存储在一块连续的内存区域中&#xff0c;每个元素占用相同大小的存储空间。通过数组实现&#xff0c;每个元素可以通过下标快速访问。 存储密度高&#xff1a; 因为顺序表使用…...

2.SQL注入-字符型

SQL注入-字符型(get) 输入kobe查询出现id和邮箱 猜测语句,字符在数据库中需要用到单引号或者双引号 select 字段1,字段2 from 表名 where usernamekobe;在数据库中查询对应的kobe&#xff0c;根据上图对应上。 select id,email from member where usernamekobe;编写payload语…...

在Ubuntu 14.04上安装和配置Elasticsearch的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 Elasticsearch 是一个用于实时分布式搜索和数据分析的平台。它因易用性、强大功能和可扩展性而备受欢迎。 Elasticsearch 支持 R…...

C++:inline关键字nullptr

inline关键字 C中inline使用关键点强调 (1)inline是一种“用于实现的关键字”&#xff0c;而不是一种“用于声明的关键字”&#xff0c;所以关键字 inline 必须与函数定义体放在一起&#xff0c;而不是和声明放在一起 (2)如果希望在多个c文件中使用&#xff0c;则inline函数应…...

数字信号处理实验三(IIR数字滤波器设计)

IIR数字滤波器设计&#xff08;2学时&#xff09; 要求&#xff1a; 产生一复合信号序列&#xff0c;该序列包含幅度相同的28Hz、50Hz、100Hz、150Hz的单音&#xff08;单频&#xff09;信号&#xff1b;其中&#xff0c;50Hz及其谐波为工频干扰&#xff08;注&#xff1a;采样…...

Why is Kafka fast?(Kafka性能基石)

Kafka概述 Why is kafka fast&#xff1f; 思考一下&#xff0c;当我们在讨论Kafka快的时候我们是在谈论什么呢&#xff1f;What does it even mean that Kafka is fast? 我们是在谈论kafka的低延迟&#xff08;low latency&#xff09;还是在讨论吞吐量&#xff08;through…...

Linux下的SSH详解及Ubuntu教程

前言 SSH&#xff08;Secure Shell&#xff09;是一种用于计算机之间安全通信的协议&#xff0c;广泛应用于远程登录、系统管理和文件传输等场景。本文将详细介绍SSH在Linux系统&#xff08;特别是Ubuntu&#xff09;下的使用&#xff0c;包括安装、配置、密钥管理和常见应用&…...

MobPush HarmonyOS NEXT 版本集成指南

开发工具&#xff1a;DevEco Studio 集成方式&#xff1a;在线集成 HarmonyOS API支持&#xff1a;> 11 集成前准备 注册账号 使用MobSDK之前&#xff0c;需要先在MobTech官网注册开发者账号&#xff0c;并获取MobTech提供的AppKey和AppSecret&#xff0c;详情可以点击查…...

什么是封装?为什么要封装?

什么是封装&#xff1f; 封装是计算机科学中的一个重要概念&#xff0c;尤其在面向对象编程&#xff08;OOP&#xff09;中占据核心地位。封装主要指的是将数据&#xff08;属性&#xff09;和对这些数据的操作&#xff08;方法&#xff09;组合在一个单元中&#xff08;我们称…...

远程桌面无法复制粘贴文件到本地怎么办?

远程桌面不能复制粘贴问题 Windows远程桌面为我们提供了随时随地访问文件和数据的便捷途径&#xff0c;大大提升了工作和生活的效率。然而&#xff0c;在使用过程中&#xff0c;我们也可能遇到一些问题。例如&#xff0c;在通过远程桌面传输文件时&#xff0c;常常会出现无法复…...

LeetCode 207. 课程表

思路&#xff1a;这是一道拓扑排序问题&#xff0c;拓扑排序听起来可能有点复杂&#xff0c;但实际上它是个相当直观的概念。想象一下&#xff0c;你有很多事情要做&#xff0c;但有些事情必须在另一些事情完成之后才能开始&#xff0c;就像你得先穿上袜子再穿鞋子 拓扑排序就…...

数据结构历年考研真题对应知识点(树的基本概念)

目录 5.1树的基本概念 5.1.2基本术语 【森林中树的数量、边数和结点数的关系&#xff08;2016&#xff09;】 5.1.3树的性质 【树中结点数和度数的关系的应用&#xff08;2010、2016&#xff09;】 【指定结点数的三叉树的最小高度分析&#xff08;2022&#xff09;】 5.1…...

Pytorch和Tensorflow安装【Win和Linux】

Ubuntu/win安装Pytorch和Tensorflow 说明: 这两种框架的搭建,均基于Anaconda进行搭建。先在系统中安装Anaconda软件。 一、Pytorch的搭建 windows安装 (1)搭建参考官网给的命令,pytorch官网 (2)下载地址:https://download.pytorch.org/whl/torch_stable.html 从上述…...

筑算网基石 创数智未来|锐捷网络闪耀2024 MWC上海

2024年6月26日至28日&#xff0c;全球科技界瞩目的GSMA世界移动大会&#xff08;MWC 上海&#xff09;在上海新国际博览中心&#xff08;SNIEC&#xff09;盛大召开。作为行业领先的网络解决方案提供商&#xff0c;锐捷网络以“筑算网基石 创数智未来”为主题&#xff0c;带来了…...

T4打卡 学习笔记

所用环境 ● 语言环境&#xff1a;Python3.11 ● 编译器&#xff1a;jupyter notebook ● 深度学习框架&#xff1a;TensorFlow2.16.1 ● 显卡&#xff08;GPU&#xff09;&#xff1a;NVIDIA GeForce RTX 2070 设置GPU from tensorflow import keras from tensorflow.keras…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...