3 个版本

0.1.2 2022 年 11 月 14 日
0.1.1 2022 年 11 月 9 日
0.1.0 2022 年 11 月 9 日

60macOS 和 iOS API


hyperpom 中使用

GPL-3.0-or-later

125KB
1.5K SLoC

APPLEVISOR
苹果硅 Hypervisor 框架的 Rust 绑定


shields.io license shields.io version shields.io platform
shields.io rust version shields.io crates.io shields.io crates.io


目录

此库可用于构建利用 Apple Silicon 上 Hypervisor 框架的 Rust 应用程序。它主要针对 Hyperpom 构建,但也可以用于更广泛的目的。

入门

自签名二进制文件和 Hypervisor 权限

为了能够访问 Hypervisor 框架,必须授予二进制可执行文件 hypervisor 权限

证书链

要将此权限添加到您的项目,您首先需要一个证书链来签名您的二进制文件,可以通过以下说明创建。

  • 打开 钥匙串访问 应用程序。
  • 转到 钥匙串访问 > 证书助理 > 创建证书
  • 填写 名称 字段,此值将在以后用于标识我们要签名的证书,并将被称为 ${CERT_NAME}
  • 身份类型 设置为 Self-Signed Root
  • 证书类型 设置为 Code Signing
  • 单击 创建

现在您可以使用以下命令对二进制文件进行签名并添加权限

codesign --entitlements entitlements.xml -s ${CERT_NAME} /path/to/binary

注意: entitlements.xml 文件位于 Applevisor 仓库的根目录。

编译流程

创建一个 Rust 项目,并在 Cargo.toml 中将 Applevisor 添加为依赖项。您可以从 crates.io ...

# Check which version is the latest, this part of the README might not be updated
# in future releases.
applevisor = "0.1.2"

... 或者直接从 GitHub 仓库 获取。

applevisor = { git="https://github.com/impalabs/applevisor", branch="master" }

在项目的根目录下创建一个名为 entitlements.txt 的文件,并添加以下内容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.hypervisor</key>
    <true/>
</dict>
</plist>

编写代码然后构建项目。

cargo build --release

对二进制文件进行签名并授权虚拟机权限。

codesign --entitlements entitlements.xml -s ${CERT_NAME} target/release/${PROJECT_NAME}

运行二进制文件。

target/release/${PROJECT_NAME}

文档

文档可在以下地址在线获取: https://docs.rs/applevisor

或者,您可以使用 cargo 生成文档。

cargo doc --open

示例

以下示例

  • 为当前进程创建一个虚拟机;
  • 创建一个虚拟 CPU;
  • 启用虚拟机的调试功能,以便稍后使用断点;
  • 创建 0x1000 字节的物理内存映射,并将其映射到地址 0x10000,具有读写执行权限;
  • 在地址 0x10000 处写入指令 mov x0, #0x42; brk #0;
  • 设置 PC 为 0x10000;
  • 启动 vCPU 并运行程序;
  • 遇到断点时返回。
use applevisor::*;

fn main() {
    // Creates a new virtual machine. There can be one, and only one, per process. Operations
    // on the virtual machine remains possible as long as this object is valid.
    let _vm = VirtualMachine::new().unwrap();

    // Creates a new virtual CPU. This object abstracts operations that can be performed on
    // CPUs, such as starting and stopping them, changing their registers, etc.
    let vcpu = Vcpu::new().unwrap();

    // Enables debug features for the hypervisor. This is optional, but it might be required
    // for certain features to work, such as breakpoints.
    assert!(vcpu.set_trap_debug_exceptions(true).is_ok());
    assert!(vcpu.set_trap_debug_reg_accesses(true).is_ok());

    // Creates a mapping object that represents a 0x10000-byte physical memory range.
    let mut mem = Mapping::new(0x1000).unwrap();

    // This mapping needs to be mapped to effectively allocate physical memory for the guest.
    // Here we map the map the region at address 0x10000 and set the permissions to
    // Read-Write-Execute.
    assert_eq!(mem.map(0x10000, MemPerms::RWX), Ok(()));

    // Writes a `mov x0, #0x42` instruction at address 0x10000.
    assert_eq!(mem.write_dword(0x10000, 0xd2800840), Ok(4));
    // Writes a `brk #0` instruction at address 0x10004.
    assert_eq!(mem.write_dword(0x10004, 0xd4200000), Ok(4));

    // Sets PC to 0x10000.
    assert!(vcpu.set_reg(Reg::PC, 0x10000).is_ok());

    // Starts the Vcpu. It will execute our mov and breakpoint instructions before stopping.
    assert!(vcpu.run().is_ok());

    // The *exit information* can be used to used to retrieve different pieces of
    // information about the CPU exit status (e.g. exception type, fault address, etc.).
    let _exit_info = vcpu.get_exit_info();

    // If everything went as expected, the value in X0 is 0x42.
    assert_eq!(vcpu.get_reg(Reg::X0), Ok(0x42));
}

您还可以查看 Hyperpom 项目的源代码,了解这些绑定在实际中的应用。

运行测试

要使用项目提供的 Makefile 运行测试,您首先需要安装 jq。您可以使用 brew 来安装。

brew install jq

然后,您可以使用以下命令使用提供的 Makefile 运行测试

CERT_KEYCHAIN=${CERT_NAME} make tests

作者

依赖项