我正在寻找一种巧妙的方法来捕获和摆弄 Linux 进程的 CPUID 指令。玩弄 ptrace() 并修补由进程创建的所有可执行 mmap'ed 区域中的所有 cpuid 操作码,用 int3 替换它们。由于 CPUID 操作码字节经常作为其他较长操作码的一部分出现,因此效果不佳。
所以基本上我正在寻找一种方法,允许我不在特定的内存地址上设置断点,而是在每次调用操作码时设置断点。任何人都知道如何做到这一点?
我正在寻找一种巧妙的方法来捕获和摆弄 Linux 进程的 CPUID 指令。玩弄 ptrace() 并修补由进程创建的所有可执行 mmap'ed 区域中的所有 cpuid 操作码,用 int3 替换它们。由于 CPUID 操作码字节经常作为其他较长操作码的一部分出现,因此效果不佳。
所以基本上我正在寻找一种方法,允许我不在特定的内存地址上设置断点,而是在每次调用操作码时设置断点。任何人都知道如何做到这一点?
通常,在任意 x86 代码上执行此操作并捕获所有极端情况的唯一方法是:
PTRACE_SINGLESTEP
见下文);或者第一种方法可能更好。
(尝试反编译操作码,而不是使用单步执行即时反编译是行不通的,因为它不会捕获诸如自我修改代码或跳转到另一条指令中间的情况)。
要实现单步法,每次被跟踪的进程停止时,您将使用PTRACE_GETREGS
获取孩子的寄存器,然后将孩子的%eip
寄存器值作为地址传递给PTRACE_PEEKTEXT
,获取下一个要执行的单词。检查该词以查看它是否是 CPUID 指令 - 如果是,则通过调整孩子的寄存器集(包括%eip
超越 CPUID 指令)来模拟该指令。然后打电话PTRACE_SINGLESTEP
让这个过程继续。
我知道没有简单的好方法。
一个讨厌的方法可能是使用 GDB 的 python 脚本 API 来自动单步执行程序,在执行之前检查每条指令。
另一种讨厌的方法可能是获取诸如Bochs之类的源代码,一个开源 x86 仿真器,并对其进行更改,以便在执行您感兴趣的指令时执行您想要的操作。