一些小知识

Ring

 Intel的 CPU 将特权级别分为 4 个级别: RING0、RING1、RING2、RING3。Windows 只使用其中的两个级别 RING0 和 RING3,
RING0 只给操作系统用,RING3 谁都能用。如果普通应用程序企图执行RING0 指令,则 Windows 会显示”非法指令”错误信息。图示如下,可以看到RING2与RING1都是驱动文件使用的:

image-20230601132542209

Powershell&CMD

 Powershell 是新的命令行和脚本环境,它基于 .NET Framework。cmd 是 Windows 中传统的命令行工具,它继承了 DOS 的命令和语法,主要用于执行一些简单的系统操作。Powershell有更强大的脚本能力。

MFC程序与GUI程序有什么区别?

 MFC程序是使用 Microsoft Foundation Class (MFC) 库开发的 Windows 应用程序。MFC 是一组针对大部分 Win32 和 COM API 提供面向对象的包装器的类。MFC 程序通常使用 MFC 应用程序向导来创建,并且可以创建标准 Windows 应用程序、对话框、基于窗体的应用程序、资源管理器样式的应用程序和 Web 浏览器样式的应用程序。

 GUI程序是使用图形用户界面 (GUI) 来与用户交互的应用程序。GUI 程序可以使用不同的框架或库来创建,例如 MFC、WPF、Qt、GTK+ 等。GUI 程序通常包含窗口、菜单、按钮、文本框等控件,以及响应用户输入的事件处理逻辑。

MFC程序是 GUI程序 的一种,但不是唯一的一种。MFC 是一个较旧的框架,已经不再更新,而且只能用于 Windows 平台。新入门的人可以根据自己的需求和兴趣选择合适的 GUI 框架来学习,例如 WPF、Qt、Flutter 等。

STM32中hex文件&bin文件&axf文件

 与C语言类似,STM32程序也是用C写的,其编译过程与C差不多。两者编译过程图如下:

image-20230621182445636

image-20230621182459144

 例如,LED灯程序的编译过程如下:

image-20230621182735616

axf文件、hex文件与bin文件都是可以运行在stm32上,它们都存储了编译器根据源代码生成的机器码。

1
2
3
axf文件:包含调试信息。
hex文件:包含地址信息。
bin文件:最直接的代码映像。

 axf文件是编译默认生成的文件,不仅包含代码数据,而且还包含着调试信息,在MDK里进行debug调试用的就是这个文件。bin文件是根据axf文件生成的。

 hex 文件是一种使用十六进制符号表示的代码记录, 记录了代码应该存储到FLASH 的哪个地址,下载器可以根据这些信息辅助下载。

unicorn

 开源的CPU模拟器框架,用于模拟多种不同的处理器架构。

OP-TEE

OP-TEE 是一个开源可信执行环境,应用在Arm上的Linux内核中。 主要包括 Secure world OS(optee_os)、normal world client(optee_client)、test suite(optee_test/xtest)以及 Linux 驱动部分。OP-TEE,open source project Trusted Execution Environment (TEE)。TEE与Rich Execution Environment (REE)相对应。REE中运行的是non-secure OS,安卓,Linux系统等都运行在REE。TEE中运行的是secure OS,他需要Arm TrustZone技术的支持,依赖硬件设计,REE中的系统和应用是无法直接访问TEE中的资源的,只能通过TEE提供的接口获取一个结果,其间的运算和存储等操作对REE中的系统和应用都是不可见的,从而来保证安全性。比如我们手机录入的指纹信息就会通过这项技术保存在TEE中,应用无法获得指纹数据,只能得到一个是否验证通过的结果。

 TrustZone可以认为是操作系统间实现相互独立(例如硬件平台上同时运行了两个OS)。在同一个CPU上运行两个OS,其中一个OS只负责一些安全存储或者计算的操作,比如存储我们的指纹数据等。另一个OS就是平时用的OS,比如安卓系统,对于这个OS来说,安全OS是不可见的,所以根本没有权限获取到安全OS中的隐私数据。 两个OS之间需要交互,因此我们需要一种机制来访问安全OS的服务,也就是CA/TA这种调用机制

 OP-TEE的执行流程如下:

image-20230712232638590

(1)CA调用函数部分,发起一次调用请求,是整个流程的开端。

(2)TEE_client(libteec)做某些事。OP-TEE提供给用户在linux 用户层面调用的接口实现。

(3)tee-supplicant做某些事。OP-TEE能够通过tee_supplicant来访问REE端文件系统中的资源,例如加载存放在文件系统中的TA镜像到TEE中,对REE端数据库的操作。

(4)OP-TEE在linux端的驱动部分做某些事。REE与TEE端进行数据交互的桥梁作用。

(5)Monitor mode 接收中断请求。

(6)OPTEE OS处理请求。

(7)TA(可信应用)部分实现功能并返回结果。

交叉编译工具

 在传统的编译过程中,开发人员需要在目标平台上进行编译,这意味着他们需要在目标平台上安装编译器、链接器、调试器等开发工具,这可能会带来很多问题。

 交叉编译工具的出现解决了以上这些问题,它们可以在开发人员的主机上构建目标平台的软件,并将生成的二进制文件移植到目标平台上运行,从而提高了开发效率和软件质量

SMC调用

 SMC(Secure Monitor Call)调用是一种在ARM处理器上进行安全监控的机制,它允许运行在非安全模式下的软件向运行在安全模式下的软件发起请求。

 SMC调用的实现不同于普通的函数调用。SMC调用需要使用特殊的指令(SMC指令),来触发运行在安全模式下的软件响应请求。SMC指令包含一个参数,该参数包含请求的服务号和请求的参数。运行在安全模式下的软件根据服务号和参数来执行请求,并返回处理结果。

ubuntu apt

apt 命令会自动处理软件包的依赖关系,可以自动安装/卸载/更新软件包所需要的依赖项。而 apt-get 命令需要手动处理依赖关系。apt 命令是 apt-get 命令的改进版本。

apt install updateapt install upgradeupdate是更新本地的软件包索引数据库,upgrade用于升级系统中已安装的软件包。

zigbee与Z-ware

 Zigbee 是一种低功耗、短距离无线通信技术,用于连接智能家居和物联网设备。它基于 IEEE 802.15.4 标准,支持多种网络拓扑结构(如星型、树型、网状等),并提供安全、可靠的数据传输和设备管理功能。Zigbee 设备通常运行在 2.4GHz、915MHz 或 868MHz 频段,可以连接数百个设备,覆盖数千平方米的区域。

 Z-Wave 也是一种低功耗、短距离无线通信技术,用于连接智能家居和物联网设备。它采用专有的无线协议,支持星型网络拓扑结构,提供安全、可靠的数据传输和设备管理功能。Z-Wave 设备通常运行在 900MHz 频段,可以连接数百个设备,覆盖数千平方米的区域。

 他俩差不多,Z-ware欧洲用的多一点。

Telnet

 Telnet 是一种远程登录协议,用于在计算机网络上通过一个终端或控制台连接到远程计算机。默认23端口。

Android四大组件

 Activity, Service, Content Provider, Broadcast Receiver。

 Activity 和 Service:Activity 是用户界面的展示,Service 是后台运行的组件,它们之间可以通过 Intent 进行通信。例如,Activity 可以启动 Service 来执行耗时的任务,Service 可以将执行结果通过 Intent 返回给 Activity。

 Activity 和 Content Provider:Activity 可以通过 Content Provider 访问和共享数据,例如访问系统的联系人、短信、音乐等数据。Content Provider 会暴露一些 API 接口,供 Activity 调用,并返回相应的数据。

 Service 和 Content Provider:Service 可以通过 Content Provider 访问和共享数据,例如在后台下载文件、缓存数据等。Content Provider 会暴露一些 API 接口,供 Service 调用,并返回相应的数据。

 Broadcast Receiver 和其他组件:Broadcast Receiver 可以接收系统广播和应用程序广播,并根据广播内容进行相应的操作。例如,Broadcast Receiver 可以接收系统发出的电池电量变化广播,并通知 Service 或 Activity 进行相应的操作。

Android的其他组件

 Bundle 是一种用于在不同组件(如 Activity、Service、BroadcastReceiver)之间传递数据的数据结构。Bundle 对象中可以包含不同类型的数据,例如基本数据类型、数组、字符串、Parcelable 对象等。使用 Bundle 可以方便地将多个数据类型打包成一个对象,并通过 Intent 在不同组件之间传递数据。同时,由于 Bundle 对象是可序列化的,因此可以将其保存到文件或内存中,以便在需要时重新恢复数据。

 Parcelable 是一种用于在不同组件之间传递复杂对象的机制。当需要在不同的组件之间传递自定义的数据对象时,可以使用Parcelable接口来实现。它允许将一个对象序列化为一个二进制数据流,然后在不同的进程中进行传输和反序列化。Parcelable 接口的实现需要将对象的状态保存在一个 Parcel 对象中,以便在不同进程之间进行传输。

 Binder 是一种用于实现跨进程通信(IPC)的机制。

 system_server 是 Android 系统中的一个重要进程,主要功能是启动和管理 Android 系统中的各种服务和组件,包括 Activity Manager、Window Manager、Package Manager、Notification Manager 等。

Settings系统应用是用于管理设备系统设置的应用程序。它包含了多个设置选项,例如网络、声音、显示、应用程序管理、安全性和账户等选项。

gcc&clang

 gcc:跨平台的C/C++编译器,可在linux、windows、mac上运行。

 clang也是跨平台的C/C++编译器。

白盒AES

 白盒AES是一种加密算法实现技术,旨在在不泄漏密钥的情况下保护AES加密算法的安全性。在传统的AES加密中,密钥是加密过程中的核心组成部分,因此如果密钥被泄露,整个加密系统的安全性将被破坏。而白盒AES通过将密钥分散在算法的多个子函数中,并使用混淆和掩码等技术,使得攻击者无法直接访问到密钥,从而提高了加密算法的安全性和抵抗暴力攻击的能力。

STM32中的寄存器库与HAL库

 寄存器级库提供了对STM32内部寄存器的直接访问,开发者可以直接操作寄存器来控制STM32的外设。这种库的使用需要对STM32的底层硬件有深入的了解,因此使用起来需要较高的技术水平。但是,寄存器级库具有较小的代码量和较快的执行速度,对于对代码大小和性能要求较高的项目非常适用。

 HAL库是STMicroelectronics提供的一种抽象层,它提供了一套高级API,使得开发者可以通过更高层次的抽象来操作STM32的外设。HAL库中的函数会将开发者的请求转换为对底层硬件寄存器的相应操作。HAL库的使用相对较为简单,但它会增加代码的大小和执行速度,因为HAL库需要在底层操作之上提供额外的抽象层。

闭包

 闭包实际上就是把几个值和函数绑定在一起。

回调函数

 将一个函数作为参数传递到另一个函数中,并在需要的时候调用它。

JIT编译与AOT编译

AOT编译(Ahead-Of-Time compilation)在运行程序之前将源代码编译成机器代码。JIT编译在程序运行时将字节码编译成机器代码。

 AOT编译器将源代码编译成机器代码,并将其打包到可执行文件中。当程序运行时,不需要再进行编译,而是直接执行机器代码。

 AOT编译通常用于编译静态语言(如C++、Java和C#)的程序,而JIT编译通常用于解释性语言(如Python和JavaScript)的程序。

ueb128编码

 uleb128是一种常见的压缩形式的数据存储方式,经常应用到Android DEX文件格式中。它最长采用5个字节表示数据的大小,最少采用1个字节表示数据的大小。具体采用的位数,可以通过判断每字节的最高位是否为1,为1则使用下一字节的数据。

AI的Prompt

 Prompt是给模型的一条指令,告诉它要做什么。Prompt可以是简单的句子,也可以是更复杂的指令。例如,如果您想让模型生成一首诗,您可以给它一个Prompt,如“写一首关于爱情的诗”,模型将使用其训练数据生成一首诗,符合Prompt的要求。

gdbus

 GLib dbus(GDBus)是 GLib 库中提供 D-Bus 功能的一部分。D-Bus 用于在运行在 Linux 或具有 D-Bus 实现的其他操作系统上的应用程序之间进行通讯。

svc

 SVC 用于向内核发送请求。SVC 调用由一个特殊的异常处理程序处理,该处理程序将请求转发到内核。SVC 调用通常用于执行系统调用。例如,svc 调用可以用于打开文件、读取文件或写入文件。SVC 调用也可以用于执行其他操作,例如创建线程或设置定时器。

LLVM pass

 LLVM Pass 是 LLVM 编译器框架中的一组可重用的函数,用于对中间语言 (IR) 进行操作。LLVM Pass 可以用于执行各种任务,例如优化、分析和转换 IR。LLVM Pass 是编写为 C++ 代码的模块。它们可以独立运行,也可以组合在一起以创建更复杂的 Pass。

ctx中的cipher指针

 ctx 结构体中的 cipher 指针指向一个加密器对象。加密器对象包含加密算法的所有必要信息,例如密钥、块大小和工作模式。cipher 指针在 AES 中很重要,因为它允许加密器对象在加密和解密数据时使用。

C++的虚函数

 C++中的虚函数可以被派生类重写。虚函数在基类中使用virtual关键字声明。当基类的指针或引用指向派生类对象时,调用虚函数时,会根据实际对象的类型来调用派生类中的函数定义。虚函数的主要作用是实现多态性。

 以下是虚函数的使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Base {
public:
virtual void func() {
cout << "Base::func()" << endl;
}
};

class Derived : public Base {
public:
void func() override {
cout << "Derived::func()" << endl;
}
};

int main() {
Base* base = new Derived;
base->func(); // 输出:Derived::func()
delete base;
return 0;
}

RTTI

 RTTI 是 Run-Time Type Identification 的缩写,它指的是运行时类型识别。在 C++ 中,RTTI 允许程序在运行时获取对象的类型信息。RTTI 在 C++ 中使用 typeid 运算符来获取对象的类型信息。typeid 运算符返回一个 type_info 对象,该对象包含了对象的类型信息。

程序以独占方式运行

 程序以独占方式运行,是指程序在运行时,其他程序无法访问该程序所使用的资源。例如,一个程序正在使用一个文件,如果该程序以独占方式运行,则其他程序无法访问该文件。

 程序以独占方式运行通常是为了确保程序的安全性和稳定性。例如,一个程序正在写入一个文件,如果该程序以独占方式运行,则其他程序无法访问该文件,从而避免了文件被意外修改或损坏。

 程序以独占方式运行通常是通过操作系统的进程管理机制来实现的。操作系统会为每个程序分配一个唯一的进程 ID,并将该进程 ID 与该程序所使用的资源相关联。当一个程序以独占方式运行时,操作系统将阻止其他程序访问该程序所使用的资源。

VIR文件

 VIR文件是Avira Antivirus Pro 2016创建的病毒感染文件。

srv.sys

 srv.sys 是 Windows 操作系统的核心组件,负责文件系统的读取和写入。srv.sys 驱动程序负责以下任务:

  • 读取和写入文件
  • 管理文件句柄
  • 管理文件属性
  • 管理文件权限

SSE指令

指令名称 描述
pmovmskb eax, xmm2 取xmm2(8字节)中的每个字节的符号位,并赋给eax(低8位)
packsswb xmm2, xmm2 将xmm2寄存器中的单精度浮点数转换为有符号整数

syscall/sysenter

 syscall(系统调用)是Linux内核中提供给用户空间程序使用的接口,也称为系统调用函数。它可以让用户空间程序向内核发出请求,并获取内核返回的结果。syscall是操作系统与应用程序之间进行通信的桥梁,是Linux系统中最基本、最底层的API之一。sysenter是Intel 64和IA-32处理器中的一个特殊指令,用于快速进入系统模式。它是一种在ring 0级别上的入口点,用于启动特权模式代码。通过sysenter指令,可以跳转到由IA32_SYSENTER_CS(段选择子)和IA32_SYSENTER_EIP指定的特权模式代码,从而进入内核模式。

 syscall主要用于实现用户空间程序与内核的通信,而sysenter则用于快速进入系统模式。

kernel-bypass frameworks

 能够绕过操作系统的内核级检查和授权,直接访问硬件资源的应用程序编程接口(API)和库集合,应用于高性能计算、大数据处理、虚拟化和安全领域。

Syscall User Dispatch (SUD)

 用于在Linux上运行Windows游戏时提高性能和兼容性,SUD允许通过系统调用(syscall)在用户空间中调度和执行部分Ring3权限的函数,从而使得在Linux上运行Windows游戏时,不需要进行内核级别的修改或使用虚拟化技术。

BSD Packet Filter (BPF)/eBPF

 BSD Packet Filter (BPF)是一种抓取并过滤网络数据包的内核结构,主要目的是允许用户空间程序对网络流量进行监控和分析,以便实现网络管理和安全审计等功能。

 BPF包含两个重要的组成部分:网络分流器(network tap)和包过滤器(packet filter)。网络分流器负责从网络驱动拷贝数据包,而包过滤器则根据用户空间程序提交的过滤规则,过滤掉不符合条件的数据包,只把符合需求的数据包上报给应用程序。

 BPF的过滤规则使用一种类似于汇编语言的伪汇编码语言来编写,这种语言可以被编译成可以在BPF虚拟机上运行的指令。BPF虚拟机运行在内核空间中,它可以从网络分流器获取数据包,并根据过滤规则对数据包进行过滤操作。

 eBPF(extended Berkeley Packet Filter)是一个能够在内核运行沙箱程序的技术,它允许用户态程序将C语言编写的一小段“内核代码”注入到内核中运行,使得非内核开发人员也可以对内核进行控制。

 eBPF的核心特性包括:

  1. 在内核事件发生时安全地注入代码:用户态程序可以编写一段C语言代码,并将其注入到内核中运行。这使得非内核开发人员也可以对内核进行控制。
  2. 提供了强大的工具集:eBPF提供了一组强大的工具,包括用于跟踪和调试的bpftrace和bpftool等工具。
  3. 提供了安全检查:为了防止注入的代码导致内核崩溃或其他安全问题,eBPF会对注入的代码进行严格检查,拒绝不合格的代码的注入。
  4. 提供了与用户程序的通信机制:用户态程序和注入到内核中的程序可以通过共享内存实现通信,从而实现了更高效的交互。

callq/call

callq指令是64位模式下使用的,它直接跳转到目标地址去执行,同时将目标地址(即函数入口)压入栈(但是论文zopline中写的是caller address)中。这个指令相当于将控制权完全转移给被调用的函数。

 而call指令可以在16位、32位和64位模式下使用。在32位模式下,call指令会将下一条指令的地址压入栈中,并跳转到目标地址去执行。

Trampoline code

 Trampoline code是一种用于控制程序跳转的代码结构,它可以让程序从一个函数或任务跳转到另一个函数或任务,并可以按照特定的流程顺序执行这些函数或任务。

dlmopen

 dlmopen是Linux中的一个函数,它用于打开动态链接库。dlmopen函数允许应用程序在运行时动态地加载和链接共享对象,以便使用其中的函数和数据。dlmopen函数支持对象加载隔离,即在新的命名空间中加载共享对象符号,这些符号不会暴露给应用程序的其他部分。

Bitmap

 bitmap通过使用每一bit位代表一个数,位号就是数值,1标识有,0标识无。如下所示:

image-20230907113634047

vDSO (virtual dynamic shared object)

 vDSO(virtual Dynamic Shared Object,虚拟动态共享对象)是一个比较小的共享库,内核动态地将它映射到所有应用程序的地址空间中。vDSO包含了一组用于优化系统调用的函数,它通过将频繁使用的系统调用改写为库函数,并将该库函数以用户空间的形式实现,从而加速系统调用的速度。vDSO主要被用户态的程序频繁调用,例如数据库或Web服务器等。

IOCP套接字模型

 IOCP(I/O Completion Port),常称I/O完成端口。就是用于高效处理很多很多的客户端进行数据交换的一个模型。IOCP有一个队列,当你要发数据时,收数据和连接时,都交由IOCP队列处理,不会与操作系统底层交互。发送数据时,先将缓冲区和长度封好,这个请求会发送到IOCP队列,IOCP内部会帮你把请求发出去。收数据时,收数据的请求丢掉IOCP队列,IOCP会将收到的数据填入指定的缓冲区里边,当数据收好后会通知你来收数据。建立连接时,IOCP帮你把连接建立好,告诉你新的连接已经来了。

Rundll32

 Rundll32(Run a DLL as an App)是Windows操作系统中的一个可执行文件,用于加载和执行DLL(Dynamic Link Library)文件中的函数。它允许将DLL文件中的函数作为独立的应用程序来执行。

lwIP

 lwIP (lightweight IP) 是一个轻量级的开源 TCP/IP 协议栈,专门设计用于嵌入式系统和资源受限设备。它提供了实现基本的网络通信所需的核心协议,如 IP、TCP、UDP 和 ICMP,以及一些常见的网络应用协议,如 DHCP、DNS 和 HTTP。

Underminer Exploit Kit

 Underminer Exploit Kit(Underminer 攻击工具包)是一个恶意软件工具包,用于进行大规模的网络攻击和利用漏洞。它被用于分发恶意软件、实施网络钓鱼、进行勒索软件攻击和窃取敏感信息等恶意活动。

MS Detours

 MS Detours(Microsoft Detours)是一种软件开发库,用于在 Windows 操作系统上进行函数挂钩(Function Hooking)。函数挂钩是一种技术,允许开发者在运行时修改或替换目标函数的行为,以实现定制化的功能扩展或拦截。MS Detours 包括软件调试、反病毒软件、代码注入、API 监视、性能分析等。

LibPEConv

 LibPEConv(Library PE Conv)是一个开源的C++库,用于在Windows平台上进行可执行文件(PE文件)的加载、解析和修改。它提供了一组功能强大的API,使开发者能够处理和操作PE文件的各个部分,包括头部信息、节表、导入表、导出表、重定位表等等。

LibPEConv的主要特点和功能包括:

  1. 加载和解析PE文件:LibPEConv可以加载和解析PE文件,提取出各个组成部分的信息。
  2. 导入表和导出表操作:开发者可以使用LibPEConv来读取和修改PE文件的导入表和导出表,包括添加、删除、修改导入导出函数等。
  3. 重定位表处理:LibPEConv支持处理PE文件的重定位表,即使在修改PE文件后也能正确处理重定位。
  4. 节表操作:开发者可以使用LibPEConv来读取和修改PE文件的节表,包括添加、删除、重命名节等。
  5. 异常处理:LibPEConv支持处理PE文件中的异常处理表,包括添加、删除、修改异常处理信息。
  6. 兼容性:LibPEConv具有较好的兼容性,能够处理不同类型的PE文件,包括32位和64位的可执行文件和动态链接库(DLL)。

TSO/WMM

 TSO 是一种内存一致性模型,每个处理器核心的存储操作(Store)都会按照程序中的顺序进行排序和提交到主内存。在每个处理器核心看来,存储操作是按照其在程序中出现的顺序执行的,即每个处理器看到的存储操作顺序是一致的。然而,不同处理器核心之间的存储操作的顺序可能是不确定的,可能会发生重排序,因此程序员需要使用同步原语(如锁、原子操作等)来确保正确的顺序和同步。

 WMM 是一种较弱的内存一致性模型,它允许更多的存储操作重排序和乱序执行。在 WMM 下,处理器核心之间的内存操作的顺序可能会被重排,这包括存储操作和加载操作(Load)。这意味着在多核系统中,不同核心看到的存储和加载操作的顺序可能是不确定的,可能会产生一些奇怪的行为和错误。在 WMM 下编写正确的并发程序更加困难,因为程序员需要显式地使用同步原语(如内存屏障、原子操作等)来保证正确的顺序和同步。

Shell脚本中$0 | $? | $! | $$ | $* | $# | $@

名称 描述
$$$$ shell本身的pid
$? 返回值
$! shell最后运行的后台进程的pid
$0 shell文件本身的文件名
$* 所有参数列表,以"$1 $2 ... $n"的形式输出
$# 参数个数
$@ 所有参数列表,以"$1" "$2" ... "$n"的形式输出

Shell脚本中$() | `` | ${} | $[] | $(()) | [] | (()) | [[]]

$() | ``

 两者都可以当作命令替换来用,例如:

1
2
version = $(uname -r)
version = `uname -r`

 但是,`` 基本上可用在全部的 unix shell 中使用,而$()并不是所有shell都支持。

${}

${}用于变量替换。一般情况下,$var${var}并没有啥不一样。但是用${}会比较精确的界定变量名称的范围。

$[]$(())

 都是进行数学运算的,但是注意,bash只能作整数运算,对于浮点数是当作字符串处理的。而(()) | [[]]是数学表达式的加强版。

反汇编器

 机器指令到汇编语言。

vsyscall/vdso

vsyscall 是一种特殊的内核映射区域,用于提供对一些常用系统调用的快速访问。在早期的 Linux 内核版本中,系统调用是通过软中断(software interrupt)的方式实现的,这需要从用户空间切换到内核空间,并执行相应的系统调用处理例程。这种切换的开销相对较高,对于频繁调用的系统调用来说,会导致性能下降。

 为了解决这个问题,Linux 内核引入了 vsyscall 机制。vsyscall 是一个位于用户空间的内存映射区域,它包含了一些常见的系统调用的实现代码,如获取当前时间、获取系统信息等。这些系统调用的实现在 vsyscall 区域中直接运行,而不需要进行用户空间到内核空间的切换。

 需要注意的是,vsyscall 机制在较新的 Linux 内核版本中已经被废弃,并被 vdso(Virtual Dynamic Shared Object)机制所取代。vdso 是一个用户空间的共享库,其中包含了一些常用系统调用的实现代码。它通过动态链接器的机制自动加载到每个用户空间进程的虚拟内存空间中,从而提供快速的系统调用访问。

WebDAV/UNC

 WebDAV(Web-based Distributed Authoring and Versioning)用于在远程服务器上进行文件管理和协作。它允许用户通过 Web 进行文件的读取、写入、复制、移动和删除操作,类似于本地文件系统的访问方式。

 UNC(Universal Naming Convention)用于在网络上访问共享资源,如文件和打印机。UNC 路径使用特定的格式来标识网络上的共享资源,通常以双斜杠开头,后面跟着服务器名称或 IP 地址,然后是共享资源的名称或路径。

js中的异步函数与同步函数

 同步函数按照代码的顺序逐行执行,每一行代码都会等待上一行代码执行完成后再执行下一行。而异步函数执行时,虽然此函数还没运行完,但是就直接运行下一行代码。

io_uring

 传统的 I/O 操作(如读取文件、网络通信等)通常需要使用系统调用(如 read、write、recv、send 等),这些调用会导致进程阻塞等待 I/O 完成。在阻塞期间,进程无法执行其他任务,效率较低。

 io_uring 引入了一种新的异步 I/O 模型,它通过使用 I/O 事件环(I/O event ring)来实现高效的非阻塞 I/O 操作。它的设计目标是减少系统调用的开销和提高 I/O 操作的吞吐量。

bootloader锁

 bootloader 锁是一种安全机制,用于限制用户对设备的操作和修改。Bootloader 是手机启动时加载的程序,负责引导操作系统的启动。Bootloader 锁限制了用户在手机上安装非官方固件、自定义操作系统或进行其他修改的能力。

 当手机的 bootloader 被锁定时,只能安装由手机制造商或官方渠道提供的经过验证的固件和操作系统。这意味着用户无法自行安装第三方 ROM(如刷入自定义的 Android ROM)或进行其他需要访问 bootloader 功能的操作。

TWRP

 Team win recovery project是一个开放源码软件的定制Recovery映像,允许用户向第三方安装固件和备份当前的系统,Recovery指的是一种可以对安卓机内部的数据或系统进行修改的模式,类似于Windows PE。

android studio的DDMS

 早期的android studio中,DDMS(Dalvik Debug Monitor Server)是用于调试和监视 Android 设备和模拟器的工具。

一代整体加固(Whole-Program Obfuscation)与二代抽取加固(Code and Resource Extraction Protection)

 一代整体加固是指将整个应用程序的代码进行混淆和加密,使得逆向工程师难以理解和还原源代码,通常包括代码混淆、字符串加密、控制流混淆、反调试。

 二代抽取加固是指将应用程序的关键逻辑和资源从原始的可执行文件中提取出来,以加密和保护,而将剩余的代码保留在原始的可执行文件中,包括代码与资源提取、加密保护、运行时解密。

ART虚拟机与Dalvik虚拟机

 ART(Android Runtime)是 Android 系统中的一种虚拟机,用于执行和管理 Android 应用程序的运行时环境。它是在 Android 5.0中引入的,之前是 Dalvik 虚拟机。

安卓中的zygote与Libart.so

 zygote 是安卓的关键进程,作为应用程序的孵化器。它在系统启动时被初始化,负责创建和管理应用程序的进程(作用1)。当启动新的应用程序时,复制自身并生成新的进程,作为新应用程序的基础。预加载并共享一些常用的系统类和资源,以减少应用程序启动时间和系统资源的消耗(作用2)。执行应用程序进程的安全隔离,确保不同应用程序之间的互相隔离和保护(作用3)。

 libart.so(或ART Runtime)是安卓的运行时库,用于执行应用程序的代码。其实现了安卓应用程序的AOT(Ahead-of-Time)编译,将应用程序的字节码转换为本地机器代码,以提高应用程序的执行效率。还提供了一些优化功能,如垃圾回收、内存管理和即时编译等。

vmware桥接模式与仅主机模式

 桥接模式(Bridged Mode):宿主机的副本。桥接模式允许虚拟机与物理网络中的其他设备直接连接,就像虚拟机是网络中的一个独立计算机一样。在桥接模式下,虚拟机会获得与主机所连接的物理网络相同的网络信息(ip地址在同一c段下)

 仅主机模式:在仅主机模式下,虚拟机之间可以相互通信,但无法与物理网络中的其他设备进行通信。仅主机模式提供了一种安全的网络环境,适用于需要虚拟机之间进行通信,但不需要与外部网络进行交互的场景

http与socks5

 http工作在应用层,socks5工作在传输层,socks5可以观察到更多的协议信息。

frida -f与-F

-f参数后面跟着应用程序的标识符,可以是应用程序的包名、进程名或应用程序的可执行文件路径。-F 又可以写为--attach-frontmost,会自动搜索正在运行的进程,此时确保要调试的app,处在前台=正在运行=当前界面。

SSL Pinning

 SSL Pinning(SSL 锐化)是一种用于增强应用程序与服务器之间的安全通信的技术。它可以防止中间人攻击和窃听

 通常情况下,应用程序与服务器之间的通信通过 SSL/TLS 加密协议进行保护,SSL Pinning 引入了一个额外的验证步骤,以确保应用程序只信任特定的服务器证书或公钥

 其工作原理如下:

(1)预先固定证书或公钥:开发者在应用程序中嵌入了服务器的证书或公钥信息。这些信息是预先固定的。

(2)运行时验证:当应用程序与服务器建立 SSL/TLS 连接时,它会验证服务器的证书或公钥是否与预先固定的信息匹配。如果匹配成功,连接被认为是受信任的,通信继续进行。

image-20231010175359561

 SSL Pinning实际上是客户端锁定服务器端的证书,在要与服务器进行交互的时候,服务器端会将CA证书发送给客户端,客户端会调用函数对服务器端的证书进行校验,与本地的服务器端证书(存放在.asset目录或resraw下)进行比对

尾指令与非尾指令

 尾指令:直接跳转到其他指令,而不是继续执行当前指令后面的指令,通常是无条件跳转或条件跳转。

 非尾指令:接着执行后面的指令。

子资源完整性(Subresource Integrity,SRI)

 验证和确保在网页中引用的外部资源(如脚本文件、样式表文件等)的完整性的安全技术。SRI 使用哈希算法来生成资源的完整性校验值,并将其与引用资源的网页中的对应值进行比对。如果校验值匹配,表示资源未被篡改,可以安全加载和使用。

内容安全策略 (Content Security Policy, CSP)

 一种安全机制,用于保护网站免受恶意脚本注入、跨站脚本攻击(XSS)、数据泄露和点击劫持等。CSP 允许网站所有者通过定义一组策略规则,明确指定允许加载的资源来源和允许执行的操作,从而限制网页中可执行的内容和行为。

goroot vs gopath

  • GOROOT:GOROOT就是Go的安装目录,(类似于java的JDK)
  • GOPATH:GOPATH是工作空间,保存go项目代码和第三方依赖包。设置了GOPATH,则无法使用go mod(依赖文件)。

ps的Invoke-Expression与Invoke

Invoke-Expression 命令用于执行以字符串形式提供的 PowerShell 表达式或命令。

Invoke(也称为 Invoke-Command)是通用的 PowerShell 命令,用于执行命令、脚本块或脚本文件。

CIDR表示法

 Classless Inter-Domain Routing,一种用于表示 IP 网络和子网的简洁表示方法,例如192.0.2.0/24

波束成形

 波束成形(Beamforming)通过对传输或接收的信号进行加权和相位调整,实现对特定方向的信号增强或抑制。传统的无线通信系统中,信号以均匀扩散的方式传输和接收,导致信号的能量在空间中的分布较为平均。而波束成形技术通过调整信号的相位和幅度分布,使得信号在某个特定的方向上形成一个集中的波束,从而将信号的能量聚焦在目标方向上

Constant False Alarm Rate (CFAR) 算法

 首先对输入的噪声进行处理后确定一个门限,将此门限与输入端信号相比,如输入端信号超过了此门限,则判为有目标,否则,判为无目标。

Gradient Reversal Layer (GRL) 梯度反转层

 在反向传播过程中,GRL层将输入的梯度乘以一个负的标量权重(通常为-1),从而实现梯度反转。

 作用:

  • 域自适应:GRL层主要用于域自适应任务,其中训练数据包含来自不同领域的样本,但目标是在目标领域中获得良好的性能。
  • 域不变表示学习:GRL层通过反转梯度的方向,鼓励模型在域自适应任务中学习到与输入域无关的特征表示。
  • 特征混淆:通过反转梯度的方向,GRL层试图最大化源域和目标域之间的特征差异,从而迫使模型学习到与域相关的特征,并减小域之间的分布差异。
  • 提升模型泛化性能:通过减小域之间的分布差异,GRL层有助于提高模型在目标域中的泛化性能。

dilated conv(扩张卷积)

 传统的卷积操作是在输入数据上滑动一个固定大小的卷积核,进行局部感知和特征提取。Dilated Convolution引入了一个称为膨胀率的概念。膨胀率定义了卷积核中采样点之间的间隔,卷积核的每个采样点之间通过添加固定的间隔来形成一个网格。这样,卷积核在输入数据上的感受野变得更大,从而能够捕捉更广泛的上下文信息。

t-SNE(t-Distributed Stochastic Neighbor Embedding)

 非线性降维和可视化技术,用于将高维数据映射到低维空间,并保持数据点之间的相似性关系。

java反射

 在Java中,反射(Reflection)是指在运行时动态地获取和操作类的信息,包括类的结构、字段、方法和构造函数等。

hypervisor

  Hypervisor(虚拟机监控程序)允许在物理计算机上同时运行多个虚拟机(Virtual Machine),每个虚拟机都可以执行独立的操作系统和应用程序。Hypervisor负责管理和分配物理资源给虚拟机,并提供虚拟化环境,使得每个虚拟机都能够运行和管理自己的操作系统和应用程序。

selinux policies

 SELinux (Security-Enhanced Linux) 是一种在 Linux 操作系统上实施强制访问控制(MAC)的安全机制。SELinux Policies 文件是用于定义和配置 SELinux 策略的文件。SELinux Policies 文件包含了一组规则和规范,用于控制系统上进程、文件、网络通信等资源的访问权限。这些策略规则定义了哪些进程可以访问哪些文件、网络端口、设备等,并规定了访问权限的具体规则和限制。

/proc/self/attr/prev 文件

 是与 SELinux 相关的特殊文件之一,用于存储进程的安全上下文(Security Context)的先前值。

True Positive(TP):将正类预测为正类

True Negative(TN):将负类预测为负类

False Positive(FP):将负类预测为正类数(误报)

False Negative(FN):将正类预测为负类数(漏报)

Gradle

 Gradle 是强大的构建工具和构建自动化系统,用于构建和管理软件项目。它采用了基于 Groovy 或 Kotlin 的领域特定语言(DSL)来定义项目的构建脚本。它可以用于构建Java项目。

DSL

 领域特定语言(Domain-Specific Language,DSL)是一种针对特定领域或问题域的编程语言。DSL 的设计目标是为了解决特定领域中的问题,并提供更高级、更专注的表达能力。分为内部DSL与外部DSL。内部 DSL 是嵌入在通用编程语言中的领域特定语言,例如,Java 中的流式 API(Stream API)就是一种内部 DSL。外部 DSL 是一种独立的编程语言,用于解决特定领域的问题,例如,正则表达式是一种外部 DSL。

java的泛型

 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。java 中泛型标记符:

  • E - Element (在集合中使用,因为集合中存放的是元素)
  • T - Type(Java 类)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数值类型)
  • - 表示不确定的 java 类型

image-20231117200539593

image-20231117200733591

fld与fstp

fld:将浮点数值加载到浮点寄存器中。

fstp:用于将浮点寄存器中的值存储到指定的目标位置。

CIP 与长连服务器

 CIP(Common Industrial Protocol)通道是一种用于工业自动化领域的通信协议,其允许在工业网络中以一种标准化的方式来管理和控制不同厂商的设备,使它们能够相互通信并协同工作。

 长连接服务器(Long-polling Server)是一种服务器端技术,可以实现实时的双向通信。与传统的短连接不同,长连接服务器允许客户端与服务器之间建立持久的连接,以便在任何时间点上进行双向的数据传输。长连接服务器通过保持连接的持久性来解决这个问题,长连接服务器可以用于实现各种实时通信应用,如实时聊天、实时数据推送、多人协作、在线游戏等,长连接服务器技术包括 WebSocket、Server-Sent Events(SSE)等。

Socket

 Socket 本身并不是协议,它是对传输层协议(如 TCP 或 UDP)的抽象和封装。通过 Socket 编程接口,开发人员可以使用底层的传输层协议进行网络通信。

网络字节序与主机字节序

 网络字节序是一种固定的大端字节序,用于在计算机网络中进行数据交换;而主机字节序是指主机使用的字节序,可能是大端字节序或小端字节序。常用的字节序转换函数包括 ntohl(网络字节序转主机字节序)和 htonl(主机字节序转网络字节序)。

java’s visitor mode

Define new operation in object structure’s element without modifing object structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
interface Visitor {
void visit(ElementA elementA);
void visit(ElementB elementB);
}
interface Element {
void accept(Visitor visitor);
}

class ElementA implements Element {
// implements Element interface
@Override
public void accept(Visitor visitor) {
// implements Visitor interface
visitor.visit(this);
}
// ElementA's feature
}

class ElementB implements Element {
// implements Element interface
@Override
public void accept(Visitor visitor) {
// implements Visitor interface
visitor.visit(this);
}
// ElementB's feature
}

// implement concrete class of visitor
class ConcreteVisitor implements Visitor {
@Override
public void visit(ElementA elementA) {
System.out.println("访问者对 ElementA 进行操作");
}

@Override
public void visit(ElementB elementB) {
System.out.println("访问者对 ElementB 进行操作");
}
}

public class Main {
public static void main(String[] args) {
Element elementA = new ElementA();
Element elementB = new ElementB();
// define a visitor
Visitor visitor = new ConcreteVisitor();
// for different element, do different thing
elementA.accept(visitor);
elementB.accept(visitor);
}
}

call/ret

call = push IP, jmp near ptr 标号

ret = pop ip

Cpp 的一些特性

explicit

 防止编译器进行隐式的类型转换。如下所示,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyClass {
public:
explicit MyClass(int x) {
// 构造函数的实现
}
};

void func(MyClass obj) {
// 函数的实现
}

int main() {
MyClass obj1(10); // 直接调用构造函数,显式创建对象
MyClass obj2 = 20; // 错误!禁止隐式类型转换
MyClass obj3 = MyClass(30); // 正确,显式调用构造函数进行类型转换
func(40); // 错误!禁止隐式类型转换
func(MyClass(50)); // 正确,显式调用构造函数进行类型转换
return 0;
}
inline

 向编译器提供函数内联展开的建议。如下所示:

1
2
3
4
5
6
7
8
inline int add(int a, int b) {
return a + b;
}

int main() {
int result = add(3, 4); // 函数调用被内联展开,即不使用 call
return 0;
}

cpp 中函数参数定义为 const 有什么好处?使用 const 修饰参数可以向函数的调用者传达一种约束,即函数内部不会修改参数的值。

cpp 中函数定义为 const 有什么好处?这意味着该函数在执行过程中不会修改对象的成员变量。常量成员函数可以在常量对象上调用,这样可以提供对常量对象的操作。如果没有将成员函数定义为 const,则无法在常量对象上调用该函数。将函数定义为 const 的前提是该函数是类的成员函数。对于非成员函数,不能将其定义为 const

virtual

 用于声明类的成员函数为虚函数。虚函数允许在派生类中进行函数的覆盖,实现运行时的多态性。

protected

 private成员在类内部可见,外部无法直接访问。protected` 成员在类内部和派生类中可见,外部无法直接访问。

类的公有继承与私有继承

 公有继承特点为:基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。私有继承的特点是:基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问

friend

 一个类可以授权其他类或函数访问其私有成员。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyClass {
private:
int privateData;

public:
friend void friendFunction(); // 声明友元函数

void publicFunction() {
privateData = 10; // 友元函数可以访问私有成员
}
};

void friendFunction() {
MyClass obj;
obj.privateData = 20; // 可以访问 MyClass 的私有成员
}
constexpr 与 const

const 关键字用于声明一个常量,表示它的值不能在程序运行时被修改。constexpr 关键字用于声明一个常量表达式,表示它在编译时就能被计算出来。

using

using 用于引入类型别名、类型别名模板以及模板别名。例如:

1
2
using MyInt = int;
using MyFunction = std::function<void(int)>;
智能指针

 显著简化内存管理,并避免手动释放内存的工作。std::unique_ptr:独占所有权的智能指针,它提供了对单个对象的独占所有权,并确保在其生命周期结束时自动释放内存。

右值引用&&
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A {
public:
A() {
std::cout << "Default constructor" << std::endl;
}
A(const A& other) {
std::cout << "Copy constructor" << std::endl;
}
A(A&& other) {
std::cout << "Move constructor" << std::endl;
}
};

void foo(A&& a) {
// 使用 a 进行操作,可能会进行移动操作
}

int main() {
A obj; // 创建一个对象

foo(std::move(obj)); // 将 obj 转为右值引用传递给 foo 函数。注意:在实际应用中,将 obj 转为右值引用时需要谨慎,确保 obj 不再被使用。
return 0;
}

cmake 与 make 指令

1
2
CMake:生成 Makefile 的工具,侧重于跨平台构建配置。
Make:根据 Makefile 执行实际的构建命令,侧重于执行编译任务并管理依赖关系。

python 的 co_lnotab

co_lnotab 的名称来自 line number table,即行号表。每条记录通常包含两个部分:

1
2
字节码偏移的增量。
从上一个记录到当前记录的行号增量。

 如下图所示:

image-20240325215644570

mmap 与 vdso 页面

mmap 内存映射:

image-20240507204927809

 系统调用涉及到从用户态切换到内核态,这是一个耗时的操作。vDSO 提供了一种机制,允许用户程序直接在用户态执行某些系统调用,无需切换到内核态。这通过将一小块代码(即 vDSO 代码)映射到每个进程的地址空间来实现。

gcc 编译选项

1
2
3
4
5
6
7
8
9
-no-pie。不生成位置无关的可执行文件。
-fno-pie。不生成位置无关的代码。
-ldl。告诉 GCC 链接时需要包括动态链接库 libdl。这个库提供了动态加载和链接功能,如 dlopen, dlclose, dlsym, dlerror 等函数。
-fpic。为共享库生成位置无关代码。
-pie。生成动态链接的位置无关可执行文件,通常需要同时指定 -fpie。
-fpie。类似于-fpic,但生成的位置无关代码只能用于可执行文件,通常同时指定 -pie。
-m32。32 位编译。
-fno-stack-protector。关闭 canary。
-z noexecstack。开启 NX。

.got 与 .got.plt 的区别

1
2
3
4
5
.got (Global Offset Table)。.got 用于动态链接的程序中,它存储了全局数据的地址,如全局变量和静态变量的动态地址。这些地址在程序启动时由动态链接器填充,并在程序执行期间被直接访问。

.got.plt (Procedure Linkage Table's Global Offset Table)。主要用于解决动态链接的函数地址。它是 .plt(Procedure Linkage Table)的一个扩展,.plt 用于管理动态链接的函数调用。

区别:.got 用于全局变量的地址解析;.got.plt 专门用于动态链接的函数地址解析。

.plt.got 与 .got.plt 有什么区别

1
2
3
.got.plt。Global Offset Table 的一个部分,专门用于处理动态链接的函数地址。它与 Procedure Linkage Table (.plt) 直接关联,主要涉及延迟绑定的函数调用。

.plt.got。通常在使用静态链接的 PIE (Position Independent Executables) 下使用,用于处理全局偏移表的条目。.plt.got 是一个小的 .plt 表,用于实现对全局变量的动态解析,尤其是那些需要通过 GOT 进行访问的全局变量。

.rel.plt、.rel.dyn、.plt.got、.got.plt

  • .rel.plt。记录的是重定位表的信息,所有外部过程调用符号的重定位信息会出现在这个节区中。每个重定位项记录了重定位的操作地址(r_offset),重定位类型的信息和符号的符号表索引(r_info)。是 Elf32_Rel 数组。
  • .rel.dyn。记录除外部过程调用的符号以外的所有重定位对象,比如引用外部的全局变量等。每个重定位项记录了重定位的操作地址(r_offset),重定位类型的信息和符号的符号表索引(r_info)。是 Elf64_Rel 数组。
  • .plt.got。用于存放 cxa_finalize 函数对应的 PLT 条目。`cxa_finalize` 是一个在 C++ 中用于处理全局对象析构的函数,它通常在动态库卸载时或程序退出时被调用。
  • .got.plt。运行时可读写的,在延迟绑定过程中与 .plt 一起使用,如果关闭了延迟绑定则没有该节。.got.plt[1] 存放了link_map 结构体的地址,.gotplt[2] 存放了 _dl_runtime_resolve 函数的地址,后面的各项则用于存放函数的加载地址,在使用延迟绑定的时候这些项里会统一初始化为 .plt[0] 的地址,用于执行_dl_runtime_resolve函数。

寄存器与参数传递

 在 Linux 上,前六个参数分别通过 RDI、RSI、RDX、RCX、R8 和 R9 进行传递。在 Windows 中,前四个参数通过 RCX、RDX、R8 和 R9 来传递。

幂等操作与非幂等操作

幂等授权 (idempotent authorization):幂等性是指某个操作可以重复执行多次,但只会产生与执行一次相同的结果。例如,在授权操作中,无论你执行多少次授权操作,结果都是相同的,不会因为多次执行而产生不同的影响。这意味着即使重复执行相同的授权操作,也不会改变系统的状态或引起错误。

非幂等操作 (non-idempotent):与幂等操作相对,非幂等操作是指每次执行都会改变系统的状态,并且每次执行的结果都可能不同。例如,账户余额的增减操作属于非幂等操作,因为每次执行都会改变账户的余额,重复执行会产生不同的结果。因此,非幂等操作需要全局排序来确保正确性和一致性。

gossip 协议

 Gossip 协议是一种分布式通信协议,用于在网络节点之间传播信息。它模仿了人类传播谣言的方式,节点间随机地与其他节点交换信息,逐渐使整个网络所有节点都获得相同的信息。具体步骤如下:

1
2
3
4
5
6
7
8
9
1 初始传递:控制器向一小部分见证人发送新事件和收据。
2 信息传播:
- 接收到信息的见证人会随机选择其他几个见证人,向他们传播新事件和收据。
- 这些见证人接收信息后,再随机选择其他见证人,继续传播。
3 逐步传播:
- 随着时间推移,信息逐渐在整个网络中传播,每个见证人都通过与其他见证人交换信息获得新事件和收据。
- 由于每个见证人都不断向其他见证人传播信息,信息传播速度呈指数级增长。
4 效率:
- Gossip 协议的通信负载通常为 N·log(N),其中 N 是见证人的数量。这比轮询协议的 2·N 更高效,特别是在大规模网络中。虽然看起来 Gossip 协议的通信次数更多,但其效率体现在实际传播速度和可靠性上。轮询协议需要逐个节点确认,传播速度线性增长,可能在大规模网络中造成延迟。而 Gossip 协议通过并行传播,可以快速覆盖整个网络,提高了整体传播效率。

ret 与 leave 指令

1
2
ret 相当于 pop eip; jmp esip
leave 相当于 mov esp, ebp; pop ebp

控制流完整性 CFI 的原理

1
2
3
4
5
6
7
Step1. 控制流图(CFG)构建
- 静态分析:编译时,构建控制流图(Control Flow Graph, CFG),描述程序中所有可能的合法控制流路径
- 动态验证:运行时,动态检查每个间接分支是否符合预先构建的 CFG
Step2. 插入校验点
- 在每个函数调用、返回地址和间接跳转指令前插入校验点,验证目标地址是否在合法范围内。例如,在函数指针调用前,验证目标地址是否在合法的函数地址范围内。使用堆栈金丝雀(stack canary)或影子堆栈(shadow stack)等机制保护返回地址,确保其未被篡改。在使用虚函数前,验证虚函数表指针是否指向合法的虚函数表。
Step3. 保护间接分支
- 使用硬件或软件机制保护函数指针、虚函数表指针和返回地址等关键数据,确保它们只能指向合法的代码位置

 LLVM 提供了 CFI 的实现,通过编译器插入校验点,并在运行时进行控制流保护。Intel 的 Control-flow Enforcement Technology (CET) 提供硬件级别的 CFI 支持,包括 Shadow Stack 和 Indirect Branch Tracking (IBT)。

syscall、vsyscall 与 vdso

  • syscall 就是将控制权从用户态转移到内核态。
  • vsyscall 旨在减少某些系统调用的开销,它通过在用户空间中提供固定地址的虚拟函数,使某些频繁调用的系统调用(timegetcpu)不需要切换到内核态,从而提高性能。vsyscall 区域在内核启动时被映射到用户空间的一个固定地址(通常是 0xffffffffff600000),但存在安全性问题。
  • 为了替代 vsyscall,内核引入了 vdso(Virtual Dynamically linked Shared Object)。vdso 是一种共享库,内核会将其映射到用户空间,提供了一些系统调用的用户态实现。vdsovsyscall 更灵活,并且解决了安全性问题,因为它允许动态链接库的加载和地址的随机化。

unistd.h 的作用

 提供了对 mac/linux 操作系统 API 的访问,是许多系统调用和库函数的声明,例如 read、fork、close 等。

MSR 寄存器

 Model-Specific Register (MSR) 寄存器通常用于配置 CPU 的特定硬件功能、性能监控、调试以及其他功能。MSR 寄存器可以启用或禁用处理器的某些功能,如硬件预取、超线程、虚拟化支持等,还可以控制处理器的电源状态、频率调节等,还可以监控指令执行、缓存命中/未命中、分支预测等,还可以设置硬件断点和陷阱,用于调试程序执行,还可以用于控制虚拟化扩展和管理虚拟机。

 访问 MSR 寄存器通常需要特权级别,只有操作系统内核或特权软件才能直接读写这些寄存器。在 x86 架构中,可以使用 RDMSR 指令读取 MSR 寄存器的值,可以使用 WRMSR 指令写入 MSR 寄存器。

Extended Page Tables (EPT) 的原理与作用

 Extended Page Tables (EPT) 是 Intel 虚拟化技术(Intel VT-x)的一部分,用于支持硬件辅助的虚拟化,特别是在处理虚拟机内存管理时。EPT 可管理虚拟机的内存地址翻译,从而提高虚拟化性能

 没有 EPT 的情况下,虚拟机管理程序(Hypervisor)需要模拟二级页表翻译。每次虚拟机访问内存时,虚拟机管理程序需要将虚拟机的虚拟地址(Guest Virtual Address, GVA)转换为虚拟机的物理地址(Guest Physical Address, GPA),然后再转换为宿主机的物理地址(Host Physical Address, HPA),这会影响性能。

 EPT 允许虚拟机管理程序直接将虚拟机的虚拟地址(GVA)翻译为宿主机的物理地址(HPA)(其实不是)。EPT 使用四级页表结构,类似于传统的 x86-64 页表结构。这四级页表分别是:EPT PML4 (Page Map Level 4)、EPT Page Directory Pointer Table (PDPT)、EPT Page Directory (PD)、EPT Page Table (PT)。

 每个表项的格式与传统页表项相似,但包含更多的信息来支持虚拟化。例如,每个 EPT 页表项除了指向下一级页表的物理地址外,还包含了访问权限和内存类型等信息

 EPT 的工作原理:

1
2
1. GVA 到 GPA:虚拟机中的操作系统将应用程序的虚拟地址(GVA)通过其页表转换为虚拟机的物理地址(GPA)。
2. GPA 到 HPA:EPT 将虚拟机的物理地址(GPA)转换为宿主机的物理地址(HPA)。

PAE(Physical Address Extension)

 PAE 用于扩展 32 位 x86 架构的物理内存寻址能力。在没有 PAE 的情况下,32 位 x86 系统可寻址 4GB 的物理内存。启用 PAE 后,可以寻址更多的物理内存,最高可以达到 64GB。PAE 通过增加 CPU 寻址位数以及使用分页机制来实现这一扩展。

留言

2023-06-01

© 2024 wd-z711

⬆︎TOP