【问题标题】:What is the stack pointer used for in this shellcode?这个 shellcode 中使用的堆栈指针是什么?
【发布时间】:2021-12-24 21:56:55
【问题描述】:

https://www.exploit-db.com/exploits/46907

global _start
section .text
_start:
    xor rsi,rsi
    push rsi
    mov rdi,0x68732f2f6e69622f
    push rdi
    push rsp
    pop rdi
    push 59
    pop rax
    cdq
    syscall

一条指令是push %rsp,然后将其弹出rdi。我很迷惑。根据文档,execve 系统调用中的rdi 应该包含可执行文件的路径名。这里和rsp 有什么关系?其他 shellcode 不操纵rsp

【问题讨论】:

  • 您正在将该 API 的参数推送到堆栈中。 FILO
  • 在堆栈上构造数据,然后将堆栈指针复制到另一个reg,是完全正常的。许多 shellcode 操纵 RSP。 push rsp / pop rdi 只是 mov rdi, rsp 的 2 字节版本,它是在推送 0 和 8 字节的 ASCII 数据之后出现的。使用调试器单步执行 asm,并在 syscall 执行时查看 RDI 指向的内存,然后向后工作以了解您是如何到达那里的。

标签: assembly x86-64 nasm shellcode


【解决方案1】:

在堆栈上构造数据,然后将堆栈指针复制到另一个reg,是完全正常的。大量的 shellcode 操纵 RSP。

push rsp / pop rdi 只是 mov rdi, rsp 的 2 字节版本,它是在推送 0 和 8 字节的 ASCII 数据之后出现的。 (在 NASM 语法中可以更清楚地写成 mov rdi, '/bin//sh')。

使用调试器单步执行 asm,并在 syscall 执行时查看 RDI 指向的内存,然后向后工作以了解您是如何到达那里的。


奇怪的是,他们使用 push/pop 将 mov rdi,rsp 降低到 2 个字节,但在 xor-zeroing 指令上使用了 REX 前缀。 xor esi,esi 是等价的。 NASM 会将该源优化为xor esi,esi,但您的链接会显示反汇编。

另外,push 59 / pop rax 是寄存器中的standard 3-byte way to construct a small constant (__NR_execve),不依赖于任何其他寄存器值。他们本可以完成lea eax, [rsi+59],这也是3个字节,并且还避免了任何0字节。 (5 字节 mov eax, 59 将包含一个带有三个零字节的 imm32,这就是为什么大多数 shellcode 必须避免它。)

cdq 只是设置 RDX=0 (envp=NULL),因为此时 EAX 为正数。与xor edx,edx 相比,另一种节省字节的代码高尔夫方式。在这种情况下,他们显然知道在编写 32 位 reg (EDX) 时要利用完整 64 位 reg 的隐式归零,所以更奇怪的是,他们对 RSI 使用了 64 位异或归零。也许他们对 x86-64 了解不多,甚至没有意识到 cqo 会明确使用 64 位操作数大小,将 RAX 符号扩展为 RDX:RAX,并打算在任何地方使用 64 位,因为他们认为他们需要这样做。

【讨论】:

  • 我看到谢谢你的详细信息。所以这意味着在压入寄存器时,首先压入最高有效字节,这样 2f (/) 是最后压入堆栈的字节,因此 esp 指向它,这也与字节序一致,因为最低有效字节将位于最低地址(堆栈向较低地址增长)
  • @user2370139:x86 是 little-endian。 qword 存储将最低有效字节放在最低地址。这与堆栈增长的方向无关,这只是一个巧合。 push 更改 RSP 并执行 qword 存储到堆栈内存,就像任何其他存储一样。全部8个字节同时写入;对齐的 qword 存储是 guaranteed to be atomic on x86
  • @Peter Cordes:请注意,如果您汇编例如mov eax, "abcd",那么 NASM 和 MASM 样式的汇编器将在字符串字节的顺序上存在分歧。 NASM 使db "abcd"eax 在我的mov 之后的存储产生相同的数据(61h,然后是 62h,然后是 63h,然后是 64h,little-endian dword 6463_6261h)。 (这也与 cpuid 的叶 0 中的字符串使用的顺序相匹配。)MASM 反转了 mov 的字母顺序,因此“abcd”变成了 6162_6364h;第一个(最左边的)字母用作数字的第一个(最左边,最重要的)8 位。
  • @ecm:对,MASM(和 GAS .intel_syntax)都讨厌方便地使用 ASCII 字符串作为立即数。 (有一个关于 MASM 与 NASM 与 GAS 的规范问答:When using the MOV mnemonic to load/copy a string to a memory register in MASM, are the characters stored in reverse order?)。在关注问题中的链接之前,我假设这是手写的 NASM 源(在这种情况下,我所说的 100% 适用:用简单的方式编写它,因为您使用 NASM 语法编写),但它可能只是自动生成的来自机器码。
猜你喜欢
  • 2010-11-30
  • 2012-02-05
  • 2015-11-16
  • 1970-01-01
  • 2016-11-14
  • 2017-08-18
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
相关资源
最近更新 更多