Сборка execve / bin / bash (x64)

Я новичок в asm и пытаюсь выполнить системный вызов / bin / bash. Однако в настоящее время я сталкиваюсь со следующей проблемой:

Мой код работает для любого вызова execve, длина 1-го аргумента которого меньше 8 байтов, то есть «/ bin / sh» или «/ bin / ls»:

.section .data

    name: .string "/bin/sh"

.section .text

.globl _start

_start:
    #third argument of execve, set to NULL
    xor %rdx, %rdx 

    #push nullbyte to the stack
    pushq %rdx 

    #push /bin/sh to the stack
    pushq name 

    #copy stack to rdi, 1st arg of execve
    mov %rsp, %rdi 

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 

    #3rd arg of execve set to NULL
    movq $0, %rsi 

    syscall

Меня озадачивает то, что я не могу заставить его работать с

name: .string "/bin/bash"

Я попытался разбить строку на части, чтобы нажать q "/ bash", затем "/ bin" в стек, похоже, ничто не позволяет мне заставить его работать, и я каждый раз получаю сообщение об ошибке "Недопустимая инструкция". Что я делаю неправильно?

Нерабочий код:

.section .data

    name: .string "/bin/bash"

.section .text

.globl _start

_start:
    #third argument of execve, set to NULL
    xor %rdx, %rdx 

    #push nullbyte to the stack
    pushq %rdx 

    #push /bin/sh to the stack
    pushq name 

    #copy stack to rdi, 1st arg of execve
    mov %rsp, %rdi 

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 

    #3rd arg of execve set to NULL
    movq $0, %rsi 

    syscall

Другой нерабочий код:

.section .data

.section .text

.globl _start

_start:
    #third argument of execve, set to NULL
    xor %rdx, %rdx 

    #push nullbyte to the stack
    pushq %rdx 

    #push /bin/bash to the stack
    pushq $0x68
    pushq $0x7361622f
    pushq $0x6e69622f

    #copy stack to rdi, 1st arg of execve
    mov %rsp, %rdi 

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 

    #3rd arg of execve set to NULL
    movq $0, %rsi 

    syscall

person Goujon    schedule 20.12.2017    source источник
comment
Вы забыли показать нерабочий код. Также вы забыли использовать отладчик. Возможно, вы забыли, что стек работает наоборот. И вы, наверное, забыли, что push всегда записывает 8 байтов. Таким образом, вы должны разделить вашу строку на 8-байтовые части, за исключением последней части (которую вы нажимаете первой).   -  person Jester    schedule 20.12.2017
comment
Очевидно, что если у вас есть строка в .data, нет необходимости копировать ее в стек. Вы можете просто использовать его адрес напрямую и покончить с этим.   -  person Jester    schedule 20.12.2017
comment
Вы смотрели соглашение о вызовах X86_64 ABI для функций? Это может помочь вам понять, где дела идут не так.   -  person David Hoelzer    schedule 20.12.2017
comment
@Jester Спасибо за помощь. Я действительно учел тот факт, что стек работает в обратном направлении, и соответственно упорядочил нажатия, ошибка осталась прежней.   -  person Goujon    schedule 20.12.2017
comment
@MichaelPetch Спасибо за предложение. Это работает для / bin / sh, как упоминалось в моем вопросе. У меня проблемы с вызовом / bin / bash, даже если я разделю строку (см. Редактирование). / bin / bash будет 0x687361622f6e69622f и не может поместиться в 64-битный регистр.   -  person Goujon    schedule 20.12.2017


Ответы (1)


Вы, кажется, полностью запутались, слишком сильно, чтобы перечислить все ошибки. Тем не менее, вот неполный список:

  1. вы устанавливаете esi в ноль, что означает argv это NULL
  2. push nullbyte to the stack на самом деле NULL указатель для завершения массива argv (это не нулевой байт, завершающий строку).
  3. Вам нужно указать адрес имени файла как argv[0]. Копировать строку в стек не нужно.

Вот фиксированная версия:

.section .data

    name: .string "/bin/bash"

.section .text

.globl _start

_start:
    # third argument of execve is envp, set to NULL
    xor %rdx, %rdx 

    # push NULL to the stack, argv terminator
    pushq %rdx 

    # first argument to execve is the file name
    leaq name, %rdi

    # also argv[0]
    push %rdi

    # second argument to execve is argv
    mov %rsp, %rsi

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 
    syscall

И версия, которая создает строку в стеке из кода без нулевых байтов:

.section .text

.globl _start

_start:
    # third argument of execve is envp, set to NULL
    xor %rdx, %rdx 

    # zero terminator
    push %rdx

    # space for string
    sub $16, %rsp

    # end is aligned to the zero terminator
    movb $0x2f, 7(%rsp)        # /
    movl $0x2f6e6962, 8(%rsp)  # bin/
    movl $0x68736162, 12(%rsp) # bash

    # first argument to execve is the file name
    leaq 7(%rsp), %rdi

    # push NULL to the stack, argv terminator
    pushq %rdx 

    # also argv[0]
    push %rdi

    # second argument to execve is argv
    mov %rsp, %rsi

    # copy 59 to rax, defining syscall number for execve
    # avoid zero byte
    xor %eax, %eax
    movb $59, %al 
    syscall
person Jester    schedule 20.12.2017
comment
Вы правы, я запутался, как указано в моем вопросе, я совершенно новичок в ASM :). В любом случае большое спасибо за вашу помощь и исправление моих ошибок, теперь он работает. Еще один вопрос, если я хочу избежать раздела .data, как мне действовать? - person Goujon; 20.12.2017
comment
@Goujon: вам нужно будет поместить строку в стек - person Michael Petch; 20.12.2017
comment
@Jester, поскольку он предназначен для кода оболочки, я бы не рекомендовал movq $59, %rax, поскольку он вводит байт 0x00. Может быть, предпочтительнее xor %eax, %eax mov $59, %al? - person Michael Petch; 20.12.2017
comment
@MichaelPetch Что-то вроде push $ 0x68 - push $ 0x7361622f - push $ 0x6e69622f - mov% rsp,% rdi - я предполагаю, но это не работает (потому что я ошибаюсь :)) - person Goujon; 20.12.2017
comment
Да, но помните, 8 байтов за раз! К сожалению, push не принимает сразу 8 байтов, поэтому пройдите регистр. - person Jester; 20.12.2017
comment
Нет, не 32-битные значения за раз. 32-битные значения помещаются в стек с расширенным нулем. Это приводит к размещению дополнительных нулей в стеке, поэтому это не удается. - person Michael Petch; 20.12.2017
comment
Вот почему я рекомендовал использовать movabsq в регистре и протолкнуть полный 64-битный регистр. Просто так случилось, что то, что я опубликовал в качестве комментария, было не для той строки. Если вы выполняете код оболочки, вам придется избегать включения любых байтов 0x00 в поток, поэтому построение строки в стеке немного сложнее для последнего байта и NUL. Я почти уверен, что вы в конечном итоге закодируете это как эксплойт оболочки, чтобы попытаться избежать 0x00 в потоке байтов из закодированных инструкций. - person Michael Petch; 20.12.2017
comment
Этот ответ выглядит лучше, теперь я могу проголосовать за него. Поскольку он не спрашивал о проблеме введения 0x00 в поток байтов для эксплойта оболочки, в этом случае объяснения не нужны. - person Michael Petch; 20.12.2017
comment
@Jester Большое спасибо, действительно хороший ответ. Большое спасибо за то, что нашли время предоставить рабочий код. Я вижу, что мне нужно многому научиться в asm ... Я внимательно прочитаю ваш код и попытаюсь в качестве упражнения добавить параметры к вызову / bin / bash (например, -p). - person Goujon; 20.12.2017
comment
@MichaelPetch Я действительно решил запустить asm для создания шелл-кода. Я действительно ценю усилия по предоставлению решения без нулевых байтов. Если честно, сейчас я просто хочу разобраться в asm и уметь создавать хороший код, удаление нулевого байта будет вторым шагом :) - person Goujon; 20.12.2017
comment
Что, если я хочу передать параметр? - person K.Sopheak; 09.07.2019