这个 shellcode 中的栈指针有什么用?
What is the stack pointer used for in this shellcode?
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
.
在栈上构造数据,然后将栈指针复制到另一个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 个字节,但在异或归零指令中使用了 REX 前缀。 xor esi,esi
是等价的。 NASM 会将源优化为 xor esi,esi
,但您的 link 显示反汇编。
此外,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 -到处都是,因为他们认为他们需要。
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
.
在栈上构造数据,然后将栈指针复制到另一个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 个字节,但在异或归零指令中使用了 REX 前缀。 xor esi,esi
是等价的。 NASM 会将源优化为 xor esi,esi
,但您的 link 显示反汇编。
此外,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 -到处都是,因为他们认为他们需要。