UE4外挂实现分析-PC端-附源码
UE4外挂实现分析-PC端
游戏分析
分析工具:
Cheat Engine 7.5
x64dbg
IDA Pro
参考文章:
UE4逆向笔记之GWORLD GName GameInstance - 小透明‘s Blog
【项目源码下载】https://download.csdn.net/download/Runnymmede/90079718
本次分析的游戏使用UE4.22引擎开发,外挂实现功能有透视和自瞄,两项功能都基于游戏内玩家对象和敌人对象的坐标位置实现。UE4游戏内对象的结构如下图所示
图片中的对象偏移与UE引擎版本相关,存在误差。
根据上图的关系,游戏中所有的对象都挂在UWorld
下面,通过UWorld->GameInstance->ULocalPlayer->LocalPlayer->PlayerController->Actor
可以获取到游戏玩家的Actor对象,进而获取玩家的坐标等信息
通过PWorld->ULevel->ActorCount
和PWorld->ULevel->ActorArray
可以遍历游戏中所有的Actor对象,包括敌人的Actor对象,进而获取敌人坐标信息,在一局游戏中,PWorld
指针与UWorld
相同
CE分析UWorld
开启游戏使用CE打开游戏进程
寻找游戏内能直接获取的与玩家信息有关的详细数据,游戏中子弹数量能够直接查看到准确数值,并且方便控制,因此使用CE查找子弹数量的地址
首先搜索准确的32位整数50
开枪减少子弹数量,继续搜索48
只剩两个地址,修改这两个地址处的值,查看游戏内子弹数量是否发生变化,
可以确定子弹数量储存在0x1E3EDF40684
地址处,对该地址进行指针分析
根据GameInstance
到PlayerController
的偏移关系0x38 -> 0x0 -> 0x30
过虑到如下指针链
其中存在条指针链
"ShooterClient.exe"+02F6E6E8->0xD80->0x38->0x0->0x30->0x3B0->0x778->0x584
"ShooterClient.exe"+02F71060->0x160->0x38->0x0->0x30->0x3B0->0x778->0x584
因此可以分析出UWorld
为ShooterClient.exe+02F6E6E8
或ShooterClient.exe+02F71060
UWorld = [ShooterClient.exe+0x02F71060]
GameInstance = [UWorld+0x160]
ULocalPlayer = [GameInstance+0x38]
LocalPlayer=[ULocalPlayer]
PlayerController = [LocalPlayer+0x30]
PlayerActor = [PlayerController+03B0]ReadProcessMemory(hProcess, (LPVOID)((BYTE*)baseAddr + 0x2E6E0C0), (LPVOID)&GName, 8, NULL);
继续使用浮点数模糊搜索玩家坐标、视角信息等,由于已经确定玩家子弹数量地址,因此可以缩小搜索范围在0x1E3EDF40684
附近
得到如下指针信息
bullet = [[PlayerActor+0x778]+0x584]
posi_x = [[PlayerActor+0x3A0]+0x1A0]
posi_y = [[PlayerActor+0x3A0]+0x1A4]
posi_z = [[PlayerActor+0x3A0]+0x1A8]
persp_x = [[PlayerActor+0x3A0]+0x154]
persp_y = [[PlayerActor+0x3A0]+0x174]
基于上述信息,还能确定ULevel
ULevel = [UWorld+0x30]
ActorCount
和ActorArray
的偏移可以使用CE的结构体分析功能
经过分析,确定ActorCount
和ActorArray
的偏移
ActorCount = [ULevel+0xA0]
ActorArray = [ULevel+0x98]
遍历ActorArray
可以获得游戏内所有的Actor对象,包含了敌人对象,但还需要识别是否为敌人,所以还需要查找对象的Name
CE分析GName
UE4.23以下版本使用的GName算法如下
BYTE *GetName(int id)
{int idx0 = id / 0x4000;int idx1 = id % 0x4000;BYTE *NameArray = [GName + idx0 * 8];BYTE *Name = [NameArray + idx1 * 8] + 0xC;return Name;
}
使用CE搜索进程内存,查找关键字符串ByteProperty
如果上一个字符串为None
,则表示搜索到了正确位置,此处为游戏对象的Name表
由于ByteProperty
字符串id为1,可以根据GetName
算法逆推GName
搜索地址0x1E3D5EA0024-0xC
搜索0x1E3D5E80008-1*8
搜索0x1E3D5E70080
可以确定GName为ShooterClient.exe+2D310B0
或ShooterClient.exe+2E6E0C0
编写代码验证上述分析的偏移
int main()
{LPCWSTR procName = L"ShooterClient.exe";DWORD dwPID;HANDLE hProcess;LPVOID baseAddr;dwPID = getDwPidByName(procName);printf("PID: %d\n", dwPID);hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);if (hProcess == NULL){printf("open process failed\n");return 0;}baseAddr = getModuleBase(dwPID);printf("proc base: 0x%llx\n", baseAddr);LPVOID UWorld;LPVOID GName;LPVOID GameInstance;LPVOID ULocalPlayer;LPVOID LocalPlayer;LPVOID PlayerController;LPVOID PlayerActor;LPVOID PlayerPosition;LPVOID ULevel;DWORD ActorCount;LPVOID ActorArray;// 读取UWorldReadProcessMemory(hProcess, (LPVOID)((BYTE*)baseAddr + 0x02F71060), (LPVOID)&UWorld, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)UWorld + 0x160), (LPVOID)&GameInstance, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)GameInstance + 0x38), (LPVOID)&ULocalPlayer, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)ULocalPlayer, (LPVOID)&LocalPlayer, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)LocalPlayer + 0x30), (LPVOID)&PlayerController, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)PlayerController + 0x3B0), (LPVOID)&PlayerActor, 8, NULL);printf("\n");printf("UWorld: 0x%llx\n", UWorld);printf("GameInstance: 0x%llx\n", GameInstance);printf("ULocalPlayer: 0x%llx\n", ULocalPlayer);printf("LocalPlayer: 0x%llx\n", LocalPlayer);printf("PlayerController: 0x%llx\n", PlayerController);printf("PlayerActor: 0x%llx\n", PlayerActor);printf("\n");ReadProcessMemory(hProcess, (LPVOID)((BYTE*)UWorld + 0x30), (LPVOID)&ULevel, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)ULevel + 0xA0), (LPVOID)&ActorCount, 4, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)ULevel + 0x98), (LPVOID)&ActorArray, 8, NULL);// 读取玩家坐标FLOAT posi[3];ReadProcessMemory(hProcess, (LPVOID)((BYTE*)PlayerActor + 0x3A0), (LPVOID)&PlayerPosition, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)PlayerPosition+0x1A0), (LPVOID)posi, 0xC, NULL);printf("\n");printf("posi: [%f, %f, %f]\n", posi[0], posi[1], posi[2]);// 读取玩家视角FLOAT persp_x, persp_y;ReadProcessMemory(hProcess, (LPVOID)((BYTE*)PlayerPosition + 0x154), (LPVOID)&persp_x, 0x4, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)PlayerPosition + 0x174), (LPVOID)&persp_y, 0x4, NULL);printf("perspective: [%f, %f]\n", persp_x, persp_y);printf("\n");printf("ULevel: 0x%llx\n", ULevel);printf("ActorCount: %d\n", ActorCount);printf("ActorArray: 0x%llx\n", ActorArray);// 读取GNameReadProcessMemory(hProcess, (LPVOID)((BYTE*)baseAddr + 0x2E6E0C0), (LPVOID)&GName, 8, NULL);printf("GName: 0x%llx\n", GName);printf("\n");// 遍历ActorArryfor (DWORD i = 0; i < ActorCount; i++){LPVOID AActor;DWORD id;LPVOID PNameArray;LPVOID PName;CHAR name[0x100];ReadProcessMemory(hProcess, (LPVOID)((BYTE*)ActorArray + i * 8), (LPVOID)&AActor, 8, NULL);if (ReadProcessMemory(hProcess, (LPVOID)((BYTE*)AActor + 0x18), (LPVOID)&id, 4, NULL)){ReadProcessMemory(hProcess, (LPVOID)((BYTE*)GName + (id / 0x4000) * 8), (LPVOID)&PNameArray, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)PNameArray + (id % 0x4000) * 8), (LPVOID)&PName, 8, NULL);if (ReadProcessMemory(hProcess, (LPVOID)((BYTE*)PName + 0xC), (LPVOID)name, 0x100, NULL)){printf("%d: %s\n", i, name);}}}return 0;
}
;
if (!strcmp(name, "BotPawn_C"))
{LPVOID botPosition;FLOAT botPosi[3];ReadProcessMemory(hProcess, (LPVOID)((BYTE*)AActor + 0x3A0), (LPVOID)&botPosition, 8, NULL);ReadProcessMemory(hProcess, (LPVOID)((BYTE*)botPosition + 0x1A0), (LPVOID)botPosi, 0xC, NULL);printf("bot: [%f, %f, %f] \n", botPosi[0], botPosi[1], botPosi[2]);
}
至此,已实现获取玩家坐标、玩家视角、敌人坐标的目标,对坐标数据进行数学处理,使用GUI工具绘制到屏幕上,即可实现透视效果,同样可以通过计算玩家视角需要转动的角度,实现自瞄的功能。
外挂分析
VMP脱壳DUMP
入口push call,典型vmp,使用API断点回溯确定程序逻辑是否加密
根据外挂实现原理,读取进程需要使用ReadProcessMemory
API,而这之前还需要使用OpenProcess
API打开进程,OpenProcess
需要的参数为进程PID,但是该外挂程序不需要提供PID,因此该外挂运行早期会使用某些方式获取目标游戏的PID,需要利用Thelp32
功能,对CreateThelp32Snapshot
下断点
ScyllaHide过VMP反调试
3处nop断下后F9运行
Thelp32断下,第一次是VMP反调试调用的,忽略掉,F9运行
Thelp32第二次断下,分析调用栈回溯
发现此处为典型的msvc编译器主函数调用入口
因此该层为start
,可以确定程序逻辑未加密,向上找到程序入口点OEP
对OEP下断点,取消Thelp32断点,重新运行程序,3次nop之后OEP断下
使用Scylla插件DUMP外挂内存
使用Fix Dump修复DUMP文件的导入数据
删除带X的FThunk
运行恢复后的DUMP文件hack_dump_SCY.exe
,外挂功能正常
外挂脱壳完成
外挂逻辑分析
使用IDA Pro打开脱壳后的hack_dump_SYC.exe
分析逻辑,动态调试之后对主函数注释如下,程序中的字符串大部分被加密,算法比较简单,但是使用动态调试也可以直接得到解密之后的字符串
主要功能就是打开游戏进程,获取游戏加载地址,创建窗口等操作,API断点回溯时断下的位置在GetPidByName
函数中
作弊的主要逻辑在CheatProc
过程函数中
showGUI
函数调用imGUI
库在屏幕上显示窗口
这里使用GetAsyncKeyState
API判断HOME键是否被按下,HOME按下之后切换GUI显示状态
CheatMain
里第一个和最后一个函数是用来刷新屏幕上显示的文本标签的,可以直接忽略
继续进入到cheatMain
函数,这里是主要的外观逻辑实现
首先使用ReadProcessMemory
API读取进程内存,获取UWorld
,GName
等数据,偏移的计算在游戏分析部分得到的偏移基本相同,对所有的全局变量进行注释,方便后续分析
遍历游戏中所有的Actor对象,并且获取对象的name,与BotPawn_C
进行比较,判断该AActor是否为机器人
是机器人时读取机器人坐标,根据玩家坐标、窗口分辨率计算是否在屏幕显示范围内,是的话则会在屏幕上显示玩家与机器人的距离
此部分还计算了机器人在屏幕上显示坐标与窗口中心的距离,循环结束后保持与屏幕中心距离最近的机器人坐标,用于自瞄功能
自瞄功能同样使用GetAsyncKeyState
判断按键是否按下,这里判断的是鼠标右键,当鼠标右键按下时,修改玩家视角使其瞄向距离屏幕中心最近的机器人
至此,外挂程序功能分析完成。
【项目源码下载】https://download.csdn.net/download/Runnymmede/90079718
相关文章:
UE4外挂实现分析-PC端-附源码
UE4外挂实现分析-PC端 游戏分析 分析工具: Cheat Engine 7.5 x64dbg IDA Pro 参考文章: UE4逆向笔记之GWORLD GName GameInstance - 小透明‘s Blog 【项目源码下载】https://download.csdn.net/download/Runnymmede/90079718 本次分析的游戏使用UE4.2…...
力扣88题:合并两个有序数组
力扣88题:合并两个有序数组 题目描述 给定两个按非递减顺序排列的整数数组 nums1 和 nums2,以及它们的长度 m 和 n,要求将 nums2 合并到 nums1,使得合并后的数组仍按非递减顺序排列。 输入与输出 示例 1: 输入&am…...
Lua面向对象实现
Lua中的面向对象是通过表(table)来模拟类实现的,通过setmetatable(table,metatable)方法,将一个表设置为当前表的元表,之后在调用当前表没有的方法或者键时,会再查询元表中的方法和键,以此来实现…...
小程序 模版与配置
WXML模版语法 一、数据绑定 1、数据绑定的基本原则 (1)在data中定义数据 (2)在WXML中使用数据 2、在data中定义页面的数据 3、Mustache语法的格式(双大括号) 4、Mustache语法的应用场景 (…...
【Elasticsearch】实现分布式系统日志高效追踪
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
探索Go语言中的循环单链表
简介 循环单链表是一种特殊的链表数据结构,它的最后一个节点指向链表的头节点,形成一个闭环。今天我们将探讨如何在Go语言中实现和操作这种数据结构。 为什么选择循环单链表? 连续访问:在循环单链表中,可以无限循环…...
[go-redis]客户端的创建与配置说明
创建redis client 使用go-redis库进行创建redis客户端比较简单,只需要调用redis.NewClient接口创建一个客户端 redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",Password: "",DB: 0, })NewClient接口只接收一个参数red…...
Windows 和 Linux 系统命令行操作详解:从文件管理到进程监控
1.切换盘符与目录操作 在命令行中,切换盘符和目录是最常见的操作。尽管 DOS 和 Linux 在这些操作上有所不同,但它们都能实现相似的功能。 (1)切换盘符 ①DOS命令:在 DOS 中,切换盘符非常简单,使用 盘符名:ÿ…...
SpringBoot中@Import和@ImportResource和@PropertySource
1. Import Import注解是引入java类: 导入Configuration注解的配置类(4.2版本之前只可以导入配置类,4.2版本之后也可以导入普通类)导入ImportSelector的实现类导入ImportBeanDefinitionRegistrar的实现类 SpringBootApplication…...
etcd-v3.5release-(3)-readIndexRead
笔记1:读操作包括两种,readIndex和serilizable,readIndex指一致性读,一旦a读到了数据x,那么a及a以后的数据都能读到x,readIndex读会先确认本leader是不是有效地leader,如果有效则记录此刻的comm…...
Chrome 中小于 12px 文字的实现方式与应用场景详解
让 Chrome 支持小于 12px 的文字 在 Web 开发中,有时需要将文字显示为小于 12px 的尺寸,尤其是在设计精细的 UI 元素时。虽然大多数浏览器支持小于 12px 的字体大小,但 Chrome 默认情况下会通过调整文本渲染来确保文字可读性,尤其在非常小的文字尺寸下,可能会进行抗锯齿处…...
数据挖掘之数据预处理
引言 数据挖掘是从大量数据中提取有用信息和知识的过程。在这个过程中,数据预处理是不可或缺的关键步骤。数据预处理旨在清理和转换数据,以提高数据质量,从而为后续的数据挖掘任务奠定坚实的基础。由于现实世界中的数据通常…...
slam学习笔记6---样例展示雅可比手推过程
背景:一直在使用模板、自动化求导,对于背后雅可比推导只剩一个基本概念,有必要好好梳理巩固一下。本人水平有限,若推导过程有误,欢迎评论区提出。 假设一个二维slam问题,使用欧式距离观测模型,…...
ThreadLocal 详解
ThreadLocal 详解 ThreadLocal 是 Java 提供的一种线程本地存储机制,用于为每个线程提供独立的变量副本,变量的值仅在线程内可见,从而实现线程隔离。这种特性在需要为每个线程维护独立状态的场景中非常有用,例如用户上下文、事务…...
SQL SERVER 2016 AlwaysOn 无域集群+负载均衡搭建与简测
之前和很多群友聊天发现对2016的无域和负载均衡满心期待,毕竟可以简单搭建而且可以不适用第三方负载均衡器,SQL自己可以负载了。windows2016已经可以下载使用了,那么这回终于可以揭开令人憧憬向往的AlwaysOn2016 负载均衡集群的神秘面纱了。 …...
Unity 基于Collider 组件在3D 物体表面放置3D 物体
实现 从鼠标点击的屏幕位置发送射线,以射线监测点击到的物体,根据点击物体的法线向量调整放置物体的位置及朝向。 Ray ray Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit, 100)) {obj.transform.…...
项目搭建:springboot,mybatis, maven
创建一个基于Spring Boot、MyBatis和Maven的项目可以简化很多配置,因为Spring Boot自带了很多自动配置的功能。下面我将给出一个简单的示例来展示如何搭建这样一个项目。 ### 1. 创建一个新的Spring Boot项目 你可以通过Spring Initializr(https://sta…...
网页端五子棋对战(四)---玩家匹配实现上线下线处理
文章目录 1.游戏大厅用户匹配1.1请求和响应1.2设计匹配页面1.3获取玩家信息1.4玩家信息的样式设置1.5初始化我们的websocket1.6点击按钮和客户端交互1.7点击按钮和服务器端交互 2.服务器端实现匹配功能框架2.1方法重写2.2借用session 3.处理上线下线3.1什么是上线下线3.2实现用…...
Linux笔记---进程:进程替换
1. 进程替换的概念 进程替换是指在一个正在运行的进程中,用一个新的程序替换当前进程的代码和数据,使得进程开始执行新的程序,而不是原来的程序。 这种技术通常用于在不创建新进程的情况下,改变进程的行为。 我们之前谈到过for…...
【AI日记】24.12.04 kaggle 比赛 Titanic-7
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 内容: 学习 kaggle 入门比赛 Titanic - Machine Learning from Disaster学习机器学习基础(pandas,numpy,sklearn,seaborn,matplotl…...
使用 Flutter 进行移动应用开发:深入探索
文章目录 前言一、介绍二、安装 Flutter 环境三、Flutter 应用结构与基础组件四、状态管理策略五、高级主题结语 前言 随着移动技术的迅猛发展,跨平台开发的需求日益增长。开发者们一直在寻找一种既能保证应用性能又能减少开发成本和时间的技术方案。Flutter 应运而…...
SQLServer 服务器只接受 TLS1.0,但是客户端给的是 TLS1.2
Caused by: javax.net.ssl.SSLHandshakeException: the server selected protocol version TLS10 is not accepted by client preferences [TLS12] 原因描述:SQLServer 服务器只接受 TLS1.0,但是客户端给的是 TLS1.2 解决方法如下: 打开文件…...
Linux命令行解释器的模拟实现
欢迎拜访:羑悻的小杀马特.-CSDN博客 本篇主题:Linux命令行解释器 制作日期:2024.12.04 隶属专栏:linux之旅 本篇简介: 主线带你用ubuntu版系统步步分析实现基础版本的shell;比如支持重定向操作࿰…...
模块化设计割草机器人系统研究与实现(系统架构师论文)
摘要: 割草机器人项目旨在实现自主草坪修剪,以提高园艺工作的效率。本文以具体项目为背景,介绍系统架构师在项目开发过程中的架构设计策略、关键技术应用、问题解决方案和优化措施。首先,本文分析割草机器人项目的总体架构需求&a…...
javascript(前端)作为客户端端通过grpc与cpp(服务端)交互
参考文章 https://blog.csdn.net/pathfinder1987/article/details/129188540 https://blog.csdn.net/qq_45634989/article/details/128151766 前言 临时让我写前端, 一些配置不太懂, 可能文章有多余的步骤但是好歹能跑起来吧 你需要提前准备 公司有自带的这些, 但是版本大都…...
股市复盘笔记
复盘是股市投资中非常重要的一个环节,它指的是投资者在股市收盘后,对当天的市场走势、个股表现以及自己的交易行为进行回顾和总结,以便更好地指导未来的投资决策。以下是对复盘的详细解释: 一、复盘的目的 总结市场走势ÿ…...
【SARL】单智能体强化学习(Single-Agent Reinforcement Learning)《纲要》
📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅…...
Linux 权限管理:用户分类、权限解读与常见问题剖析
🌟 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。🌟 🚩用通俗易懂且不失专业性的文字,讲解计算机领域那些看似枯燥的知识点🚩 目录 💯L…...
Windows通过指令查看已安装的驱动
Windows通过指令查看已安装的驱动 在 Windows 操作系统中,有几种命令可以用来查看已安装的驱动程序。以下是常见的几种方法: 1. 使用 pnputil 查看已安装驱动程序 pnputil 是一个 Windows 内置工具,可以列出所有已安装的驱动程序包。 命令…...
Springboot(五十一)SpringBoot3整合Sentinel-nacos持久化策略
上文中我记录了在Springboot项目中链接sentinel-dashboard使用限流规则的全过程。 但是呢,有一个小小的问题,我重启了一下我本地的sentinel-dashboard服务,然后,我之前创建的所有的流控规则都没了…… 这……好像有点不合理啊,咱就不能找地儿存储一下?你这一重启就没了,…...
Scala的正则表达式
package hfdobject Test35_3 {def main(args: Array[String]): Unit {println("a\tb")//定义一个规则 正则表达式//1. .表示除了换行之外的其他的任意单个字符//2. \d等于[0-9] 匹配一个数字//3. \D除了\d之外的其他的任意字符,表示非数字//4. \w等价于[…...
cuda12.1版本的pytorch环境安装记录,并添加到jupyter和pycharm中
文章目录 前置准备使用anaconda prompt创建虚拟环境创建虚拟环境激活pytorch虚拟环境把pytorch下载到本地使用pip把安装包安装到pytorch环境中进入python环境检验是否安装成功将环境添加到jupyter在pycharm中使用该环境: 前置准备 安装anaconda,我的版本…...
牛客linux
1、 统计文件的行数 # 方法 1 wc -l ./nowcoder.txt | awk {print $1} # 方法 2 ,awk 可以打印所有行的行号, 或者只打印最后一行 awk {print NR} ./nowcoder.txt |tail -n 1 awk END{print NR} ./nowcoder.txt # 方法 3 grep -c 、-n等等 grep -c "" ./…...
通过HTML Canvas 在图片上绘制文字
目录 前言 一、HTML Canvas 简介 二、准备工作 三、绘制图片 四、绘制文字 五、完整代码 效果演示: 前言 HTML canvas 为我们提供了无限的创意可能性。今天,我们就来探索一下如何通过 HTML canvas 将图片和文字绘制到图片上,创造出独特…...
【C#】ListBox中找到多个image中的其中一个并重置赋值以便清理占用内存
1.ListBox中定义多个image 定义ListBox前台代码及Image控件的赋值 <ListBox Background"{DynamicResource BackgroundBrush}" ItemsSource"{Binding ElementNameDRFinish,PathImages}" Style"{x:Null}" Name"ImageList"ItemConta…...
Apache Commons工具类库使用整理
文章目录 Apache Commons工具类库分类- commons-lang3字符串工具:StringUtils日期工具:DateUtils数值工具:NumberUtils对象工具:ObjectUtils数组工具:ArrayUtils异常工具:ExceptionUtils枚举工具࿱…...
npm 设置镜像
要在npm中设置镜像,你可以使用npm config命令。以下是设置npm镜像的步骤: 临时使用淘宝镜像: npm --registry https://registry.npmmirror.com install package-name 永久设置镜像: npm config set registry https://registry…...
数据结构自测5
第6章 树和二叉树 自测卷解答 一、下面是有关二叉树的叙述,请判断正误(每小题1分,共10分) ( √ )1. 若二叉树用二叉链表作存贮结构,则在n个结点的二叉树链表中只有n—1个非空指针域。 ÿ…...
【后端面试总结】缓存策略选择
一般来说我们常见的缓存策略有三种,他们各自的优劣势和实现逻辑分别如下 Cache Aside(旁路缓存) 特点: 灵活性高:应用程序直接与缓存和数据库交互,具有高度的灵活性,可以根据业务需求自定义缓…...
40分钟学 Go 语言高并发:RPC服务开发实战
RPC服务开发实战 一、RPC服务基础概览 开发阶段关键点重要程度考虑因素接口设计API定义、协议选择、版本控制⭐⭐⭐⭐⭐可扩展性、兼容性服务实现业务逻辑、并发处理、资源管理⭐⭐⭐⭐⭐性能、可靠性错误处理异常捕获、错误码、故障恢复⭐⭐⭐⭐稳定性、可维护性性能测试负载…...
Linux 无界面模式下使用 selenium
文章目录 前言什么是无界面模式?具体步骤安装谷歌浏览器查看安装的谷歌浏览器的版本下载对应版本驱动并安装Python 测试代码 总结个人简介 前言 在 Linux 服务器上运行自动化测试或网页爬虫时,常常需要使用 Selenium 来驱动浏览器进行操作。然而&#x…...
算法第一弹-----双指针
目录 1.移动零 2.复写零 3.快乐数 4.盛水最多的容器 5.有效三角形的个数 6.查找总价值为目标值的两个商品 7.三数之和 8.四数之和 双指针通常是指在解决问题时,同时使用两个指针(变量,常用来指向数组、链表等数据结构中的元素位置&am…...
学习如何解决“区间划分”问题(一般方法论+实例应用讲解)
文章目录 解决“区间划分”问题的一般方法论方法论:解决区间划分问题的四步法1. 问题分析与建模2. 动态规划状态的定义3. 状态转移方程4. 初始条件与边界 方法论应用:最小和最大石子合并得分问题描述步骤 1:问题分析与建模步骤 2:…...
消息中间件-Kafka2-3.9.0源码构建
消息中间件-Kafka2-3.9.0源码构建 1、软件环境 JDK Version 1.8Scala Version 2.12.0Kafka-3.9.0 源码包 下载地址:https://downloads.apache.org/kafka/3.9.0/kafka-3.9.0-src.tgzGradle Version > 8.8Apache Zookeeper 3.7.0 2、源码编译 打开源码根目录修改…...
达梦归档文件名与实例对应关系
默认的,达梦归档文件名比较难以看懂,且多实例下不好区分 靠它就行 select upper(to_char((select DB_MAGIC), xxxxxxxxxx)) mag_id; 这样就对上号了。...
STL算法之sort
STL所提供的各式各样算法中,sort()是最复杂最庞大的一个。这个算法接受两个RandomAccessIterators(随机存取迭代器),然后将区间内的所有元素以渐增方式由小到大重新排列。还有一个版本则是允许用户指定一个仿函数代替operator<作为排序标准。STL的所有…...
elementui table滚动分页加载
文章目录 概要 简化的实现示例: 小结 概要 在使用 Element UI 的 Table 组件时,如果需要实现滚动分页加载的功能,可以通过监听 Table 的滚动事件来动态加载更多数据。 简化的实现示例: <template><el-table ref"…...
【MySQL 进阶之路】索引的使用
5.索引的使用规则 在数据库管理系统(DBMS)中,索引是提高查询效率的关键机制之一。MySQL索引优化是指通过设计、调整和选择合适的索引策略,以提高数据库的查询性能和降低资源消耗。以下是一些关键的索引使用规则: 1. …...
FPGA中所有tile介绍
FPGA中包含的tile类型,以xinlinx 7k为例,可以通过f4pga项目中的原语文件夹查看,主要包含以下这些: 以下是您提到的 Xilinx 7 系列 FPGA 中各种模块的含义及用途: 1. BRAM (Block RAM) BRAM 是 FPGA 中的块存储资源&…...
理解 Python PIL库中的 convert(‘RGB‘) 方法:为何及如何将图像转换为RGB模式
理解 Python PIL库中的 convert(RGB) 方法:为何及如何将图像转换为RGB模式 在图像处理中,保持图像数据的一致性和可操作性是至关重要的。Python的Pillow库(继承自PIL, Python Imaging Library)提供了强大的工具和方法来处理图像&…...