shanept/assembly-simulator

允许逐行执行编译后的汇编代码。提供访问寄存器和堆栈,以便轻松查询值。

0.1.0 2024-05-22 13:29 UTC

This package is auto-updated.

Last update: 2024-09-09 11:49:49 UTC


README

AssemblySimulator项目提供了一种逐行执行编译后的汇编代码的方法,每次操作并提供访问寄存器和堆栈,以便轻松查询值。实现非常简单,我们只实现了几个基本指令。然而,该架构允许轻松扩展指令集,以满足您的项目需求。

模拟器

模拟器可以手动实例化,也可以通过模拟器工厂实例化。请注意,使用模拟器工厂并不限制您在创建模拟器后注册更多指令。以下两种方法等价:

<?php
// METHOD 1: Using the factory.
$simulator = SimulatorFactory::createSimulator(Simulator::PROTECTED_MODE);

// METHOD 2: Manually creating the simulator.
$simulator = new Simulator(Simulator::PROTECTED_MODE);

// Instantiate default instruction set manually.
$xor = new ExclusiveOr();
$lea = new LoadEffectiveAddress();
$mov = new Move();
$pop = new Pop();
$push = new Push();

// Link instruction set to simulator.
$xor->setSimulator($simulator);
$lea->setSimulator($simulator);
$mov->setSimulator($simulator);
$pop->setSimulator($simulator);
$push->setSimulator($simulator);

模式

模拟器支持在真实模式、保护模式和长模式下运行。为了指定模拟器应运行的模式,请将其中一个模式常量提供给构造函数或setMode函数

  • Simulator::REAL_MODE
  • Simulator::PROTECTED_MODE
  • Simulator::LONG_MODE

注意:如果您使用$simulator->setMode()函数设置模拟器模式,则在执行任何模拟之前必须先调用$simulator->reset()进行重置。请参阅模拟器重置部分。

重置模拟器

在某些情况下,您需要重置模拟器——就像按下电脑的重置开关一样。重置函数用于将模拟器恢复到更好的已知状态。这包括清除寄存器和堆栈。

注册自定义指令

为了使用模拟器,必须用您希望使用的指令集实例化它。这里提供了一个使用默认指令集的示例。请注意,如果您希望使用默认指令集使用模拟器,您可以直接使用模拟器工厂。

更多信息,请参阅自定义指令示例。

<?php
$simulator = new Simulator(Simulator::PROTECTED_MODE);

// Instantiate our instruction set.
$exclusiveOr = new ExclusiveOr;
$lea = new LoadEffectiveAddress;
$mov = new Move;
$pop = new Pop;
$push = new Push;

// Link our instruction set with the simulator.
$exclusiveOr->setSimulator($simulator);
$lea->setSimulator($simulator);
$mov->setSimulator($simulator);
$pop->setSimulator($simulator);
$push->setSimulator($simulator);

代码缓冲区

在模拟之前,模拟器必须提供代码缓冲区以从中操作。这必须以二进制字符串的形式提供。

<?php
$simulator = new Simulator(Simulator::PROTECTED_MODE);

// Taken from PHP v8.3.7 Thread-Safe Windows "php8ts.dll" binary.
$assemblyCode =
    "\x56" .                                        // push esi
    "\x68\x18\xA7\x60\x10" .                        // push 0x1060A718
    "\x6A\x0B" .                                    // push 0xB
    "\x68\x98\x4D\x61\x10";                         // push 0x10614D98

$simulator->setCodeBuffer($assemblyCode);

// OR: Reads the same string from the php8ts.dll file.
$fp = fopen("php8ts.dll", "rb");
fseek($fp, 4782677);
$assemblyCode = fread($fp, 13);
fclose($fp);

$simulator->setCodeBuffer($assemblyCode);

// The simulator can now run.
$simulator->simulate();

示例

更多信息,请参阅示例目录下的示例。

  • examples/getCdeclFunctionCallParameters.php - 如何使用模拟器的基本示例。
  • examples/registeringCustomInstruction.php - 如何构建和使用自定义指令的示例。
  • examples/registeringCustomInstructionWithFactory.php - 如上所述,使用模拟器工厂。
  • examples/myCustomInstruction.php - 自定义指令如何实现的示例。