用于品脱字符串"/bin/sh“的简单asm,然后退出
global _start:
_start:
jmp what
are:
mov rbx,0x68732f6e69622fff
shr rbx,0x8
push rbx
mov rsi,rsp
mov dl,0x8
xor rax,rax
mov al,1
syscall
xor rax,rax
mov al,0x3c
syscall
what:
call arenasm -f elf64 test.asm ld -o test test.o
按预期运行。
但在外壳代码中使用:
const char shellcode[] = "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe6\xb2\x08\x48\x31\xc0\xb0\x01\x0f\x05\x48\x31\xc0\xb0\x3c\x0f\x05";
int main(){
( (void (*)(void))&shellcode )();
return 0;
}gcc -fno-stack-protector -z execstack -o test2 test.c
它什么也不印。


发布于 2017-03-31 10:20:40
您的代码假定rdi == 0、1或2,而56位高rdx为零。在这个过程开始的时候,这恰好是真的。在你调用外壳代码的时候,这不是真的。
要修复,需要将rdi设置为1(如果要将输出设置为标准输出)或2(如果要将输出设置为标准错误),并设置rdx 8。
x86-64上的Linux中的syscall ABI是
rax中的syscall数char、short、int、long和rdi、rsi、rdx、r10、r8和r9寄存器中的指针参数rax中;如果发生错误,大多数syscalls返回-errno。
(实际的errno变量是一个C库结构,内核对它一无所知)rcx和r11被关闭(可能被syscall修改);所有其他寄存器都被保存因此,对于write (SYS_write == __NR_write == 1),可以设置rax == 1;rdi ==描述符号(标准输出的STDOUT_FILENO == 1,标准错误的STDERR_FILENO == 2);要写入的数据的rsi ==指针,以及要写入的字符数。
https://stackoverflow.com/questions/43137865
复制相似问题