|
||||||||||||||||||||||||||
Автор: bi0w0rM. Дата публикации: 05.08.2004
|
Исследование P-Code Visual Basic[ Исследование P-Code Visual Basic ]Эхх!! Я очень часто слышу отрицательные отзывы типа: ненавижу ломать VB-программы, там не код, там какая-то помойка вообще! И многие, видать не из большой любви к языку Visual Basic, который считают почему-то ламерским, забрасывают исследовние. Часто из-за того, что их любимый w32dasm не может найти UNICODE-строк. Тут бы я посоветовал юзать IDA Pro и, если поможет, прогу VBREF. Но код и вправду превращается в набор недизассемблируемых байтов, если прога собрана... в P-Code. Именно такой тип сборки я указал в опциях проекта, когда писал свой P-Code crackme. Всего у VB два типа компиляции: Native и P-Code. Native легко дизассемблировать, так как это обычные команды процессора intel x86, а вот P-Code(псевдокод) представляет нечто другое: команды записаны в виде номер функций и их аргументов; эти команды читаются Dll-кой MSVBVM60.DLL(ну или у кого какая версия). Так что можно считать псевдокод неломаемым, если... не иметь нормального декомпилятора псевдокода, который бы преобразовывал байт-коды в нормальный для восприятия вид. Таких прог я знаю две: EXDEC и VBParser. Последний мне не очень нравится, потому что весь GUI сделан на китайском и сама прога порой виснет при декомпиляции больших программ(листинг хоть и сохраняется в файл, но не весь) :( Хотя VBParser более подробно описывает команды, нежели EXDEC, который типа находится в стадии разработки :)) Итак, я написал крякмис, по которому сегодня будем учиться ломать псевдокод, его можно скачать здесь: http://bioworm.narod.ru/soft/bio_keygenme.rar . Сам EXDEC есть у меня же на сайте. 1) При нажатии на кнопку "Check your lamerizm" форма некоторое покрывается красными точками. такую херь я организовал естественно при помощи цикла, и мы постараемся избежать этот цикл, чтоб побыстрее шло дело. Запустим EXDEC и дизасмим там наш exe’шник. В первой же процедуре такой код: Proc: 40479c 404548: 28 LitVarI2: ( local_00C4 ) 0x64 (100) 40454D: 25 PopAdLdVar 40454E: 28 LitVarI2: ( local_00B4 ) 0x64 (100) 404553: 25 PopAdLdVar 404554: 28 LitVarI2: ( local_00A4 ) 0x0 (0) 404559: 25 PopAdLdVar 40455A: 28 LitVarI2: ( local_0094 ) 0x0 (0) 40455F: 25 PopAdLdVar 404560: f4 LitI2_Byte: 0x4 4 (.) 404562: 08 FLdPr local_param_0008 404565: 0d VCallHresult ?$ 40456A: f5 LitI4: 0xff 255 (....) 40456F: 05 ImpAdLdRf: 406008 404572: 24 NewIfNullPr 401b4c (MainForm) 404575: 0d VCallHresult put_FORECOLORFORM LitVarI2 в псевдокодах что-то вроде push. А в исходнике первые строчки у меня были такие: Scale (0, 0)-(100, 100). 40456A: f5 LitI4: 0xff 255 (....) 40456F: 05 ImpAdLdRf: 406008 404572: 24 NewIfNullPr 401b4c (MainForm) 404575: 0d VCallHresult put_FORECOLORFORM А вот из этого кода можно судить, что здесь меняется цвет на красный(#FF0000). Попробуем поменять цвет. В HIEW делаем Go To: ".40456A". Длина команды 5 байтов(40456A-404565). Там стоит: F5 FF 00 00 00. Меняем на F5 FF 22 FF 00. Теперь красный поменялся на фиолетовый :) Далее наблюдаем в EXDEC такой код: 40457A: f4 LitI2_Byte: 0x0 0 (.) 40457C: eb CR8I2 40457D: 08 FLdPr local_param_0008 404580: 06 MemLdRfVar local_param_0034 404583: f5 LitI4: 0x4e200 320000 (....) 404588: ec CR8I4 404589: Lead3/65 ForR4 40458F: 04 FLdRfVar local_00DC 404592: 0a ImpAdCallFPR4: 404597: 04 FLdRfVar local_00DC 40459A: 0a ImpAdCallFPR4: 40459F: 73 FStFPR4 4045A2: 04 FLdRfVar local_00EC 4045A5: 0a ImpAdCallFPR4: 4045AA: 04 FLdRfVar local_00EC 4045AD: 0a ImpAdCallFPR4: 4045B2: 73 FStFPR4 4045B5: f5 LitI4: 0x0 0 (....) 4045BA: 6e FLdFPR4 4045BD: f4 LitI2_Byte: 0x64 100 (d) 4045BF: eb CR8I2 4045C0: b3 MulR8 4045C1: 37 PopFPR4 4045C2: 6e FLdFPR4 4045C5: f4 LitI2_Byte: 0x64 100 (d) 4045C7: eb CR8I2 4045C8: b3 MulR8 4045C9: 37 PopFPR4 4045CA: f4 LitI2_Byte: 0x0 0 (.) 4045CC: 08 FLdPr local_param_0008 4045CF: 0d VCallHresult meth__imethPSET 4045D4: 36 FFreeVar 4045DB: 08 FLdPr local_param_0008 4045DE: 06 MemLdRfVar local_param_0034 4045E1: 68 NextStepR4: (continue) 40458F 4045E6: 21 FLdPrThis 4045E7: 0d VCallHresult meth__imethCLS meth__imethPSET - это поставить точку, PSET в VB. meth__imethCLS - очистить, CLS в VB. NextStepR4 - это элемент цикла. В начале видно, что цикл пойдет от 0 до 0x4e200(320000). Также в HIEW меняем 0x4e200 на 000000. Теперь нормально :) Дальше можно наткнуться на такой код: 4045F9: 0d VCallHresult get__ipropTEXTEDIT 4045FE: 6c ILdRf local_00FC 404601: 4a FnLenStr 404602: f5 LitI4: 0x6 6 (....) 404607: db GtI4 404608: 2f FFree1Str local_00FC 40460B: 1a FFree1Ad local_00F8 40460E: 1c BranchF: 404772 Надеюсь, что делает get__ipropTEXTEDIT, объяснять не надо. И что такое FnLenStr тоже с виду понятно :) Здесь происходит сравнение на длину, можете проверить, поменяв 6 на другие числа. BranchF: 404772 - условный переход на 404772. Как они работают в VB, расскажу позже. Дальше видим такой код: 40468F: 08 FLdPr local_00F8 404692: 0d VCallHresult get__ipropTEXTEDIT 404697: 27 LitVar_Missing 40469A: 27 LitVar_Missing 40469D: 27 LitVar_Missing 4046A0: f5 LitI4: 0x10 16 (....) 4046A5: 1b LitStr: Hey 4046A8: 6c ILdRf local_00FC 4046AB: 2a ConcatStr 4046AC: 23 FStStrNoPop local_0100 4046AF: 1b LitStr: ! it’s a BAD C0DE >:)) 4046B2: 2a ConcatStr 4046B3: 23 FStStrNoPop local_0104 4046B6: 1b LitStr: 4046B9: 2a ConcatStr 4046BA: 23 FStStrNoPop local_0108 4046BD: 1b LitStr: Try again! 4046C0: 2a ConcatStr 4046C1: 46 CVarStr local_00DC 4046C4: 0a ImpAdCallFPR4: ImpAdCallFPR4 - вызов функции. Тут непонятно, какой именно. Но по строчкам it’s a BAD C0DE >:)) можно догадаться, что это тот MsgBox :)) LitVar_Missing - это push аргумента, который программист опустил. Я например могу в VB написать просто: MsgBox "pizka", упустив остальные аргументы. ConcatStr - это соединение строк в одну. Тут я просто формировал обращение по введенному имени :)) А чуть выше такой код: 404648: 08 FLdPr local_param_0008 40464B: 06 MemLdRfVar local_param_0048 40464E: 4d CVarRef: ( local_0094 ) 4008 404653: 3e FLdZeroAd local_00FC 404656: 46 CVarStr local_00DC 404659: 0a ImpAdCallFPR4: 40520c 40465E: 1a FFree1Ad local_00F8 404661: 35 FFree1Var local_00DC 404664: 08 FLdPr local_param_0008 404667: 06 MemLdRfVar local_param_0038 40466A: 08 FLdPr local_param_0008 40466D: 8a MemLdStr 404670: 46 CVarStr local_0094 404673: 5d HardType 404674: Lead0/40 NeVarBool 404676: 1c BranchF: 4046E5 ImpAdCallFPR4 - снова вызов функции/процедуры, но уже 40520c. Раскрою секрет - это моя процедура GetCode. Чтоб написать нормальный кейген к этому крякмису, копайте ее. В листинге EXDEC есть такой код: Proc: 40520c 404AC8: Lead2/16 ILdRfDarg local_param_000C 404ACE: Lead0/eb FnLenVar 404AD2: 28 LitVarI2: ( local_0254 ) 0x1 (1) 404AD7: Lead0/9c SubVar ........................................... Хех, а почему процедура зовется 40520c, а начинается с 404AC8?? Потому что названия процедур даются по их концу, здесь это 40520c. Теперь надо бы запатчить, что все время выдавалось сообщение о правильности кода(как мы патчили JE на JMP и т.д.:)). Только тут способ немного извращенней. Команда BranchF - условный переход, начинается на 1C Команда Branch - безусловный переход, начинается на 1E Следовательно в HIEW меняем 1C на 1E по VA ".404676". И все нормально :)0 А вот если бы нам надо было вбить что-то вроде асмовского nop?? Вроде бы где-то в листингах псевдокодов я встречал подобную команду, но сейчас забыл :( тогда можно поставить безусловный переход на следующую команду! Как? Полностью команда у нас такая: 1C 9D 01. Где 019D - длина перехода, а 1C номер p-code функции. Длина перехода считается от начала процедуры. То есть 404548+19D. А для перехода на следующую процедуру нам нужна длина... 404679 - 404548 = 0131. Пропишем это в HIEW: 1E 13 01. И теперь всегда будет сообщение BAD C0DE, в независимости от правильности кода... Вот так. Удачного исследования P-Code программ! bi0w0rM[AHT] 22 июня 2004.
|
|
| |||||||||||||||||||||||