花子LingMo 2021-08-27 16:52 采纳率: 50%
浏览 43
已结题

关于vmp壳的堆栈原理问题

一个程序要vm的代码里有几句push pop指令,那vmp虚拟机在遇到这种指令要怎么处理。毕竟vmp自己也是基于堆栈的虚拟机。它会把这些与堆栈操作有关的指令是在真实的堆栈上处理,还是在vmp的虚拟堆栈里处理?

  • 写回答

1条回答 默认 最新

  • FadeTrack 2021-08-31 18:21
    关注

    这种需要和宿主打交道的vm,其操作最终会反应到真实机器的寄存器和内存(也就是你这里说的真实的栈,即操作esp和其指向的内容)。

    举个例子,伪代码

    typedef struct vcpu {
        uint32_t eax;
        uint32_t ebx;
        uint32_t ecx;
        // ....
        uint32_t esp;
    } vcpu;
    
    void foo() {
      printf("entry_vm\n");
      entry_vm();
      do_vmcode(vpush, value, 0);
      do_vmcode(vadd, eax, ebx);
      exit_vm();
      // 注意 vpush之后这里栈没平衡
      printf("exit_vm\n"); 
    }
    

    这里的 entry_vm 和 exit_vm 一般采用汇编构造,在 entry_vm 阶段保存当前寄存器信息到vcpu结构,exit_vm() 反之。
    do_vmcode 会对 vcpu 结构进行操作。

    do_vmcode(vpush, value) 操作对应 vcpu->esp-=4; *(int*)(vcpu->esp) = value;
    do_vmcode(vadd, eax, ebx) 操作对应 vcpu->eax += vcpu->ebx;

    通过以上方式就可以简单将原始汇编二进制转为等价的 vmcode (通常是更为简洁的自定义指令集),这里为了简单用了一一对应的指令关系。


    一般流程是 entry_vm 保存寄存器信息后,会进入一个环境初始化部分(负责异常处理等),然后开始一个循环,读取 vcpu->eip 指向的 vmcode,然后调用 do_vmcode 完成上述解析执行操作,直到退出vm,调用 exit_vm(反应寄存器信息回真实机器),在 do_vmcode 中操作的内存即是真实内存,故内存操作在vm内部已经被反应(也可以像 qemu 那样搞个 vmmu,可以,但没必要)。


    实际上这种vm最难的地方在于重定位,异常等处理上面,希望有天你能分析分析,写篇报告。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 12月31日
  • 已采纳回答 12月23日
  • 专家修改了标签 8月30日
  • 创建了问题 8月27日

悬赏问题

  • ¥15 yolov8边框坐标
  • ¥15 matlab中使用gurobi时报错
  • ¥15 WPF 大屏看板表格背景图片设置
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真