Автор: ORS <ors05@mail.ru>

Инструменты:
OllyDbg, W32Dasm

Исследуемая программа: @Text Replacer http://www.infortech.ru/prj/open/tr/

Описание:
Программа @Text Replacer предназначена для многострочного поиска и замены текста в файлах выбранной директории и поддиректорий с учетом регистра и игнорируемых символов - таких, как перевод строки, пробел и прочих.

Недостатки:
В незарегистрированной версии недоступны поиск и замена в файлах формата Word.

Пойдем по самому простому пути: не бедем регистрировать программу, а просто уберем ограничения.
После непродолжительных экспериментов выяснилось, что программа отказывается проводить операции с файлами с расширениями .doc и .rtf (если поменять расширение на другое, то можно проводить поиск), значит где-то проводится сравнение расширений найденых файлов с .doc и .rtf.
Чтобы это место TR.exe в W32Dasm и ищем строку doc.

Находим это:
* Reference To: MSVCRT._mbsicmp, Ord:015Fh
|
:00419872 8B3590374200 mov esi, dword ptr [00423790]
:00419878 8D956CFEFFFF lea edx, dword ptr [ebp+FFFFFE6C]

* Possible StringData Ref from Data Obj ->".doc"
|
:0041987E 6864CE4200 push 0042CE64
:00419883 52 push edx
:00419884 FFD6 call esi <- здесь происходит сравнение (mbsicmp)
:00419886 83C41C add esp, 0000001C
:00419889 85C0 test eax, eax
:0041988B 0F84D1000000 je 00419962

И это:
* Reference To: MSVCRT._mbsicmp, Ord:015Fh
|
:0041C40D 8B3D90374200 mov edi, dword ptr [00423790]
:0041C413 8D95B4FEFFFF lea edx, dword ptr [ebp+FFFFFEB4]

* Possible StringData Ref from Data Obj ->".doc"
|
:0041C419 6864CE4200 push 0042CE64
:0041C41E 52 push edx
:0041C41F 8975FC mov dword ptr [ebp-04], esi
:0041C422 FFD7 call edi <- здесь тоже mbsicmp
:0041C424 83C408 add esp, 00000008
:0041C427 85C0 test eax, eax
:0041C429 7415 je 0041C440

Запускаем TR.exe в OllyDbg, ставим брейкпоинты по найденным адресами производим поиск в папке с файлами Word.

Останавливаемся по адресу 0041C422, смотрим что в стеке:

00B8FA38 00B8FA4C |s1 = ".doc" <- расширение файла00B8FA3C 0042CE64 \s2 = ".doc" <- строка для сравнения

Можно конечно поменять условный переход ниже (0041C429), но после замены произведенной таким образом документы, созданные в Word 2002 перестают открываться. Поэтому идем дальше по F8 и попадаем в довольно странное место:

0041C4EA A1 DB A1 <- мы здесь0041C4EB 6C DB 6C ; CHAR 'l'0041C4EC D1 DB D10041C4ED 42 DB 42 ; CHAR 'B'0041C4EE 00 DB 000041C4EF BB DB BB0041C4F0 04 DB 040041C4F1 00 DB 000041C4F2 00 DB 00

Похоже на данные, а не на код, и что еще более странно это начинает выполняться.
Это и есть полиморфный код, чтобы он отображался нормально нужно снова произвести анализ (Всплывающее меню/Analysis/Analyse code).

Во время проверки на зарегистрированнось происходит чтение файла лицензии tr.ipml (как написано в справке). Создадим его в папке с программой и поставим брейкпоинт на CreateFileA нажимаем F9 и останавливаемся здесь:

0040A878 . FF15 98304200 CALL DWORD PTR DS:[<&KERNEL32.CreateFile>; \CreateFileA

В этой процедуре происходит проверка на зарегестрированность. Можно в ней не разбираться, а просто нажать Ctrl+F9, и выти из нее сюда:

0041C4A4 . E8 27E1FEFF CALL TR.0040A5D0 <- Функция проверки0041C4A9 . 8D4D B4 LEA ECX,DWORD PTR SS:[EBP-4C]0041C4AC . A3 6CD14200 MOV DWORD PTR DS:[42D16C],EAX <- Записываем результат проверки...0041C4EA > A1 6CD14200 MOV EAX,DWORD PTR DS:[42D16C]0041C4EF . BB 04000000 MOV EBX,40041C4F4 . 3BC3 CMP EAX,EBX <- Результат проверки сравнивается с 40041C4F6 . 75 3A JNZ SHORT TR.0041C532

Если программа зарегистрирована, то функция проверки возвращает 4. Если сократить ее до

mov eax, 4ret

то при первом поиске вылезает ошибка, поэтому надо изменить переход по адресу 0041C4F6 на противоположный. Теперь все работает, но только под отладчиком: это полиморфный код и сохранить изменение не получится.

Исследуем как происходит расшифровка кода:
До запуска программы поставим hardware breakpoint на запись по адресу 0041C4F6, запустим и остановимся здесь:

00418656 8A9B B84C4200 MOV BL,BYTE PTR DS:[EBX+424CB8]0041865C 32D9 XOR BL,CL0041865E 8818 MOV BYTE PTR DS:[EAX],BL00418660 B3 EB MOV BL,0EB00418662 8B4D C4 MOV ECX,DWORD PTR SS:[EBP-3C]00418665 40 INC EAX00418666 8D4C0E F4 LEA ECX,DWORD PTR DS:[ESI+ECX-C]0041866A 3BC1 CMP EAX,ECX0041866C ^72 82 JB SHORT TR.004185F0

Здесь происходит расшифровка кода при помощи XOR. Можно кнечно разобраться в алгоритме и узнать каким должен быть изменяемый байт в зашифрованном состоянии, но можно поступить проще:
Уже расшифрованный байт (в нашем случае заменяем 75 на 74) надо зашифровать XOR с тем же ключем, которым происходила его расшифровка. Но как это сделать?:
Перезапускаем программу и до запуска изменяем байт по адресу 0041C4F6 на 74. Нажимаем F9 (предварительно удалив Hardware breakpoint), и смотрим что находиться по адресу 0041C4F6. Это и есть нужный нам байт в зашифрованном состоянии (EF). Теперь можно заменить этот байт в файле программы.
Теперь все должно работать. Запускаем поиск и … получаем сообщение “Исполняемый модуль поврежден”. Но ведь под отладчиком все работает. Вывод один: программа проверяет контрольную сумму своего файла.
Чтобы найти место проверки ставим брейкпоинт на CreateFileA (после запуска программы, т.к. проверка находится в зашифрованном коде), нажимаем кнопку “Поиск” и останавливаемся здесь:

00414A2C FF15 98304200 CALL DWORD PTR DS:[<&KERNEL32.CreateFile>; kernel32.CreateFileA

В стеке:

0012F2B4 0012F2DC |FileName = "D:\Program Files\@Text Replacer\TR.exe" <- открывает сам себя0012F2B8 80000000 |Access = GENERIC_READ <- для чтения0012F2BC 00000001 |ShareMode = FILE_SHARE_READ0012F2C0 00000000 |pSecurity = NULL0012F2C4 00000003 |Mode = OPEN_EXISTING0012F2C8 00000080 |Attributes = NORMAL0012F2CC 00000000 \hTemplateFile = NULL

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

00414B62 . 74 5A JE SHORT TR.00414BBE <- заменить на jmp00414B64 > 8D4D F0 LEA ECX,DWORD PTR SS:[EBP-10]00414B67 . E8 34AD0000 CALL 00414B6C . 68 3AE00000 PUSH 0E03A00414B71 . 8D4D F0 LEA ECX,DWORD PTR SS:[EBP-10]00414B74 . 897D FC MOV DWORD PTR SS:[EBP-4],EDI00414B77 . E8 36B00000 CALL 00414B7C . 6A 0C PUSH 0C00414B7E . E8 B5AE0000 CALL 00414B83 . 8BF0 MOV ESI,EAX00414B85 . 83C4 04 ADD ESP,400414B88 . 8975 EC MOV DWORD PTR SS:[EBP-14],ESI00414B8B . 3BF7 CMP ESI,EDI00414B8D . C645 FC 01 MOV BYTE PTR SS:[EBP-4],100414B91 . 74 14 JE SHORT TR.00414BA700414B93 . 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10]00414B96 . 51 PUSH ECX ; /Arg100414B97 . 8BCE MOV ECX,ESI ; |00414B99 . FF15 50314200 CALL DWORD PTR DS:[<&Logger.??0CFatalExc>; \??0CFatalException@@QAE@PBD@Z <- сообщение "Исполняемый модуль поврежден"

Изменяем переход по адресу 00414B62, но это не единственное место где вылезает ошибка.
??0CFatalException@@QAE@PBD@Z вызывается 7 раз, изменяем 7 соответсвующих переходов по адресам: 00414B62, 0040A800, 00414DF2, 0041B583, 00403013, 0040DC7D, 00414270.
Находим байты в зашифрованном состоянии и применяем изменения в полиморфном коде, также как делали раньше.
Теперь программа полностью работает в результате изменения полиморфного кода, которые многие разработчики считают не взламываемым или хотя-бы не пропатчиваемым.

Список пропатченых байтов:

0041C4F6 EE->EF00414B62 75->EA0040A800 EE->7100414DF2 CC->530041B583 D3->4C00403013 49->D60040DC7D 5B->C400414270 F1->6E

P.S. Использовать только в образовательных целях.