在IA-32汇编语言中,如果没有LIDT、LGDT和LLDT指令,是否可以修改IDTR、GDTR或LDTR或'loaded'?

In IA-32 assembly language, can IDTR, GDTR or LDTR be modified or 'loaded' without the LIDT, LGDT and LLDT instructions?

在 IA-32 汇编语言中,是否可以修改 IDTR、GDTR 或 LDTR/'loaded' 没有 LIDT、LGDT 和 LLDT 指令?

另外,是否有可用于修改其他寄存器的完整指令列表?我想知道哪些指令可以用来修改CR3,哪些指令可以用来修改ECX

我是 IA-32 装配的新手。我知道 MOV、ADD、SUB 等,但是它需要是一个完整的列表,我相信可能有很多指令可以用来修改这些寄存器。

谢谢! :)

编辑:我想知道的原因是因为我正在考虑监视已执行指令的指令跟踪(使用硬件调试)是否是一种可行的检测方法 - 在外部 'integrity monitoring' 机器中 - 任何恶意软件Rootkit 更改这些寄存器中的地址以执行所谓的地址转换重定向攻击 (ATRA)。因此,我试图确定是否有可能确定修改每个寄存器的潜在恶意指令序列的完整列表。

Regarding IDTR, GDTR, and LDTR, the Intel System Programming Guide has the answers :

Section 2.4.1, "Global Descriptor Table Register" (GDTR) :

The LGDT and SGDT instructions load and store the GDTR register, respectively.

Section 2.4.2, "Local Descriptor Table Register" (LDTR) :

The LLDT and SLDT instructions load and store the segment selector part of the LDTR register, respectively. The segment that contains the LDT must have a segment descriptor in the GDT. When the LLDT instruction loads a segment selector in the LDTR: the base address, limit, and descriptor attributes from the LDT descriptor are auto- matically loaded in the LDTR. When a task switch occurs, the LDTR is automatically loaded with the segment selector and descriptor for the LDT for the new task. The contents of the LDTR are not automatically saved prior to writing the new LDT information into the register.

So, there are only two instructions used for modifying the table, but task switching in the processor (though it's not used by any of the mainstream operating systems anymore, so whether you should worry about this depends on what you're actually doing) can cause the contents of this register to change.

Section 2.4.3, "IDTR Interrupt Descriptor Table Register" :

The LIDT and SIDT instructions load and store the IDTR register, respectively.

Regarding ECX, however, there is no one clear answer. Since it was used as a "count" register back in the days of real mode, it might be modified by some loop-related instructions implicitly. Off the top of my head :

  • LOOP (and its derivatives), which decrements ECX and jumps if it's not zero. However, you shouldn't really see this instruction a lot in new code, as it's mostly a leftover from CISC days and as such its use is discouraged when emitting code for today's CPUs. This is due to relatively long time (compared to test + jump) it takes to decode it.
  • REP (and its derivatives), which repeats a given instruction as long as ECX is not zero.
  • CPUID, which uses all the registers to return CPU identification information.

I'm sure there's some more. I'd be surprised if such a list exists, though it would certainly be useful sometimes.

可以通过以下方式修改 IDTR、GDTR 或 LDTR:

  • LIDT、LGDT 和 LLDT 指令
  • 进入系统管理模式,修改"state save"区域中的值,然后离开系统管理模式导致加载修改的值
  • 使用硬件虚拟化扩展,其中主机能够修改来宾使用的虚拟 IDTR、GDTR 或 LDTR

请注意,此列表不包括保持 IDTR、GDTR 或 LDTR 相同以及修改它们指向的数据(IDT、GDT 或 LDT)。

CR3 可以通过以下方式更改:

  • mov cr3 说明
  • 硬件任务切换
  • 代码运行系统管理模式
  • 硬件虚拟化扩展(主机修改来宾)

ECX 可以通过以下方式更改:

  • 数百种不同的指令(太多无法列出)
  • 硬件任务切换
  • 代码运行系统管理模式
  • 硬件虚拟化扩展(主机修改来宾)

请注意,硬件任务切换几乎从未使用过,并且在长模式下也不再受支持;系统管理模式通常对软件完全不可用(包括软件 运行 at CPL=0),只有系统的固件才能真正使用它。