基于Electron的应用程序安全测试基础 — 提取和分析.asar文件的案例研究
目录:
4.4. 案例研究
4.4.2. 情况描述
4.4.3. 信息收集
4.4.3.2. 检查隐藏目录(点目录)的可能性
4.4.3.3. 使用 DB Browser for SQLite 打开 .db 文件
4.4.3.4. 寻找加密算法
4.4.3.5. 找到加密算法
4.4.3.6. 理解加密流程
4.4.3.7. 找到“Key”存储位置
4.4.4. 解密密钥值
4.4.5. 其他信息
硬编码密钥(在SQLite中)和加密算法(在AesFormula.js文件中)信息泄露导致真实凭据被泄露
4.4. 案例研究
本节案例研究将讨论我们的一项测试结果,涉及基于Electron的应用程序中的客户端-服务器模型。
4.4.2. 情况描述
在首次运行相关桌面应用程序时,我们注意到该应用程序具有记住输入凭据的功能。这似乎是合理的,因为应用程序提供的默认凭据相当复杂且难以记住。
(为了维护程序所有者的隐私,在本案例研究中我们不会使用真实的图像和代码。然而,为了便于讨论,我们将尝试绘制示意图并重写代码,以大致代表我们提供的解释内容)。
然而,在原生应用程序的概念中,有一个我们需要理解的原则。当我们使用应用程序提供的“记住我”功能时,本质上该应用程序会将我们的凭据存储在当前操作系统的本地环境中。尽管存储方法和形式有所不同,但为了清晰地理解流程,这一原则必须被牢牢遵守。
那么,这些数据存储在哪里呢?从技术角度来看,第三方应用程序数据的存储位置因操作系统而异。例如,macOS上的应用程序数据通常存储在用户“Library”目录中的“Application Support”文件夹中。而在Windows上,第三方应用程序数据通常存储在用户“AppData”目录中的一个隐藏文件夹中。在Linux系统中,应用程序数据通常存储在用户目录中的“.config”文件夹中。
由于此次测试是在适用于macOS的应用程序上进行的,因此接下来的说明将重点关注macOS的相关细节。
4.4.3. 信息收集
注意:为了分析该应用程序的行为,我们需要尝试先登录,并勾选“记住我的密钥”选项。
4.4.3.1. 检查 Application Support 和 Preferences 目录
在macOS环境中的初步实验中,我们检查了应用程序的目录,这些目录通常位于“Application Support”和“Preferences”中。
需要说明的是,“Application Support”目录主要用于macOS应用程序存储运行应用程序所需的数据,或者至少是与用户相关的应用程序数据。这些数据可能包括配置文件、本地数据库、缓存,或其他用于确保应用程序平稳运行的文件。例如,一个数据处理应用程序可能会在此存储文档模板,而一个游戏应用程序可能会在此存储用户的游戏进度数据。
另一方面,“Preferences”目录主要用于存储用户自定义的应用程序配置文件。它包括用户偏好设置,例如显示设置、语言偏好、键盘设置等。在这种情况下,用户设置通常“存储”在.plist文件中。
那么我们该如何操作呢? 在这种情况下,我们使用了一种相当传统的方法,即利用 grep
命令并结合针对我们用于登录应用程序的用户名的特定搜索。
以下是我们使用的命令:
grep -r username_of_the_apphere /Users/username/Library/Application\ Support/target_app/
以下是对该命令的简单解释:
grep:这是一个用于匹配给定输入中指定字符串模式的命令。
-r:这是一个选项,用于递归地搜索目录及其子目录中的内容。
username_of_the_apphere:这是我们要搜索的字符串,即我们在应用程序中使用的用户名。
/Users/username/Library/Application Support/target_app/:这是我们想要执行搜索的目录。在这种情况下,grep 将在目录 /Users/**username**/Library/Application\ Support/target_app/
及其子目录中的所有文件内搜索该字符串。
我们同样对首选项目录下的 “target_app” 文件进行了相同的操作。
grep -r username_of_the_apphere /Users/username/Library/Preferences/com.electron.target-app.plist
那么结果如何? 简而言之,通过这次分析,我们没有发现任何与用户名相关的数据。随后,我们尝试转向另一个位置进行检查。
可能有人会问,为什么我们如此确信该用户名是以明文(未保护的)形式存储的?实际上,我们并不确定该用户名的存储状态,但尝试搜索并无妨。
4.4.3.2. 检查隐藏目录(点目录)的可能性
我们需要注意的一点是,在 macOS(以及通用的 Unix 系统)中,有一些目录对用户是隐藏的。这些目录通常以一个点(.)开头,位于 /Users/username
路径下。
在实际应用中,第三方应用程序有时会利用这些类型的目录来存储与应用程序相关的信息,而这些信息从技术角度讲并不需要用户访问。
注意:有时也会有应用程序将其数据存放在 /Users/Username/.local/share
目录中。
基于这种情况,我们决定检查 /Users/Username
路径,看看是否存在这类目录。长话短说,我们找到了一个肯定的结果,也就是目标应用(target_app)确实拥有这样一个目录。
当我们首次发现.data.db
文件的存在时,我们就已经相当确信该文件可能包含我们正在寻找的凭据。然而,为了确认这一点,我们按照之前提到的方法使用grep
进行了传统搜索。果然,结果如我们所预料,这个用户名确实存在于相关的.db
文件中。
4.4.3.3. 使用 DB Browser for SQLite 打开 .db 文件
通常,一个应用程序(无论是移动端还是桌面端)都会使用轻量级的数据库管理系统(DBMS)在本地计算机上进行存储。一种常见的选择是 SQLite。
在确认该文件确实是 SQLite 格式后,我们使用了一个名为 DB Browser for SQLite 的简单工具将其打开(尽管也可以使用其他工具)。
长话短说,我们找到了我们想要的内容,也就是存储用户名、URL 和密钥的列。
然而,在进一步检查我们使用的值后,发现密钥的值与预期的值不符。从它的格式来看,我们认为这是一种AES加密格式,这是常用的数据安全算法。
Value: eLy2xThk+y7Rki4J13zvGVxrnqZbrOtznvNbhOKIgWo=
再次需要指出的是,为了简化讨论,同时隐藏任何加密值和代码,我们已经用其他样本替换了它们(是的,这是从ChatGPT重制的)。
4.4.3.4. 寻找加密算法
根据我们描述的情况,我们继续测试,探索用于“保护”密钥值的潜在算法和公式。简而言之,考虑到target_app应用程序是基于Electron构建的,我们尝试提取包内容中的app.asar文件。
请注意:
要了解如何检测基于Electron的应用程序以及提取过程,可以参考前几篇文章。
成功提取后,我们可以继续搜索应用程序使用的算法和公式,以保护前面提到的密钥值。
4.4.3.5. 找到加密算法
在仔细检查提取目录中的每个文件后,我们发现了一个引起我们注意的文件,即AesFormula.js:
4.4.3.6. 理解加密流程
在检查AesFormula.js文件中的代码流程时,我们发现了一个负责动态生成加密密钥和初始化向量(IV)的代码段。该代码段包含两个函数:generateEncryptionKey和generateIV。
在generateEncryptionKey函数中,使用crypto.randomBytes方法生成一个随机的密钥组件,长度由KEY_LENGTH指定。随后,使用generatePBKDF2Salt函数生成一个盐值(SALT)。
这些随机密钥组件和默认密钥通过按位异或(XOR)操作结合,生成一个唯一的密钥。这个生成的密钥与生成的SALT一起,通过PBKDF2算法进行密钥派生,最终得到一个派生密钥(pbkdfKey)。最后,从这个派生密钥中选取前部分(等于KEY_LENGTH字节)作为AES加密的加密密钥。
类似地,在generateIV函数中,使用crypto.randomBytes方法生成一个随机的初始化向量(IV),其长度由IV_LENGTH指定。这个IV将在AES加密过程中作为唯一的初始化向量使用。
这些动态生成过程确保每次加密操作使用不同的密钥和初始化向量(IV),从而增强了加密机制的安全性。
从技术上讲,AesFormula通过为每次加密操作动态生成加密密钥和IV,提供了安全的加密功能。
为了验证我们的假设,我们尝试多次登录和登出,并观察SQLite中密钥的变化。
那么,结果如何?结果是积极的。在三次有效的登录尝试中,我们发现SQLite中的密钥值确实发生了变化。以下是相同值的三次不同加密结果:
接下来是什么呢?当然是要找到由这段代码生成的salt、key和IV的值。至于过程,我们继续研究现有代码的流程,直到最终遇到了以下这段代码:
这段代码显示,所有密钥生成过程的结果将存储在一个名为“encryptionMaterial”的部分中。
4.4.3.7. 找到“Key”存储位置
在这种情况下,我们需要查找存储在encryptionMaterial中的值。长话短说,在尝试分析SQLite数据库的内容后,我们最终发现encryptionMaterial的值硬编码存储在同一张表中,即t_user表的some_secret_name列中。
4.4.4. 解密密钥值
我们已经得到了密钥的加密值,并且我们也有用来加密的密钥值(iv、keyComponentBuf和salt),接下来我们将尝试解密现有的密钥值。
要执行此解密操作,最简单的方法之一是利用程序本身(在本例中,是AesFormula.js文件中可用的函数)。
以下是一个简单的代码,可以用来解密密钥值:
const AesFormula = require('./AesFormula');
const encryptedValue = 'VQwSxZiICNhGjzLpcLSz1CDP11bEib26LFw+4av6VmE=';
const encryptionMaterial = {
iv: Buffer.from([0xb0, 0xe3, 0x88, 0x26, 0x7c, 0xe3, 0xc3, 0x91, 0x5d, 0x95, 0xec, 0x72, 0xa7, 0x67, 0xd5, 0x20]),
keyComponentBuf: Buffer.from([0xb8, 0x02, 0x63, 0x02, 0xe6, 0xcf, 0x1e, 0x61, 0xa9, 0x56, 0x1f, 0x49, 0xb1, 0x74, 0x77, 0x23, 0xb0, 0x59, 0xca, 0xa3, 0xa2, 0x8b, 0x34, 0x71, 0x23, 0x6c, 0xa5, 0x4d, 0x34, 0x85, 0x78, 0xeb]),
pbkdf2SaltBuf: Buffer.from([0x4e, 0xc4, 0x6f, 0x21, 0x4b, 0x55, 0xc7, 0x58, 0x38, 0x9d, 0x6e, 0x31, 0xc0, 0x37, 0xaa, 0x68])
};
const decryptValue = async () => {
try {
const decryptedResult = await AesFormula.decryptWithAES(encryptedValue, encryptionMaterial);
console.log('Decrypted value:', decryptedResult);
} catch (error) {
console.error('Error while decrypting:', error);
}
};
decryptValue();
我们需要做的就是将来自encryptionMaterial的值(iv、keyComponentBuf和salt)输入到其中。将这段代码保存(例如命名为:decrypt.js)。然后,将AesFormula.js文件放在与此代码相同的目录中。
要执行这段代码,我们需要借助node.js。以下是运行程序后的最终结果:
总之,PoC(概念验证)过程包括:
1.从data.db文件中的t_user表的key列获取key值。
2.从data.db文件中的t_user表的some_secret_name列获取encryptionMaterial值。
3.将key值复制到我们之前创建的decrypt.js代码中。
4.将encryptionMaterial值(逐个为iv、keyComponentBuf和salt)复制到我们创建的decrypt.js代码中。
5.将AesFormula.js文件放置在与decrypt.js文件相同的目录中。
6.使用node.js运行decrypt.js代码,命令为**node decrypt.js**
。
4.4.5. 其他信息
4.4.5.1. 观点
从这个案例中,我们也可以认识到,应用程序实施的加密相当稳健,例如使用动态密钥,这无疑使得攻击者猜测变得困难。然而,关键问题最终集中在密钥公式和密钥本身的存储方式。
这个问题的执行可能引发一个问题:“获得本地访问权限的攻击者是否能够直接通过启用‘记住我的密钥’功能的target_app登录?”
本质上,这是一个有效的问题。然而,我们需要更深入地思考,因为攻击者在本地目标上的存在通常是有时间限制的。攻击者要想探索target_app中的每一条数据,无疑会受到限制,并且对于攻击者来说并不理想。
因此,通过利用本报告中描述的问题,攻击者将不再受时间限制,从用户的target_app中窃取数据。因为攻击者可以快速执行窃取操作,通过访问存储在SQLite数据库中的硬编码用户名、URL、key和encryptionMaterial。随后,攻击者可以从本地目标之外的各种位置进行探索。
尽管关于某些程序中这个问题的有效性的争论仍然存在,但在红队演习中无疑是有益的。
4.4.5.2. SafeStorage模块
需要注意的是,Electron框架提供了一个名为SafeStorage[1]的模块,用于保护存储在磁盘上的数据,以免被其他应用程序或具有完全磁盘访问权限的用户访问。从技术上讲,Electron中的safeStorage利用操作系统本地的安全存储API,以加密形式存储数据(因此,这可能是一个不错的替代方案)。
References
[1]
SafeStorage: https://www.electronjs.org/docs/latest/api/safe-storage
申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关
相关文章:
基于Electron的应用程序安全测试基础 — 提取和分析.asar文件的案例研究
目录: 4.4. 案例研究 4.4.2. 情况描述 4.4.3. 信息收集 4.4.3.2. 检查隐藏目录(点目录)的可能性 4.4.3.3. 使用 DB Browser for SQLite 打开 .db 文件 4.4.3.4. 寻找加密算法 4.4.3.5. 找到加密算法 4.4.3.6. 理解加密流程 4.4.3.7. 找到“Ke…...
Vue3生命周期以及与Vue2的区别
文章目录 一、Vue3生命周期核心阶段与钩子函数二、Vue3生命周期示例:选项式 vs 组合式 API选项式 API 示例(Vue2)组合式 API 示例(Vue3) 三、Vue3与Vue2生命周期的核心差异1. 钩子函数更名2. 组合式 API 的影响3. 新增…...
windows下安装CUDA-本地微调大模型
1、查看NVIDIA的控制面板的版本号 2 下载CUDA Toolkit https://developer.nvidia.com/cuda-toolkit-archive 这里要下载和自己电脑NVIDIA适配CUDA的大版本要保持一致 选择对应的版本进行下载 文件比较大,直接右键复制链接,放到迅雷中两分钟就下好了 3 …...
LeetCode:132. 分割回文串 II(DP Java)
目录 132. 分割回文串 II 题目描述: 实现代码与解析: DP 原理思路: 132. 分割回文串 II 题目描述: 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串。 返回符合要求的 最少分割次数…...
C# 13与.NET 9革新及工业开发应用
摘要 微软推出的C# 13与.NET 9以“高效且智能”为导向,具备扩展类型、半自动属性、锁对象优化等十大革新。本文深入剖析新特性于工业级开发的应用场景,包含性能优化策略、AI集成方案以及EF Core实战技巧,为开发者提供从理论到实践的完整指引…...
IPoIB源码深度解析:如何基于TCP/IP协议栈实现高性能InfiniBand通信
一、IPoIB的核心设计理念 IPoIB(IP over InfiniBand)是一种在InfiniBand网络上承载IP流量的技术,其核心目标是在不修改上层应用的前提下,利用InfiniBand的高带宽和低延迟特性。与自定义协议栈不同,IPoIB通过深度集成到Linux内核TCP/IP协议栈中,将InfiniBand设备抽象为标…...
《白帽子讲 Web 安全:点击劫持》
目录 摘要: 一、点击劫持概述 二、点击劫持的实现示例:诱导用户收藏指定淘宝商品 案例 构建恶意页面: 设置绝对定位和z - index: 控制透明度: 三、其他相关攻击技术 3.1图片覆盖攻击与 XSIO 3.2拖拽劫持与数据…...
PostgreSQL10 逻辑复制实战:构建高可用数据同步架构!
PostgreSQL10 逻辑复制实战:打造高可用数据同步架构! 概述 PostgreSQL 10 引入了逻辑复制(Logical Replication),为数据库高可用和数据同步提供了更灵活的选择。PostgreSQL 复制机制主要分为物理复制和逻辑复制两种&…...
Spring Boot 异步编程深入剖析
Spring Boot 异步编程深入剖析 1. 异步方法的使用 原理深度解析 Spring Boot 的异步方法基于 Spring 的 AOP(面向切面编程)实现。当在方法上添加 Async 注解时,Spring 会为该方法所在的类创建一个代理对象。当调用该异步方法时,…...
《动手学习深度学习》的笔记,将会持续更新。
1.什么是机器学习? 机器学习是:换句话说,我们用数据训练(train)模型。 数据不断的训练出比较好的模型。 1.2 机器学习的关键零件 1.学习的数据。 2. 如何转换数据的模型。 3.一个目标函数。 4.调整模型参数以优化目标函数的算法。 1,数据有什么组成? 数据=样本+…...
[STM32]从零开始的STM32 BSRR、BRR、ODR寄存器讲解
一、前言 学习STM32一阵子以后,相信大家对STM32 GPIO的控制也有一定的了解了。之前在STM32 LED的教程中也教了大家如何使用寄存器以及库函数控制STM32的引脚从而点亮一个LED,之前的寄存器只是作为一个引入,并没有深层次的讲解,在教…...
VUE3+Vite使用TailwindCSS【若依前后端分离框架】
参考:https://tailwind.nodejs.cn/docs/guides/vite#vue 和 https://blog.csdn.net/hjl_and_djj/article/details/144694485依次运行命令: cnpm install -D tailwindcss3.4.17 postcss autoprefixernpx tailwindcss init -p修改配置文件tailwind.config.…...
【Linux文件IO】系统IO详情
目录 一、前言 二、相关API介绍 2.1 open 2.2 read 2.3 write 2.4 lseek 2.5 close 三、简单示例 3.1 示例1 3.2 示例2 一、前言 在 Linux 系统编程中,系统 I/O(又称低级 I/O)是直接通过操作系统提供的系统调用实现的文件操作接口…...
【弹性计算】弹性裸金属服务器和神龙虚拟化(三):弹性裸金属技术
弹性裸金属服务器和神龙虚拟化(三):弹性裸金属技术 1.弹性裸金属技术背景1.1 传统 KVM 虚拟化系统导致 CPU 计算特性损失1.2 传统 KVM 虚拟化系统导致资源争抢不可避免1.3 传统 KVM 虚拟化系统导致 I/O 性能瓶颈 2.弹性裸金属技术实现2.1 VPC…...
(贪心 合并区间)leetcode 56
思路来源:代码随想录--代码随想录_合并区间题解 首先用lambda 按照左界值升序排序 建立答案的二维数组,将第一个行区间放入,判断从第二行开始 第i行的左区间一定大于第i-1行的左区间(排序过了),所以只判断…...
如何理解语言模型
统计语言模型 先看语言模型,语言即自然语言,模型及我们要解决的某个任务。 任务一:判断哪句话出现的概率大 任务二:预判空缺的位置最有可能是哪个词 再看统计,统计即解决上述两个任务的解决方法。先对语句进行分词…...
动态规划/贪心算法
一、动态规划 动态规划 是一种用于解决优化问题的算法设计技术,尤其适用于具有重叠子问题和最优子结构性质的问题。它通过将复杂问题分解为更简单的子问题,并保存这些子问题的解以避免重复计算,从而提高效率。 动态规划的核心思想 最优子结…...
Hadoop简介
1. Hadoop简介 官网:http://hadoop.apache.org 1.1 Hadoop架构 Hadoop由三个模块组成:分布式存储HDFS、分布式计算MapReduce、资源调度引擎YARN 1.2 Hadoop历史 Hadoop作者Doug Cutting Apache Lucene是一个文本搜索系统库 Apache Nutch作为前者的一部…...
Vscode 便用快捷键设置教程
文章目录 简介:1. go to define (跳转到函数定义的位置)2. go to declaration (跳转到函数声明的位置)3. move line (上下移动本行代码)3.1上下复制本行代码 4. 前进和后退(就是前进到光标上一次停留的位置,和后退到那…...
数据库(MySQL):使用命令从零开始在Navicat创建一个数据库及其数据表(一).创建基础表
一. 使用工具和命令 1.1 使用的工具 Navicat Premium 17 :“Navicat”是一套可创建多个连接的数据库管理工具。 MySQL版本8.0.39 。 1.2 使用的命令 Navicat中使用的命令 命令 命令解释 SHOW DATABASES; 展示所有的数据库 CREATE DATABASE 数据…...
水滴tabbar canvas实现思路
废话不多说之间看效果图,只要解决了这个效果水滴tabbar就能做出来了 源码地址 一、核心实现步骤分解 布局结构搭建 使用 作为绘制容器 设置 width=600, height=200 基础尺寸 通过 JS 动态计算实际尺寸(适配高清屏) function initCanvas() {// 获取设备像素比(解决 Re…...
windows安装vue
1、下载nodejs安装包 https://nodejs.cn/download/ 2、安装node 中途记得可以自己改安装路径,其他都是下一步 3、安装完成后检查 node -v :查看nodejs的版本 npm -v :查看npm的版本 4、修改npm默认安装目录与缓存日志目录的位置 在nodejs目…...
使用3090显卡部署Wan2.1生成视频
layout: post title: 使用3090显卡部署Wan2.1生成视频 catalog: true tag: [Kubernetes, GPU, AI] 使用3090显卡部署Wan2.1生成视频 1. 环境说明2. 模型下载3. 克隆仓库4. 安装依赖5. 生成视频 5.1. 使用generate脚本生成5.2. 使用gradio启动UI界面生成 5.2.1. 启动gradio服务5…...
DCN讲解
DCN是DeepFM的升级版,后者是只能做二阶交叉特征,随着阶数上升,模型复杂度大幅提高,且FM网络层较浅,表达能力有限。google团队通过构建深度交叉网络来自动进行特征的高阶交叉,且时空复杂度均为线性增长&…...
ARM 架构下 cache 一致性问题整理
本篇文章主要整理 ARM 架构下,和 Cache 一致性相关的一些知识。 本文假设读者具备一定的计算机体系结构和 Cache 相关基础知识,适合有相关背景的读者阅读 1、引言 简单介绍一下 Cache 和内存之间的关系 在使能 Cache 的情况下,CPU 每次获取数…...
算法-二分查找
二分查找 其实二分查找是一个很简单理解的东西,从他的名字就可以看出,就是要分为两段去查找一个元素 我们确定一个中间元素,然后将这一个元素和左边的部分和右边的部分做对比 然后根据实际情况来选择一个部分来继续做这么一个步骤 直到找…...
Python Cookbook-2.24 在 Mac OSX平台上统计PDF文档的页数
任务 你的计算机运行着比较新的MacOSX系统(10.3的“Panther”或更新的版本),现在需要知道一个 PDF 文档的页数。 解决方案 PDF格式和 Python都已经集成到了Mac OsX系统中(10.3或更高版本),因而这个问题解决起来也相对比较容易: #!/usr/bin python im…...
【MySQL】索引(页目录、B+树)
文章目录 1. 引入索引2. MySQL与磁盘交互的基本单位3. 索引的理解3.1 页目录3.2 B树 4. 聚簇索引、非聚簇索引5. 索引的操作5.1 索引的创建5.1.1 创建主键索引5.1.2 创建唯一索引5.1.3 普通索引的创建5.1.4 全文索引的创建 5.2 索引的查询5.3 删除索引 1. 引入索引 索引&#…...
工业AR眼镜的‘芯’动力:FPC让制造更智能【新立电子】
随着增强现实(AR)技术的快速发展,工业AR智能眼镜也正逐步成为制造业领域的重要工具。它不仅为现场工作人员提供了视觉辅助,还极大地提升了远程协助的效率、优化了仓储管理。FPC在AI眼镜中的应用,为工业AR智能眼镜提供了…...
开启mysql的binlog日志
mysql版本5.7 1.查看是否开启bin_log show global variables like’log_bin’; off的话需要先开启 在mysql的文件夹目录中找到my.ini 加一行log-bin“C:/ProgramData/MySQL/MySQL Server 5.7/logs/log-bin” 并提前创建好目录 2.数据库会把日志放进logs目录中 3.查看log日…...
SpringSecurity基于JWT实现Token的处理
前面介绍了手写单点登录和JWT的应用,本文结合SpringSecurity来介绍下在SpringBoot项目中基于SpringSecurity作为认证授权框架的情况下如何整合JWT来实现Token的处理。 一、认证思路分析 SpringSecurity主要是通过过滤器来实现功能的!我们要找到SpringSecurity实现认证和校验…...
数据结构与算法-图论-最短路-floyd扩展
floyd和它的拓展: 在计算机科学领域,Floyd通常指Floyd Warshall算法,由罗伯特弗洛伊德(Robert W. Floyd)提出,这是一种用于在加权有向图中查找所有顶点对之间最短路径的算法。 算法原理 Floyd Warsha…...
c++中所有构造函数的介绍与使用
C 中,构造函数是一种特殊的成员函数,用于在创建对象时对对象进行初始化。C 中有多种类型的构造函数,下面详细介绍这些构造函数及其特点和使用场景。 1. 默认构造函数 定义:默认构造函数是指在没有提供任何参数的情况下可以被调用…...
力扣1584. 连接所有点的最小费用
力扣1584. 连接所有点的最小费用 题目 题目解析及思路 题目要求返回最小生成树 最小生成树模版题 法一:prim 主要思想是每次找离树最近的顶点,将其加入树种,并更新其他所有点到该点的距离 代码 class Solution { public:int minCostCo…...
FPGA开发,使用Deepseek V3还是R1(8):FPGA的全流程(简略版)
以下都是Deepseek生成的答案 FPGA开发,使用Deepseek V3还是R1(1):应用场景 FPGA开发,使用Deepseek V3还是R1(2):V3和R1的区别 FPGA开发,使用Deepseek V3还是R1&#x…...
处理大数据的架构模式:Lambda 架构 和 Kappa 架构
Lambda 架构 和 Kappa 架构 是两种用于处理大数据的架构模式,尤其在实时数据处理场景中广泛应用。 1. Lambda 架构 核心思想 Lambda 架构将数据处理分为两条独立的流水线: 批处理层(Batch Layer): 处理全量数据&…...
Docker网络模式实战
docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分 docker安装后会自动创建3种网络:bridge、host、none docker原生bridge网路 docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口 docker安装时…...
Linux网络基础(协议 TCP/IP 网络传输基本流程 IP VS Mac Socket编程UDP)
文章目录 一.前言二.协议协议分层分层的好处 OSI七层模型TCP/IP五层(或四层)模型为什么要有TCP/IP协议TCP/IP协议与操作系统的关系(宏观上是如何实现的)什么是协议 三.网络传输基本流程局域网(以太网为例)通信原理MAC地址令牌环网 封装与解包分用 四.IP地址IP VS Mac地址 五.So…...
MFC: 控件根据文本内容大小自动调整
背景: 针对不同语言下,控件显示不全的现象; 例如: 现象1:中文下显示全部信息,英语下只能显示部分文字 现象2:中文下显示不全## 实现思路: 控件绑定按钮计算控件文本长度根据文本长…...
记一次线上Tomcat服务内存溢出的问题处理
背景:JavaWeb项目部署在Tomcat服务器上,服务器用的Windows。 问题表现:系统出现偶发性无法访问(隔几天就会在早上无法访问) Tomcat的日志catalina中,有如下报错信息。 java.lang.OutOfMemoryError: GC ov…...
go设计模式
刘:https://www.bilibili.com/video/BV1kG411g7h4 https://www.bilibili.com/video/BV1jyreYKE8z 1. 单例模式 2. 简单工厂模式 代码逻辑: 原始:业务逻辑层 —> 基础类模块工厂:业务逻辑层 —> 工厂模块 —> 基础类模块…...
通往 AI 之路:Python 机器学习入门-语法基础
第一章 Python 语法基础 Python 是一种简单易学的编程语言,广泛用于数据分析、机器学习和人工智能领域。在学习机器学习之前,我们需要先掌握 Python 的基本语法。本章将介绍 Python 的变量与数据类型、条件语句、循环、函数以及文件操作,帮助…...
【再谈设计模式】备忘录模式~对象状态的守护者
一、引言 在软件开发过程中,我们常常会遇到需要保存对象状态以便在之后恢复的情况。例如,在文本编辑器中,我们可能想要撤销之前的操作;在游戏中,玩家可能希望恢复到之前的某个游戏状态。备忘录模式(Memento…...
算法:判断链表是否有环
/*** brief 判断链表是否有环* * 该函数使用快慢指针法来判断链表中是否存在环。* 快指针每次移动两步,慢指针每次移动一步。* 如果链表中存在环,那么快指针最终会追上慢指针;* 如果链表中不存在环,快指针会先到达链表末尾。* * p…...
Android Logcat 高效调试指南
工具概览 Logcat 是 Android SDK 提供的命令行日志工具,支持灵活过滤、格式定制和实时监控,官方文档详见 Android Developer。 基础用法 命令格式 [adb] logcat [<option>] ... [<filter-spec>] ... 执行方式 直接调用(通过ADB守…...
【数据结构与算法】Java描述:第一节:ArrayList顺序表
这篇文章我们自己实现一个顺序表, 从而更好的认识它。 一、顺序表的本质 顺序表的本质其实就是一个数组,但是在插入,查找与删除上,有些复杂,顺序表通过对方法进行封装,方便了使用。 二、自己的顺序表 2.…...
报错The default superclass, “jakarta.servlet.http.HttpServlet“(已经配置好tomcat)
报错报错DescriptionResourcePathLocationType The default superclass,“jakarta.servlet.http.HttpServlet”, according to the project’s Dynamic Web Module facet version (5.0), was not found on the Java Build Path. 解决办法: 根据错误信息࿰…...
在笔记本电脑上用DeepSeek搭建个人知识库
最近DeepSeek爆火,试用DeepSeek的企业和个人越来越多。最常见的应用场景就是知识库和知识问答。所以本人也试用了一下,在笔记本电脑上部署DeepSeek并使用开源工具搭建一套知识库,实现完全在本地环境下使用本地文档搭建个人知识库。操作过程共…...
数学建模:MATLAB极限学习机解决回归问题
一、简述 极限学习机是一种用于训练单隐层前馈神经网络的算法,由输入层、隐藏层、输出层组成。 基本原理: 输入层接受传入的样本数据。 在训练过程中随机生成从输入层到隐藏层的所有连接权重以及每个隐藏层神经元的偏置值,这些参数在整个…...
Immich自托管服务的本地化部署与随时随地安全便捷在线访问数据
文章目录 前言1.关于Immich2.安装Docker3.本地部署Immich4.Immich体验5.安装cpolar内网穿透6.创建远程链接公网地址7.使用固定公网地址远程访问 前言 小伙伴们,你们好呀!今天要给大家揭秘一个超炫的技能——如何把自家电脑变成私人云相册,并…...