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

2023-12-08

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

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

它被编译成这样:

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

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


TL:DR: IDA 混淆使用cs:指示 64 位代码中的 RIP 相对寻址模式。


In IDA mov eax, x means mov eax, DWORD [x]这又意味着从变量中读取 DWORDx.
为了完整性,mov rax, OFFSET x means mov rax, x(即将地址x in rax).

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

在 NASM 中,RIP 相对寻址采用以下形式mov eax, [REL x],在气体中它是mov x(%rip), %eax.
另外,在 NASM 中,如果DEFAULT REL处于活动状态,指令可以缩短为mov eax, [x]这与 32 位语法相同。

每个反汇编器都会以不同的方式反汇编 RIP 相关操作数。正如您所评论的,Ghidra 给出了mov eax, DWORD PTR [x].
国际开发协会用途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

简而言之,您基本上可以忽略cs:因为这正是 64 位模式下变量寻址的方式。
当然,如上面的列表所示,使用或不使用 RIP 相对寻址告诉您该程序可以加载到任何位置或刚好低于 4GiB。


The csIDA 显示的前缀让我很失望。

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

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 为什么 Visual Studio 使用 xchg ax,ax

    我正在查看程序的反汇编 因为它崩溃了 并注意到很多 xchg ax ax 我用谷歌搜索了一下 发现它本质上是一个 nop 但是为什么 Visual Studio 会执行 xchg 而不是 noop 该应用程序是一个C NET3 5 64位应
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 两个基本的 ANTLR 问题

    我正在尝试使用 ANTLR 来获取简单的语法并生成汇编输出 我在 ANTLR 中选择的语言是 Python 许多教程看起来非常复杂或详细阐述与我无关的事情 我真的只需要一些非常简单的功能 所以我有两个问题 将值从一个规则 返回 到另一规则
  • 汇编8086监听键盘中断

    我有与此完全相同的问题 边画边听键盘 https stackoverflow com questions 13970325 8086 listen to keyboard while drawing 但第一个答案 接受的答案 只听键盘一次
  • 页面错误陷阱的成本

    我有一个应用程序 它定期 每 1 或 2 秒后 通过分叉自身来获取检查点 因此 检查点是原始进程的一个分支 它一直保持空闲状态 直到原始进程发生某些错误时被要求启动 现在我的问题是fork的写时复制机制的成本有多大 每当原始进程写入内存页面
  • 使用 Easy 68K (68000) 组装范围内的随机数

    我正在使用 Easy 68K 模拟器创建一个简单的黑杰克游戏 需要使用随机数来分配牌 我的牌必须在 2 到 11 的范围内 我似乎每次都得到相同的数字 但它不在我预期的范围内 我的卡值需要以 D3 结束 因此我有以下随机数代码 CLR L
  • 68HC11计算sin(x)的汇编代码

    68HC11 使用泰勒级数或查找表计算正弦值的汇编代码是什么 显示值只能是整数 查找表如何工作 在这种情况下 如何使用它来实现泰勒级数 http en wikipedia org wiki Taylor series 如果您正在寻找浮点解决
  • 寄存器寻址模式与直接寻址模式

    我在试卷中遇到过这个问题 它指出 哪种给定的寻址模式更快 为什么 寄存器寻址方式 直接寻址方式 现在根据我的说法 寄存器寻址模式应该更快 因为寄存器是计算机中最快的存储位置 这是正确答案吗 请帮忙 谢谢 两种寻址模式之间的区别是 地址的来源
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • AVX-512CD(冲突检测)与原子变量访问有何不同?

    所以我在看他们展示了如何 void Histogram const float age int const hist const int n const float group width const int m const float o
  • 使用 (float&)int 进行类型双关可以正常工作,(float const&)int 会像 (float)int 一样转换吗?

    VS2019 发布 x86 template
  • 从 exe 文件中获取汇编级代码?

    我当时正在做linux汇编编程 在过去的几天里我已经转而学习windows汇编编程 我在用ml作为我的汇编器和golink作为我的链接器 我有我的汇编代码并已获得我的exe从中 现在我需要取回它的十六进制 xff xab x55等等 在li
  • 使用 MIPS 从 Big Endian 到 Little Endian 无需逻辑运算?

    我正在使用 MIPS QtSpim 将 32 位字从 Big Endian 转换为 Little Endian 我下面显示的内容已检查且正确 不过我想知道还有什么其他方法可以让我进行转换 我虽然只使用了旋转和移位 但如果没有逻辑运算 我就无
  • 如何拦截 .Net 中第三方库对非虚拟方法的调用?

    我认为我需要的是 net 人们称之为 透明动态代理 的东西 但到目前为止我所看到的所有实现 Castle DynamicProxy Spring NET AOP 等 都要求我至少执行以下操作之一 将拦截的方法声明为虚拟方法 包装类并创建包装
  • FreePascal x64 上系统单元函数的汇编调用

    我有一些 Delphi 汇编代码 可以在 Win32 Win64 和 OSX 32 上编译并正常工作 XE2 但是 由于我需要它在 Linux 上工作 所以我一直在考虑编译它的 FPC 版本 到目前为止 Win32 64 Linux32 6
  • 为什么 clang 使用 -O0 生成低效的 asm(对于这个简单的浮点和)?

    我正在 llvm clang Apple LLVM 版本 8 0 0 clang 800 0 42 1 上反汇编此代码 int main float a 0 151234 float b 0 2 float c a b printf f c
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • 整数溢出问题

    我不断遇到整数溢出问题 我不知道如何解决它 有人可以帮忙吗 edx 包含 181 eax 包含 174 xor eax edx mov edx 2 div edx 假设你谈论的是x86 div edx这实际上没有意义 32位div将edx
  • movzbl(%rdi, %rcx, 1), %ecx 在 x86-64 汇编中意味着什么?

    我想我明白 movzbl rdi rcx 1 ecx 意思是 将零扩展字节移至长整型 并表示将 ecx 扩展为 32 位 但我不完全确定语法 rdi rcx 1 指的是什么 我在某处看到该语法指的是 Base Index Scale 但我找

随机推荐