x86-64汇编Shellcode开发:系统调用栈指针及寄存器恢复问题
Great question—let’s break this down so you can see exactly what’s happening with your shellcode.
First, let’s clarify the core point about system calls and the stack pointer (rsp):
- The
syscallinstruction itself does not modifyrspfrom a user-space perspective. When you trigger a system call, the kernel switches to its own kernel stack to handle the request, but when it returns to user-space, your originalrspis restored exactly as it was before thesyscallinstruction ran. So ifexecvefails and returns to your code, your stack pointer is still pointing to the right place for yourpopinstructions.
The problem you’re hitting comes down to how execve works when it succeeds:
execvereplaces the entire address space of the current process with the new program you’re executing. That includes your original stack—all the registers you pushed onto the stack (rdi, rsi, rdx, rcx) get overwritten or discarded entirely when the new program loads its own stack.
In other words:
- If
execveruns successfully, your shellcode’s code (including thepopinstructions you wrote to restore registers) is no longer in memory. The new program’s code starts executing instead, so thosepops never run at all. - Only if
execvefails (e.g., invalid path, permission issues) will it return to your shellcode. In that case,rspis still where you left it, and you can safely execute yourpop rcx; pop rdx; pop rsi; pop rdisequence to restore the original register values (including yourrdi=123test value).
Quick Recommendation for Your Shellcode
If your shellcode’s goal is just to execute the new program and exit, you don’t need to worry about restoring registers at all—since the successful execve will replace your code anyway. If you want to handle errors (e.g., retry if execve fails), make sure your error-handling path comes after the syscall and uses the intact stack to restore registers before trying again.
内容的提问来源于stack exchange,提问作者Topper Harley

