Введение в крэкинг с нуля, используя OllyDbg - Глава 30

  • На форуме работает ручное одобрение пользователей. Это значит, что, если Ваша причина регистрации не соответствует тематике форума, а также Вы используете временную почту, Ваша учётная запись будет отклонена без возможности повторной регистрации. В дальнейшем - пожизненная блокировка обоих аккаунтов за создание мультиаккаунта.
  • Мы обновили Tor зеркало до v3!
    Для входа используйте следующий url: darkv3nw2...bzad.onion/
  • Мы вновь вернули telegram чат форуму, вступайте, общайтесь, задавайте любые вопросы как администрации, так и пользователям!
    Ссылка: https://t.me/chat_dark_time

AnGel

Администратор
Команда форума

AnGel

Администратор
Команда форума
27 Авг 2015
3,411
2,025
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!


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

У нас есть ещё кое-какие опкоды, собранные из туториалов 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”, который, предположительно, распространялся Микрософтом. Он может немного помочь, так как в нём перечислены опкоды и что они делают (но не все, хе-хе), так что если встретим незнакомый опкод, то можем посмотреть, есть ли там описание.

Как я и обещал вам, сначала рассмотрим крэкми «clave 2», которое осталось у нас в качестве домашнего упражнения с прошлого раза. Посмотрим, можем ли мы получить листинг с помощью EXDEC’а.

600ec58ee74af5810e34ca9d4705f580.png

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

d12d82d2fd3095b589a8e1feb4f874b1.png

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

ba4c7207bdd5e67bc06a09e774864ea3.png

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

d3c9ec9ccc3e010fa991d677c7062fcd.png

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

34d5e436bed811a234381e4f7d51ed9b.png

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

После нажатия на «REGISTRAR» срабатывает останов на JMP. Идём в первую секцию (помните, что не надо использовать пропатченный OllyDbg для OEP’ов) и устанавливаем “BPM ON ACCESS” на секцию кода.

ff0bb5800d8e483d7ae86fac0c2e3d02.png

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

33b33d50a124e44898b4724511ef1499.png

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

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



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



04 567B 0B8E 2 1 2 Push arg
7a242968953bb02a2dbc59273a5aa247.png

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

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



401D4C: 0d VCallHresult get__ipropTEXTEDIT

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

62af6b6e23ea8d051f9bc71abb48c39e.png

Allí esta el opcode y le coloco el BPM y doy RUN.

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

d4f1a465ce7384020f2af585abcc2c0a.png

Bueno ahora traceemos hasta el siguiente opcode, a ver si ingresa el nombre.

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

c62e67d5d94ceb61a07605fd9c20ccba.png

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



401D4C: 0d VCallHresult get__ipropTEXTEDIT
401D51: 3e FLdZeroAd local_008C
Как видим, продолжается работа с локальной переменной 8c (или EBP-8C). Проверим, что там сохранено. На моей машине в ebp-8c содержит 12f454.

0764e582dfa5865a883f4f7188207738.png

Busco en el stack esa dirección a ver si esta allí mi nombre

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

08b3a2fbc61155066d7fe22e8aa09b50.png

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



401DFB: 0d VCallHresult get__ipropTEXTEDIT
3f9889ef9138783b9b9a4f9188145e51.png

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

c46f66ffb3881c1fc27ea7e893d61860.png

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

6c64af2a0dd0f6e37b8787eab6baf88b.png

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



401DFB: 0d VCallHresult get__ipropTEXTEDIT
401E00: 3e FLdZeroAd local_008C
Как и в прошлый раз используется EBP-8C.

b4d3d71eb4d765f99f235a4e1d117f9c.png

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



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 с сообщением о правильном серийном номере, а если перехода не происходит, то отображается сообщение о том, что серийник неверен.

6e712bce44e8412b0dbccb5e1046843b.png

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



401E0F: Lead0/ef ConcatVar
401E13: Lead0/40 NeVarBool
c59bcdad10a72bddb9ca7aa3d4e39792.png

Ок, делаем RUN.

71c915f9cbb9780acb2ae4747c5845ec.png

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

55f864b8983c70f82b73c4d04945706e.png

Второй опкод равен 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. Выясним, что находится в каждой из вышеупомянутых переменных.

34fa1b8209956c33ae170b6573d61ef9.png

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

d71e9afba4631633aeb52d0f33ae7676.png

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

be1ea11ba161175eff400716acdc8b07.png

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

44cabc8ed5cddf65aa505ecbaa3d6b90.png

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

8cdaebd87e4bcce44878aa682ac8cf8b.png

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

78416a70f7556147b9c42b31de88d7e7.png

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

34c5862424ead1a531b96d90571aca20.png

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

2ee1cfec8a702b3583164aef66eac908.png

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

fbc12ebc8ed6ca14b261b02fbdb9d5de.png

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

c2a4a782f0bc6ad6a5b5613f52f82667.png

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

fa085c3b02c6ca7a96a4e43289da1a77.png

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

89372691b0ac7c87c1777f81ab81bfdb.png

e69fbaf9e295b79e846563aa32ba6732.png

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

741ddc8a9eabee9652349efaa117450c.png

Lo transforma a string ya que 02EA es

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

1c6840b22561d7dbcf1e38f3b2c57a54.png

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

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

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

8ab339822f54a9ff48e8614b5498c939.png

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

3acb3e1648494adcf8df9b18410c41d5.png

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

2c3a00dc35cbc210e134dbcab84cba73.png

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

80e1bb52f981d32522fda3374015563a.png

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

76b63a1672780c5698e7b03180a04768.png



401E13: Lead0/40 NeVarBool
Это FB40, и он двойной. Трассируем, пока не дойдём до считывания второго опкода.

8b307ed62c205e096dd836b489a30e63.png

4a1c751fff738d82f517a8f99d7a81c5.png

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

8ee8fae46d738decc9794f6b6902ab0d.png

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

80b9d21e8e362062f7ba43c6f739a914.png

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

aaec8fb88e358872f7ab37451ef3e325.png

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

dff8b4145ecab420fd7940dea8da5731.png

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

e486d5ad0a81d2e3bf3d3945cb562517.png

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

5e62cb829183f99ad0a0e8190496ba4f.png

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

b7f193f11d4d6f945555d3ee434344c9.png

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

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

d99db8f18bf912538a53b840c3ec6407.png

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

a43bd90d6822e2d28bfd89430b559375.png

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

28d37b725edc89c0a8b24a14f4e2ead3.png

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

15067685c2f9358ab0fa95a2c5dc082d.png

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

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



401CC0: 04 FLdRfVar local_008C
401CC3: 21 FLdPrThis ; Load reference pointer into item pointer. Загрузка ссылочного указателя в указатель на элемент
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 ; Переход если ложноSalta si falso (>= 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, который просит нас убрать первоначальное наг-окно. Смотрим его листинг в 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’ов, хе-хе, поэтому нам нужно забить эту функцию опкодами, которые не изменят хода выполнения программы.

609f228e285a6e7479c18d35cdb456b2.png

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



401A2D: 0a ImpAdCallFPR4: _rtcMsgBox
47368e6f572941b5c0792c0f5531cb84.png

f6ee32437b22cb7880a56870e23bed4f.png

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

6a00beaca38d50225d055113c7b9cc22.png

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

b4cfbd03da9f86da723254543f598e1b.png

46b16423efd321a918b152224803bd78.png

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

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

0511b45a05a55ce8ab4dd412fa1860c5.png

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



F5 5CBE 1377 4 1 4 Push imm#4
У нас 4 параметра размером равные 0A. Столько нам нужно заменить.



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

566fee89744db24778d0322321cfa8ff.png

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

2875d758b9d9380bae3dd8bf3646b499.png

4a2799bf474257b791dba086d446d31c.png

0e5f2ee4e04599f97f6f8c1a1c98e050.png

b276e8a9fb18dff8e75e5cbf14445ec8.png

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

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

О нас

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

    Dark-Time 2015 - 2022

    При поддержке: XenForo.Info

Быстрая навигация

Меню пользователя