某漫画网站JS逆向反混淆流程分析
文章目录
- 1. 写在前面
- 1. 接口分析
- 2. 反混淆分析
【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1. 写在前面
前段时间有几个小伙伴咨询过关于某漫画网站的图片数据如何下载获取,看了一下觉得这个网站蛮适合初学者或者逆向分析爱好者练手的!它涉及到反调试、数据解密、JS反混淆、Cookie反爬虫、TLS指纹的检测
分析目标:
aHR0cHM6Ly93d3cuY29sYW1hbmdhLmNvbS9tYW5nYS1tZjg3NDEyNy8xLzU2Lmh0bWw=
初看时有小伙伴也提出过使用自动化的方式来获取图片链接再下载,但是这个链接是临时的。自动化是可以的,但只能是等待所有服务端下发的图片内容加载完毕渲染呈现到页面后使用截图的方式来获取,如下所示:
1. 接口分析
打开网站准备调试分析之前是有一个反调试的,一般这种大多通过动态生成的函数或代码片段触发!然后过这种反调试的方案是很多的(还有一些大佬开源分享的绝大场景下通杀的方案)如下所示:
这里我们也是可以通过重写构造函数与其原型方法拦截且移除动态生成代码中反调试语句,代码如下所示:
(function () {'use strict';const OriginalFunction = Function;Function = function (...args) {handleDebuggerRemoval(args);logStackTrace("Function");return OriginalFunction(...args);};Function.prototype = OriginalFunction.prototype;Function.prototype.constructor = function (...args) {handleDebuggerRemoval(args);logStackTrace("Function.constructor");return OriginalFunction(...args);};/*** 移除字符串参数中的 "debugger" 语句* @param {Array} args - 参数数组*/function handleDebuggerRemoval(args) {for (let i = 0; i < args.length; i++) {if (typeof args[i] === "string") {args[i] = args[i].replace(/debugger/g, "");}}}function logStackTrace(context) {const stackTrace = new Error().stack;log(`[${context}] Call Stack:`, stackTrace);if (DEBUG?.deb === 0) {debugger;}log(`[${context}] =============== End ===============`);}
})();
过了反调试之后,我们首先去看一下发包的情况。其实初次看的话没有明确的特征告诉我们从哪里下手,只能花点时间来各方面来分析一下,如下所示:
点击可发现这个接口貌似就是图片请求加载的发包(不过注意请求的是.enc.webp)大概率是经过处理的,而且在Cookies中也是添加了某些关键的字段,如下所示:
这里猜测在后续的请求中可能是需要携带这个Cookie参数请求的
这种场景下通过经验来梳理一下流程分析我们可以从网页加载的源码中来开始,它这种实时章节的加载大概率是不断的拼接后续的漫画图来获取资源的!然后在首次请求页面资源的时候肯定有基础的数据或者一些特征可以挖掘的
这里我们过掉反调试之后重方一下页面请求(请求记得过一下TLS检测)并保证Cookie请求的时候携带了__cf__bkm参数,如下所示:
可以看到请求的HTML内容中有一串密文(C_DATA)这个就是需要去解密的,解密后会拿到当前漫画章节中的详情信息JSON数据
2. 反混淆分析
它这个JS代码都是经过混淆的!不要硬看,浪费时间。核心逻辑基本都在custom.js、read.js文件中,先把JS拿下来反混淆静态分析一下!找到解密C_DATA的地方,混淆代码如下所示:
整个这块拿下来先解一下混淆,静态分析就很清晰了。处理解密C_DATA的混淆源码还原之后的JS代码如下所示:
if (__cad.isInReadPage()) {let decryptedData;__cad.useCodeIndex = 1;try {decryptedData = window.devtools.jsd("USJZOHqNw84GoMA9",window.devtools.jsc.enc.Base64.parse(window.C_DATA).toString(window.devtools.jsc.enc.Utf8));if (decryptedData === '') {__cad.useCodeIndex = 2;decryptedData = window.devtools.jsd("c9UPIOaql84fJIoz",window.devtools.jsc.enc.Base64.parse(window.C_DATA).toString(window.devtools.jsc.enc.Utf8));}window.devtools.jse(decryptedData);} catch (error) {__cad.useCodeIndex = 2;decryptedData = window.devtools.jsd("c9UPIOaql84fJIoz",window.devtools.jsc.enc.Base64.parse(window.C_DATA).toString(window.devtools.jsc.enc.Utf8));}window.devtools.jse(decryptedData);const decodedUrls = window.devtools.jsc.enc.Base64.parse(window.image_info.urls__direct).toString(window.devtools.jsc.enc.Utf8);window.__images_yy = decodedUrls.split("|SEPARATER|");window.__specialDisplay = 1;if (!window.image_info.img_type) {window.__specialDisplay = 0;}
}
直接在控制台把进行解密的JS代码执行可以看到明文的C_DATA数据,如下所示:
来!接下来分析一下上面还原之后的JS代码到底做了些什么。首先可以看到入口则是检测是否处于阅读页面,开始对C_DATA密文数据进行解密操作,它这个解密的逻辑基本都是一样的,先尝试使用默认的第一个密钥加B64的解码,数据钥匙解出来没有继续尝试切换使用第二个密钥!最后解密图片的URL信息并分割URL列表,最后的话是设置显示的操作
下面作者根据反混淆之后的JS代码使用Python算法来实现对C_DATA的解密操作,代码实现所示:
import base64
from loguru import logger
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Protocol.KDF import scryptdef base64Decode(base64Str):return base64.b64decode(base64Str).decode('utf-8')def aesDecrypt(encData, key):key_bytes = key.encode('utf-8')cipher = AES.new(key_bytes, AES.MODE_ECB)decrypted = unpad(cipher.decrypt(encData), AES.block_size)return decrypted.decode('utf-8')def jsd(key, encryptedData):decodedData = base64Decode(encryptedData)encData = base64.b64decode(decodedData)return aesDecrypt(encData, key)def decryptCData(c_data):key1 = 'USJZOHqNw84GoMA9'decryptedData = jsd(key1, c_data)logger.info(f"解密数据:{decryptedData}")if __name__ == '__main__':c_data = '' # 密文数据decryptCData(c_data)
这里直接到浏览扣一个加密数据丢进去测试,得到运行如下所示:
通过下面混淆代码调试标记出来的的几处不难发现大致的流程
对混淆的JS代码简单做一下还原可以更加直观有效的帮助分析。__cad[_0x3b6833(0x591)]实则就是一个setCookieValue的操作,通过获取上面JSON数据中的enc_code2跟enc_code1的值来对下面Cookies中的值进行一个解密操作,如下所示:
接下来,针对还原后的JS代码来进行分析,代码如下所示:
let decryptedValue = window.devtools.jsd(_0x447fdd,window.devtools.jsc.enc.Base64.parse(window.mh_info.enc_code2).toString(window.devtools.jsc.enc.Utf8)
);if (decryptedValue === '') {decryptedValue = window.devtools.jsd("RMjidK1Dgv0Ojuhm", window.devtools.jsc.enc.Base64.parse(window.mh_info.enc_code2).toString(window.devtools.jsc.enc.Utf8));
}if (!decryptedValue.startsWith(mh_info.mhid + '/')) {decryptedValue = window.devtools.jsd("RMjidK1Dgv0Ojuhm", window.devtools.jsc.enc.Base64.parse(window.mh_info.enc_code2).toString(window.devtools.jsc.enc.Utf8));
}let cookieOptions = { "expires": 0.005 };
__cad.cookie(_0x29107e, decryptedValue, cookieOptions);let decryptedValue2 = window.devtools.jsd(_0x447fdd,window.devtools.jsc.enc.Base64.parse(window.mh_info.enc_code1).toString(window.devtools.jsc.enc.Utf8)
);if (decryptedValue2 === '') {decryptedValue2 = window.devtools.jsd("HNoYX7fJXcM1PWAK", window.devtools.jsc.enc.Base64.parse(window.mh_info.enc_code1).toString(window.devtools.jsc.enc.Utf8));
}// 转换解密后的值为整数
let valueAsInt = parseInt(decryptedValue2);// 如果转换失败(NaN),再次尝试解密
if (String(valueAsInt) === "NaN") {decryptedValue2 = window.devtools.jsd("HNoYX7fJXcM1PWAK", window.devtools.jsc.enc.Base64.parse(window.mh_info.enc_code1).toString(window.devtools.jsc.enc.Utf8));
}// 存储第二个cookie
let cookieOptions2 = { "expires": 0.005 };
__cad.cookie(_0x3ee2e4, decryptedValue2, cookieOptions2);
通过对上面还原后的JS代码进行静态分析可以发现,初始化的时候是给了一个密钥,然后假设解密是空的,就会使用默认的密钥进行解密!如果解密值不符合预期(不以mh_info.mhid/
开头),则重试解密,enc_code1的流程差不多
接下来我们看一下devtools.jsd的解密算法调用,用的什么
这里我们根据调试以及反混淆后的JS代码还原一下对mh_info参数中的字段解密,加密算法如下所示:
const CryptoJS = require('crypto-js');function aesDecrypt(encData, key) {const parsedKey = CryptoJS.enc.Utf8.parse(key);const decrypted = CryptoJS.AES.decrypt(encData, parsedKey, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return CryptoJS.enc.Utf8.stringify(decrypted);
}function parseBase64(encodedStr) {return CryptoJS.enc.Base64.parse(encodedStr);
}function decryptProcess(encCode1, encCode2, pageId, mhId) {const key1 = "ZsfOA40m7kWjodMH";const parsedEncCode2 = parseBase64(encCode2).toString(CryptoJS.enc.Utf8);const parsedEncCode1 = parseBase64(encCode1).toString(CryptoJS.enc.Utf8);let decryptedEncCode2;try {decryptedEncCode2 = aesDecrypt(parsedEncCode2, key1);if (!decryptedEncCode2 || !decryptedEncCode2.startsWith(`${mhId}/`)) {decryptedEncCode2 = aesDecrypt(parsedEncCode2, key2);}} catch (e) {decryptedEncCode2 = aesDecrypt(parsedEncCode2, key2);}return {cookie: { key: `_tkb_${pageId}`, value: decryptedEncCode2 },};
}// 测试数据
const mh_info = {"startimg": 1,"enc_code1": "cDJSdkkyUFUzbVZrUXZ1S213TFBuQT09","mhid": "873947","enc_code2": "Q1FrNTVrRGZHZjhQM3dEdkg0cU4vYnVmTU9RWjBWdzMzYmhYSlpyKzM0QjN3cmxFSTdYV1VVWUlXRkNMVHhhNw==","mhname": "捉刀人","pageid": 7557687,"pagename": "56","pageurl": "1/57.html","readmode": 3,"maxpreload": 10,"defaultminline": 1,"domain": "img.colamanga.com","manga_size": "","default_price": 0,"price": 0,"use_server": "","webPath": "/manga-mf874127/"
};const result = decryptProcess(mh_info.enc_code1, mh_info.enc_code2, mh_info.pageid, mh_info.mhid);
console.log(result);
注意一下上面算法解密所使用到的AES密钥是每天都在更新的哈
解决完Cookie生成解密后我们来看最终的图片如何才能去下载的!从前往后分析的话已经拿到了C_DATA数据并解密,通过对解密数据中的Key成功解密获取到Cookie参数,下面就需要知道完整的图片地址,携带Cookie去请求即可,如下继续分析:
图片地址生存获取的JS混淆代码同样需要还原,还原如下所示:
window.getpice = function (pageIndex) {let imageUrl = '';if (!window.image_info.img_type) {let currentLine = window.lines[chapter_id].use_line;let imageIndex = parseInt(window.mh_info.startimg) + pageIndex - 1;let fileName = __cr.PrefixInteger(imageIndex, 4) + ".jpg";if (window.image_info.imgKey != undefined && window.image_info.imgKey !== '') {fileName = __cr.PrefixInteger(imageIndex, 4) + ".enc.webp";}let baseDomain;let sanitizedDomain = currentLine.replace("img.", '');sanitizedDomain = document.domain.replace("www.", '');let cookieValue = __cad.getCookieValue();let pageId = mh_info.pageid;let cookieKey = cookieValue[0] + pageId.toString();let encodedPath = __cad.cookie(cookieKey);if (encodedPath == null) {__cad.setCookieValue();encodedPath = __cad.cookie(cookieKey);}if (mh_info.use_server === '') {baseDomain = `//img.${sanitizedDomain}/comic/${encodeURI(encodedPath)}${fileName}`;} else {baseDomain = `//img${mh_info.use_server}.${sanitizedDomain}/comic/${encodeURI(encodedPath)}${fileName}`;}imageUrl = baseDomain;} else {let imagePath = window.__images_yy[pageIndex - 1];if (window.image_info.img_type === '1') {imageUrl = __cr.switchWebp(imagePath, window.mh_info.manga_size);} else {imageUrl = imagePath;}}return imageUrl;
};
先获取当前章节的线路信息再计算图片序号,根据序号生成图片文件名JPG然后替换它的主域名。其中也进行了一些Cookie的设置操作最终拿到完整图片路径
最后的图片数据则是通过AES解密二进制图片数据,然后就可以直接下载了!_0x1d85d5是密文对象,包含了加密的图片数据,解密的结果_0x5183f2则是图片的二进制数据(WordArray类型)
var key = "KZTC0WwWqyeStZD2";
var _0x5183f2 = window.CryptoJS.AES.decrypt(_0x1d85d5, key, {'iv': window.CryptoJS.enc.Utf8.parse("0000000000000000"),'mode': window.CryptoJS.mode.CBC,'padding': window.CryptoJS.pad.Pkcs7
});
貌似不携带Cookie里面的参数也是可以的,感兴趣的自己尝试
相关文章:
某漫画网站JS逆向反混淆流程分析
文章目录 1. 写在前面1. 接口分析2. 反混淆分析 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Pyth…...
如何获取文件的MIME类型
文章目录 1. 概念介绍2. 方法与类型2.1 使用方法2.2 常见类型3. 示例代码4. 内容总结我们在上一章回中介绍了"如何加载本地图片"相关的内容,本章回中将介绍如何获取文件类型.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中提到的文件类型是指MI…...
Three.js 基础概念:构建3D世界的核心要素
文章目录 前言一、场景(Scene)二、相机(Camera)三、渲染器(Renderer)四、物体(Object)五、材质(Material)六、几何体(Geometry)七、光…...
Linux web服务器
Linux 作为 Web 服务器操作系统 安装 Web 服务器软件(以 Apache 为例) 步骤一:更新系统软件包列表 在 CentOS 系统中,使用命令 yum update -y 这个命令会连接到 CentOS 的软件包仓库,检查所有已安装软件包是否有更…...
Linux 下信号的保存和处理
信号的几个状态 信号抵达: 当接收到的信号被处理时, 此时就成为信号的抵达信号的未决: 从信号的产生到信号抵达这个时间段之间, 称为信号未决信号阻塞: 当进程设置了某个信号为阻塞后, 这个进程就不会在接收到这个信号信号忽略: 将信号设置为忽略后, 接收到这个信号, 对这个信…...
宝塔安装教程,bt怎么安装 linux
Centos安装脚本 yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 37a09b35 Ubuntu/Deepin安装脚本 wget -O install.sh http://download.bt.cn/install/install-ubuntu_6.0.sh && sudo b…...
java通过ocr实现识别pdf中的文字
需求:识别pdf文件中的中文 根据github项目mymonstercat 改造,先将pdf文件转为png文件存于临时文件夹,然后通过RapidOcr转为文字,最后删除临时文件夹 1、引入依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId&g…...
基于SpringBoot的养老院管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
阿里云发现后门webshell,怎么处理,怎么解决?
当收到如下阿里云通知邮件时,大部分管理员都会心里一惊吧!出现Webshell,大概是网站被入侵了。 尊敬的 xxxaliyun.com: 云盾云安全中心检测到您的服务器:47.108.x.xx(xx机)出现了紧急安全事件…...
韩顺平老师Linux学习笔记【持续更新...】
1、课程内容 1.1、课程大纲 1.2、Linux使用在哪些地方 Linux运维工程师Linux嵌入式工程师Linux下开发项目:JavaEE、大数据、Python、PHP、C/C、Go 1.3、Linux的应用领域 个人桌面领域服务器领域(最强领域)嵌入式领域 2、Linux入门 2.1、…...
Cognitive architecture 又是个什么东东?
自Langchain: https://blog.langchain.dev/what-is-a-cognitive-architecture/ https://en.wikipedia.org/wiki/Cognitive_architecture 定义 A cognitive architecture refers to both a theory about the structure of the human mind and to a computational…...
【css】浏览器强制设置元素状态(hover|focus……)
直接上步骤: 打开浏览器控制台 → 找到样式选项 → 找到:hov选项 → 点击:hov选项,会展开【设置元素状态】。 只要选中就会展示出自己写在css里面的该种状态下的样式了。...
leetcode热题100——NO.160相交链表——JAVA
一、题目描述 题目:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。题目数据 保证 整个链式结构中不存在环。 注意,函数返回结果后,链表必…...
基于Media+Unity的手部位姿三维位姿估计
使用mediapipe Unity 手部位姿三维位姿估计 参考文章 基于Mediapipe的姿势识别并同步到Unity人体模型中 MediapipeUnity3d实现虚拟手_unity mediapipe-CSDN博客 需求 我的需求就是快速、准确的跟踪手部位姿并实现一个三维显示。 主要思路 搭建mdeiapipe系统,…...
cJson——序列化格式json和protobuf对比
cJson——序列化格式json和protobuf对比 1. 更小的消息体积2. 更快的序列化与反序列化速度3. 类型安全4. 向后和向前兼容性5. 更低的带宽消耗6. 高效的编码方式7. 易于跨语言支持8. 支持复杂的数据结构9. 更好的支持大型数据交换总结 Protocol Buffers (Protobuf) 和 JSON 都是…...
STM32F1学习——ADC模数转换器
一、ADC模数转换器 ADC的全称 Analog-Digital Converter 模拟-数字转换器,他可以用来将引脚上连续变换的模拟电压转换为内存中存储的数字变量。 ADC有两个重要指标,分辨率和频率。 STM32的ADC是 12位 逐次逼近型,1us转换时间,也就…...
2025-1-10-sklearn学习(36、37) 数据集转换-无监督降维+随机投影 沙上并禽池上暝。云破月来花弄影。
文章目录 sklearn学习(36、37) 数据集转换-无监督降维随机投影sklearn学习(36) 数据集转换-无监督降维36.1 PCA: 主成份分析36.2 随机投影36.3 特征聚集 sklearn学习(37) 数据集转换-随机投影37.1 Johnson-Lindenstrauss 辅助定理37.2 高斯随机投影37.3 稀疏随机矩阵 sklearn学…...
Linux之线程池与单例模式
目录 线程池 线程池代码 单例模式 饿汉模式单例模式 懒汉模式单例模式 在前几期,我们已经学习了多线程的创建和控制,学习了多线程中的同步和互斥,学习了多线程中的条件变量和信号量,基于此我们实现了基于阻塞队列和基于环形队…...
LabVIEW调用不定长数组 DLL数组
在使用 LabVIEW 调用 DLL 库函数时,如果函数中的结构体包含不定长数组,直接通过 调用库函数节点(Call Library Function Node) 调用通常会遇到问题。这是因为 LabVIEW 需要与 DLL 中的数据结构完全匹配,而包含不定长数…...
计算机的错误计算(二百零七)
摘要 利用两个数学大模型计算 arccot(0.125664e2)的值,结果保留16位有效数字。 实验表明,它们的输出中分别仅含有3位和1位正确数字。 例1. 计算 arccot(0.125664e2)的值,结果保留16位有效数字。 下面是与一个数学解题器的对话。 以上为与…...
基于 GEE 利用 RF 回归模型实现空间降尺度
目录 1 前言 2 完整代码 3 运行结果 1 前言 本篇讲述在GEE上基于回归模型降尺度,也就是要复现以下论文,该论文发表在J-Star期刊上。 “Ebrahimy H, Aghighi H, Azadbakht M, et al. Downscaling MODIS land surface temperature product using an a…...
Linux 系统下磁盘相关指令:df、du、fdisk、lsblk
文章目录 I df、du、fdisk、lsblk指令df命令用于显示文件系统的磁盘空间使用情况du命令用于估算目录或文件的磁盘空间使用情况fdisk命令用于对磁盘进行分区操作lsblk指令查看设备信息II 应用du估算目录或文件的磁盘空间使用情况lsblk查看服务器上查看硬盘个数III 知识扩展磁盘阵…...
在线或离线llama.cpp安装和模型启动
该版本安装时间是2025-01-10,因为不同版本可能安装上会有所不同,下面也会讲到。 先说下问题——按照官方文档找不到执行命令llama-cli或./llama-cli 先附上llama.cpp的github地址:https://github.com/ggerganov/llama.cpp,build…...
(Arxiv-2023)LORA-FA:针对大型语言模型微调的内存高效低秩自适应
LORA-FA:针对大型语言模型微调的内存高效低秩自适应 paper是香港浸会大学发表在Arxiv 2023的工作 paper title:LORA-FA: MEMORY-EFFICIENT LOW-RANK ADAPTATION FOR LARGE LANGUAGE MODELS FINE-TUNING ABSTRACT 低秩自适应 (LoRA) 方法可以大大减少微调…...
Ubuntu | 系统软件安装系列指导说明
文章目录 Ubuntu 系统软件安装系列指导说明工具系列1. Docker 与 Docker-Compose部署与安装 环境系列1. Golang部署与安装 数据库系列1. PostgreSQL17.2源码部署与安装 Ubuntu 系统软件安装系列指导说明 工具系列 1. Docker 与 Docker-Compose部署与安装 链接 环境系列 1…...
攻防靶场(32):两个爆破技巧 Funbox 7 EasyEnum
目录 攻击路径一 1. 侦查 1.1 收集目标网络信息:IP地址 1.2 主动扫描:扫描IP地址段 1.3 主动扫描:字典扫描 2. 初始访问 2.1 有效帐号:本地账户 3. 权限提升 3.1 滥用特权控制机制:Sudo和Sudo缓存 4. 凭据访问 4.1 凭据…...
Vue3初学之插槽(slot)使用
在 Vue 3 中,插槽(Slots)是一种强大的内容分发机制,允许你在组件中定义可替换的内容区域,从而使组件更加通用和灵活。以下是 Vue 3 中插槽的几种常见用法: 默认插槽 默认插槽是最基本的插槽类型࿰…...
从 0 开始上手 Solana 智能合约
Solana CLI 基础知识 Solana CLI 是一个命令行界面工具,提供了一系列用于与 Solana Cluster 交互的命令。 我们将介绍一些最常见的命令,但你始终可以通过运行 solana --help 查看所有可能的 Solana CLI 命令列表。 Solana CLI 配置 Solana CLI 存储了…...
USB基础 -- USB 控制传输(Control Transfer)的重传机制
USB 控制传输(Control Transfer)的重传机制 1. 控制传输的事务结构 控制传输分为三个阶段,每个阶段都有自己的事务,并可能触发重传机制: 设置阶段(Setup Stage):主机发送 8 字节的…...
创建基本的 Electron 应用项目的详细步骤
创建一个基本的 Electron 应用项目的详细步骤。我们将从安装 Node.js 开始,然后创建项目文件夹并初始化 Electron 项目。 1. 安装 Node.js 首先,确保你已经安装了 Node.js 和 npm。你可以在终端中运行以下命令来检查是否已经安装: node -v…...
《异步编程之美》— 全栈修仙《Java 8 CompletableFuture 对比 ES6 Promise 以及Spring @Async》
哈喽,大家好!在平常开发过程中会遇到许多意想不到的坑,本篇文章就记录在开发过程中遇到一些常见的问题,看了许多博主的异步编程,我只能说一言难尽。本文详细的讲解了异步编程之美,是不可多得的好文…...
Android 修改SVG属性并显示图片(AndroidSvg)
引入依赖: dependencies {implementation com.caverock:androidsvg-aar:1.4 }核心代码: import com.caverock.androidsvg.SVG import org.w3c.dom.Document import java.io.StringWriter import javax.xml.transform.OutputKeys import javax.xml.tran…...
Ubuntu 磁盘修复
Ubuntu 磁盘修复 在 ubuntu 文件系统变成只读模式,该处理呢? 文件系统内部的错误,如索引错误、元数据损坏等,也可能导致系统进入只读状态。磁盘坏道或硬件故障也可能引发文件系统只读的问题。/etc/fstab配置错误,可能…...
移动云自研云原生数据库入围国采!
近日,中央国家机关2024年度事务型数据库软件框架协议联合征集采购项目产品名单正式公布,移动云自主研发的云原生数据库产品顺利入围。这一成就不仅彰显了移动云在数据库领域深耕多年造就的领先技术优势,更标志着国家权威评审机构对移动云在数…...
Java一个简单的反弹动画练习
文章目录 说明代码详解创建窗体代码创建绘图板创建线程 运行结果完整代码 说明 做了一个小球和星型做反弹动画的窗体作为练习,分享给大家,为了方便和我一样的小白可以看的比较明白,所以尽量详细的标注了注释,希望能帮到同样在学习…...
互联网架构变迁:从 TCP/IP “呼叫” 到 NDN “内容分发” 的逐浪之旅
本文将给出关于互联网架构演进的一个不同视角。回顾一下互联网的核心理论基础产生的背景: 左边是典型的集中控制通信网络,很容易被摧毁,而右边的网络则没有单点问题,换句话说它很难被全部摧毁,与此同时,分…...
git push命令
git push 常用命令 1. 拉取远程仓库最新数据 使用 git fetch git fetch作用: 获取远程仓库的最新数据(包括分支、标签等),但不会修改本地工作目录。 结果: 仅更新远程分支(如 origin/main)的…...
day01-HTML-CSS——基础标签样式表格标签表单标签
目录 此篇为简写笔记下端1-3为之前笔记(强迫症、保证文章连续性)完整版笔记代码模仿新浪新闻首页完成审核不通过发不出去HTMLCSS1 HTML1.1 介绍1.1.1 WebStrom中基本配置 1.2 快速入门1.3 基础标签1.3.1 标题标签1.3.2 hr标签1.3.3 字体标签1.3.4 换行标…...
软考信安16~网络安全风险评估技术原理与应用
1、网络安全风险评估概述 1.1、网络安全风险评估概念 网络安全风险评估(简称“网络风险评估")就是指依据有关信息安全技术和管理标准,对网络系统的保密性、完整性、可控性和可用性等安全属性进行科学评价的过程,评估内容涉及网络系统的脆弱性、网络安全威胁以及脆弱性被…...
嵌入式C语言:二维数组
目录 一、二维数组的定义 二、内存布局 2.1. 内存布局特点 2.2. 内存布局示例 2.2.1. 数组元素地址 2.2.2. 内存布局图(简化表示) 2.3. 初始化对内存布局的影响 三、访问二维数组元素 3.1. 常规下标访问方式 3.2. 通过指针访问 3.2.1. 指向数…...
计算机网络期末复习(知识点)
概念题 在实际复习之前,可以看一下这个视频将网络知识串一下,以便更好地复习:【你管这破玩意叫网络?】 网络规模的分类 PAN(个人区域网络):用于个人设备间的连接,如手机与蓝牙耳机…...
LeetCode:3298. 统计重新排列后包含另一个字符串的子字符串数目 II(滑动窗口 Java)
目录 3298. 统计重新排列后包含另一个字符串的子字符串数目 II 题目描述: 实现代码与解析: 滑动窗口 原理思路: 3298. 统计重新排列后包含另一个字符串的子字符串数目 II 题目描述: 给你两个字符串 word1 和 word2 。 如果…...
【SpringAOP】Spring AOP 底层逻辑:切点表达式与原理简明阐述
前言 🌟🌟本期讲解关于spring aop的切面表达式和自身实现原理介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 &am…...
es 3期 第23节-运用Pipeline实现二转聚合统计
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
T-SQL语言的编程范式
T-SQL编程范式探析 引言 随着信息技术的迅猛发展,数据库在各个行业的应用日益广泛。在众多数据库管理系统中,SQL Server以其高性能和易用性受到广泛欢迎。T-SQL(Transact-SQL)是SQL Server的扩展版本,是一种用于查询…...
【ArcGIS微课1000例】0137:色彩映射表转为RGB全彩模式
本文讲述ArcGIS中,将tif格式的影像数据从色彩映射表转为RGB全彩模式。 参考阅读:【GlobalMapper精品教程】093:将tif影像色彩映射表(调色板)转为RGB全彩模式 文章目录 一、色彩映射表预览二、色彩映射表转为RGB全彩模式一、色彩映射表预览 加载配套数据包中的0137.rar中的…...
论文笔记(六十一)Implicit Behavioral Cloning
Implicit Behavioral Cloning 文章概括摘要1 引言2 背景:隐式模型的训练与推理3 隐式模型与显式模型的有趣属性4 policy学习成果5 理论见解:隐式模型的通用逼近性6 相关工作7 结论 文章概括 引用: inproceedings{florence2022implicit,titl…...
网络安全核心目标CIA
网络安全的核心目标是为关键资产提供机密性(Confidentiality)、可用性(Availablity)、完整性(Integrity)。作为安全基础架构中的主要的安全目标和宗旨,机密性、可用性、完整性频频出现,被简称为CIA,也被成为你AIC,只是顺序不同而已…...
hive迁移后修复分区慢,怎么办?
我有1个30TB的分区表,客户给的带宽只有600MB,按照150%的耗时来算,大概要迁移17小时。 使用hive自带的修复分区命令(一般修复分区比迁移时间长一点),可能要花24小时。于是打算用前面黄大佬的牛B方案。 Hive增…...
一块钱的RISC-V 32位芯片
之前跟一个朋友聊天,说以后的芯片一定是越来越趋向于定制化,比如我们需要一个ADC芯片,这颗ADC芯片需要有串口功能,那就只开发一颗这样的芯片就好了,其他的功能都可以裁剪掉。 ➵➵➵➵➵➵➵➵➵➵➵➵➵➵➵…...