指令序列 call/cdqe/ret 有什么作用?

逆向工程 核心 汇编
2021-06-18 18:34:53

我正在尝试反转 Linux 模块。ioctl例程中,我有以下指令序列(由 生成objdump -M intel -d test.ko):

 3f9:   74 3b                   je     436 <device_ioctl+0x46>
...
 436:   e8 00 00 00 00          call   43b <device_ioctl+0x4b>
 43b:   48 98                   cdqe   
 43d:   c3                      ret

我不确定跳转完成后会发生什么。

首先,我们有一个call指令。操作码是E8 00对下一条指令的接近调用。EIP 寄存器(包含下一条指令的地址)也被压入堆栈。

然后,我们继续cdqe指令。它将 EAX 寄存器的符号扩展到 RAX。换句话说,它什么都不做。顺便提一下,EAX/RAX 寄存器从例程开始就没有被修改。

最后,ret执行指令。它将堆栈弹出到对应于前一条指令的 EIP 中,我们从该点继续执行例程。

因此,cdqe再次执行(什么都不做)并ret再次调用指令。这一次,我们离开ioctl例程并返回到被调用者。

我说这没有任何作用是对的吗?如果是这样,该代码的重点是什么?


这是完整的例程:

00000000000003f0 <device_ioctl>:
 3f0:   48 89 d7                mov    rdi,rdx
 3f3:   81 fe 03 b0 fe ca       cmp    esi,0xcafeb003
 3f9:   74 3b                   je     436 <device_ioctl+0x46>
 3fb:   77 18                   ja     415 <device_ioctl+0x25>
 3fd:   81 fe 01 b0 fe ca       cmp    esi,0xcafeb001
 403:   74 39                   je     43e <device_ioctl+0x4e>
 405:   81 fe 02 b0 fe ca       cmp    esi,0xcafeb002
 40b:   75 39                   jne    446 <device_ioctl+0x56>
 40d:   e8 00 00 00 00          call   412 <device_ioctl+0x22>
 412:   48 98                   cdqe   
 414:   c3                      ret    
 415:   48 c7 c0 00 00 00 00    mov    rax,0x0
 41c:   48 c7 c2 ff ff ff ff    mov    rdx,0xffffffffffffffff
 423:   48 2d 00 00 00 00       sub    rax,0x0
 429:   81 fe 04 b0 fe ca       cmp    esi,0xcafeb004
 42f:   89 c0                   mov    eax,eax
 431:   48 0f 45 c2             cmovne rax,rdx
 435:   c3                      ret    
 436:   e8 00 00 00 00          call   43b <device_ioctl+0x4b>
 43b:   48 98                   cdqe   
 43d:   c3                      ret    
 43e:   e8 00 00 00 00          call   443 <device_ioctl+0x53>
 443:   48 98                   cdqe   
 445:   c3                      ret    
 446:   48 83 c8 ff             or     rax,0xffffffffffffffff
 44a:   c3                      ret    

这是来自pbctf 2021的夜总会挑战


1个回答

cdqe 执行 EAX 的 RAX ← 符号扩展。
仅适用于 x64
下面显示的是 x86 cdq 的演示,它不是使用 rax 而是使用 eax,edx 组合 edx 在 x86 中获得符号扩展

对于 cdqe 寄存器 rax 将成为 0xffffffff<eax> or 0x00000000<eax>

在此处输入图片说明

也许ctf正在检查标志