CS:覆盖对 IDA 输出中全局变量的访问,如 mov eax、cs:x?

Inc*_*ace 2 assembly x86-64 ida disassembly addressing-mode

我正在编写简单的程序然后分析它们。今天我写了这个:

#include <stdio.h>
 
int x;
 
int main(void){
    printf("Enter X:\n");
 
    scanf("%d",&x);
 
    printf("You enter %d...\n",x);
 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它被编译成这样:

push    rbp
mov     rbp, rsp
lea     rdi, s          ; "Enter X:"
call    _puts
lea     rsi, x
lea     rdi, aD         ; "%d"
mov     eax, 0
call    ___isoc99_scanf
mov     eax, cs:x   <- don't understand this
mov     esi, eax
lea     rdi, format     ; "You enter %d...\n"
mov     eax, 0
call    _printf
mov     eax, 0
pop     rbp
retn
Run Code Online (Sandbox Code Playgroud)

我不明白什么cs:x意思。
我使用 Ubuntu x64、GCC 10.3.0 和 IDA pro 7.6。

Mar*_*oom 9

TL:DR:IDAcs:在 64 位代码中混淆地用于指示 RIP 相对寻址模式。


在 IDA 中mov eax, x意味着mov eax, DWORD [x]这意味着从变量中读取 DWORD x
为完整起见,mov rax, OFFSET x表示mov rax, x(即放入xin的地址rax)。

在 64 位位移中仍然是 32 位,因此,对于位置无关的可执行文件,并非总是可以通过对其地址进行编码来寻址变量(因为它是 64 位并且不适合 32 位字段)。在与位置无关的代码中,这是不可取的。
相反,使用RIP 相对寻址

在 NASM 中,RIP 相对寻址的形式是mov eax, [REL x],在 gas 中是mov x(%rip), %eax.
此外,在 NASM 中,如果DEFAULT REL处于活动状态,则可以将指令缩短mov eax, [x]为与 32 位语法相同的指令。

每个反汇编器都会以不同的方式反汇编 RIP 相关的操作数。正如您所评论的,Ghidra 给出了mov eax, DWORD PTR [x].
IDA 用于mov eax, cs:x表示mov eax, [REL x]/ mov x(%rip), %eax

;IDA listing, 64-bit code
mov eax, x                ;This is mov eax, [x] in NASM and most likely wrong unless your exec is not PIE and always loaded <= 4GiB
mov eax, cs:x             ;This is mov eax, [REL x] in NASM and idiomatic to 64-bit programs
Run Code Online (Sandbox Code Playgroud)

简而言之,您几乎可以忽略 ,cs:因为这只是在 64 位模式下寻址变量的方式。
当然,如上面的清单所示,使用或不使用 RIP 相关寻址告诉您程序可以加载到任何地方或仅低于 4GiB。


csIDA 显示的前缀让我失望。

我可以看到它在精神上可能类似于“代码”,因此类似于rip寄存器,但我认为 RIP 相对寻址并不意味着cs段覆盖。

在 32 位模式下,代码段通常是只读的,所以像这样的指令mov [cs:x], eax会出错。
在这种情况下,将 acs:放在操作数前面是错误的。

在 64 位模式下,段覆盖(除fs/ 之外gs)将被忽略(并且代码段的读取位无论如何都会被忽略),因此 a 的存在cs:并不重要,因为 adscs实际上是无法区分的。(即使ssords覆盖也不会更改非规范地址的 #GP 或 #SS 异常。)
可能 AGU 甚至不再读取fsor以外的段基址的段影子寄存器gs。(尽管即使在 32 位模式下,对于段基数 = 0 的正常情况,也有较低延迟的快速路径,因此硬件可能只是让它完成它的工作。)

cs:在我看来仍然具有误导性-2E在机器代码中仍然可以使用前缀字节作为填充。大多数工具仍将其称为 CS 前缀,尽管http://ref.x86asm.net/coder64.html在 64 位模式下将其称为“空前缀”。这里没有这样的字节,cs:也不是暗示 RIP 相对寻址的明显或明确的方式。

  • IDA 似乎完全不一致,在 `lea rdi, format` 中没有使用 `cs:`,当然也使用 RIP 相对寻址。(这是 GCC 输出,所以如果它使用 32 位绝对值,它将使用`mov edi,OFFSET 格式`)。它似乎几乎是 GNU `.intel_syntax`,尽管我猜它实际上与它在 Windows 上使用的语法相同,因此不会使用 `[RIP + format]`,因为它更像是实际的 MASM。总的来说,对于您想要在混淆/手工制作的机器代码上使用的反汇编程序来说,这似乎是一个糟糕的选择。 (2认同)
  • @PeterCordes 在实际指令之前的 `db` 指令。我也很好奇就试了一下。 (2认同)