我有一个x64处理器,我正在研究shellcode 我有以下代码:
section .text
global _start
_start:
push rax
mov rbx, 0x68732f6e69622f2f
shr rbx, 0x8
push rbx
mov rdi, rsp
;mov rdi, com
mov al, 59
syscall
使用foolowing命令编译时:
nasm -g -f elf64 execve.asm
并与:
相关联ld execve.o -o execve
运行正常。它打开一个shell。如果我从中获取shellcode:
"\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
并使用此C程序:
int main(void)
{
const char shellcode[] = "\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05";
(*(void (*)()) shellcode)();
return 0;
} 编译它:
gcc -fno-stack-protector -z execstack -o ex2 ex.c
如果运行它会返回分段错误,但它应该执行shell。为什么? 感谢帮助!
答案 0 :(得分:3)
您的独立程序集依赖于注册rsi
和rdx
被归零。
(正如您在http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/中看到的那样
sys_execve
通过寄存器rdi
,rsi
和rdx
获取三个参数,如果rdi
是正确的文件名且rsi
,Linux也会接受它}和rdx
为零)。
程序启动时可能就是这种情况,但是当你从程序中运行指令时却不是这样 中间的一个程序。
因此,如果rsi
和rdx
中包含垃圾,则系统调用将失败并且指令流
将继续执行它在syscall指令之后找到的垃圾字节,最终导致崩溃(这确实是你的情况下发生的事情,因为你可以看到你是否通过{{1运行程序}})
使系统调用成功的最简单方法是将第二个和第三个参数清零:
gdb
对应的C代码:
section .text
global _start
_start:
xor rax, rax
xor rsi, rsi ; zero 2nd argument
xor rdx, rdx ; zero 3rd argument
push rax
mov rbx, 0x68732f6e69622f2f
shr rbx, 0x8
push rbx
mov rdi, rsp
mov al, 59
syscall
答案 1 :(得分:0)
您遗漏了\x6e
。
这会导致segv,因为exec失败并且在系统调用之后没有返回。