某手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的方法调用。
- 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代码中发现了如下图。

- pyobj2nsobj 用来将python类型转为oc类型,int 类型默认即可。
- 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框架,Chomper 是一个模拟执行iOS可执行文件的框架,类似于安卓端大名鼎鼎的Unidbg。 这篇文章使用Chomper模拟执行某手的sig3算法,初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的…...
登录-05.JWT令牌-介绍
一.JWT令牌 JWT令牌是一种简洁的、自包含的格式,用于在通讯双方之间以json数据格式安全的传输数据。说白了,JWT令牌就是将json格式的数据进行封装,从而实现安全传输。 所谓简洁,就是指JWT令牌就是一个简单的字符串。 所谓自包含…...
Mac下Python版本管理,适用于pyenv不起作用的情况
前言 声明:之前也在网上看到过可以使用pyenv来管理python版本,但由于作者的python安装路径实在是繁杂不堪,因此安装完成pyenv体验下来没有任何用处,但偶然发现vscode似乎可以看到各个python版本,因此写下这篇博客记录…...
Ubuntu 服务器Llama Factory 搭建DeepSeek-R1微调训练环境
1.首先了解一下什么是LLM微调 LLM 微调指的是在已经预训练好的大型语言模型基础上,使用特定的任务数据或领域数据,通过进一步的训练来调整模型的参数,使其在特定任务或领域上能够表现得更好。简单来说,就是对一个已经具备了丰富语…...
【redis】redis内存管理,过期策略与淘汰策略
一:Redis 的过期删除策略及处理流程如下: 1. 过期删除策略 Redis 通过以下两种策略删除过期键: 1.1 惰性删除 触发时机:当客户端访问某个键时,Redis 会检查该键是否过期。执行流程: 客户端请求访问键。…...
RabbitMQ学习—day6—死信队列与延迟队列
目录 死信队列 1. 死信的概念 2. 死信的来源 实战演练 1. 消息TTL过期 2. 队列达到最大长度 3. 消息被拒绝 延迟队列 概念 使用场景 TTL的两种设置 死信队列 1. 死信的概念 1.1 先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的…...
seacmsv9联合注入数据以及绕过 ORDERBY
seacmsv9联合注入数据 php源码 <?php session_start(); require_once("../../include/common.php"); $id (isset($gid) && is_numeric($gid)) ? $gid : 0; $page (isset($page) && is_numeric($page)) ? $page : 1; $type (isset($type) …...
day58 第十一章:图论part08
拓扑排序精讲 关键: 先找到入度为0的节点,把这些节点加入队列/结果,然后依次循环再找。 #include <iostream> #include <vector> #include <queue> #include <unordered_map> using namespace std; int main() {int …...
网络安全-openssl工具
OpenSSl是一个开源项目,包括密码库和SSL/TLS工具集。它已是在安全领域的事实标准,并且拥有比较长的历史,现在几乎所有的服务器软件和很多客户端都在使用openssl,其中基于命令行的工具是进行加密、证书管理以及测试最常用到的软件。…...
Java面试第六山!《MySQL基础知识点》
一、引言 MySQL 作为一款广泛使用的开源关系型数据库管理系统,在软件开发领域占据着重要地位。无论是小型项目还是大型企业级应用,都能看到 MySQL 的身影。今天就来和大家分享 MySQL 的相关知识,帮助大家更好地应对日常开发和面试。 二、My…...
云计算中的API网关是什么?为什么它很重要?
在云计算架构中,API网关(API Gateway)是一个重要的组件,主要用于管理、保护和优化不同服务之间的接口(API)通信。简单来说,API网关就像是一个中介,它充当客户端和后端服务之间的“桥…...
【WebGL】fbo双pass案例
双pass渲染案例(离线渲染一个三角面,然后渲染到一个占满屏幕的矩阵上) 离线渲染如何需要开启深度测试的话,需要额外操作,这里不展开 <!DOCTYPE html> <html lang"en"><head><meta ch…...
Unity面板介绍_层级面板(23.1.1)
一、Inspector(检视面板) 显示当前选定游戏对象附加的组件及其属性信息。为重要游戏物体选择图标 二、面板详情...
详解Nginx 配置
一、Nginx 介绍 Nginx 是一款轻量级的 Web 服务器 / 反向代理服务器及电子邮件(IMAP/POP3)代理服务器。它由俄罗斯的程序设计师 Igor Sysoev 所开发,自 2004 年发布以来,凭借其高性能、低内存消耗、高并发处理能力等特点…...
数据库系统概念
1. 绪论 数据库的基本概念: 数据(data): 数据库中存储的基本对象, 可以是文字, 声音, 图片, 视频等。 数据库(DB): 概括来说就是永久存储, 有组织, 可共享的大量数据的集合。 数据库管理系统(DBMS): 和操作系统一样是计算机基础软件, 主要有数据定义语言(DDL, 对数据对象的组…...
51单片机学习之旅——定时器
打开软件 1与其它等于其它,0与其它等于0 1或其它等于1,0或其它等于其它 TMODTMOD&0xF0;//0xF01111 0000进行与操作,高四位保持,低四位清零,高四位定时器1,低四位定时器0 TMODTMOD|0x01;//0x010000 0…...
一台服务器将docker image打包去另一天服务器安装这个镜像
一台服务器将docker image打到去另一天服务器安装这个镜像 1. 打包2.另一台服务器执行 1. 打包 docker save -o nebula-graph-studio.tar harbor1.vm.example.lan/dockerio/vesoft/nebula-graph-studioxxx.tar 是打包好的文件 后面的是 docker image 2.另一台服务器执行 docke…...
QT串口通信之二,实现单个温湿度传感器数据的采集(采用Qt-modbus实现)
接上 QT串口通信之一,实现单个温湿度传感器数据的采集 上述文章中用QSerialPort实现了温湿度传感器的采集,实际上比较麻烦的,因为需要自定义解析帧, 接下来,用Qt-modbus-封装度更高的协议,来实现温湿度的采集; #include "MainWindow.h" #include "ui_M…...
基于SpringBoot的校园消费点评管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
【小沐学Java】VSCode搭建Java开发环境
文章目录 1、简介2、安装VSCode2.1 简介2.2 安装 3、安装Java SDK3.1 简介3.2 安装3.3 配置 4、安装插件Java Extension Pack4.1 简介4.2 安装4.3 配置 结语 1、简介 2、安装VSCode 2.1 简介 Visual Studio Code 是一个轻量级但功能强大的源代码编辑器,可在桌面上…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
