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

.net也能写内存挂

最近在研究.net的内存挂。

写了很久的c++,发现c#写出来的东西实在太香。

折腾c#外挂已经有很长时间了。都是用socket和c++配合。

这个模式其实蛮成功的,用rpc调用的方式加上c#的天生await 非常好写逻辑

类似这样

最近想换个口味。注入托管dll到非托管进程

这样做只是为了解决我目前遇见的一个问题。

在一个多线程的程序上逆向,我挂了很多钩子,导致我读写数据和储存我自己的数据

非常容易出现多线程冲突问题,换到.net里以后

lock 和Monitor 在.net里是同线程不互锁。这样能让我不容易出现互锁现象。

有一段时间正在烦恼那些卖驱动的,只有读写功能为什么还能实现很多功能。

在我的认知里,要调用游戏部分函数才能更方便自己做出更有用的功能

当然这里确实有些外挂是只读取角色顶点就能绘制的。

后来细想一下其实不需要调用功能通过写入代码的方式获取执行就可以了。

就是只要有读写就可以了。

游戏外挂无非就是 读写和调用。 调用是可以通过写来实现。

比如hook某个dx的函数。或者修改虚函数表的地址,然后jmp 到自己的函数里

达到获取执行权限。

好比挂钩了GetTickCount  这个API ,然后目标游戏不断的调用这个API

我们在这里插入自己的调用逻辑就可以了。

想明白了这个,于是我就干起了注入托管dll 到游戏进程里的勾当

当然这个托管dll实在是太大了(因为会用Costura.Fody把第三方库都打包在一起)

想法是这样,注入到游戏进程里以后申请内存空间,然后通过asm编译成bytes

然后写入到内存后,再去调用他就可以了

这里要安利一个asm的库 

GitHub - icedland/iced: Blazing fast and correct x86/x64 disassembler, assembler, decoder, encoder for Rust, .NET, Java, Python, Lua

这个库很香

在c#里写asm长这样子,大概就是写好asm以后编译成bytes的过程

然后要介绍在c#内怎么完成thiscall

游戏大部分是thiscall  所以我在内存中申请一段asm

然后通过c#去调用这个段代码就可以了

asm 的作用就是把传入的参数 push到堆栈然后call

之后返回eax 这样就完整的跑通调用了。

用iced把asm生成好,然后通过c#的委托去调用这段asm代码即可

最后实现的效果类是这样

至于读写就更简单了。C#自带Marshal可以直接读写。

而且c#也支持不安全指针 直接 *(int*)(0x123456) = 100;

然后我们无限的包装自己的读写函数,比如byte float int string 之类的读写就可以

至于hook 也可以通过委托回调到自己的c#代码,hook在c#完成编译以后写入到目标地址

至此,完整的c#外挂需要的功能都实现了。

例子分3个工程

TestApp:测试工程模拟调用目标程序比如游戏

InjectionDLL:注入DLL,负责加载.net的dll,如果是远线程注入,就注入这个DLL即可,例子工程是主动loadlibrary

CShareLoadModule : c#的主要工作dll

附上源码一份

netInjection.rar

//以下是补充 2022 10 09

/

因为上面代码是用asm作为Thiscall 调用的,后来发现c#是自带调用约定的可以更优美的实现thiscall 调用

        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_0(IntPtr ptr);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_1(IntPtr ptr, IntPtr p1);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_2(IntPtr ptr, IntPtr p1, IntPtr p2);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_3(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_4(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_5(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_6(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_7(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_8(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_9(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_10(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_11(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_12(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_13(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12, IntPtr p13);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate IntPtr ThisCall_14(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12, IntPtr p13, IntPtr p14);unsafe public static IntPtr ThisCall(IntPtr address, IntPtr dwECX, params object[] args){IntPtr p1 = IntPtr.Zero;IntPtr[] paramPtr = new IntPtr[args.Length*2];int addParamCount = 0;for (int i = 0; i < args.Length; i++){var paramtype = args[i].GetType();if (paramtype == typeof(float)){var v = (float)args[i];paramPtr[addParamCount] = *(IntPtr*)&v;}else if (paramtype == typeof(double)){var v = (double)args[i];paramPtr[addParamCount] = *(IntPtr*)&v;addParamCount++;paramPtr[addParamCount] = *(IntPtr*)((&v) +4);}else if (paramtype == typeof(long)){var v = (long)args[i];paramPtr[addParamCount] = *(IntPtr*)&v;addParamCount++;paramPtr[addParamCount] = *(IntPtr*)((&v) + 4);}else if (paramtype == typeof(IntPtr)){var v = (IntPtr)args[i];paramPtr[addParamCount] = v;}else if (paramtype == typeof(PtrGameUIWindow)){paramPtr[addParamCount] = (args[i] as PtrGameUIWindow).ptr;}else{paramPtr[addParamCount] = (IntPtr)Convert.ToInt32(args[i]);}addParamCount++;}Log.Console($"ThisCall:0x{address.ToString("X8")} ECX:0x{dwECX.ToString("X8")} {paramPtr.ArrayToString(0, addParamCount)}");switch (args.Length){case 0:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_0>(address).Invoke(dwECX);break;case 1:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_1>(address).Invoke(dwECX, paramPtr[0]);break;case 2:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_2>(address).Invoke(dwECX, paramPtr[0], paramPtr[1]);break;case 3:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_3>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2]);break;case 4:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_4>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3]);break;case 5:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_5>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4]);break;case 6:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_6>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5]);break;case 7:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_7>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6]);break;case 8:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_8>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7]);break;case 9:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_9>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8]);break;case 10:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_10>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9]);break;case 11:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_11>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10]);break;case 12:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_12>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10], paramPtr[11]);break;case 13:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_13>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10], paramPtr[11], paramPtr[12]);break;case 14:p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_14>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10], paramPtr[11], paramPtr[12], paramPtr[13]);break;default:Log.Error(new Exception("ThisCall 参数个数未预测"));p1 = IntPtr.Zero;break;}return p1;}

因为c#会定期GC的问题,导致c#自身函数可能会被GC修改函数位置

所以需要固定住代码位置新增一下函数固定Delegate

        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]public delegate IntPtr Delegate_NewStringID2String(IntPtr dwESP);public uint LockDelegate(Delegate func){GCHandleList.Add(GCHandle.Alloc(func));GCHandleList.Add(GCHandle.Alloc(Marshal.GetFunctionPointerForDelegate(func), GCHandleType.Pinned));GCHandleList.Add(GCHandle.Alloc(func.Method.MethodHandle.GetFunctionPointer()));return (uint)Marshal.GetFunctionPointerForDelegate(func);}//使用方法public static IntPtr MyStringID2String(IntPtr dwESP){var ret = IntPtr.IntPtr.Zero;return ret;}public override void Start(){var asm = new Assembler(32);asm.pushad();asm.mov(eax, esp);asm.add(eax, 0x20);asm.push(eax);asm.mov(eax, LockDelegate(new Delegate_NewStringID2String(MyStringID2String)));asm.call(eax);asm.mov(__[esp + 0x1c], eax);asm.popad();asm.ret();var newJmpCode = PatchSelfHelper.AllocMem(0x30);PatchSelfHelper.WriteAssembler(newJmpCode, asm);}

相关文章:

.net也能写内存挂

最近在研究.net的内存挂。 写了很久的c,发现c#写出来的东西实在太香。 折腾c#外挂已经有很长时间了。都是用socket和c配合。 这个模式其实蛮成功的&#xff0c;用rpc调用的方式加上c#的天生await 非常好写逻辑 类似这样 最近想换个口味。注入托管dll到非托管进程 这样做只…...

python学习笔记2-数字转化为String

题目链接 str() 强制转换&#xff0c; sorted() 转换为有序列表&#xff0c;join() 将列表中的元素连接到字符串中&#xff0c;然后奇偶位组合成数字 class Solution:def splitNum(self, num: int) -> int:stnum "".join(sorted(str(num)))num1, num2 int(stn…...

MAC版Gradle构建Spring5.X源码阅读环境

前言&#xff1a; 三年前鄙人有幸在现已几乎报废的Window的DELL中搭建过Spring源码环境&#xff0c;今天&#xff0c;Mac版的搭建&#xff0c;来了。 本篇文章环境搭建&#xff1a;Spring5.2.1 Gradle5.6.3-all jdk8 IDEA2022.3版本 文章目录 1、Spring源码下载2、Gradle下载…...

Linux 常用通配符

通配符是一种特殊语句&#xff0c;主要有星号&#xff08;*&#xff09;和问号&#xff08;&#xff1f;&#xff09;&#xff0c;用来模糊搜索文件。当查找文件夹时&#xff0c;可以使用它来代替一个或多个真正字符&#xff1b;当不知道真正字符或者懒得输入完整名字时&#x…...

Python皮卡丘

系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮爱心https://want…...

【数据结构与算法】三种简单排序算法,包括冒泡排序、选择排序、插入排序算法

冒泡排序算法 冒泡排序他是通过双重循环对每一个值进行比较&#xff0c;将小的值向后移动&#xff0c;以达到最终排序的结果&#xff0c;他的时间复杂度为O(n^2)。 /*** 冒泡排序* param arr*/public static void bubbleSort(int[] arr){int l arr.length;for (int i 0; i <…...

视频太大怎么压缩变小?超过1G的视频这样压缩

视频已经成为了我们日常生活中不可或缺的一部分&#xff0c;然而&#xff0c;很多时候&#xff0c;我们可能会遇到视频文件过大&#xff0c;无法在某些平台上传或保存的问题。那么&#xff0c;如何将过大的视频文件压缩变小呢&#xff1f; 下面就给大家分享三款实用的工具&…...

Edge 无法登录/同步问题【一招搞定】

目录 前言 一、打开 Edge 浏览器显示未同步&#xff0c;点击同步无效 二、Edge 登录报错 0x801901f4 或 0x80190001 解决方法 2.1 报错 0x801901f4 解决方法 2.1.0 Edge 登陆报错图示 2.1.1 添加 Edge 推荐的 DNS 地址 2.1.2 重新登录 Edge 账号成功 2.2 报错 0x801…...

ESP32-S3上手开发

1、搭建开发环境 首先搭建开发环境&#xff0c;这里采用了windows下集成开发环境ide进行开发&#xff0c;具体的安装方法&#xff1a;ESP-IDF安装配置 这里使用的乐鑫的esp32s3&#xff0c;N16R8 2、esp32s3模块 从上面图中可以看到&#xff0c;N16R8这里使用了外扩16M的fl…...

UE4和C++ 开发-编程基础记录(UE4+代码基础知识)

1、UE4基础元素 ①Actor 我们又见面了Actor&#xff0c;Actor是在一个关卡中持续存在的&#xff0c;通常他包含几个Actor组件。支持网络复制和多人游戏。   Actor不包含位置&#xff0c;方向。这些东西在Root Component中存储。对于UE3 中的Pawn也由PlayerCharacter继承了…...

【Unity】【VR】如何让Distance Grab抓取物品时限制物品的Rotation

【背景】 遇到这样的场景,希望抓取Canvas时,Canvas不会沿Z轴旋转。 【问题】 发现Freeze Canvas的Rigid Body没有用。 【分析】 应该是RigidBody的限制仅在物理互动下生效,抓取可能不属于物理互动(比如碰撞),所以不生效。 【思路】 还是得写脚本挂载在Interacta…...

为什么3ds max渲染效果图有噪点?点进来,CG Magic告诉您!

大家在使用3ds max渲染效果图时&#xff0c;可能渲染结果往往会出现的都是不真实&#xff0c;有小伙伴会问如何使3dmax渲染效果图真实呢&#xff1f; 不真实就算了&#xff0c;渲染过程中&#xff0c;会出现3Dmax渲染噪点多这类问题。 什么原因3ds max渲染效果图有噪点呢&a…...

Element UI怎么安装呢?

安装 :::warning 注意 后续演示将会在 Vue CLI 搭建的 Vue 项目上进行操作。如需要请查看 Vue CLI 安装 ::: 通过 YARN 命令安装 $ yarn add element-ui完整引入 代表一次性引入所有组件&#xff0c;比较省心省事&#xff0c;但是项目的打包体积也会跟着变大。 // main.js…...

redis批量删除命令

./redis-cli -h 127.0.0.1 -p 6379 -n 2 KEYS "170*:redisKeyStr" | xargs ./redis-cli -h 127.0.0.1 -p 6379 -n 2 DEL...

kubernetes环境 搭建

1、准备2台机器 2、安装docker环境&#xff08;参考官网&#xff09; 1、 sudo apt-get update sudo apt-get install ca-certificates curl gnupg2、 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dea…...

TCP习题总结

1、在采用TCP连接的数据传输阶段&#xff0c;如果发送端的发送窗口值由1000变为2000&#xff0c;那么发送端在收到一个确认之前可以发送&#xff08;&#xff09;。 A. 2000个TCP报文段 B. 2000B C. 1000B D. 1000 个 TCP 报文 这道题考察的是TCP的基本…...

华为发布LampSite X室内数字化创新解决方案,释放数字世界无限潜能

【阿联酋&#xff0c;迪拜&#xff0c;2023年10月11日】2023全球移动宽带论坛&#xff08;Global MBB Forum 2022&#xff09;期间&#xff0c;华为董事、ICT产品与解决方案总裁杨超斌重磅发布了全新一代5G室内数字化产品解决方案LampSite X系列&#xff0c;助力运营商打开商业…...

麒麟操作系统设置QT程序开机自启动有效方法

在麒麟操作系统上设置QT程序开机自启动的两种简单有效的方法。支持请点赞&#xff01; 一、QT程序打包 1.设置环境变量 设置QT和linuxdeployqt的环境变量&#xff0c;已设置可忽略该步骤。 在/etc/profile文件末尾添加一下内容&#xff1a; export PATH/usr/local/Qt-5.15.…...

Python数组删除元素pop与remove对比

pop()和remove()函数都可以用来删除列表中的函数&#xff0c;pop()是按索引来删除的&#xff0c;remove()是按元素来删除的。 1、pop()默认删除列表中最后一个元素&#xff0c;而且会返回删除的元素。此时的时间复杂度为O&#xff08;1&#xff09; 下面的例子中&#xff0c;…...

【Java 进阶篇】Java Web 编写注册页面案例

当涉及到创建一个Java Web注册页面时&#xff0c;你将需要涵盖很多不同的主题&#xff0c;包括HTML、CSS、Java Servlet和数据库连接。在这篇文章中&#xff0c;我们将详细介绍每个步骤&#xff0c;以帮助你创建一个完整的注册页面。 1. 介绍 注册页面是许多Web应用程序的关键…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...