它为什么不打印?

时间:2017-03-31 09:59:29

标签: c assembly x86 shellcode

简单的asm for ptint字符串" / bin / sh"然后退出

    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 are

nasm -f elf64 test.asm ld -o test test.o

按预期运行。

但在shellcode中使用:

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

它什么都不打印。

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:2)

您的代码假设rdi == 0,1或2,而rdx的56位高位为零。在流程开始时,这恰好是正确的。在你调用shellcode的时候,它是不正确的。

要修复,您需要将rdi设置为1(如果希望输出为标准输出)或2(输出设置为标准错误),并设置rdx 8。

Linux on x86-64上的系统调用ABI是

  • rax

  • 中的系统调用号码 {li>

    charshortintlong以及rdirsi,{{1}中的指针参数分别是},rdxr10r8个寄存器

  • 返回值将在r9;如果发生错误,大多数系统调用都会返回rax

    (实际的-errno变量是一个C库构造,内核对它一无所知)

  • errnorcx被破坏(可能被系统调用修改);保留所有其他寄存器

因此,对于r11write == SYS_write == 1),您设置__NR_write == 1; rax ==描述符编号(rdi == 1表示标准输出,STDOUT_FILENO == 2表示标准错误); STDERR_FILENO ==指向要写入的数据的指针,rsi ==要写入的字符数。