> For the complete documentation index, see [llms.txt](https://backoftut.gitbook.io/intro-cracking-with-ollydbg/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://backoftut.gitbook.io/intro-cracking-with-ollydbg/ch-30.md).

# Глава 30

*(для запуска крэкми понадобиться MSVBVM50.dll* [*\[ссылка\]*](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/27/MSVBVM50.7z)*)*

Ок, после того, как попрактиковались, и если вы ещё живы, продолжаем с P-CODE.

У нас есть ещё кое-какие опкоды, собранные из туториалов JBDUC’а.

* 6c -> ILdRf Поместить адрес в стек
* 1b -> LitStr5 Поместить строку в стек
* fb -> Lead0 Сравнить две строки (хе-хе, для чего это могло служить ?)
* 30 -> EqStr Сравнить две строки(хе-хе, для чего это могло служить ?)
* 2f -> FFree1Str Освободить используемую память
* 1a -> FFree1Ad Освободить используемую память
* 0f -> VCallAd Выполнить опкод в виртуальной машине
* 1c -> BranchF Сделать переход, если предшествующее сравнение дало ложь ( аналог jne/jnz в ассемблере )
* 1d -> BranchT Сделать переход, если предшествующее сравнение дало истину ( аналог je/jz в ассемблере )
* 1e -> Безусловный переход ( хе-хе, угадайте, для чего её можно использовать )
* fc -> Lead1 Прерывает выполнение программы (хе-хе, прекрасно...)
* c8 -> End Прерывает выполнение программы (хе-хе, прекрасно...)
* f3 -> LitI2 Сохраняет заданное число типа Integer в стек
* f4 -> LitI2\_Byte Конвертирует Byte-значение в Integer и помещает его в стек
* 70 -> FStI2 Сохраняет последний Integer, помещённый в стек, в заданную глобальную переменную
* 6b -> FLdI2 Загружает в стек Integer из заданной локальной переменной
* a9 -> AddI2 Складывает два последних Integer'а, помещённых в стек, на вершину которого помещает результат
* ad -> SubI2 Использует для вычитания два последних Integer’а, помещённых в стек, и кладёт в последний результат
* b1 -> MulI2 Умножает два последних Integer’а, помещённых в стек, и кладёт в последний результат. Думаю, что если переполнение игнорируется.

Ок, есть ещё опкоды, которые мы сейчас рассматривать не будем. К статье прилагает файл под названием "P-CODE OPCODES" [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/30/P-Code%20OPCODES.7z), который, предположительно, распространялся Микрософтом. Он может немного помочь, так как в нём перечислены опкоды и что они делают (но не все, хе-хе), так что, если встретим незнакомый опкод, то можем посмотреть, есть ли там описание.

Как я и обещал вам, сначала рассмотрим крэкми "clave 2" [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/29/clave2.7z), который остался у нас в качестве домашнего упражнения с прошлого раза. Посмотрим, можем ли мы получить листинг с помощью EXDEC’а [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/29/exdec.7z).

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-f18d990dd42e14099788c4bc618735b80b407135%2F1.png?alt=media)

Вот он, и видим, что начинается с 401cc0. Не будем слепо верить EXDEC’у, так как бывали случаи, когда он обманывал. Посмотрим, сможем ли мы найти первый опкод вручную, как мы это делали в предыдущей части.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-1b38266e7d8b49707c8767a851c9a6f6d4eb06ba%2F2.png?alt=media)

Смотрим, находится ли переход на API-функцию MethCallEngine за EP.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-758a0f8acfa32fe093be1e2950e236045c37b602%2F3.png?alt=media)

Вот он. Становимся на него, делаем FOLLOW, чтобы перейти к API-функции и также устанавливаем там BP.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-b164365702a2d784df0ce02d00f64a4efa62ccd3%2F4.png?alt=media)

Готово, теперь делаем RUN, чтобы остановиться на одном из установленных BP.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-b6d7e75dfed6aa8a8f0b59513ecbf9a2aebc75d0%2F5.png?alt=media)

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

После нажатия на "REGISTRAR" срабатывает останов на JMP. Идём в первую секцию (помните, что не надо использовать пропатченный OllyDbg для OEP’ов [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/26/olly_parcheado_para_vb.7z)) и устанавливаем "BPM ON ACCESS" на секцию кода.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-58fad83954cce85376910761f7504c080d911473%2F6.png?alt=media)

Теперь жмём RUN, пока не встретится знакомая инструкция, где читается опкод.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-f3ec4c9751922b51cfb089de3aad367c2d42b8d4%2F7.png?alt=media)

Вот тут, помним, что ESI всегда должен указывать на опкод (который сам перемещается в AL).

Как видим, EXDEC не ошибся, и первый опкод – это 04 и начинается с 401cc0.

```
Proc: 401e90
401CC0: 04 FLdRfVar                local_008C
```

Помним, что 04 – это просто PUSH, в данном случае его аргументом является EBP-8C, как это видно из пояснения рядом с опкодом

`04 567B 0B8E 2 1 2 Push arg`

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-f84df387e5ca0842e497dfbc15824886a71569e2%2F8.png?alt=media)

Из этого нам становится понятно, что каждая цифра, в нашем случае 0B8E, является RVA опкода, 2 – это количество байтов, которые в общей сложности занимают параметры, 1 нам говорит, что аргумент только один, и последнее значение (2) указывает нам размер, занимаемый каждым аргументом в отдельности.

Хорошо, вот PUSH EBP-8C, продолжаем изучать исходник, пока без трассировки шаг за шагом. Смотрим.

```
401D4C: 0d VCallHresult            get__ipropTEXTEDIT

401DFB: 0d VCallHresult            get__ipropTEXTEDIT
```

Видим, что используется два вызова для считывания введённого в окне регистрации, вероятно, что в первый раз читает имя, а во второй – неправильный серийник, использованный нами. Устанавливаем BPM ON ACCESS на первом вызове, то есть на 401d4C.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-5a275268f95d1a69807f4bdba3c255e27dfa7362%2F9.png?alt=media)

Вот опкод, устанавливаем на него BPM и делаем RUN.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-e0fe6555d31358dc212e5afeaf36547a6439330c%2F10.png?alt=media)

Ок, теперь трассируем до следующего опкода, чтобы посмотреть, что будет происходить с именем.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-761f288879e66dbaf268cc4dd8d44bb932a3c7b8%2F11.png?alt=media)

Дошли до следующего опкода, смотрим стек, чтобы узнать, что там находится

```
401D4C: 0d VCallHresult            get__ipropTEXTEDIT
401D51: 3e FLdZeroAd               local_008C
```

Как видим, продолжается работа с локальной переменной 8c (или EBP-8C). Проверим, что там сохранено. На моей машине в ebp-8c содержит 12f454.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-9e2e6453369ae9a4a02b8b1690acbdcdf8d4ebce%2F12.png?alt=media)

Ищем этот адрес в стеке и видим, что там находится моё имя.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-57ba39164d236016d08dcacd8f5cec29bccd38be%2F13.png?alt=media)

Конечно же, оно находится здесь, так что всё идёт хорошо. Раз здесь находится моё имя, то логично предположить, что в следующем будет идти работа с серийником, поэтому устанавливаем на второй опкод BPM ON ACCESS.

`401DFB: 0d VCallHresult get__ipropTEXTEDIT`

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-5a67f3217767a70e3e26bb1683330220f2f3dfd2%2F14.png?alt=media)

Готово, теперь жмём RUN, чтобы оказаться рядом с этим опкодом.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-ad6027bb3b8cea87e696f10268a206d92b29add1%2F15.png?alt=media)

Как и в предыдущем случае, трассируем до следующего опкода.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-1237faad7a8478403cc55c16a66ca7bed69c31fd%2F16.png?alt=media)

И смотрим, сохранён ли в используемой переменной неправильный серийный номер.

```
401DFB: 0d VCallHresult            get__ipropTEXTEDIT
401E00: 3e FLdZeroAd               local_008C
```

Как и в прошлый раз используется EBP-8C.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-7ea2d5c30b10c9c54b7124c570e9d4be40b923ef%2F17.png?alt=media)

Хорошо, вот мы и дошли до места, куда помещён наш неправильный серийник. Видим, что зная опкоды, не обязательно трассировать всю программу, можем просто установить BPM и оказаться в нужной части программы. В прошлой главе мы трассировали всё подряд, чтобы понять механизмы, согласно которым работает P-CODE, но как правильно, нам не нужно делать это. Как мы увидим в следующей главе, когда исследуем большую программу, будем локализовывать интересующую нас часть программы и работать именно с ней.

```
401E0F: Lead0/ef ConcatVar
401E13: Lead0/40 NeVarBool
401E15: 1a FFree1Ad                local_0088
401E18: 36 FFreeVar         local_00CC local_00AC
401E1F: 1c BranchF:                401E59
```

Далее видим, что здесь есть все признаки сравнения, потом освобождение локальных переменных с помощью FREE, а затем условный переход, который ведёт в 401e59, где вызывается rtcMsgBox с сообщением о правильном серийном номере, а если перехода не происходит, то отображается сообщение о том, что серийник неверен.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-07233344d565c8362f21b965c1057e09a2f78183%2F18.png?alt=media)

Тут всё совершенно понятно. Вероятное сравнение и условный переход, в зависимости от которого отображается окошко с соответствующим сообщением, так что устанавливаем сюда BPM ON ACCESS.

```
401E0F: Lead0/ef ConcatVar
401E13: Lead0/40 NeVarBool
```

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-3e2d00fa10e052fd502be1194b69648b73b1020b%2F19.png?alt=media)

Ок, делаем RUN.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-98c8d9021621e17e6ee3bda584ea939f00b280c6%2F20.png?alt=media)

Останавливаемся тут, в первом опкоде и трассируем до второго, который производит некую операцию.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-4738e98dd1753e7a489debdabdfc68d795883533%2F21.png?alt=media)

Второй опкод равен EF.

Смотрим в списке опкодов.

```
FB EF 6BAB 25AD 2
FB F0 6B99 259B 0          vbaStrCat
FB F1 C423 B981 0          Push [FC0D134]
```

Что такое FB EF нам ещё не совсем понятно, EXDEC говорит нам что-то о конкатенации переменных, смотрим.

```
401E07: 3a LitVarStr:              ( local_009C ) CRK
401E0C: 04 FLdRfVar                local_018C
401E0F: Lead0/ef ConcatVar
401E13: Lead0/40 NeVarBool
```

Видим, что прямо до этого опкода идёт работа с двумя локальными переменными, в одной из которых находится строка CRK, а другая является EBP-018C. Выясним, что находится в каждой из вышеупомянутых переменных.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-873b8889b8574b3418bc624aa56f081f6a9bebac%2F22.png?alt=media)

Первая переменная – это EBP-9C, которая на моей машине равна 12f444 и находится там следующее:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-04ab7f3d4ff96023667e1157eba6844a67671041%2F23.png?alt=media)

Как мы знаем, в случае с переменными сначала идёт байт, указывающий тип, в данном случае это 3, а ещё выше находится сама переменная, которая равна 2EA.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-865869089a1e80db2562362249f25d47a2315f0b%2F24.png?alt=media)

Входим в опкод.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-2318fb8a99019164af915d9f2c9d2d3ff6d5b599%2F25.png?alt=media)

Здесь читаются параметры.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-46ccf3d3620e12562890fba28afcebc5d4e7c3bf%2F26.png?alt=media)

После сложения с EBP получается 12f434.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-9bc2636d0b92009e7f50088079945a8071db9bf9%2F27.png?alt=media)

Доходим до API-функции vbaVarCat, у которой три аргумента в стеке.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-2283faff69dd8dfaa025ab3a71ce0fb37c8d8a7c%2F28.png?alt=media)

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-8c6c40c731466121122c68298ffc62cffb4971b0%2F29.png?alt=media)

Это первый аргумент.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-bdc5324197597114caeec37f6a4f799b79697b2d%2F30.png?alt=media)

Во втором сначала идёт 3, а потом 02EA, задающее значение.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-6fefdfffd614d8875f4e6aa28f1bb4588f32d8ec%2F31.png?alt=media)

А в третьем в начале 8, означающее, что 4017648 – это указатель на строку CRK.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-af3a7122874f5dfbc9df3ad0ac25fcf27100d3ea%2F32.png?alt=media)

Ок, у нас тут мешанина из переменных, посмотрим, что останется. Если войдём в функцию vbaVarCat, то окажемся у внутренней API-функции, которая ясно покажет нам, что будет объединяться.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-12c1d5f3ccf541771461a6bdbf3476d029879d53%2F33.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-28736f828fca378df521fef62a7e620b1c2eb7e8%2F34.png?alt=media)

То есть предстоит объединение CRK с 746. А теперь выясним, что значит параметр 02EA.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-13fd7a81cdce8500e075bdaf6a2654d1b592e99f%2F35.png?alt=media)

Он конвертируется в строку. 02EA – это:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-be34d3d6ddd185fd47b43c09d57151f0d3a6aee6%2F36.png?alt=media)

То есть vbaVarCat, в данном случае, получила строку и численную переменную, которая конвертируется в строку, после чего обе объединяются.

Продолжаем трассировать с помощью F8.

Дойдя до RET’а из функции, видим:

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-8317368937f655a816748156c5ba46a76f170eec%2F37.png?alt=media)

Обе переменных объединились в одну строку.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-0c4c0f9e97ffaa7a8d3344f6fc6e3ea44c8b1407%2F38.png?alt=media)

И, как и раньше, до начала следующего опкода это значение сохраняется в качестве первого аргумента.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-a414cce035ec24531e60ceb1d483bcd1aa40250f%2F39.png?alt=media)

Видим, что первый аргумент сейчас имеет тип 8, то есть строку, и указывает на 15d88c, то есть на сконкатенированную строку.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-debdcfe6491341e20ce22decb64f4b46ee510620%2F40.png?alt=media)

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-4f43e625ea77da585f0ecd059c9ddb923596d182%2F41.png?alt=media)

`401E13: Lead0/40 NeVarBool`

Это FB40, и он двойной. Трассируем, пока не дойдём до считывания второго опкода.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-dbd8f846c1a3319b59223cd9b612a18d081c342a%2F42.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-fcbd4739b97c7b3d7ab96046391776f752bbfc22%2F43.png?alt=media)

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-8d345a4efb6130230058169f43200ab196edb8e1%2F44.png?alt=media)

Видим, что в опкоде всего один вызов, после которого сразу следует завершение. Смотрим параметры вызова.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-79a6aba468a873de9ced8049d84269f044649873%2F45.png?alt=media)

Первый равен нулю, а второй 12f434. Смотрим, что там находится.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-ec7f4b3951790e4fecd545ddc51d19019069e79e%2F46.png?alt=media)

Ок, 08 говорит нам, что это строка, теперь осталось посмотреть, на что указывает 15d88c.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-68bcb8f3cb90053884a96a0534ad50d70c1312a6%2F47.png?alt=media)

Вот строка, смотрим следующий аргумент.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-7a16123b12f859ab778322f1c3298e68f3be9d09%2F48.png?alt=media)

В данном случае 15ca94 указывает на строку с нашим неправильным серийным номером.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-f363da2f2af056ca2a8ee823159a5c970ee1e252%2F49.png?alt=media)

Похоже, что это сравнение двух строк.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-f1e2e5f7ae871d5d0872354fc650bd627173b229%2F50.png?alt=media)

Чтобы рассеять сомнения, устанавливаем BP, минуем вызов с помощью F8 и идём к следующему опкоду.

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-aebd440543f06145b85796422f1ae8d60c8a213a%2F51.png?alt=media)

Нажимаем на кнопку "Registrar".

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-04636d69a11debae5617eef64c4cb8d2d7521958%2F52.png?alt=media)

Снова оказались у этого вызова, проходим его с помощью F8 и идём к следующему опкоду, как в прошлый раз.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-dc461a6d7ce26d9a599d7045899755130dae4655%2F53.png?alt=media)

Видим, что в данном случае результатом является ноль, так как обе строки одинаковы.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-a222cb70720652e2646136d6c86fd3c9697487c4%2F54.png?alt=media)

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

Для заинтересованных – более детализированный список, где изложены сведения, которые нам удалось узнать.

```
401CC0: 04 FLdRfVar                local_008C
401CC3: 21 FLdPrThis              **; Загрузка ссылочного указателя в указатель на элемент**
401CC4: 0f VCallAd                 text			; Доступ к методу **ITEM DESCRIPTOR TABLE**
401CC7: 19 FStAdFunc               local_0088
401CCA: 08 FLdPr                   local_0088
401CCD: 0d VCallHresult            get__ipropTEXTEDIT  ; Читаем содержимое из текстового поля
401CD2: 6c ILdRf                   local_008C  ; Имя
401CD5: 1b LitStr:                 &  ; Поместить строку в стек
401CD8: Lead0/30 EqStr            	  ; Сравнить две строки
401CDA: 2f FFree1Str               local_008C
401CDD: 1a FFree1Ad                local_0088
401CE0: 1c BranchF:                401CE6  ; Переход, если сравнение не удалось
401CE3: 1e Branch:                 401e8c  ; Безусловный переход
401CE6: 04 FLdRfVar                local_008C
401CE9: 21 FLdPrThis
401CEA: 0f VCallAd                 text  ; Доступ к методу **ITEM DESCRIPTOR TABLE**
401CED: 19 FStAdFunc               local_0088
401CF0: 08 FLdPr                   local_0088
401CF3: 0d VCallHresult            get__ipropTEXTEDIT  ; Читаем содержимое текстового поля
401CF8: 6c ILdRf                   local_008C          ; Имя
401CFB: 4a FnLenStr
401CFC: f5 LitI4:                  0x6  6  (....)  ; Передаём элемент из 4-ёх байт
401D01: d1 LtI4                   			       ; Сравнение меньше чем (?)
401D02: 2f FFree1Str               local_008C
401D05: 1a FFree1Ad                local_0088
401D08: 1c BranchF:                401D3F  ; Переход если ложно (>= 6)
401D0B: 27 LitVar_Missing
401D0E: 27 LitVar_Missing
401D11: 3a LitVarStr:              ( local_00BC ) P-Code
401D16: 4e FStVarCopyObj           local_00CC
401D19: 04 FLdRfVar                local_00CC
401D1C: f5 LitI4:                  0x40  64  (...@)
401D21: 3a LitVarStr:              ( local_009C ) Минимум 6 символов
401D26: 4e FStVarCopyObj           local_00AC
401D29: 04 FLdRfVar                local_00AC
401D2C: 0a ImpAdCallFPR4:          _rtcMsgBox
401D31: 36 FFreeVar                local_00AC local_00CC local_00EC local_010C
401D3C: 1e Branch:                 401e8c  ; Если < 6 символов в строке
401D3F: 04 FLdRfVar                local_008C
401D42: 21 FLdPrThis
401D43: 0f VCallAd                 text
401D46: 19 FStAdFunc               local_0088
401D49: 08 FLdPr                   local_0088
401D4C: 0d VCallHresult            get__ipropTEXTEDIT  ; Читаем содержимое текстового поля
401D51: 3e FLdZeroAd               local_008C		   ; Имя
401D54: 46 CVarStr                 local_00AC
401D57: 04 FLdRfVar                local_00CC
401D5A: 0a ImpAdCallFPR4:          _rtcLowerCaseVar  ; Конвертируем в строчные символы
401D5F: 04 FLdRfVar                local_00CC
401D62: 04 FLdRfVar                local_00EC
401D65: 0a ImpAdCallFPR4:          _rtcTrimVar
401D6A: 04 FLdRfVar                local_00EC
401D6D: Lead1/f6 FStVar            local_011C
401D71: 1a FFree1Ad                local_0088
401D74: 36 FFreeVar                local_00AC local_00CC
401D7B: 04 FLdRfVar                local_011C
401D7E: Lead0/eb FnLenVar
401D82: Lead1/f6 FStVar            local_012C
401D86: 28 LitVarI2:               ( local_00BC ) 0x1  (1)
401D8B: 04 FLdRfVar                local_013C
401D8E: 04 FLdRfVar                local_012C
401D91: Lead3/68 ForVar:           (when done) 401DE0		, Начало цикла for next
401D97: 28 LitVarI2:               ( local_00AC ) 0x1  (1)
401D9C: 04 FLdRfVar                local_013C
401D9F: Lead1/22 CI4Var
401DA1: 04 FLdRfVar                local_011C
401DA4: 04 FLdRfVar                local_00CC
401DA7: 0a ImpAdCallFPR4:          _rtcMidCharVar  ; Загрузка символов из...
401DAC: 04 FLdRfVar                local_00CC	   ; ... имени
401DAF: Lead2/fe CStrVarVal        local_008C
401DB3: 0b ImpAdCallI2             _rtcAnsiValueBstr  **; конвертируем значения символов в  hexadec**
401DB8: 44 CVarI2                  local_00BC
401DBB: Lead1/f6 FstVar		       local_016C
401DBF: 2f FFree1Str        	   local_008C
401DC2: 36 FFreeVar                local_00AC local_00CC
401DC9: 04 FLdRfVar                local_017C
401DCC: 04 FLdRfVar                local_016C
401DCF: Lead0/94 AddVar            local_00AC
401DD3: Lead1/f6 FStVar            local_017C
401DD7: 04 FLdRfVar                local_013C
401DDA: Lead3/7e NextStepVar:      (continue) 401D97  ; Конец цикла for-next?
401DE0: 04 FLdRfVar                local_017C
401DE3: 04 FLdRfVar                local_012C
401DE6: Lead0/94 AddVar            local_00AC
401DEA: Lead1/f6 FStVar            local_018C
401DEE: 04 FLdRfVar                local_008C
401DF1: 21 FLdPrThis
401DF2: 0f VCallAd                 text
401DF5: 19 FStAdFunc               local_0088
401DF8: 08 FLdPr                   local_0088
401DFB: 0d VCallHresult            get__ipropTEXTEDIT  ; Читаем содержимое текстового поля
401E00: 3e FLdZeroAd               local_008C		   ; Серийный номер
401E03: 46 CVarStr                 local_00CC
401E06: 5d HardType
401E07: 3a LitVarStr:              ( local_009C ) CRK
401E0C: 04 FLdRfVar                local_018C
401E0F: Lead0/ef ConcatVar
401E13: Lead0/40 NeVarBool
401E15: 1a FFree1Ad                local_0088
401E18: 36 FFreeVar                local_00CC local_00AC
401E1F: 1c BranchF:                401E59
401E22: 27 LitVar_Missing
401E25: 27 LitVar_Missing
401E28: 3a LitVarStr:              ( local_00BC ) P-Code
401E2D: 4e FStVarCopyObj           local_00CC
401E30: 04 FLdRfVar                local_00CC
401E33: f5 LitI4:                  0x10  16  (....)
401E38: 3a LitVarStr:              ( local_009C ) Серийный номер неверен!
401E3D: 4e FStVarCopyObj           local_00AC
401E40: 04 FLdRfVar                local_00AC
401E43: 0a ImpAdCallFPR4:          _rtcMsgBox
401E48: 36 FFreeVar                local_00AC local_00CC local_00EC local_010C
401E53: 1e Branch:                 401e8c
401E56: 1e Branch:                 401e8c
401E59: 27 LitVar_Missing
401E5C: 27 LitVar_Missing
401E5F: 3a LitVarStr:              ( local_00BC ) P-Code
401E64: 4e FStVarCopyObj           local_00CC
401E67: 04 FLdRfVar                local_00CC
401E6A: f5 LitI4:                  0x30  48  (...0)
401E6F: 3a LitVarStr:              ( local_009C ) Серийный номер верен!!
401E74: 4e FStVarCopyObj           local_00AC
401E77: 04 FLdRfVar                local_00AC
401E7A: 0a ImpAdCallFPR4:          _rtcMsgBox
401E7F: 36 FFreeVar                local_00AC local_00CC local_00EC local_010C
401E8A: Lead1/c8 End
401E8C: 13 ExitProcHresult
```

Отсюда ясно, как работает крэкми.

Полезно знать, как работать с P-CODE в OllyDbg, так как есть программы, которые защищены от WKT и EXDEC, но в случае с OllyDbg мы можем использовать плагины, которые спрячут её практически ото всех, кроме очень редких исключений.

Загружаем прилагающийся крэкми nags1 [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/30/nags1.7z), который просит нас убрать первоначальное наг-окно. Смотрим его листинг в EXDEC.

```
;Proc: 401a40

401A14: 27 LitVar_Missing
401A17: 27 LitVar_Missing
401A1A: 27 LitVar_Missing
401A1D: f5 LitI4:                  0x0  0  (....)
401A22: 3a LitVarStr:              ( local_0094 ) NAG
401A27: 4e FStVarCopyObj           local_00A4
401A2A: 04 FLdRfVar                local_00A4
401A2D: 0a ImpAdCallFPR4:          _rtcMsgBox
401A32: 36 FFreeVar         local_00A4 local_00C4 local_00E4 local_0104
401A3D: 13 ExitProcHresult
```

```
;Proc: 401958

401954: Lead1/c8 End
401956: 13 ExitProcHresult**
```

Видим, что знаменитый NAG – это просто rtcMsgBox. В P-Code нет NOP’ов, хе-хе, поэтому нам нужно забить эту функцию опкодами, которые не изменят хода выполнения программы.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-2667ad5a8d5b5b6e3ae33382be8544236ea89d43%2F55.png?alt=media)

Устанавливаем BPM на опкоде, вызывающем rtcMsgBox, и запускаем программу.

`401A2D: 0a ImpAdCallFPR4: _rtcMsgBox`

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-9857465ef0596d7b0cd1887deb9070c8686c0e48%2F56.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-26c900b012ab17fbdea6e1ceaeaf111c074c546d%2F57.png?alt=media)

Останавливаемся, когда считывается опкод.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-143e746dfdd2a400996d7ef2090ddd994cf1b14e%2F58.png?alt=media)

Видим, что в стеке находится 12f9e8. Идём к следующему опкоду. Сначала, конечно, выскочит наг-окошко, поэтому надо будет нажать "Aceptar".

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-20cc0e67e8aa63c43569cdc3540985e28bcaafa2%2F59.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-4c92f0d30f86a9de9c5da1856fcf5414919b893c%2F60.png?alt=media)

Здесь мы доходим до следующего опкода после CALL EAX, который вызывал API-функцию rtcMsgBox.

В стеке находится 12f9fc.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-57c6d815eb4617e8bb2c8546661da9ca91c70a03%2F61.png?alt=media)

То есть, для того, чтобы оставить равные, нужно сделать различные POP’ы. Сюда мы не вмешиваемся, можем попробовать использовать PUSH с помощью F5.

`F5 5CBE 1377 4 1 4 Push imm#4`

У нас 4 параметра размером равные 0A. Столько нам нужно заменить.

`0A 664E 1F30 4 2 2 2`

Пробуем изменить 0A на F5 и делаем все параметры равными нулю.

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-89da6537acc171b5fa88e3c4cd6d5f6f16eb47df%2F62.png?alt=media)

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

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-29e01af7bf207b8c39dd8f13742efdd76011d314%2F63.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-0bfcf93f4aee371af280ed0862e240209e3408a9%2F64.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-b7d6d113f0cbde41b6682a55ce755366f5c7c8a4%2F65.png?alt=media)

![](https://2931627293-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LnwCNY88kcGMCQxNdy6%2Fuploads%2Fgit-blob-e4b04d0631403e2569510e60be714df34c9a2a3b%2F66.png?alt=media)

Доходим досюда без появления наг-окна. В другой раз, вероятно, можно использовать иной опкод для патчинга. В качестве домашнего упражнения вы можете попробовать решить крэкми nags2 [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/30/nags2.7z), прилагающийся к данной статье.

31 часть будет последней посвящённой P-CODE, и в ней будет рассмотрена коммерческая программа.

\[C] Рикардо Нарваха, пер. Aquila
