l.somnus
l.somnus

Reputation: 1

Why it didn't print?

simple asm for ptint the string "/bin/sh" and then exit

    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

Run as expected .

but use in 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

it prints nothing.


enter image description here

enter image description here

Upvotes: 0

Views: 107

Answers (1)

Nominal Animal
Nominal Animal

Reputation: 39306

Your code assumes rdi == 0, 1, or 2, and that 56 high bits of rdx are zero. This happens to be true at the start of the process. It just isn't true at the point where you call your shellcode.

To fix, you need to set rdi to 1 (if you want the output to be to standard output) or 2 (for output to go to standard error), and set rdx 8.


The syscall ABI in Linux on x86-64 is

  • syscall number in rax

  • char, short, int, long, and pointer parameters in rdi, rsi, rdx, r10, r8, and r9 registers, respectively

  • return value will be in rax; most syscalls return -errno if an error occurs

    (the actual errno variable is a C library construct, and the kernel does not know anything about it)

  • rcx and r11 are clobbered (may be modified by the syscall); all other registers are preserved

Thus, for write (SYS_write == __NR_write == 1) you set rax == 1; rdi == descriptor number (STDOUT_FILENO == 1 for standard output, STDERR_FILENO == 2 for standard error); rsi == pointer to the data to be written, and rdx == the number of chars to be written.

Upvotes: 2

Related Questions