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

浅谈进程隐藏技术

前言

在之前几篇文章已经学习了解了几种钩取的方法

  • 浅谈调试模式钩取
  • 浅谈热补丁
  • 浅谈内联钩取原理与实现
  • 导入地址表钩取技术

这篇文章就利用钩取方式完成进程隐藏的效果。

进程遍历方法

在实现进程隐藏时,首先需要明确遍历进程的方法。

CreateToolhelp32Snapshot

CreateToolhelp32Snapshot函数用于创建进程的镜像,当第二个参数为0时则是创建所有进程的镜像,那么就可以达到遍历所有进程的效果。

#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>int main()
{//设置编码,便于后面能够输出中文setlocale(LC_ALL, "zh_CN.UTF-8");//创建进程镜像,参数0代表创建所有进程的镜像HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (hSnapshot == INVALID_HANDLE_VALUE){std::cout << "Create Error" << std::endl;exit(-1);}/** typedef struct tagPROCESSENTRY32 { * DWORD dwSize;               进程信息结构体大小,首次调用之前必须初始化* DWORD cntUsage;              引用进程的次数,引用次数为0时,则进程结束* DWORD th32ProcessID;           进程的ID* ULONG_PTR th32DefaultHeapID;       进程默认堆的标识符,除工具使用对我们没用* DWORD th32ModuleID;                  进程模块的标识符* DWORD cntThreads;             进程启动的执行线程数* DWORD th32ParentProcessID;           父进程ID* LONG  pcPriClassBase;          进程线程的基本优先级* DWORD dwFlags;              保留* TCHAR szExeFile[MAX_PATH];          进程的路径* } PROCESSENTRY32; * typedef PROCESSENTRY32 *PPROCESSENTRY32; */PROCESSENTRY32 pi;pi.dwSize = sizeof(PROCESSENTRY32);//取出第一个进程BOOL bRet = Process32First(hSnapshot, &pi);while (bRet){wprintf(L"进程路径:%s\t进程号:%d\n", pi.szExeFile, pi.th32ProcessID);//取出下一个进程bRet = Process32Next(hSnapshot, &pi);}
}

EnumProcesses

EnumProcesses用于将所有进程号的收集。

#include <iostream>
#include <Windows.h>
#include <Psapi.h>int main()
{setlocale(LC_ALL, "zh_CN.UTF-8");DWORD processes[1024], dwResult, size;unsigned int i;//收集所有进程的进程号if (!EnumProcesses(processes, sizeof(processes), &dwResult)){std::cout << "Enum Error" << std::endl;}//进程数量size = dwResult / sizeof(DWORD);for (i = 0; i < size; i++){//判断进程号是否为0if (processes[i] != 0){//用于存储进程路径TCHAR szProcessName[MAX_PATH] = { 0 };//使用查询权限打开进程HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,FALSE,processes[i]);if (hProcess != NULL){HMODULE hMod;DWORD dwNeeded;//收集该进程的所有模块句柄,第一个句柄则为文件路径if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),&dwNeeded)){//根据句柄获取文件路径GetModuleBaseName(hProcess, hMod, szProcessName,sizeof(szProcessName) / sizeof(TCHAR));}wprintf(L"进程路径:%s\t进程号:%d\n", szProcessName, processes[i]);}}   }
}

ZwQuerySystemInfomation

ZwQuerySystemInfomation函数是CreateToolhelp32Snapshot函数与EnumProcesses函数底层调用的函数,也用于遍历进程信息。代码参考https://cloud.tencent.com/developer/article/1454933

#include <iostream>
#include <Windows.h>
#include <ntstatus.h>
#include <winternl.h> 
#pragma comment(lib, "ntdll.lib") //定义函数指针
typedef NTSTATUS(WINAPI* NTQUERYSYSTEMINFORMATION)(IN      SYSTEM_INFORMATION_CLASS SystemInformationClass,IN OUT   PVOID                    SystemInformation,IN      ULONG                    SystemInformationLength,OUT PULONG                   ReturnLength);int main()
{//设置编码setlocale(LC_ALL, "zh_CN.UTF-8");//获取模块地址HINSTANCE ntdll_dll = GetModuleHandle(L"ntdll.dll");if (ntdll_dll == NULL) {std::cout << "Get Module Error" << std::endl;exit(-1);}NTQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;//获取函数地址ZwQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(ntdll_dll, "ZwQuerySystemInformation");if (ZwQuerySystemInformation != NULL){SYSTEM_BASIC_INFORMATION sbi = { 0 };//查询系统基本信息NTSTATUS status = ZwQuerySystemInformation(SystemBasicInformation, (PVOID)&sbi, sizeof(sbi), NULL);if (status == STATUS_SUCCESS){wprintf(L"处理器个数:%d\r\n", sbi.NumberOfProcessors);}else{wprintf(L"ZwQuerySystemInfomation Error\n");}DWORD dwNeedSize = 0;BYTE* pBuffer = NULL;wprintf(L"\t----所有进程信息----\t\n");PSYSTEM_PROCESS_INFORMATION psp = NULL;//查询进程数量status = ZwQuerySystemInformation(SystemProcessInformation, NULL, 0, &dwNeedSize);if (status == STATUS_INFO_LENGTH_MISMATCH){pBuffer = new BYTE[dwNeedSize];//查询进程信息status = ZwQuerySystemInformation(SystemProcessInformation, (PVOID)pBuffer, dwNeedSize, NULL);if (status == STATUS_SUCCESS){psp = (PSYSTEM_PROCESS_INFORMATION)pBuffer;wprintf(L"\tPID\t线程数\t工作集大小\t进程名\n");do {//获取进程号wprintf(L"\t%d", psp->UniqueProcessId);//获取线程数量wprintf(L"\t%d", psp->NumberOfThreads);//获取工作集大小wprintf(L"\t%d", psp->WorkingSetSize / 1024);//获取路径wprintf(L"\t%s\n", psp->ImageName.Buffer);//移动psp = (PSYSTEM_PROCESS_INFORMATION)((PBYTE)psp + psp->NextEntryOffset);} while (psp->NextEntryOffset != 0);delete[]pBuffer;pBuffer = NULL;}else if (status == STATUS_UNSUCCESSFUL) {wprintf(L"\n STATUS_UNSUCCESSFUL");}else if (status == STATUS_NOT_IMPLEMENTED) {wprintf(L"\n STATUS_NOT_IMPLEMENTED");}else if (status == STATUS_INVALID_INFO_CLASS) {wprintf(L"\n STATUS_INVALID_INFO_CLASS");}else if (status == STATUS_INFO_LENGTH_MISMATCH) {wprintf(L"\n STATUS_INFO_LENGTH_MISMATCH");}}}
}

进程隐藏

通过上述分析可以知道遍历进程的方式有三种,分别是利用CreateToolhelp32SnapshotEnumProcesses以及ZwQuerySystemInfomation函数

但是CreateToolhelp32SnapshotEnumProcesses函数底层都是调用了ZwQuerySystemInfomation函数,因此我们只需要钩取该函数即可。

由于测试环境是Win11,因此需要判断在Win11情况下底层是否还是调用了ZwQuerySystemInfomation函数。

可以看到在Win11下还是会调用ZwQuerySystemInfomation函数,在用户态下该函数的名称为NtQuerySystemInformation函数。

这里采用内联钩取的方式对ZwQuerySystemInfomation进行钩取处理,具体怎么钩取在浅谈内联钩取原理与实现已经介绍过了,这里就不详细说明了。这里对自定义的ZwQuerySystemInfomation函数进行说明。

首先第一步需要进行脱钩处理,因为后续需要用到初始的ZwQuerySystemInfomation函数,紧接着获取待钩取函数的地址即可。

...//脱钩UnHook("ntdll.dll", "ZwQuerySystemInformation", g_pOrgBytes);HMODULE hModule = GetModuleHandleA("ntdll.dll");//获取待钩取函数的地址PROC    pfnOld = GetProcAddress(hModule, "ZwQuerySystemInformation");//调用原始的ZwQuerySystemInfomation函数NTSTATUS status = ((NTQUERYSYSTEMINFORMATION)pfnOld)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
...

为了隐藏指定进程,我们需要遍历进程信息,找到目标进程并且删除该进程信息实现隐藏的效果。这里需要知道的是进程信息都存储在SYSTEM_PROCESS_INFORMATION结构体中,该结构体是通过单链表对进程信息进行链接。因此我们通过匹配进程名称找到对应的SYSTEM_PROCESS_INFORMATION结构体,然后进行删除即可,效果如下图。

通过单链表中删除节点的操作,取出目标进程的结构体。代码如下

...pCur = (PSYSTEM_PROCESS_INFORMATION)(SystemInformation);while (true){if (!lstrcmpi(pCur->ImageName.Buffer, L"test.exe")){//需要隐藏的进程是最后一个节点if (pCur->NextEntryOffset == 0)pPrev->NextEntryOffset = 0;//不是最后一个节点,则将该节点取出elsepPrev->NextEntryOffset += pCur->NextEntryOffset;}//不是需要隐藏的节点,则继续遍历elsepPrev = pCur;//链表遍历完毕if (pCur->NextEntryOffset == 0)break;pCur = (PSYSTEM_PROCESS_INFORMATION)((PBYTE)pCur + pCur->NextEntryOffset);}
...

完整代码:https://github.com/h0pe-ay/HookTechnology/blob/main/ProcessHidden/inlineHook.c

但是采用内联钩取的方法去钩取任务管理器就会出现一个问题,这里将断点取消,利用内联钩取的方式去隐藏进程。

首先利用bl命令查看断点

紧着利用 bc [ID]删除断点

在注入之后任务管理器会在拷贝的时候发生异常

在经过一番调试后发现,由于多线程共同执行导致原本需要可写权限的段被修改为只读权限

windbg可以用使用!vprot + address查看指定地址的权限,可以看到由于程序往只读权限的地址进行拷贝处理,所以导致了异常。

但是在执行拷贝阶段是先修改了该地址为可写权限,那么导致该原因的情况就是其他线程执行了权限恢复后切换到该线程中进行写,所以导致了这个问题。

因此内联钩取是存在多线程安全的问题,此时可以使用微软自己构建的钩取库Detours,可以在钩取过程中确保线程安全。

帮助网安学习,全套资料S信免费领取:
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

Detours

项目地址:https://github.com/microsoft/Detours

环境配置

参考:https://www.cnblogs.com/linxmouse/p/14168712.html

使用vcpkg下载

vcpkg.exe install detours:x86-windows
vcpkg.exe install detours:x64-windows
vcpkg.exe integrate install

实例

挂钩

利用Detours挂钩非常简单,只需要根据下列顺序,并且将自定义函数的地址与被挂钩的地址即可完成挂钩处理。

...//用于确保在 DLL 注入或加载时,恢复被 Detours 修改的进程镜像,保持稳定性DetourRestoreAfterWith();//开始一个新的事务来附加或分离DetourTransactionBegin();//进行线程上下文的更新DetourUpdateThread(GetCurrentThread());//挂钩DetourAttach(&(PVOID&)TrueZwQuerySystemInformation, ZwQuerySystemInformationEx);//提交事务error = DetourTransactionCommit();
...

脱钩

然后根据顺序完成脱钩即可。

...//开始一个新的事务来附加或分离DetourTransactionBegin();//进行线程上下文的更新DetourUpdateThread(GetCurrentThread());//脱钩DetourDetach(&(PVOID&)TrueZwQuerySystemInformation, ZwQuerySystemInformationEx);//提交事务error = DetourTransactionCommit();
...

挂钩的原理

从上述可以看到,Detours是通过事务确保了在DLL加载与卸载时后的原子性,但是如何确保多线程安全呢?后续通过调试去发现。

可以利用x ntdl!ZwQuerySystemInformation查看函数地址,可以看到函数的未被挂钩前的情况如下图。

挂钩之后原始的指令被修改为一个跳转指令把前八个字节覆盖掉,剩余的3字节用垃圾指令填充。

该地址里面又是一个jmp指令,并且完成间接寻址的跳转。

该地址是自定义函数ZwQuerySystemInformationEx,因此该间接跳转是跳转到的自定义函数内部。

跳转到TrueZwQuerySystemInformation内部发现ZwQuerySystemInformation函数内部的八字节指令被移动到该函数内部。紧接着又完成一个跳转。

该跳转到ZwQuerySystemInformation函数内部紧接着完成ZwQuerySystemInformation函数的调用。

综上所述,整体流程如下图。实际上Detours实际上使用的是热补丁的思路,但是Detours并不是直接在原始的函数空间中进行补丁,而是开辟了一段临时空间,将指令存储在里面。因此在挂钩后不需要进行脱钩处理就可以调用原始函数。因此就不存在多线程中挂钩与脱钩的冲突。

完整代码:https://github.com/h0pe-ay/HookTechnology/blob/main/ProcessHidden/detoursHook.c

相关文章:

浅谈进程隐藏技术

前言 在之前几篇文章已经学习了解了几种钩取的方法 浅谈调试模式钩取浅谈热补丁浅谈内联钩取原理与实现导入地址表钩取技术 这篇文章就利用钩取方式完成进程隐藏的效果。 进程遍历方法 在实现进程隐藏时&#xff0c;首先需要明确遍历进程的方法。 CreateToolhelp32Snapsh…...

【C++】Google Test(gtest)单元测试

文章目录 Google Test&#xff08;gtest&#xff09;单元测试使用示例更多用法测试夹具 Google Test&#xff08;gtest&#xff09;单元测试 单元测试是一种软件测试方法&#xff0c;它旨在将应用程序的各个部分&#xff08;通常是方法或函数&#xff09;分离出来并独立测试&a…...

水箱高低水位浮球液位开关

水箱高低水位浮球液位开关概述 水箱高低水位浮球液位开关是一种用于监测和控制水箱中液位的自动化设备&#xff0c;它能够在水箱液位达到预设的高低限制时&#xff0c;输出开关信号&#xff0c;以控制水泵或电磁阀的开闭&#xff0c;从而维持水箱液位在一个安全的范围内。这类设…...

Autoware内容学习与初步探索(一)

0. 简介 之前作者主要是基于ROS2&#xff0c;CyberRT还有AutoSar等中间件完成搭建的。有一说一&#xff0c;这种从头开发当然有从头开发的好处&#xff0c;但是如果说绝大多数的公司还是基于现成的Apollo以及Autoware来完成的。这些现成的框架中也有很多非常好的方法。目前作者…...

【手写数据库内核组件】01 解析树的结构,不同类型的数据结构组多层的链表树,抽象类型统一引用格式

不同类型的链表 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 不同类型…...

Pandas 进阶 —— 数据转换、聚合与可视化

引言 在数据分析的旅程中&#xff0c;Pandas 库提供了从数据转换到聚合再到可视化的全面解决方案。上篇我们掌握了数据的导入和清洗&#xff0c;本篇我们将探索如何通过 Pandas 对数据进行更高级的处理&#xff0c;包括数据转换、聚合分析以及可视化展示。 数据转换 数据转换…...

华为OD机试 - 来自异国的客人(Java 2024 D卷 100分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…...

期末上分站——计组(3)

复习题21-42 21、指令周期是指__C_。 A. CPU从主存取出一条指令的时间 B. CPU执行一条指令的时间 C. CPU从主存取出一条指令的时间加上执行这条指令的时间。 D. 时钟周期时间 22、微型机系统中外设通过适配器与主板的系统总线相连接&#xff0c;其功能是__D_。 A. 数据缓冲和…...

IDA*——AcWing 180. 排书

IDA* 定义 IDA*&#xff08;Iterative Deepening A*&#xff09;是一种结合了深度优先搜索&#xff08;DFS&#xff09;的递归深度限制特性和A搜索的启发式估价函数的搜索算法。它主要用于解决启发式搜索问题&#xff0c;尤其是当搜索空间很大或者搜索成本不确定时。 IDA* 是…...

【云计算】公有云、私有云、混合云、社区云、多云

公有云、私有云、混合云、社区云、多云 1.云计算的形态1.1 公有云1.2 私有云1.3 混合云1.4 社区云1.5 多云1.5.1 多云和混合云之间的关系1.5.2 多云的用途1.5.3 影子 IT 和多云1.5.4 优缺点 2.不同云形态的对比 1.云计算的形态 张三⾃⼰在家做饭吃&#xff0c;这是 私有云&…...

MySQL中的MVCC解析

MySQL中的MVCC解析 多版本并发控制是MySQL中实现高并发的一种关键技术。通过对数据进行多版本的管理&#xff0c;MVCC能够在保证数据一致性的同时&#xff0c;提高数据库的并发性能。本文将深入探讨MySQL中的MVCC机制&#xff0c;包括其原理、实现方式以及优势。 MVCC的原理 …...

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的生日聚会(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…...

初识STM32:芯片基本信息

STM32简介 STM32是ST公司基于ARM公司的Cortex-M内核开发的32位微控制器。 ARM公司是全球领先的半导体知识产权&#xff08;IP&#xff09;提供商&#xff0c;全世界超过95%的智能手机和平板电脑都采用ARM架构。 ST公司于1987年由意大利的SGS微电子与法国的Thomson半导体合并…...

Zabbix 配置PING监控

Zabbix PING监控介绍 如果需要判断机房的网络或者主机是否正常&#xff0c;这就需要使用zabbix ping&#xff0c;Zabbix使用外部命令fping处理ICMP ping的请求&#xff0c;在基于ubuntu APT方式安装zabbix后默认已存在fping程序。另外zabinx_server配置文件参数FpingLocation默…...

异常解决(三)-- Wandb fails with ServiceStartProcessError

原文链接&#xff1a;https://github.com/wandb/wandb/issues/5765 我的环境配置&#xff1a; Python3.8.16 Wandb0.17.4 在使用Wandb记录实验数据时&#xff0c; 报以下错误&#xff1a; ServiceStartProcessError: The wandb service process exited with 1. Ensure that s…...

Qt调用Matlab(一)

目录 1 概述2 创建Qt工程2.1 增加Matlab支持3 调用Matlab3.1 widget.h3.2 widget.cpp4 运行4.1 配置4.2 运行1 概述 MATLAB是MathWorks公司出品的商业数学软件,用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人,控制系统等领域…...

网络爬虫(二) 哔哩哔哩热榜高频词按照图片形状排列

我们有时候需要爬取结果生成为自定义的词云图 生成自定义的词云图通常需要以下步骤&#xff1a; 1. 爬取数据&#xff1a;使用爬虫工具或库&#xff0c;如requests、BeautifulSoup等&#xff0c;可以爬取网页、论坛、社交媒体等平台上的文本数据。 2. 数据预处理&#xff1a…...

MySQL 常见错误及解决方案

1. Too many connections 运行环境&#xff1a;Winows11、Phpstudy V8.1.1.3、MySQL 5.7.26 同一时间 MySQL 的连接数量有限制&#xff0c;当超过上限时将提示下面错误信息&#xff1a; 1040 - Too many connections 查看当前最大连接数 mysql> show variables like %max_…...

STM32 - 内存分区与OTA

最近搞MCU&#xff0c;发现它与SOC之间存在诸多差异&#xff0c;不能沿用SOC上一些技术理论。本文以STM L4为例&#xff0c;总结了一些STM32 小白入门指南。 标题MCU没有DDR&#xff1f; 是的。MCU并没有DDR&#xff0c;而是让代码存储在nor flash上&#xff0c;临时变量和栈…...

RAG理论:ES混合搜索BM25+kNN(cosine)以及归一化

接前一篇:RAG实践:ES混合搜索BM25+kNN(cosine) https://blog.csdn.net/Xin_101/article/details/140230948 本文主要讲解混合搜索相关理论以及计算推导过程, 包括BM25、kNN以及ES中使用混合搜索分数计算过程。 详细讲解: (1)ES中如何通过BM25计算关键词搜索分数; (2)…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目&#xff0c;核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容&#xff0c;附学习方向和应试技巧&#xff1a; 一、施工组织与进度管理 核心目标&#xff1a; 规…...

密码学基础——SM4算法

博客主页&#xff1a;christine-rr-CSDN博客 ​​​​专栏主页&#xff1a;密码学 &#x1f4cc; 【今日更新】&#x1f4cc; 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…...