Автор: ARCHANGEL <crackZZone@mail.ru>

Начало
Всем снова привет. Наконец закончилась сессия, и у меня появилось время что-то написать. Давненько я уже не “светился” на cracklab, за это время админы нашего любимого почтового сервера mail.ru успели прикрыть мой ящичек без обьяснения причин,
так что все желающие со мной пообщаться пишите на crackZZone@mail.ru. Посмотрим, сколько проживёт этот ящик :).
Ну, теперь настало время перейти к делу. Сегодня мы с вами займёмся исследованием, наверное, самой популярной на сегодня софтины. Эта вещица стопудово есть у каждого уважающего себя юзверя, но, что самое главное, она поможет нам разобраться со многими самыми популярными вопросами и даже (не побоюсь этого слова:) проблемами современного крэкерства. Дамы (хотя, это вряд ли:) и господа, сегодня мы познакомимся с видом изнутри на … Total Commander 6!!!
Знаю, кто-то уже во всю орёт, что видел крэки на эту программу. Народ, если я не прав, скажите мне об этом, но, по-моему, в нете можно практически на всё найти крэк, так что же теперь, ничего не исследовать?
На самом деле, Total привлекал меня давно своей разноплановостью защиты, а также разноплановостью его взлома другими крэкерами. Но обо всём по порядку.

Вступление - сага о Total Commander
Мало кто может вспомнить тот момент, когда на его компе вместо славного Far manager впервые засветилась надпись типа Windows Commander v x.x. До шестой версии Total был вовсе не Total, а Windows Commander. Знаменитая же шестая версия появилась в 2003, вот что об этом написали в известном “Хакере”:
Более полугода ждали фаны появления новой версии Total Commander. Все надеялись, что этот классический двухпанельный менеджер файлов порадует своих пользователей чем-то необычным и революционным. Самое забавное, что членораздельно объяснить, в чем же это “необычное и революционное” могло бы заключаться, никто не мог, поскольку большинство юзеров и “старый” Total полностью устраивал. Однако вот она - новая версия. И не какая-нибудь 5.52, а сразу - 6.0! С замиранием сердца устанавливаешь, запускаешь и… Тут же вздыхаешь с облегчением. Надо же, не обманули! Одного взгляда на экран достаточно, чтобы понять, что одними косметическими изменениями тут дело явно не обошлось…

Но, как вы сами понимаете, с 2003 прощло достаточно много времени, и развитие этого файлового менеджера не стоит на месте. На сегодня пиком совершенства является версия 6.54 с названием Podarok Edition (или каким-то близким к этому:). И это не учитывая многочисленных плагинов на всех языках мира, которые могут выполнить практически всё (может, даже картошку
почистить:). Ну, с прогой, вроде, всё ясно. Но что же в ней надо ломать?

В чём сила, брат?
Как и антигерои фильма “Брат”, создатели всем полюбившегося Total Commander считают, что сила в деньгах. За своё творение они просят 28 у.е. Не знаю, как вы, а я - бедный студент. На самом деле, ещё одним “бедным студентом”, похоже, является некий Tir Na Nog - автор крэка, который, по-моему, является самым популярным для данной софтины. С развитием тотала пираты (так теперь принято называть девушек до тридцати лет, которых хозяин поставил торговать дисками:) просто делают инсталляшку, в которую кладут уже взломанные файлы, так что установить других авторов крэков не представляется возможным. Тем не менее, все эти крэки не универсальны. Стоит лишь поставить дополнительный плагинпереустановить виндузапустить другую версию тотала и т.д., и крэка - как и не было. Каждый из крэков глючит на что-то своё, поэтому начнём с нуля.

Ограничения
Ограничений здесь, как это ни странно, практически нет. Только надпись NOT REGISTERED в заголовке главного окна и наг-скрин в виде окна, которое просит вас нажать на кнопку с цифрой, светящейся на форме чуть выше кнопки. Никаких функциональных ограничений в софтине нет, и в справке к тоталу про такие тоже ничего не сказано. Поэтому все крэкеры и патчат его, хотя можно и ключ искать, но мы тоже будем патчить, и, забегая наперёд, скажу, что это будет патч только наполовину, а наполовину лоадер. Как такое возможно? Оставайтесь с нами, и узнаете:)

Взлом
Для начала необходимо запастись софтом. Вот что нам сегодня понадобится:

1. PeID v 0.94 + плагины - для анализа подопытной проги
2. Upx 2.02 - распаковка (ну, чтоб не руками:), в принципе, можно и другую версию
3. OllyDebug v1.10 + CommandBar - просто отличный отладчик
4. LordPe Deluxe by Yoda - для корректировки ехе-файла
5. CFF Explorer IV - для простого добавления секций
6. Restorator 3.00 - можно любой другой редактор ресурсов, это для определения, где какое окно

Теперь давайте посмотрим на наш ехе. Называется он totalcmd.exe, так вот на него и натравливаем PeID. И в ответ:
UPX 0.89.6 - 1.02 / 1.05 - 1.24 (Delphi) stub -> Markus & Laszlo [Overlay]
Ну, это не страшно, вот для этого мы и приготовили upx. Следующий этап называется распаковкой (громкое название:). Думаю, всем ясно, что же будет дальше, а дальше вот что:

upx -d totalcmd.exe

Только на всякий случай сохраните оригинальный, нераспакованный файл, он нам ещё пригодится, но советую вообще
всегда так делать - мало ли какой приз нам разработчики приготовили. Так вот, теперь на распакованный файл натравим PeiD, и он ответит что-то в этом духе:
Borland Delphi 2.0

Отлично, теперь, чтоб окончательно убедиться, что распаковка произошла успешно, запустим на выполнение распакованный файл. Он запуститься то запустился, да только через 4-5 секунд выдал сообщение, что, типа, файл был модифицирован, нужно проверить всё на наличие вирусов и т.д., после чего благополучно закрылся. Нехорошо, очень нехорошо. Будем что-то делать…

Контрольные суммы
Контрольные суммы
Почему-то, когда разговор заходит о проверке целостности файла, большинство сразу вспоминает известный CRC32. Но люди, посмотрите вокруг, таких алгоритмов и методов их реализации гораздо больше, чем просто тупое вычисление CRC32 контрольной суммы для файла. Проверок на целостность можно придумать сколько угодно. Можно проверять размер файла, т.е. сколько в нём байт, можно проверять на целостность только лишь фрагмент файла, а не весь ехе, при этом эту операцию можно выполнять над кодом в памяти, а не над тем кодом, который находится на диске. При этом можно использовать любой алгоритм, как криптографический, так и самое примитивное побайтовое сложение. Но все эти проверки можно условно разделить на две части:

1. Проверка кода на диске.
2. Проверка кода в памяти.

У каждого из них есть свои сильные и слабые стороны. Для варианта под номером 1 можно применять лоадеры, ведь при использовании лоадера код файла на дисковом пространстве не модифицируется, а модифицируется непосредственно перед выполнением. С вариантом №2 лоадеры не канают, но т.к. программеры очень ленивые (почти как мы с вами:), то такие проверки они реализуют как правило через API ReadProcessMemory - согласитесь, эта функция сама по себе очень подозрительна, так что отловить такие проверки ничего не стоит. Но тут возникают проблемы другого рода - во-первых, использование лоадера не есть гуд, т.к. лоадеры в своём большинстве (если не все) аппаратно зависимы, т.е. на одном компьютере они выполняются быстрее, а на другом медленне. Это приводит к тому, что на медленных машинах приходится добавлять в код лоадера задержку, чтоб он не выполнился раньше, чем приложение загрузится в память, но нужно также просчитать время, чтоб он и не слишком затягивал с выполнением. Именно поэтому лоадеры и не очень популярны. С вариантом №2 всё вроде бы ясно, но что делать, если для подсчёта контрольной суммы используется что-то типа MD5, который вряд ли получится обратить. В зависимости от варианта подсчёта контрольной суммы и зависит выход и сложившейся ситуации, поэтому вначале определим, из памяти или с диска программа ведёт проверку на целостность. Также нужно определить степень сложности алгоритма вычисления контрольной суммы. Некоторые для этого используют плагин к PeID под названием KANAL v2.90. Давайте посмотрим, что он покажет:

ADLER32 :: 00195E6E :: 00596A6E
The reference is above.
BASE64 table :: 00081BA4 :: 004827A4
Referenced at 0059A70C
BASE64 table :: 0009B714 :: 0049C314
Referenced at 0059AE3C
CRC32 [poly] :: 00195DD2 :: 005969D2
The reference is above.
MD4 :: 0005E6E4 :: 0045F2E4
The reference is above.
MD5 :: 0005DE63 :: 0045EA63
The reference is above.
SHA1 [Compress] :: 0007493B :: 0047553B
The reference is above.
ZLIB deflate [word] :: 001997A8 :: 0059A7A8
Referenced at 0048CCB6
Referenced at 0048CEAF
{Big number} :: 000C9CB8 :: 004CA8B8
Referenced at 004CA820
{Big number} :: 000C9D8C :: 004CA98C
Referenced at 004CA82D
{Big number} :: 000C9E20 :: 004CAA20
Referenced at 004CA83A
{Big number} :: 000CA9B0 :: 004CB5B0
Referenced at 004CAFFE

Короче говоря, чего тут только нет. Ссылки даются практически на всё адресное пространство проги. Из того, что выдал мне вышеупомянутый плагин, я понял, что обратить саму проверку будет непросто, поэтому решил пойти другим путём.
Конечно, некоторые скажут, что нужно отловить MessageBoxA, который всплывает и сообщает нам о том, что файл был изменён, потом найти переход на это сообщение и поменять этот переход так, чтоб он не выполнялся, и это сработает, но не так, как нам бы хотелось. Стоит лишь открыть какое-то меню, а потом закрыть, как вся прога завершает работу. Нехорошо.
Поэтому давайте вернёмся, так сказать, к истокам. Определим, что именно проверяет прога. Сделать это очень просто - грузим в отладчик ещё запакованный ехе, меняет в отладчике какой-то байт из тех, которые равны 00 на произвольное значение и запускаем прогу. Как видите, никаких сообщений мы не получили. Значит, проверяется дисковое пространство (т.е. файл на жестком диске). Можно было бы использовать лоадер, но у меня есть другая идея - а что, если сохранить оригинальный файл в той же папке, что и модифицированный, но с именем, скажем tlcmd.bak, а потом вместо того, что прога проверяла ехе, заставить
её проверять этот самый tlcmd.bak (или как вы его назовёте), в котором мы не поменяем ни одного байтика. Тогда проверка будет проходить на ура. Теперь давайте рассмотрим этот механизм подробнее…
Подготовка рабочего пространства
Прежде чем добавлять какой-либо свой код в прогу, я обычно ищу в ней свободное место, т.е. нули. После распаковки тотала я заметил, что нулей, которые в нём есть, будет недостаточно для реализации моих планов. Поэтому я вначале сделал всему тоталу Rebuild Pe, чтоб имеющиеся там нули меня не отвлекали, а потом добавил к нему ещё одну секцию. Многие новички спросят, как я это сделал. Очень просто - открыл totalcmd.exe с помощью CFF Explorer, далее:
Section Headers[x]->клик правой кнопкой на последней секции->Add Section(Empty Space)
В появившемся окне нас просят ввести количество байт (размер) для новой секции. Я ввёл с запасом 1000h. Потом, если что, всегда можно сделать ещё один Rebuild Pe:).
Обход проверки контрольной суммы
Для того, чтоб обойти проверку подсчёта контрольной суммы, нужно хотя бы в общем понять принцип её осуществления. Ну, думаю, что в общем этот принцип итак ясен: берётся файл, с него считываются какие-то байты, над ними проводятся какие-то вычисления и т.д. Но нас волнует только как он берётся. Пока нового тут ещё не придумали, это стандартная CreateFileA, которая должна вернуть хэндл файла, имя которого передано ей в качестве аргумента. Недолго думая, пишем в CommandBar:
bpx CreateFileA
Далее жмём F9 в отладчике (для танкистов - в отладчик был загружен распакованный тотал с новой секцией) и в третий раз прервавшись по адресу 0043F646 видим, что в качестве аргумента передаётся наш ехе, заменим его под отладчиком на tlcmd.bak и продолжим выполнение. Как видите, он запустился как ни в чём ни бывало. Теперь нужно автоматизировать этот процесс. Вначале я дам словесное описание алгоритму обхода проверки, а потом уже приведу его код.
Нам необходимо изменить строку с полным адресом нашего ехе-файла так, что в конце вместо totalcmd.exe было написано tlcmd.bak. Но пользователь может изменить имя нашего ехе, в то время как имя tlcmd.bak должно оставаться константой. Таким образом, алгоритм будет универсальным при любом имени ехе-файла. В результате наблюдений я установил, что первый файл с расширением ехе, который передаётся в качестве аргумента функции CreateFileA, это именно наш totalcmd.exe, что существенно упрощает задачу. Вначале мы заменим инструкцию call CreateFileA по адресу 0043F646 на JMP 00612000. Соответственно, по адресу 00612000 будет начало алгоритма обхода проверки. Когда он отработает, мы вернёмся на одну инструкцию ниже, т.е. на адрес 0043F64B. Перед вызовом CreateFileA в eax будет содержаться адрес строки нашего totalcmd.exe (или это будет другое имя), поэтому мы в этой строке будем искать точку, т.е. символ, который разделяет имя файла и расширение файла. Далее, найдя точку, мы проверим, не являются ли два последующих за точкой символа символами “е” и “х”, ведь если это так, значит мы нашли то, что нам нужно, т.е. это адрес нашего ехе, а если нет, то мы просто выполним CreateFileA и вернёмся в основной код. Если же у нас в руках уже нужный нам адрес, то теперь мы в строке будем искать последний символ “”, т.к. наш ехе может быть установлен в любую директорию, и после последнего такого символа идёт его имя, которого мы не знаем. Так вот, найдя адрес последнего символа “”, прибавим к нему 1, и, начиная с этой позиции, запишем туда “tlcmd.bak”. После чего изменим код с JMP 00612000 обратно на call CreateFileA, и всё тип-топ.
А вот и код:

00612000 60 PUSHAD \сохраним регистры
00612001 9C PUSHFD \сохраним флаги
00612002 B3 2E MOV BL,2E \запишем в bl код символа "."
00612004 B5 65 MOV CH,65 \запишем в CH код символа "е"
00612006 B1 78 MOV CL,78 \запишем в CL код символа "х"
00612008 3818 CMP BYTE PTR DS:[EAX],BL \сравним символ из строки с адресом с символом "."
0061200A 74 15 JE SHORT totalcmd.00612021 \переход, если равно
0061200C 8038 00 CMP BYTE PTR DS:[EAX],0 \определим, не законилась ли строка
0061200F 74 03 JE SHORT totalcmd.00612014 \переход, если закончилась
00612011 40 INC EAX \переход к следующему символу строки
00612012 ^EB F4 JMP SHORT totalcmd.00612008 \переход на указаный адрес
00612014 9D POPFD \восстановим флаги
00612015 61 POPAD \восстановим регистры
00612016 FF15 E8815A00 CALL DWORD PTR DS:[<&KERNEL32.CreateFile>; kernel32.CreateFileA
0061201C -E9 2AD6E2FF JMP totalcmd.0043F64B \переход на указаный адрес
00612021 3868 01 CMP BYTE PTR DS:[EAX+1],CH \сравним символ строки с символом "е"
00612024 ^75 E6 JNZ SHORT totalcmd.0061200C \переход, если не равно
00612026 3848 02 CMP BYTE PTR DS:[EAX+2],CL \сравним символ строки с символом "х"
00612029 ^75 E1 JNZ SHORT totalcmd.0061200C \переход, если не равно
0061202B 8038 5C CMP BYTE PTR DS:[EAX],5C \сравним сивол строки с символм ""
0061202E 74 03 JE SHORT totalcmd.00612033 \переход, если равно
00612030 48 DEC EAX \переход к предыдущему символу строки
00612031 ^EB F8 JMP SHORT totalcmd.0061202B \переход по указаному адресу
00612033 BA 58206100 MOV EDX,totalcmd.00612058 ; ASCII "tlcmd.bak" no comments:)
00612038 40 INC EAX \переход к следующему символу строки
00612039 8A1A MOV BL,BYTE PTR DS:[EDX] \запись текущего символа константы в регистр BL
0061203B 8818 MOV BYTE PTR DS:[EAX],BL \замена текущего символа строки текущим символом константы
0061203D 803A 00 CMP BYTE PTR DS:[EDX],0 \проверка, не закончилась ли константа
00612040 74 03 JE SHORT totalcmd.00612045 \переход, если закончилась
00612042 42 INC EDX \переход к следующему символу константы
00612043 ^EB F3 JMP SHORT totalcmd.00612038 \переход по указаному адресу
00612045 C705 47F64300 41>MOV DWORD PTR DS:[43F647],FFFC5B41\восстановление call CreateFileA по адресу
0061204F C605 46F64300 E8 MOV BYTE PTR DS:[43F646],0E8 \0043F646
00612056 ^EB BC JMP SHORT totalcmd.00612014 \переход по указаному адресу

С проверкой контрольной суммы покончено, идём дальше. Да, чуть не забыл, что бы всё это работало, нужно изменить флаги секции CODE, а именно поставить галку напротив Writeable, сделать это можно с помощью LordPe, мне вообще с ним удобнее работать, но можно и с помощью CFF Explorer. Если этого не сделать, то не выполнятся данные команды:

00612045 C705 47F64300 41>MOV DWORD PTR DS:[43F647],FFFC5B41\восстановление call CreateFileA по адресу
0061204F C605 46F64300 E8 MOV BYTE PTR DS:[43F646],0E8 \0043F646

Как изменить заголовок окна, т.е. убрать надпись NOT REGISTERED, я рассказывать не буду, просто скажу, что за установку заголовка отвечает функция SetWindowTextA, а вы уж сами думайте, хотя там и думать нечего, но я не буду тут про это писать, а то мы так с вами скоро до таблицы умножения дойдём.
Экскурс в работу с окнами
Сейчас нам предстоит убрать наг-форму, которая лично меня раздражает больше всего. Для этого давайте обсудим, так сказать, начальные условия. Будем считать, что тотал является демкой, т.е. в нём не предусмотрена возможность запуска без этого нага. Поэтому наг не получится убрать, изменив в проге какой-то переход. Пойдём другим путём. Давайте перечислим все этапы, которые нужно пройти окну для появления на экране.

1. Создание окна.
2. Создание компонентов окна.
3. Отображение окна.
4. Действия, деляющие окно доступным (как это ещё сказать:).
5. Действия, деляющие окно активным.

Отсюда вывод, что наше наг-окно нужно скрыть, главное окно сделать доступным (таким, чтоб оно на нажатие кнопок реагировало) и активным (чтоб синим светилось). Это можно сделать с помощью API функций ShowWindow, EnableWindow и DefWindowProcA. Но перед этим нужно определить хэндлы интересующих нас окон. Это можно сделать с помощью API FindWindow. Вся проблема заключается в том, что оччччень сложно найти место в коде проги, куда бы можно было впихнуть выполнение нашего кода. Нет, я сейчас говорю не о нулях. Просто если окно ещё не отобразилось, то FindWindow его не найдёт и т.д. Но мы и не будем искать такое место, мы создадим свой собственный отдельный поток, который будет выполняться одновременно с главным. В этом и заключается идея аппаратно независимого лоадера. Да что тут говорить, сейчас поймёте:

00612073 > 60 PUSHAD
00612074 9C PUSHFD
00612075 68 98206100 PUSH totalcmd.00612098 \адрес, по которому будет сохранён ID потока
0061207A 6A 00 PUSH 0
0061207C 6A 00 PUSH 0
0061207E 68 9C206100 PUSH totalcmd.0061209C \код, с которого начнётся выполнение потока
00612083 68 00050000 PUSH 500
00612088 6A 00 PUSH 0
0061208A FF15 B0815A00 CALL DWORD PTR DS:[<&KERNEL32.CreateThre>; kernel32.CreateThread
00612090 9D POPFD
00612091 61 POPAD
00612092 -E9 6565F8FF JMP totalcmd.005985FC

Прога начинает выпольняться с этого кода, а потом делает прыжок на свой ОЕР. Для этого в LordPe в поле ОЕР впишем адрес 00212073 (00612073-00400000). А вот код самого потока:

0061209C 68 AC8A5900 PUSH totalcmd.00598AAC ; ASCII "Total Commander"
006120A1 68 B8845900 PUSH totalcmd.005984B8 ; ASCII "TTOTAL_CMD"
006120A6 FF15 2C885A00 CALL DWORD PTR DS:[<&user32.FindWindowA>>; USER32.FindWindowA
006120AC 83F8 00 CMP EAX,0
006120AF ^74 EB JE SHORT totalcmd.0061209C
006120B1 50 PUSH EAX
006120B2 6A 00 PUSH 0
006120B4 90 NOP
006120B5 90 NOP
006120B6 90 NOP
006120B7 68 62206100 PUSH totalcmd.00612062 ; ASCII "TNASTYNAGSCREEN"
006120BC FF15 2C885A00 CALL DWORD PTR DS:[<&user32.FindWindowA>>; USER32.FindWindowA
006120C2 83F8 00 CMP EAX,0
006120C5 ^74 EB JE SHORT totalcmd.006120B2
006120C7 6A 00 PUSH 0
006120C9 50 PUSH EAX
006120CA FF15 18865A00 CALL DWORD PTR DS:[<&user32.ShowWindow>] ; USER32.ShowWindow
006120D0 5B POP EBX
006120D1 6A 01 PUSH 1
006120D3 53 PUSH EBX
006120D4 FF15 48885A00 CALL DWORD PTR DS:[<&user32.EnableWindow>; USER32.EnableWindow
006120DA 6A 05 PUSH 5
006120DC 53 PUSH EBX
006120DD FF15 18865A00 CALL DWORD PTR DS:[<&user32.ShowWindow>] ; USER32.ShowWindow
006120E3 6A 00 PUSH 0
006120E5 6A 01 PUSH 1
006120E7 68 86000000 PUSH 86
006120EC 53 PUSH EBX
006120ED FF15 90885A00 CALL DWORD PTR DS:[<&user32.DefWindowPro>; USER32.DefWindowProcA
006120F3 68 F6206100 PUSH totalcmd.006120F6
006120F8 68 98206100 PUSH totalcmd.00612098
006120FD FF15 A0835A00 CALL DWORD PTR DS:[<&KERNEL32.GetExitCod>; kernel32.GetExitCodeThread
00612103 68 F6206100 PUSH totalcmd.006120F6
00612108 FF15 AC815A00 CALL DWORD PTR DS:[<&KERNEL32.ExitThread>; kernel32.ExitThread

В принципе, комментировать тут нечего, алгоритм прост донельзя, про все эти функции читайте в Microsoft® Win32® Programmer’s Reference. Хочу сказать, что Restorator нам нужен был для того, чтоб определить класс главного окна (TTOTAL_CMD) и класс нага (TNASTYNAGSCREEN). Функция FindWindowA может искать окно только по его классу, а вместо заголовка ей можно передавать 0. Напомню, как патчить ехе в Ольке:
выделяем изменённый код->правой кнопкой мыши по нему->Copy to Executable->Selection->со всем соглашаемся
Теперь, если вы проделали всё так же, как и я, то у вас теперь есть универсальный крэк ко всем версиям тотала. Правда, ехе от версии к версии немного разные, но если взять ехе из одной версии и запускать совместно с файлами другой версии, то всё будет в шоколаде. Правда, этот крэк начинает глючить, если вы запускаете вторую копию тотала, т.к. наш поток ищет окна в первой и во второй, находит их в первой, а вторая пашет, как не взломанная. Но тут к нам на помощь приходит…арма. Армой запаковываем наш ехе с опцией Allow Only One Copy. Остальные опции по вкусу. Многим этот выход не понравиться, но, как ни крути, а это один из самых-самых крэков, т.к. он меняет только один файл (добавляет еще tlcmd.bak) и работает со всеми версиями.
Финал
Хотелось бы поблагодарить cracklab за размещение моих статей, отдельно поблагодарить Ara за советы в форуме, конечно, большое спасибо моим друзьям, респект RSI за, по-моему, на сегодняшний день, самые чёткие статьи на всём cracklab, ну, и, конечно же, спасибо всем, кто пересилил себя и дочитал до конца этот изврат, ведь релизить этот крэк я не собираюсь.
To be continued…
З.Ы. В процессе, так сказать, бета тестинга, было выявлено, что для того, чтоб избавиться от тупово сообщения про какое-то неактивное окно нужно сделать так:

005747F2 . EB 1A JMP SHORT totalcmd.0057480E

Теперь вроде всё…