asm rip-relative addressing

时间:2017-10-09 14:14:53

标签: assembly x86-64 shellcode

我正在做某种CTF挑战,我有一个程序可以检查缓冲区,如果那里有syscall,sysenter或int 80指令,用户输入将逐字节地传递。

我要做的是编写一个shellcode,将syscall指令的第二个字节修改为有效的。也就是说,输入的最后两个字节是\x0f\x01,我希望shellcode本身将其覆盖为\x0f\x05(系统调用)。

所以原始shellcode的最后几条指令看起来像这样:

  ....
  21:   31 c0                   xor    %eax,%eax
  23:   88 47 07                mov    %al,0x7(%rdi)
  26:   48 89 7f 08             mov    %rdi,0x8(%rdi)
  2a:   48 89 47 10             mov    %rax,0x10(%rdi)
  2e:   48 8d 77 08             lea    0x8(%rdi),%rsi
  32:   48 89 c2                mov    %rax,%rdx
  35:   b0 3b                   mov    $0x3b,%al
  37:   0f 05                   syscall

并使用两条额外的指令来重写系统调用:

  ...
  37:   b1 05                   mov    $0x5,%cl
  39:   88 0d 01 00 00 00       mov    %cl,0x1(%rip) 
  3f:   0f 05                   syscall

然而,我看到39用一些尾随零编码,而23例如相似但位置相对于rdi而不是rip,则不是。

所以我的问题是,那看起来不错吗?如果是这样的话,为什么rip会出现尾随零。是否有一些rip-relative寻址特定的东西,例如4个字节必须遵循?

1 个答案:

答案 0 :(得分:3)

  

是否有一些rip-relative寻址特定的东西,例如4个字节必须遵循?

是。如果您查看指令集参考,第2.2.1.6节RIP相对寻址,您将看到唯一的选项是RIP + disp32,意味着32位位移。如果您需要避免零字节,则必须采用不同的方式。可能的解决方法是执行以下操作:

lea -1(%rip), %rax # -1 is needed to avoid zero bytes
movb $5, XX(%rax)  # with appropriate value of `XX`