> 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-38.md).

# Часть 38

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

**CANARY** и **SEH**.

Мы уже видели, что такое переменная **CANARY**. Это случайное значение, которое помещается в стек непосредственно перед сохраненным регистром **EBP** и адресом возврата. Так что, если это значение перезаписывается, программа проверяет это значение(Это необходимо нам для перезаписи адреса возврата). Если это значение тоже самое, то оно сохраняется, а если оно неправильное, то программа закрывается, избегая исполнение кода.

Приложенный файл - это файл **CANARY\_SIN\_DEP.EXE**. Позже, в следующей части, мы увидим случай, когда у программы включена защита **DEP** и мы должны сделать **ROP**, чтобы обойти переменную **CANARY**.

Код в программе такой же, как и в файле **NO**\_**DEP**. Только в этом случае, компилятор добавляет защищенную переменную **CANARY**, которая предотвращает эксплуатацию и перезапись **АДРЕСАВОЗВРАТА**.

Давайте будем трассировать программу, запустив тот же самый скрипт, который мы сделали для файла **NO**\_**DEP**, чтобы увидеть почему **ROP** сейчас не работает и, затем, попытаемся обойти защиту.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwjAJSPTX207omHP%2F01.png?generation=1563265877225612\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwjSREmewiEu_jdQ%2F02.png?generation=1563265865721349\&alt=media)

Я изменяю имя исполняемого файла в скрипте, для того, чтобы загрузить файл **CANARY\_SIN\_DEP.EXE**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwjoAAvFeJbMwPoN%2F03.png?generation=1563265877206880\&alt=media)

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0sApvJ0XyyQK_BV%2F38-04.png?generation=1563221050678614\&alt=media)

Мы видим, что программа считывает случайное значение **\_SECURITY\_COOKIE**, которое сохраняется в секцию данных, помещает его в регистр **EAX** и **XOR**ит его с помощью значения регистра **EBP**, чтобы сделать его более уникальным. Это значение будет **EBP** этой функции и если исполняемый файл будет рандомизирован, значение регистра **EBP** также не будет постоянным.

Программа сохраняет это значение в переменную **CANARY**. Если есть переполнение, которое пытается перезаписать адрес возврата, это значение будет изменено. Также, никто не может знать какое случайное значение будет там, чтобы перезаписать его с тем же значением.

Когда программа покинет функцию, значение снова будет восстанавливается, **XOR**ится с тем же значением регистра **EBP**, чтобы получить исходное значение **\_SECURITY\_COOKIE** и внутри **CALL**, программа будет сравнивать это значение и если значение не будет равно, программа будет выдавать ошибку или будет закрыта, в зависимости от случая.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwk_rOdsYsC-07i6%2F05.png?generation=1563265875178382\&alt=media)

Давайте поместим здесь **BP**, чтобы остановить программу и присоединиться к ней.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0sO5gnXkGRDTNcN%2F38-06.png?generation=1563221053539699\&alt=media)

Поскольку мы уже вернулись из функции **GETS\_S**, переменная **CANARY** уже была перезаписана и имеет значение **0x41414141**.

**CANARY = \_SECURITY\_COOKIE XOR EBP**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0sVqgumtIiSTJF2%2F38-07.png?generation=1563221055642913\&alt=media)

**CANARY = 0x988A1605 XOR 0x012FFB60**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0sXuIv8aU1MWVLy%2F38-08.png?generation=1563221069065931\&alt=media)

Мы можем проверить, что если мы запустим программу несколько раз, это значение **CANARY** будет меняться каждый раз. Поэтому, мы не можем предсказать значение, чтобы перезаписать его тем же самым.

Давайте продолжим трассировку.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwliSG2s-TiE_nrb%2F09.png?generation=1563265877172166\&alt=media)

Программа **XOR**ит значение **0x41414141** с помощью значения регистра **EBP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0saVPUVJ0OOPmQj%2F38-10.png?generation=1563221057121617\&alt=media)

Затем программа входит в **CALL**, чтобы проверить значение.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0scRyYK_85LtI1C%2F38-11.png?generation=1563221069034398\&alt=media)

Программа сравнивает это значение с сохраненным значением\_**SECURITY**\_**COOKIE** и поскольку они не равны, программа переходит на метку **FAILURE**. Если эти значения равны, программа переходит на инструкцию **RET** и продолжает выполнение до **АДРЕСА ВОЗВРАТА** так как значение не перезаписано.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwmR6-eqhlRvrIdh%2F12.png?generation=1563265878082922\&alt=media)

Очевидно, мы должны идти на красной блок, потому что мы переполнили значение. Давайте продолжим трассировку.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0sg6aILZZRLImlZ%2F38-13.png?generation=1563221058227465\&alt=media)

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwn3Y11wM_Nl7Hb_%2F14.png?generation=1563265878301037\&alt=media)

Поэтому вопрос заключается в следующем - Как обойти всю эту защиту? Пeрвая вешь, которая была использована и которая используется с некоторыми ограничениями и которая все ещё работает - это **SEH**.

Про неё можно прочитать здесь на испанском.

<https://msdn.microsoft.com/es-ar/library/swezty51.aspx>

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0sniEWUbQwMPyFU%2F38-15.png?generation=1563221055522074\&alt=media)

Те, у кого есть опыт в программирование, знают, что существуют структуры **TRY-EXCEPT** или **TRY – CATCH**, где код исполняется внутри ветки **TRY** и если он провоцирует какое-либо исключение, программа переходит на ветку **EXCEPT**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0sqvcIpJQkQ0rH8%2F38-16.png?generation=1563221054936479\&alt=media)

Мы видим, что существуют структуры называемые \_**EXCEPTION**\_**REGISTRATION**\_**RECORD**, которые имеют структуру внутри себя с двумя полями: **NEXT**, которое как мы видим является указателем на другое поле \_**EXCEPTION**\_**REGISTRATION**\_**RECORD** и поле **HANDLER**, которое является типом **PEXCEPTION ROUTINE**.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwnez4M1Xyz_anPB%2F17.png?generation=1563265868106143\&alt=media)

В синим облаке, мы видим простой связанный список, который находится в стеке. Каждое поле **NEXT** указывает на следующую структуру и каждое поле имеет **ОБРАБОТЧИК** или **SEH**, который указывает куда будет переходить программа. Давайте посмотрим на пример **CANARY\_SIN\_DEP.EXE**. Мы присоединимся к нему снова.

Если мы пойдем в **DEBUGGER WINDOWS → SEH LIST**, то сможем увидеть **SEH** каждой структуры в стеке. К сожалению список не показывает адрес стека где он находится, но вы можете легко создать связанный список.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwnpK3n-45pM985E%2F18.png?generation=1563265872040180\&alt=media)

Давайте посмотрим на первую ссылку.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwo0RJ3p3u_8ckeL%2F19.png?generation=1563265867859921\&alt=media)

Если я нажму на клавишу **X**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwoLCiIjcz3nFlkW%2F20.png?generation=1563265876908832\&alt=media)

Я вижу ссылку на стек. Если **IDA** не отображает ссылку, потому что стек не является секцией кода, она может быть найдена с помощью поиска непосредственного значения, нужно искать в памяти адрес **SEH** и искать где он находится в стеке.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0tAQTQeuU76eDYK%2F38-21.png?generation=1563221058028349\&alt=media)

Мы видим, что поле **NEXT** указывает на следующую структуру. В моём случае она находится по адресу **0x93FF7C**. Давайте перейдем туда.

Поэтому, весь список просто связан с каждым полем **NEXT**, которое указывает на следующую структуру.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwp70gj3tTHljZBA%2F22.png?generation=1563265866620335\&alt=media)

Когда поле **NEXT** равно **-1**, то это последняя структура, но **IDA** показывает мне ещё один указатель. Будет ли ещё одна структура?

Если мы вернемся к первой структуре, мы увидим, что поле **NEXT** имеет ссылку на стек.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0tJgQurN4wwFWZ8%2F38-23.png?generation=1563221058982532\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwpe8a9epkFeKH1g%2F24.png?generation=1563265868349014\&alt=media)

Здесь у нас есть три структуры. Поскольку я должен заполнить стек, чтобы спровоцировать исключение, когда я не могу продолжать писать, потому что секция стека уже закончилась, я буду изменять наш скрипт и запускать его, чтобы он сломал весь стек.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0tPyTb8PnIgzV-f%2F38-25.png?generation=1563221054872265\&alt=media)

Мы снова запускам скрипт.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0tRDGseLjx8TmO4%2F38-26.png?generation=1563221056975608\&alt=media)

Мы видим конец стека и программа пытается писать дальше за его пределы

Программа перестает работать здесь. Регистр **ESI** указывает, в моем случае, на адрес **0x940000**, где уже нет стека.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0tWJdnmCuXva1y2%2F38-27.png?generation=1563221057007314\&alt=media)

Давайте посмотрим список **SEH**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0t_EjwrMgL55Udk%2F38-28.png?generation=1563221053730794\&alt=media)

Мы видим, что программа перезаписывает **SEH**. Поэтому если я продолжу исполнение, программа может перейти по адресу **0x41414141**, но очевидно это имеет некоторые ограничения. Мы должны найти модуль для перехода у которого нет **ASLR** для того, что бы адреса не менялись. Кроме того, программа может перейти только в модуль, который имеет **SAFE SEH OFF**, что является опцией компилятора.(так как в этом случае у нас не будет **DEP**. Мы также может перейти в область **КУЧИ**, которую мы заполнили нашими данными и с предсказуемым адресом, потому что поскольку нет **DEP**, мы могли бы запустить код прямо там, но это не тот случай. Данные поступают непосредственно в стек и вы не можите напрямую перейти из **SEH** в стек)

Если мы посмотрим список модулей в **IDASPLOITER**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwqfshEyzeP9cfq6%2F29.png?generation=1563265878519022\&alt=media)

Хорошо. Здесь есть модуль без **ASLR** и **SAFE SEH OFF**. Это модуль **MYPEPE**. Поэтому нам придется перейти в него.

Давайте найдем позицию **SEH** в стеке.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0te2qDNJfge6Gaj%2F38-30.png?generation=1563221053371048\&alt=media)

Если я нажму здесь правую кнопку и затем выберу пункт **CREATE FUNCTION**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0thRGspgcy6wmff%2F38-31.png?generation=1563221052395621\&alt=media)

Давайте посмотрим, если ли у неё ссылки на стек.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwrM57w_Oq4Db_E4%2F32.png?generation=1563265867543855\&alt=media)

Если я не вижу ссылки, то я нахожу их через **SEARCH → INMEDIATE VALUE**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwraGGpxzrx6RGOH%2F33.png?generation=1563265875131623\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0tpNnf1vYwERkhN%2F38-34.png?generation=1563221056355233\&alt=media)

В стеке есть два места, которые используют их. Давайте посмотрим на них.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0tsZnE3tpYaDIAl%2F38-35.png?generation=1563221052802614\&alt=media)

Это связано с тем, что поле **NEXT** указывает на перезаписанную структуру.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwsZ1_szf3Z1cWjk%2F58.png?generation=1563265879766317\&alt=media)

Вот она. Сейчас, мы должны рассчитать расстояние от начала буфер до этого поля **NEXT**. В моём случае это равно **0x93F90F**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwsndT443RpggOe8%2F36.png?generation=1563265877089679\&alt=media)

Я вижу, что регистр **EDI** указывает на начало буфера. Поэтому я пойду туда и нажму сочетание клавиш **ALT + L**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0u8TxeTHGDPrfdr%2F38-37.png?generation=1563221055756815\&alt=media)

Это позволяет включить режим выделения. Если я пойду вниз с зажатой клавишей **SHIFT** программа будет делать выделение. Но поскольку нужный адрес находится очень далеко, я нажимаю клавишу **G** и ввожу конечный адрес **0x93F90F**. Если перед нажатием кнопки я продолжаю удерживать **SHIFT** центр остается выбранным.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwt9mkvquVZo-mNT%2F38.png?generation=1563265867481671\&alt=media)

Если я пойду в меню **EDIT → ARRAY**, **IDA** скажет мне, что длина выбранной области равна **844** байт в десятичной системе.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwtJzAUP-SG-8W3O%2F39.png?generation=1563265869727308\&alt=media)

Хорошо. Поэтому, чтобы перезаписать **SEH** мы должны переслать что-то вроде этого:

> **FRUTA = 844 \* "A" + NEXT + SEH + 6000 \* "B"**

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uJ_pxG-xBI58gQ%2F38-40.png?generation=1563221056194308\&alt=media)

Мы посмотрим, были ли наши подсчеты верны и мы перезаписываем **SEH** с помощью адреса **0x46474849**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwtgaFsk2bBKfJNZ%2F41.png?generation=1563265877327515\&alt=media)

Я вижу, что программа аварийно завершает работу, потому что стек заканчивается. Сейчас **SEH** перезаписан моим значением. Это означает, что расчет был верным

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uNmHmhAIQVf4cm%2F38-42.png?generation=1563221059728763\&alt=media)

Даже если я продолжу выполнение, я увижу, что регистр **EIP** по-прежнему указывает на адрес **0x46474849** как я этого хочу.

Куда сейчас мы можем перейти? Давайте посмотрим.

Адрес возврата остается в стеке по умолчанию, а затем, во втором месте этой структуры (третья часть стека), у нас есть **ESTABLISHERFRAME**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uP3KPxJNQoBuCa%2F38-43.png?generation=1563221055262122\&alt=media)

Хорошо. Этот указатель, заканчивается тем, что указывает на структуру, которая вызывает исключение, особенно в её начале, а начало это поле **NEXT**, которое мы контролируем.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uUzsLFmhGR7g1L%2F38-44.png?generation=1563221051582541\&alt=media)

Итак, поскольку здесь нет **DEP**, то если мы перейдем на гаджет **POP R32 - POP R32 - RET** мы заканчиваем переход на наше поле **NEXT**, потому что мы выталкиваем два первых значения и мы перейдем на третье с помощью инструкции **RET**.

Давайте искать среди модуля **MYPEPE** гаджет **POP – POP - RET**. Регистры не имеют значения.

Здесь мы видим гаджет **POP – POP - RET**. Давайте поместим его в **SEH** для того, чтобы перейти туда.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uW6QR_RmAYPKMD%2F38-45.png?generation=1563221051397437\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0ujAcvGgFnxY_aA%2F38-46.png?generation=1563221054474693\&alt=media)

Запустите программу снова.

Здесь она перестает работать. Давайте посмотрим наш **SEH**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0unky_zUHqbU11N%2F38-47.png?generation=1563221066084195\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uq1NiLG-pqJ5wi%2F38-48.png?generation=1563221056415737\&alt=media)

Давайте пойдем сюда и поместим здесь **BP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uu8QHlT27rJpP0%2F38-49.png?generation=1563221061285760\&alt=media)

Давайте продолжим с помощью клавиши **F9** и примем исключение.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwvyv5AAJZxlzQky%2F50.png?generation=1563265877264349\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0uyLyBUAr2Vj3cv%2F38-51.png?generation=1563221059342505\&alt=media)

Я останавливаюсь на нашем **BP**. Сейчас, если я трассирую с помощью **F7**, я должен прийти к выполнению поля **NEXT**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttww_1LFmxr39V47C%2F52.png?generation=1563265869636109\&alt=media)

Сейчас мы находимся в поле **NEXT**. Мы не видели его, потому что он похож на код, но если мы посмотрим на него в режиме **HEX DUMP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0v1trsIuOwtUgUu%2F38-53.png?generation=1563221055485751\&alt=media)

Это наш **NEXT** и **SEH**. Обычно мы делаем замену **NEXT** на байты **EB 06 90 90**, для того чтобы совершить переход выше **SEH(пропускаем его)** и программа не падает. Затем мы должны добавить шеллкод, в начало где находится байты **B**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-Ljttwx7awuPISlUXsut%2F54.png?generation=1563265877834278\&alt=media)

Это должно сработать. Давайте докажем это.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0v8v1kcMTweE7vO%2F38-55.png?generation=1563221055846159\&alt=media)

Случается так, что программа запускает множество экземпляров калькуляторов, потому что каждый раз, когда падает программа, она переходит назад к **SEH** для захвата исключения и повторно запускает калькулятор. Это можно легко устранить изменив шеллкод так, чтобы при первом его выполнении, когда он заканчивается, вызывалась функция **EXIT()** и она закроет программу.

> **780039AB.FF15 20E00278 CALL DWORD PTR DS:\[; \EXITPROCESS**

Здесь существует постоянный **CALL**, который будет закрывать программу.

Я буду добавлять байты **\x68\xAB\x39\x00\x78\xC3**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjrDv_m4LAycSFMBnkh%2F-LjrE0vCak1ME8xO-Bea%2F38-56.png?generation=1563221051779372\&alt=media)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjttkJvbq8Uocl4jWiJ%2F-LjttwyHYk_011ShsPNl%2F57.png?generation=1563265874124188\&alt=media)

Сейчас, у нас есть только один экземпляр калькулятора. В следующей части, мы увидим как сделать **ROP**, когда вы вернемся к эксплуатации **SEH**.

Мы должны уточнить, что если у них есть модуль без **ASLR**, и **SAFE SEH OFF**, и программа не переходит в свой **SEH** при обработки исключения, может быть запущена специальная защита под названием **SEHOP**, которая по умолчанию включена в серверные версии **Windows >= 2008** по умолчанию, а также в некоторых программах, таких как современные **БРАУЗЕРЫ** или некоторые сервисы.

Это защита проверяет целостность цепочки перед переходом и проверяет, что последняя **SEH** запись является корректной и не меняется, но будучу рандомизированной, невозможно перезаписать и продолжить выполнение.

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

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

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

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

07.04.2018

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