【问题标题】:Are the cmpxchg esp, eax instructions the same as the icebp instructions?cmpxchg esp, eax 指令是否与 icebp 指令相同?
【发布时间】:2020-02-07 09:41:53
【问题描述】:

根据this question,我们知道icebp指令与int1指令类似。

在这种情况下,我正在做一个愚蠢的实验,比如在没有输入的情况下进行比较和交换:

global _start
section .text

_start:

cmpxchg esp, eax

构建:nasm -f elf example.asm && ld -o example example.o

当我调试时,它会执行icebp指令

% gdb -q cmpxchg
Reading symbols from cmpxchg...(no debugging symbols found)...done.
gdb-peda$ r
Starting program: /home/user/assembly/cmpxchg 

Program received signal SIGTRAP, Trace/breakpoint trap.

[----------------------------------registers-----------------------------------]
EAX: 0xbfffee18 --> 0x3fffcc2b 
EBX: 0x0 
ECX: 0x0 
EDX: 0x0 
ESI: 0x0 
EDI: 0x0 
EBP: 0x0 
ESP: 0xbfffee00 --> 0x1 
EIP: 0x8048093 --> 0x12ff
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x804808e:   add    BYTE PTR [eax],al
   0x8048090:   add    al,0x0
   0x8048092:   icebp  
=> 0x8048093:   call   DWORD PTR [edx]
   0x8048095:   add    BYTE PTR [eax],al
   0x8048097:   add    BYTE PTR [eax],al
   0x8048099:   add    BYTE PTR [eax],al
   0x804809b:   add    BYTE PTR [eax],al
No argument
[------------------------------------stack-------------------------------------]
0000| 0xbfffee00 --> 0x1 
0004| 0xbfffee04 --> 0xbffff013 ("/home/user/assembly/cmpxchg")
0008| 0xbfffee08 --> 0x10 
0012| 0xbfffee0c --> 0xbffff044 ("XDG_SEAT=seat0")
0016| 0xbfffee10 --> 0xbffff053 ("XDG_SESSION_ID=c2")
0020| 0xbfffee14 --> 0xbffff065 ("LC_IDENTIFICATION=id_ID.UTF-8")
0024| 0xbfffee18 --> 0x3fffcc2b 
0028| 0xbfffee1c --> 0xbffff0a6 ("DISPLAY=:0")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGTRAP
0x08048093 in ?? ()
gdb-peda$

我的问题是,它是怎么发生的?

【问题讨论】:

  • 不,它们不相似,我无法重现您的结果; 0f b1 c4 在 GDB 8.3.1 中以 0x8049000 cmpxchg esp,eax 的形式出现在一个 32 位静态链接的 Linux 可执行文件中,该可执行文件使用来自 echo "cmpxchg esp, eax" > foo.asm 的 NASM + ld 构建。 (我使用的是普通的 GDB,而不是 gdb-peda)。 显示机器代码 (GDB disas /r) 和/或源代码 + 构建命令以使其成为 minimal reproducible example。我想知道您是否以某种方式看到了 GDB 设置的软件断点的反汇编?
  • 你的结果甚至不合理; call 仅在 add 之后 2 个字节,这意味着 icebp 仅 1 个字节长(正如 F1 opcode, ` int1` instruction 所期望的那样)。除非有其他错误会影响 GDB 的地址计数/打印,否则这不可能只是 cmpxchg 上的软件断点被反汇编。
  • 我的意思是,当指令被执行时,它会执行icebp指令(已编辑问题)
  • 不,这是不可能的。 cmpxchg esp,eax 有 3 个字节长,因此您的 GDB 输出不可能显示包含该指令的机器代码的反汇编。
  • @PeterCordes 这是一个错误?或....

标签: assembly x86 gdb


【解决方案1】:

您忘记单步执行cmpxchg esp, eax 指令。 执行远不止于此,直到它碰巧遇到了f1 操作码。

使用starti 从第一条用户空间指令开始,然后使用si

通常,如果您让执行落入一堆00 00 字节,您的进程会出现段错误,因为在Linux 静态可执行文件的开头,它会解码为add [eax], al 和EAX=0。 (您不必费心从您的_start 进行_exit 系统调用。)

cmpxchg esp, eax 将 EAX 设置为有效指针。(隐式操作数 EAX 最初不等于 ESP,因此“清除 ZF 并将 r/m32 加载到 EAX 中 em>”发生了。事实上,EAX 作为显式源操作数给出是无关紧要的,顺便说一句。)

通过一堆解码为00 00 add 的00 指令继续执行。然后进入您显示的块,其中第一个出错的指令恰好是f1 字节,它位于可执行文件中.text 部分结束后的某处。


当然cmpxchg 不会像icebp / int1 那样执行。如果您实际上在 cmpxchg 指令中,您的反汇编甚至是不可能的。 cmpxchg 是 3 个字节长,但相邻指令的地址之间的距离只有 1 个字节。所以不可能是 GDB 误解码了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 2013-07-23
    • 2015-05-19
    • 2011-05-16
    • 1970-01-01
    • 2012-12-10
    相关资源
    最近更新 更多