如何在x86_64 Linux环境的Shellcode中获取数据绝对地址?
x86_64 Linux Shellcode获取字符串绝对地址解决方案
我的Shellcode如下:
xor rax, rax xor rdi, rdi xor rsi, rsi xor rdx, rdx ; 获取`pathname`的地址 mov rdi, [something] mov al, 59 mov rdi, rsp syscall xor rax,rax mov al, 60 xor rdi, rdi syscall _pathname: db "/usr/bin/shutdown",0
这只是简单的execve调用和退出操作。问题在于我无法获取访问pathname所需的绝对地址。我找到的“解决方案”是编写类似这样的代码:
call _end _start: pop rdi ; _start的绝对地址 ; 然后加上偏移量得到_end的地址 _end: call start db "/usr/bin/shutdown", 0
这对我来说毫无逻辑,而且也不生效。我还尝试过使用FPU指令,据说该方法可行,但同样没有效果。
操作系统:Linux
架构:amd64
可行解决方案:利用call指令特性直接获取地址
在x86_64架构中,call指令会把下一条指令的地址压入栈中,我们可以利用这个特性直接拿到字符串的绝对地址,无需手动计算偏移。
正确实现代码
global _start _start: ; 调用get_str_addr,此时栈中会压入字符串的起始地址 call get_str_addr ; 字符串数据,必须紧跟在call指令之后 db "/usr/bin/shutdown", 0 get_str_addr: ; 弹出栈顶的字符串地址到rdi,正好作为execve的第一个参数 pop rdi ; 设置execve系统调用参数 xor rax, rax mov al, 59 ; execve的系统调用号 xor rsi, rsi ; argv = NULL xor rdx, rdx ; envp = NULL syscall ; 退出系统调用 xor rax, rax mov al, 60 xor rdi, rdi syscall
代码逻辑说明
call get_str_addr:执行这条指令时,CPU会把call之后的下一个地址(也就是字符串/usr/bin/shutdown的起始地址)压入栈,然后跳转到get_str_addr标签。pop rdi:直接把栈顶的字符串地址弹出到rdi寄存器,此时rdi就持有目标路径的绝对地址,完全满足execve对第一个参数的要求。- 后续设置
execve的系统调用号、清空rsi和rdx(对应argv和envp为NULL),调用syscall即可执行目标程序。
你之前代码失效的原因
你之前的代码存在标签命名混乱(start和_start不统一)、偏移计算逻辑错误的问题,导致无法正确定位字符串地址。上面的写法直接利用call指令的栈操作特性,逻辑简洁且可靠性高。
内容的提问来源于stack exchange,提问作者R-Rothrock
相关产品推荐
相关产品推荐

