Различные способы запуска системного вызова в коде на ассемблере без записи int 0x80

#assembly #x86 #shellcode

#сборка #x86 #шеллкод

Вопрос:

Это пример запуска системного вызова sys_execve без int 0x80 в коде ассемблера, таким образом, моя цель — установить адрес регистра указателя стека (ESP) в регистре EIP. Предполагается, что 0x80cd (int 0x80 = 0xcd80 , но нам нужно это в конце строки) находится в верхней части стека.

Состояние регистра перед кодом:

 *EAX  0xb
 EBX  0xffffd144 ◂— '/bin//sh'
 ECX  0xffffd13c —▸ 0xffffd144 ◂— '/bin//sh'
 EDX  0xffffd140 ◂— 0x0
 EDI  0x0
 ESI  0x0
 EBP  0x0
 ESP  0xffffd138 ◂— 0x80cd
*EIP  0x8049022 (_start 34) ◂— call   esp
 

На данный момент у меня есть следующее (очевидно, я знаю, что возможны варианты этих фрагментов кода с разными регистрами, но с использованием одних и тех же инструкций):

1-

 push esp
ret
 

2-

 lea edi, [esp]
jmp edi
 

3-

 call esp
 

Я хотел бы узнать больше фрагментов кода для этого.

Комментарии:

1. lea edi, [esp] просто mov edi, esp … считается ли это другим способом? Вы также можете jmp esp .

2. Я хотел бы найти несколько способов без использования этих инструкций… (jmp, lea, mov и call)

3. Вы ret уже получили версию. Вы могли бы сделать что-то подобное с iret тоже. Разрешено ли самоизменение?

4. Нет, iret в этом случае не работает, но если я заполняю другие регистры, такие как cs, он должен работать (я использовал iret для возврата из области ядра в область пользователя). В любом случае я хотел бы найти инструкцию с кодом операции <80, ret и iret равны CX. спасибо.

5. Укажите ваши фактические ограничения в вопросе. Существует почти неограниченное количество способов int 0x80 получить где-нибудь в памяти, к которым вы в конечном итоге переходите. Если вы не скажете, что делает один вариант интересным, а другой — нет, ответить довольно сложно. Также укажите что-нибудь еще, что вы знаете, например, указывает ли какой-либо регистр на известное местоположение относительно выполняемого в данный момент шелл-кода. (Это единственный способ избежать косвенного jmp, вызова или ret или подобного, предполагая, что вы не можете самостоятельно изменить IDT, прежде чем вызывать прерывание. (Вы не можете использовать пространство пользователя в операционной системе).)