tuket
tuket

Reputation: 3941

Shell code print character(64bits)

I have a problem with this shell code. When I run the assembler code it prints the caracter, but when I call it as a function from c it does not. I used gdb to test all the instruction executed and it seems to execute all the instructions. It is very weird because I debugged both asm and c versions and they do the same but in the int 0x80 it prints nothing for the C code. This is the C code:

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>

int (*sc)();
/****************************************************************
    0000000000000000 <main>:                                      /
       0:   48 31 c9                xor    %rcx,%rcx              /
       3:   48 31 c0                xor    %rax,%rax              /
       6:   eb 13                   jmp    1b <n>                 /
                                                                  /
    0000000000000008 <et>:                                        /
       8:   59                      pop    %rcx                   /
       9:   48 31 c0                xor    %rax,%rax              /
       c:   48 31 db                xor    %rbx,%rbx              /
       f:   48 31 d2                xor    %rdx,%rdx              /
      12:   b0 04                   mov    $0x4,%al               /
      14:   b3 01                   mov    $0x1,%bl               /
      16:   b2 01                   mov    $0x1,%dl               /
      18:   cd 80                   int    $0x80                  / 
      1a:   c3                      retq                          /
                                                                  /
    000000000000001b <n>:                                         /
      1b:   e8 e8 ff ff ff          callq  8 <et>                 /
                                                                  /
    0000000000000020 <abc>:                                       /
      20:   77                      .byte 0x77                    /
        ...                                                       /
******************************************************************/



char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw";
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw";

int main(int argc, char **argv) {

    char *ptr = mmap(0, sizeof(shellcode),
            PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON
            | MAP_PRIVATE, -1, 0);

    if (ptr == MAP_FAILED) {
        perror("mmap");
        exit(-1);
    }

    memcpy(ptr, shellcode, sizeof(shellcode));
    sc = ptr;

    (void)((void(*)())ptr)();
    printf("\n");

    return 0;
}

This is the nasm code:

global main

main:                           ; main

xor rcx, rcx            ; eficient way turning register to 0
xor rax, rax            ; exclusive or

jmp n            
et: 
pop rcx

xor rax, rax
xor rbx, rbx
xor rdx, rdx
mov al, 4                      ; Number of system call (write)
mov bl, 1                      ; argument(1=stdout)
mov dl, 1                      ; number of characters
int 0x80

ret

n:
call et
abc:    db 'w'            

EDIT: I have solved the problem. In this webpage: http://www.exploit-db.com/papers/13065/ I found that in 64 bits the systemcalls must be called using syscall insted of int 0x80 and the registers of the arguments are different. Then I found this other web page: http://cs.lmu.edu/~ray/notes/linuxsyscalls/. It have some examples about doing these systemcalls, think it is a good webpage.

But the question now is, why did it work with the Nasm code? Is it something about compatibility? May be the assembler code was running in compatibility mode because the assembler detected the int 0x80 instruction and in C the compiler couldn't because it cannot interpret the shellcode?

I leave here the working C code:

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>

int (*sc)();
/****************************************************************
    0000000000000000 <main>:                                    /
       0:   48 31 c9                xor    %rcx,%rcx            /
       3:   48 31 c0                xor    %rax,%rax            /
       6:   eb 16                   jmp    1e <n>               /
                                                                /
    0000000000000008 <et>:                                      /
       8:   5e                      pop    %rsi                 /
       9:   48 31 c0                xor    %rax,%rax            /
       c:   48 31 db                xor    %rbx,%rbx            /
       f:   48 31 d2                xor    %rdx,%rdx            /
      12:   b0 01                   mov    $0x1,%al             /
      14:   b3 01                   mov    $0x1,%bl             /
      16:   48 89 df                mov    %rbx,%rdi            /
      19:   b2 01                   mov    $0x1,%dl             /
      1b:   0f 05                   syscall                     /
      1d:   c3                      retq                        /
                                                                /
    000000000000001e <n>:                                       /
      1e:   e8 e5 ff ff ff          callq  8 <et>               /
                                                                /
    0000000000000023 <abc>:                                     /
      23:   77                      .byte 0x77                  /
                                                                /
****************************************************************/


char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x16\x5e\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x01\xb3\x01\x48\x89\xdf\xb2\x01\x0f\x05\xc3\xe8\xe5\xff\xff\xffw";
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw";
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw";

int main(int argc, char **argv) {

    char *ptr = mmap(0, sizeof(shellcode),
            PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON
            | MAP_PRIVATE, -1, 0);

    if (ptr == MAP_FAILED) {
        perror("mmap");
        exit(-1);
    }

    memcpy(ptr, shellcode, sizeof(shellcode));
    sc = ptr;

    (void)((void(*)())ptr)();
    printf("\n");

    return 0;
} 

Upvotes: 0

Views: 1350

Answers (1)

MarioVilas
MarioVilas

Reputation: 904

You were probably building the ELF file as a 32 bit one. Even if your OS is 64 bits, if the binary is 32 then it runs in compatibility mode.

Same thing happens on Windows (it's called "Windows-on-Windows-64" or "WOW64").

Upvotes: 1

Related Questions