Символ печати кода оболочки (64 бита)

У меня проблема с этим шелл-кодом. Когда я запускаю код ассемблера, он печатает символ, но когда я вызываю его как функцию из c, это не так. Я использовал gdb для проверки всех выполненных инструкций, и он, кажется, выполняет все инструкции. Это очень странно, потому что я отлаживал обе версии asm и c, и они делают то же самое, но в int 0x80 он ничего не печатает для кода C. Это код C:

#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;
}

Это код носа:

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'            

РЕДАКТИРОВАТЬ: я решил проблему. На этой веб-странице: http://www.exploit-db.com/papers/13065/ Я обнаружил, что в 64 битах системные вызовы должны вызываться с использованием системного вызова int 0x80, а регистры аргументов различаются. Затем я нашел эту другую веб-страницу: http://cs.lmu.edu/~ray/notes/linuxsyscalls/. У него есть несколько примеров выполнения этих системных вызовов, думаю, что это хорошая веб-страница.

Но теперь возникает вопрос: почему это работает с кодом Nasm? Это что-то о совместимости? Может быть, код на ассемблере выполнялся в режиме совместимости, потому что ассемблер обнаружил инструкцию int 0x80, а в C компилятор не смог, потому что он не может интерпретировать шелл-код?

Я оставляю здесь рабочий код C:

#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;
} 

1 ответ

Вы, вероятно, создавали файл ELF как 32-битный. Даже если ваша ОС 64-разрядная, а двоичная 32-разрядная, она работает в режиме совместимости.

То же самое происходит в Windows (это называется "Windows-on-Windows-64" или "WOW64").

Другие вопросы по тегам