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

某手sig3-ios算法 Chomper黑盒调用

Chomper-iOS界的Unidbg

最近在学习中发现一个Chomper框架,Chomper 是一个模拟执行iOS可执行文件的框架,类似于安卓端大名鼎鼎的Unidbg。

这篇文章使用Chomper模拟执行某手的sig3算法,初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的hook操作、读取操作等。

框架搭建

chomper 使用python开发,这里直接使用pip安装 pip install chomper (mac的m系列芯片,可能需要再自己电脑编译unicorn并安装)

下载chomper中rootfs​ 放在项目录下 如下:

基础代码如下:

import osfrom chomper import Chomper
from chomper.const import ARCH_ARM64, OS_IOS
from chomper.objc import ObjC
from chomper.utils import pyobj2nsobj
from chomper.os.ios.hooks import register_hook
from unicorn import arm64_constbase_path = os.path.abspath(os.path.dirname(__file__))def trace_inst_callback(self, uc, address, size, user_data):for inst in self.cs.disasm_lite(uc.mem_read(address, size), 0):self.logger.info(f"Trace at {self.debug_symbol(address)}: {inst[-2]} {inst[-1]}")message = ""for i in range(31):if message:message += ", "message += f"x{i}={hex(self.uc.reg_read(getattr(arm64_const, f'UC_ARM64_REG_X{i}')))}"self.logger.info(message)Chomper.trace_inst_callback = trace_inst_callback #这里是用来trace代码
#加载ios基础库支持。
emu = Chomper(arch=ARCH_ARM64,os_type=OS_IOS,rootfs_path=os.path.join(base_path, "rootfs/ios"),enable_ui_kit=True, #开启ui_kit库支持,
)objc = ObjC(emu)

某手核心算法调用

这里不再分析sig3怎么来的,以及如何构造的,如果需要请看兔哥公众号文章。https://mp.weixin.qq.com/s/JG56KxPC7s3oSvoGkQVBRQ

算法加载流程如下:根据frida-trace得

+[KWSecurity defaultInterface]22578 ms  -[KWSecurity atlasSign:/rest/app/square/home/mall/tab/dynamic/feed87fa757cb702565b6afa61de4f5f9617]22582 ms     | +[KWSecuritySignature atlasSignPlus:0x2852e18c0 isInner:0x0 sdkid:0x10eb67638 sdkName:0x10eb67638 ztconfigFilePath:0x10eb67638]22582 ms     |    | +[KWOpenSecurityGuardManager getInstance]22582 ms     |    | -[KWOpenSecurityGuardManager getSecureSignatureComp]22582 ms     |    |    | -[KWOpenSecurityGuardManager getComponent:0x0]22582 ms     |    |    |    | +[KWOpenComponentLibrary getInstance]22582 ms     |    |    |    | -[KWOpenComponentLibrary getComponent:0x0]22582 ms     |    |    |    |    | -[KWOpenComponentLibrary sdkDict]22582 ms     |    | +[KWOpenSecurityGuardParamContext createParamContextWithAppKey:d7b7d042-d4f2-4012-be60-d97ff2429c17 paramDict:nil requestType:0x1 input:{length = 75, bytes = 0x2f726573 742f6170 702f7371 75617265 ... 34663566 39363137 } wbindexKey:lD6We1E8i bInnerInvoke:0x0 sdkid: sdkName: ztconfigFilePath:]22589 ms     |    |    | -[KWOpenSecurityGuardParamContext setAppKey:0x100932dd8]22589 ms     |    |    | -[KWOpenSecurityGuardParamContext setWbindexKey:0x100932df8]22589 ms     |    |    | -[KWOpenSecurityGuardParamContext setParamDict:0x0]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setRequestType:0x1]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setInput:0x2876d4e70]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setOutput:nil]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setErrorCode:0x0]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setBInnerInvoke:0x0]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setSdkid:0x10eb67638]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setSdkname:0x10eb67638]22590 ms     |    |    | -[KWOpenSecurityGuardParamContext setZtconfigFilePath:0x10eb67638]22590 ms     |    | +[KWOpenSecurityGuardParamContext createParamContextWithAppKey ret:<KWOpenSecurityGuardParamContext: 0x285c9ba80>22591 ms     |    | -[KWOpenSecureSignatureComponent atlasSignPlus:0x285c9ba80]22591 ms     |    |    | +[KWOpenSecurityGuardManager getInstance]22591 ms     |    |    | -[KWOpenSecurityGuardManager isInitialize] 0x122591 ms     |    |    | -[KWOpenSecurityGuardParamContext appKey]22591 ms     |    |    | -[KWOpenSecurityGuardParamContext bInnerInvoke]22591 ms     |    |    | -[KWOpenSecurityGuardParamContext input]22591 ms     |    |    | -[KWOpenSecurityGuardParamContext sdkid]22591 ms     |    |    | -[KWOpenSecurityGuardParamContext sdkname]22591 ms     |    |    | -[KWOpenSecurityGuardParamContext ztconfigFilePath]22591 ms     |    |    | -[KWOpenSecurityGuardManager callCoreCommand:0x28b2 appkey:0x100932dd8 type:0x0 payload:0x0 context:0x0 isInputDataWithHeader:0x0 isOutputDataShuffleHeader:0x0 bInnerInvoke:0x2876d4e70 inputData:0x10eb67638 cdid:0x0 privatekeyData:0x10eb67638 sdkid:0x10eb67638 sdkName:0x10eb67638 ztconfigFilePath:0x17171f0d0 completion:0x20414ec30]22592 ms     |    |    | -[KWOpenSecurityGuardManager callCoreCommand:ret d7b7d042-d4f2-4012-be60-d97ff2429c1722592 ms     |    |    | -[KWOpenSecurityGuardParamContext setOutput:{length = 48, bytes = 0x36373736 30393335 32666262 66313665 ... 32323365 33303236 }]22593 ms     |    |    | -[KWOpenSecurityGuardParamContext setErrorCode:0x1]22593 ms     |    | -[KWOpenSecurityGuardParamContext errorCode]22593 ms     |    | -[KWOpenSecurityGuardParamContext output] {length = 48, bytes = 0x36373736 30393335 32666262 66313665 ... 32323365 33303236 }22594 ms     |    | -[KWOpenSecurityGuardParamContext output] {length = 48, bytes = 0x36373736 30393335 32666262 66313665 ... 32323365 33303236 }22595 ms  WSecurity atlasSign ret 677609352fbbf16ef42f2c2d57deecf00fdd8252223e3026
加载某手安全算法Framework

某手的算法核心是在gifCommonFramework库中。砸壳拿到ipa,从framework中拿到该dylib,开始加载,如下代码就加载完了,是不是感觉很简单。

binary_path = "gifCommonFramework"
ks = emu.load_module(module_file=os.path.join(base_path, binary_path),exec_init_array=True,#trace_symbol_calls=True,#trace symbol符号#trace_inst=True,#trace code 
)
初始化安全SDK

如下代码,模拟调用oc的方法调用。

  1. oc中的+的符号可直接调用,类似安卓中的public static方法;-符号需要进行初始化动作之后才可以调用,类似安卓中的需要new才可以调用的方法。

安全SDK进行初始化,通过getInstance之后获取该地址,并使用该地址进行调用initSDK。这块还有一个hook操作。

def hook_retval(retval): #hook 修改返回值def decorator(uc, address, size, user_data):return retvalreturn decoratoremu.add_interceptor(ks.base + 0x1387A8, hook_retval(0)) KWOpenSecurityGuardManager_addr = objc.msg_send("KWOpenSecurityGuardManager", "getInstance")
print(KWOpenSecurityGuardManager_addr)
objc.msg_send(KWOpenSecurityGuardManager_addr, "initSDK")
objc.msg_send(KWOpenSecurityGuardManager_addr, "setIsInitialize:", 1)
算法调用

根据frida-trace代码可得。atlasSignPlus传递的是KWOpenSecurityGuardParamContext createParamContextWithAppKey ​ 之后的地址。

 encrypt_str="加密信息"encrypt_addr = objc.msg_send("KWOpenSecurityGuardParamContext","createParamContextWithAppKey:paramDict:requestType:input:wbindexKey:bInnerInvoke:sdkid:sdkName:ztconfigFilePath:",pyobj2nsobj(emu, "d7b7d042-d4f2-4012-be60-d97ff2429c17"),0,1,pyobj2nsobj(emu, encrypt_str.encode()),pyobj2nsobj(emu, "lD6We1E8i"), 0, pyobj2nsobj(emu, ""), pyobj2nsobj(emu, ""),pyobj2nsobj(emu, ""))
#这里原本不是这样调用的,我为了方便不再引入其他东西,使用了类似java的new 然后直接调用atlasSignPlus,
KWOpenSecureSignatureComponent = objc.msg_send("KWOpenSecureSignatureComponent", "alloc")
KWOpenSecureSignatureComponent_init = objc.msg_send(KWOpenSecureSignatureComponent, 'init')
result = objc.msg_send(KWOpenSecureSignatureComponent_init, "atlasSignPlus:", encrypt_addr) #这里传递的就是地址,直接传。
print(result)

这里KWOpenSecurityGuardParamContext createParamContextWithApp​的方法是+,那便可以直接调用。这里也仅仅是设置好需要加密的一些参数。

这里最后其实是出不了具体的结果的,这里还要感谢兔哥的trace代码,从trace代码中发现了如下图。

  1. pyobj2nsobj 用来将python类型转为oc类型,int 类型默认即可。
  2. pyobj2cfobj python类型转为oc的cf类型。
加入hook校验

hook 之后直接返回0 使对比结果正确。


emu.add_interceptor(ks.base + 0x18F8C8, hook_retval(0)) #这里对比d7b7d042-d4f2-4012-be60-d97ff2429c17
输出结果

output其实返回的是一个nsdata类型。根据frida-trace的代码。这里就是bytes为最后需要的

    error_code = objc.msg_send(result, "errorCode")print(error_code)output = objc.msg_send(result, "output")#这里是nsdatadata_bytes = objc.msg_send(output, "bytes") #这里就是获取bytes# 4b5a08193cf6b70803030001a41524cc1f87ae7e1e121c0aprint(emu.read_string(data_bytes)) #这里直接读取bytes为string
固定随机因子

这里主要是说 随机数 时间戳等

chomper/os/ios/syscall.py

handle_sys_gettimeofday

chomper/os/ios/hooks.py

hook_srandom​、hook_time​、hook_random

补环境

如下即可。其他复杂的操作,可以看下作者的仓库。

@register_hook("-[NSUserDefaults(NSUserDefaults) registerDefaults:]")
def hook_ns_user_defaults_register_defaults(uc, address, size, user_data):print("hook_ns_user_defaults_register_defaults")return 0
其他hook操作
#直接hook oc方法 并修改返回值为oc obj类型
emu.add_interceptor("-[NSBundle bundleIdentifier]", hook_retval(pyobj2nsobj(emu, "com.ceair.b2m")))
#hook 一个地址并修改返回值
emu.add_interceptor(byd.base + 0x103C984A4, hook_retval(1))
#跳过一个函数不执行
def hook_skip(uc, address, size, user_data):pass
emu.add_interceptor("-[NSBundle initWithPath:]", hook_skip)#这也是hook 一个地址。
def hook_call_compare(uc, address, size, user_data):emu = user_data["emu"]return 0
emu.add_hook(ks.base + 0x121724, hook_call_compare)
主动调用操作

除了文章主动调用sig3的案例外,还有如下:

#主动调用symbol获取uuid
CFUUIDCreateString = emu.find_symbol("_CFUUIDCreateString").address 
cfu = emu.call_symbol("_CFUUIDCreate", 0, )
uuids = emu.call_symbol("_CFUUIDCreateString", 0, cfu)#主动调用地址
a1 = emu.create_string("1")
a2 = emu.create_string(s)
a3 = len(s)
a4 = emu.create_string(str('1'))
a5 = emu.create_buffer(8)
a6 = emu.create_buffer(8)
a7 = emu.create_string("1123123123")
emu.call_address(dddd.base + 0x109322118, a1, a2, a3, a4, a5, a6, a7)
TraceCode

目前作者官方还没支持上,不过作者也给了一份代码。后续应该有,也有下断点debug,

trace开启代码如下:


from unicorn import arm64_constdef trace_inst_callback(self, uc, address, size, user_data):for inst in self.cs.disasm_lite(uc.mem_read(address, size), 0):self.logger.info(f"Trace at {self.debug_symbol(address)}: {inst[-2]} {inst[-1]}")message = ""for i in range(31):if message:message += ", "message += f"x{i}={hex(self.uc.reg_read(getattr(arm64_const, f'UC_ARM64_REG_X{i}')))}"self.logger.info(message)Chomper.trace_inst_callback = trace_inst_callback

效果如下:

ipa本身相关的信息读取

将ipa中的info.plist放在和二进制文件一起的位置即可,chomper会自动加载处理。主要涉及如下两个。


bundle_identifier = info_data["CFBundleIdentifier"]
bundle_executable = info_data["CFBundleExecutable"]

总结

本文主要是介绍Chomper的算法模拟执行,Chomper目前已经已经是能比较完整的模拟ios可执行文件执行的模拟器,在这块有非常大的优势。

以前安卓端有强势的unidbg,现在iOS也有Chomper了,后续等待作者持续更新,完善Chomper。强势推荐一波-> Chomper地址: https://github.com/sledgeh4w/chomper。

我这块也已经使用Chomper完成雅迪系列、某手的算法调用。后续也会有更多扩展。

算法代码:
import logging
import osfrom chomper import Chomper
from chomper.const import ARCH_ARM64, OS_IOS
from chomper.objc import ObjC
from chomper.utils import pyobj2nsobj
from chomper.os.ios.hooks import register_hookbase_path = os.path.abspath(os.path.dirname(__file__))log_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
logging.basicConfig(format=log_format,level=logging.INFO,
)logger = logging.getLogger()handler = logging.FileHandler('log_ks.txt', mode='w', encoding='utf-8')
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter(log_format))console = logging.StreamHandler()
console.setLevel(logging.INFO)logger.addHandler(handler)def hook_retval(retval):def decorator(uc, address, size, user_data):return retvalreturn decorator@register_hook("-[NSUserDefaults(NSUserDefaults) registerDefaults:]")
def hook_ns_user_defaults_register_defaults(uc, address, size, user_data):print("hook_ns_user_defaults_register_defaults")return 0def hook_call_compare(uc, address, size, user_data):emu = user_data["emu"]return 0from unicorn import arm64_constdef trace_inst_callback(self, uc, address, size, user_data):for inst in self.cs.disasm_lite(uc.mem_read(address, size), 0):self.logger.info(f"Trace at {self.debug_symbol(address)}: {inst[-2]} {inst[-1]}")message = ""for i in range(31):if message:message += ", "message += f"x{i}={hex(self.uc.reg_read(getattr(arm64_const, f'UC_ARM64_REG_X{i}')))}"self.logger.info(message)Chomper.trace_inst_callback = trace_inst_callbackbinary_path = "gifCommonFramework"
emu = Chomper(arch=ARCH_ARM64,os_type=OS_IOS,rootfs_path=os.path.join(base_path, "rootfs/ios"),# trace_symbol_calls=True,
)ks = emu.load_module(module_file=os.path.join(base_path, binary_path),exec_init_array=True,trace_symbol_calls=True,trace_inst=True,# trace_symbol_calls=True
)
objc = ObjC(emu)emu.add_interceptor(ks.base + 0x1387A8, hook_retval(0))
emu.add_interceptor(ks.base + 0x18F8C8, hook_retval(0))KWOpenSecurityGuardManager_addr = objc.msg_send("KWOpenSecurityGuardManager", "getInstance")
print(KWOpenSecurityGuardManager_addr)
objc.msg_send(KWOpenSecurityGuardManager_addr, "initSDK")objc.msg_send(KWOpenSecurityGuardManager_addr, "setIsInitialize:", 1)
# 这里根据frida-trace代码实际执行的构造
encrypt_str = input("enc:")
encrypt_addr = objc.msg_send("KWOpenSecurityGuardParamContext","createParamContextWithAppKey:paramDict:requestType:input:wbindexKey:bInnerInvoke:sdkid:sdkName:ztconfigFilePath:",pyobj2nsobj(emu, "d7b7d042-d4f2-4012-be60-d97ff2429c17"),0,1,pyobj2nsobj(emu, encrypt_str.encode()),pyobj2nsobj(emu, "lD6We1E8i"), 0, pyobj2nsobj(emu, ""), pyobj2nsobj(emu, ""),pyobj2nsobj(emu, ""))
KWOpenSecureSignatureComponent = objc.msg_send("KWOpenSecureSignatureComponent", "alloc")
KWOpenSecureSignatureComponent_init = objc.msg_send(KWOpenSecureSignatureComponent, 'init')
result = objc.msg_send(KWOpenSecureSignatureComponent_init, "atlasSignPlus:", encrypt_addr)
print(result)error_code = objc.msg_send(result, "errorCode")
print(error_code)output = objc.msg_send(result, "output")
data_bytes = objc.msg_send(output, "bytes")
print(emu.read_string(data_bytes))

相关文章:

某手sig3-ios算法 Chomper黑盒调用

Chomper-iOS界的Unidbg 最近在学习中发现一个Chomper框架&#xff0c;Chomper 是一个模拟执行iOS可执行文件的框架&#xff0c;类似于安卓端大名鼎鼎的Unidbg。 这篇文章使用Chomper模拟执行某手的sig3算法&#xff0c;初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的…...

MySQL版本选择与安装

MySQL版本选择与安装 MySQL 5.5 优点: 稳定性&#xff1a;5.5版本是长期支持&#xff08;LTS&#xff09;版本&#xff0c;因此它非常稳定&#xff0c;被广泛部署在生产环境中。 兼容性&#xff1a;与旧版本的MySQL和各种应用程序有很好的兼容性。 缺点: 过时&#xff1a;…...

【飞行器原理学习】——1. 机翼及机翼参数

飞行器原理学习——1.机翼 一、 概述 飞机的各种机翼是飞机的控制面 通过铰链、钢索、液压等方式连接在机身上 操纵面运动时&#xff0c;会改变机翼的弧度和形状&#xff0c;使流经的空气发生偏转&#xff0c;从而影响空气动力的大小。使飞机围绕着3轴运动 二、机翼的操纵面…...

TS语言自定义脚手架

初始化 新建文件夹初始化命令 npm init -ytsc --initnpm i types/nodenpm i typescript# 处理别名npm i -D tsc-alias -y 表示选项都为yes 安装ts相关依赖 新建相关文件 bin 文件夹 src文件夹 commands 文件夹 &#xff08;命令 utils 文件夹 (封装方法&#xff09; index.t…...

lab4 CSAPP:Cachelab

写在前面 最简单的一集 实验室分为两个部分。在A部分中&#xff0c;实现一个缓存模拟器。在B部分中&#xff0c;编写一个矩阵针对高速缓存性能优化的转置功能。 感觉是比较经典的问题&#xff0c;之前在体系结构的课程中接触过&#xff0c;终于能通过lab实操一下了。 实验目…...

VScode C语言学习开发环境;运行提示“#Include错误,无法打开源文件stdio.h”

C/C环境配置 参考&#xff1a; VS Code 配置 C/C 编程运行环境&#xff08;保姆级教程&#xff09;_vscode配置c环境-CSDN博客 基本步骤 - 安装MinGW-W64&#xff0c;其包含 GCC 编译器&#xff1a;bin目录添加到环境变量&#xff1b;CMD 中输入gcc --version或where gcc验证…...

雷龙CS SD NAND(贴片式TF卡)测评体验

声明&#xff1a;非广告&#xff0c;为用户体验文章 前段时间偶然获得了雷龙出品的贴片式 TF 卡芯片及转接板&#xff0c;到手的是两片贴片式 nand 芯片搭配一个转接板&#xff0c;其中有一片官方已经焊接好了&#xff0c;从外观来看&#xff0c;正面和背面设计布局合理&#x…...

伯克利 CS61A 课堂笔记 11 —— Mutability

本系列为加州伯克利大学著名 Python 基础课程 CS61A 的课堂笔记整理&#xff0c;全英文内容&#xff0c;文末附词汇解释。 目录 01 Objects 02 Example: Strings Ⅰ Representing Strings: the ASCII Standard Ⅱ Representing Strings: the Unicode Standard 03 Mutatio…...

从零开始构建一个小型字符级语言模型的详细教程(基于Transformer架构)之一数据准备

最近特别火的DeepSeek,是一个大语言模型,那一个模型是如何构建起来的呢?DeepSeek基于Transformer架构,接下来我们也从零开始构建一个基于Transformer架构的小型语言模型,并说明构建的详细步骤及内部组件说明。我们以构建一个字符级语言模型(Char-Level LM)为例,目标是通…...

云原生DevOps:Zadig架构设计与企业实践分析

在云原生时代&#xff0c;随着微服务架构和容器技术的广泛应用&#xff0c;软件交付模式正经历着深刻的变革。DevOps作为一种文化、运动和实践&#xff0c;正逐渐成为企业快速交付高质量软件的关键。本文将探讨在云原生背景下&#xff0c;DevOps工程架构的设计与实践&#xff0…...

UMLS数据下载及访问

UMLS数据申请 这个直接在官网上申请即可&#xff0c;记得把地址填全&#xff0c;基本都会拿到lisence。 UMLS数据访问 UMLS的数据访问分为网页访问&#xff0c;API访问以及数据下载后的本地访问&#xff0c;网页访问&#xff0c;API访问按照官网的指示即可&#xff0c;这里主…...

DEX-EE三指灵巧手:扩展AI与机器人研究的边界

DEX-EE三指灵巧手&#xff0c;由Shadow Robot与Google DeepMind合作开发&#xff0c;以其先进技术和设计&#xff0c;正在引领AI与机器人研究的新趋势。其高精度传感器和灵活的机械手指&#xff0c;能够捕捉复杂的环境数据&#xff0c;为强化学习实验提供了可靠支持。 Shadow R…...

在ubuntu上用Python的openpyxl模块操作Excel的案例

文章目录 安装模块读取Excel数据库取数匹配数据和更新Excel数据 在Ubuntu系统的环境下基本职能借助Python的openpyxl模块实现对Excel数据的操作。 安装模块 本次需要用到的模块需要提前安装(如果没有的话) pip3 install openpyxl pip3 install pymysql在操作前&#xff0c;需…...

【STM32】外部时钟|红外反射光电开关

1.外部时钟 单片机如何对外部触发进行计数&#xff1f;先看一下内部时钟&#xff0c;内部时钟是接在APB1和APB2时钟线上的&#xff0c;APB1,APB2来自stm32单片机内部的脉冲信号&#xff0c;也叫内部时钟。我们用来定时。同样我们可以把外部的信号接入单片机&#xff0c;来对其…...

深入了解 DevOps 基础架构:可追溯性的关键作用

在当今竞争激烈的软件环境中&#xff0c;快速交付强大的应用程序至关重要。尽管如此&#xff0c;在不影响质量的情况下保持速度可能是一项艰巨的任务&#xff0c;这就是 DevOps 中的可追溯性发挥作用的地方。通过提供软件开发生命周期 &#xff08;SDLC&#xff09; 的透明视图…...

Django+Vue3全栈开发实战:从零搭建博客系统

文章目录 1. 开发环境准备2. 创建Django项目与配置3. 设计数据模型与API4. 使用DRF创建RESTful API5. 创建Vue3项目与配置6. 前端页面开发与组件设计7. 前后端交互与Axios集成8. 项目优化与调试9. 部署上线10. 总结与扩展10.1 项目总结10.1.1 技术栈回顾10.1.2 项目亮点 10.2 扩…...

深度学习之图像回归(一)

前言 图像回归任务主要是理解一个最简单的深度学习相关项目的结构&#xff0c;整体的思路&#xff0c;数据集的处理&#xff0c;模型的训练过程和优化处理。 因为深度学习的项目思路是差不多的&#xff0c;主要的区别是对于数据集的处理阶段&#xff0c;之后模型训练有一些小…...

使用vue-office报错TypeError: ft.createElementVNode is not a function

支持多种文件(.docx、.xlsx、.xls、.pdf、.pptx)预览的vue组件库&#xff0c;支持vue2/3。也支持非Vue框架的预览。 不支持.doc、.ppt&#xff08;2003年及以前的版本&#xff09; 官网&#xff1a;https://www.npmjs.com/package/vue-office/excel?activeTabreadme 官方有实…...

《深度揭秘:DeepSeek如何解锁自然语言处理密码》

在人工智能蓬勃发展的当下&#xff0c;自然语言处理&#xff08;NLP&#xff09;成为了连接人类与机器的关键桥梁。作为该领域的佼佼者&#xff0c;DeepSeek以其卓越的语义理解和生成能力&#xff0c;备受瞩目。今天&#xff0c;就让我们深入探寻DeepSeek在自然语言处理中实现语…...

解决 Mac 只显示文件大小,不显示目录大小

前言 在使用 mac 的时候总是只显示文件的大小&#xff0c;不显示文件夹的大小&#xff0c;为了解决问题可以开启“计算文件夹”。 步骤 1.进入访达 2.工具栏点击“显示”选项&#xff0c;点击 “查看显示选项” 3.勾选 显示“资源库"文件夹 和 计算所有大小 或者点击…...

从零开始学习PX4源码9(部署px4源码到gitee)

目录 文章目录 目录摘要1.gitee上创建仓库1.1 gitee上创建仓库PX4代码仓库1.2 gitee上创建子仓库2.固件在gitee部署过程2.1下载固件到本地2.2切换本地分支2.3修改.gitmodules内容2.4同步子模块仓库地址2.5同步子模块仓库地址更新(下载)子模块3.一级子模块和二级子模块的映射关…...

遗传算法与深度学习实战系列,自动调优深度神经网络和机器学习的超参数

遗传算法与深度学习实战系列文章 目录 进化深度学习生命模拟及其应用生命模拟与进化论遗传算法中常用遗传算子遗传算法框架DEAPDEAP框架初体验使用遗传算法解决N皇后问题使用遗传算法解决旅行商问题使用遗传算法重建图像遗传编程详解与实现粒子群优化详解与实现协同进化详解与…...

【Python爬虫(28)】爬虫时代,数据安全的坚盾与隐私保护的密锁

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…...

分布式光纤声波振动技术在钻井泄漏检测中的应用

在石油天然气的钻井作业中&#xff0c;及时发现并定位泄漏点对于保障开采安全、降低环境污染以及避免经济损失至关重要。传统的泄漏检测方法往往存在局限性&#xff0c;而分布式光纤声波振动技术凭借其独特的优势&#xff0c;正逐渐成为钻井过程中寻找泄漏的有力工具。 技术原理…...

2025年AI数字人大模型+智能家居HA引领未来(开源项目名称:AI Sphere Butler)

介绍 开源项目计划&#xff1a;AI Sphere Butler 打造全方位服务用户生活的AI全能管家——代号**“小粒”**&#xff08;管家名称可以随意自定义&#xff09; GitHub地址&#xff1a;https://github.com/latiaoge/AI-Sphere-Butler 项目名称&#xff1a;AI Sphere Butler&…...

UGUI RectTransform的SizeDelta属性

根据已知内容&#xff0c;SizeDelta offsetMax - offsetMin 1.锚点聚拢情况下 输出 那么此时SizeDelta就是UI元素的长宽大小 2. 锚点分散时 引用自此篇文章中的描述 揭秘&#xff01;anchoredPosition的几何意义&#xff01; SizeDelta offsetMax - offsetMin (rectMax…...

三甲医院网络架构与安全建设实战

一、设计目标 实现医疗业务网/卫生专网/互联网三网隔离 满足等保2.0三级合规要求 保障PACS影像系统低时延传输 实现医疗物联网统一接入管控 二、全网拓扑架构 三、网络分区与安全设计 IP/VLAN规划表 核心业务配置&#xff08;华为CE6865&#xff09; interface 100G…...

Ubuntu 防火墙ufw详解

ufw&#xff08;Uncomplicated Firewall&#xff09;是 Ubuntu 中一个简单易用的防火墙管理工具&#xff0c;基于 iptables&#xff0c;旨在简化防火墙配置。以下是 ufw 的详细说明和使用方法&#xff1a; 1. 安装 ufw 在大多数 Ubuntu 系统中&#xff0c;ufw 已经预装。如果没…...

机器学习笔记——常用损失函数

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本笔记介绍机器学习中常见的损失函数和代价函数&#xff0c;各函数的使用场景。 热门专栏 机器学习 机器学习笔记合集 深度学习 深度学习笔记合集 文章目录 热门…...

计算机网络:应用层 —— 动态主机配置协议 DHCP

文章目录 什么是 DHCP&#xff1f;DHCP 的产生背景DHCP 的工作过程工作流程地址分配机制 DHCP 中继代理总结 什么是 DHCP&#xff1f; 动态主机配置协议&#xff08;DHCP&#xff0c;Dynamic Host Configuration Protocol&#xff09;是一种网络管理协议&#xff0c;用于自动分…...