Автор: Broken Sword <brokensword@mail.ru>
Штирлиц шел по лесу и напоролся на сук.
- “Шли бы вы домой, девочки, война все-таки!”
Из личного дела:
Имя: Штирлиц 4.01
Вес: 738 кило
Дата рождения: 2001 год
Отец: Всеволод Лукьянин
Prelude
Наверное, нет такого человека, который никогда бы ничего не слышал о Штирлице. И речь в данной статье пойдет
не о В. Тихонове, и не об анекдотах, а о лучшем в своем роде расшифровщике-трансляторе, вернее, доведении оного до совершенства :).Любому из нас приходилось получать загадочные письма из сети, содержащие в себе прелюбопытные наборы значков и черточек. Разнообразие стандартов и кодировок породило на свет огромное количество
перекодировщиков. Во всем этом безобразном разнообразии отчетливо обозначились несколько особо продвинутых программулин. Мне почему то особенно запомнились только две – Bred и Штирлиц. И если первая ничем не достает и не просит на “покушать”, то вторая изрядно выводит из себя своим “рекламным окошком”, которое по заявлению самого автора “не мешает работать программе” (Лукьянин вообще парень с юмором). Но, ближе к делу…С чего начинается родина…
Родина, безусловно, начинается с отладчика, и не с простого
, а с большой буквы. Как вы уже догадались – это SoftIce, Многие из вас уже испугались и начали выводить кресты, однако я просто советую вам поставить на свою машину именно этот отладчик и пользуясь данным руководством в конце пути вы просто пожмете ему руку и… больше никуда не отпустите. Еще ОЧЕНЬ пригодится дизаcмер (я рекомендую ТОЛЬКО WDASM) и HIEW (который, как окажется в последствии, совершенно не понадобится, но в педагогических целях его неплохо бы заиметь).Больше нам реально ничего не понадобится…
Ах да, разве что еще ваш любимый выходной набор “мозги + прямые руки”. И конечно, листик с ручкой (запомните, ни один серьезный взлом не обходится без листика с ручкой, а еще лучше завести для этого дела специальную тетрадь, но это уже для извращенцев).Go Go Go...!
Итак, поехали! Запускаем
Shtirlitz.exe для того чтобы окончательно понять, чего же мы все таки хотим. А хотим мы убрать этот чертов баннер, ато он $%@##$ уже достал внатуре !!!Где же он ?! Вот он, сидит себе в углу, моргает. Подожди же, зараза…
SoftIce
у нас уже конечно же запущен…Сразу же жмем
ctrl-D, осмотримся, чего же у нас творится в данный момент… Оказавшись в любимом окне набиваем:addr
В ответ получим загадочную последовательность запущенных на
данный момент процессов. Где-то в самом конце списка (на всякий случай, перемещение по списку – клавиши [вверх] и [вниз]) мы просто обязаны увидеть строку такого содержания:Addr PID NAME
………… ………… …… ……….
xxxxxxxx xxxxxxxx xxxx Shtirlitz
где вместо “х”-ов будут
hex-цифры.Вот он, родимый!!! Привяжемся же к нему всей душой!!!
Набиваем:
addr xxxx
, где вместо иксов подставляем соотв. значение из колонки PID.Теперь, повторно набрав в строке
addr убеждаемся, что Штирлиц стал текущим процессом (т.е. голубым :).Далее. Добившись
того, чтобы Shtirlitz стал текущим процессом, можно смело узнать про него много всего полезного. Набиваем:hwnd Shtirlitz
(Shtirlitz,
кстати, в данном случае берется из колонки NAME)И что мы видим ? А видим мы длинный список инфы про нашего пациента. Чего мы вообще хотим ? Убрать баннеры… Смотрим, чего тут можно нарыть по нашей проблеме… Ага!!! Вот оно!!! Первой же строкой!!! И не стыдно
…?Shtirlitz.banner …
запомним.Теперь запускаем
WDASM. Грузим Shtirlitz.exe. Пошарим по файлу (теперь мы знаем чего искать). В строке поиска пишем banner. Ждем… Вуаля!* Reference To: GDI32.GetStockObject, Ord:00FAh
|
:00401B1C FF15B4E54400 Call dword ptr [0044E5B4]
:00401B22 50 push eax
:00401B23 6800080000 push 00000800
* Possible StringData Ref from Data Obj ->"Shtirlitz.Banner"
|
:00401B28 6804414400 push 00444104
:00401B2D B938BA4400 mov ecx, 0044BA38
:00401B32 E8BF6B0000 call 004086F6
:00401B37 84C0 test al, al
:00401B39 7473 je 00401BAE
:00401B3B 57 push edi
:00401B3C 56 push esi
:00401B3D 8B742418 mov esi, dword ptr [esp+18]
:00401B41 53 push ebx
:00401B42 55 push ebp
:00401B43 6800004086 push 86400000
:00401B48 56 push esi
* Reference To: USER32.AdjustWindowRect, Ord:0001h
|
:00401B49 FF156CE94400 Call dword ptr [0044E96C]
:00401B4F 8B7E08 mov edi, dword ptr [esi+08]
:00401B52 8B5E0C mov ebx, dword ptr [esi+0C]
:00401B55 2B3E sub edi, dword ptr [esi]
:00401B57 2B5E04 sub ebx, dword ptr [esi+04]
:00401B5A 55 push ebp
* Reference To: USER32.GetSystemMetrics, Ord:012Ch
|
:00401B5B 8B2D64E94400 mov ebp, dword ptr [0044E964]
:00401B61 FFD5 call ebp
:00401B63 83E814 sub eax, 00000014
:00401B66 6A01 push 00000001
:00401B68 894608 mov dword ptr [esi+08], eax
:00401B6B FFD5 call ebp
:00401B6D 8B4E08 mov ecx, dword ptr [esi+08]
:00401B70 83C0EC add eax, FFFFFFEC
:00401B73 89460C mov dword ptr [esi+0C], eax
:00401B76 2BCF sub ecx, edi
:00401B78 2BC3 sub eax, ebx
:00401B7A 890E mov dword ptr [esi], ecx
:00401B7C 894604 mov dword ptr [esi+04], eax
* Reference To: KERNEL32.GetTickCount, Ord:0145h
|
:00401B7F FF1598E74400 Call dword ptr [0044E798]
:00401B85 8B4C2410 mov ecx, dword ptr [esp+10]
:00401B89 89415C mov dword ptr [ecx+5C], eax
:00401B8C 33C0 xor eax, eax
:00401B8E 50 push eax
:00401B8F 50 push eax
:00401B90 50 push eax
:00401B91 56 push esi
:00401B92 6800004086 push 86400000
:00401B97 68D8B64400 push 0044B6D8
* Possible StringData Ref from Data Obj ->"Shtirlitz.Banner"
|
:00401B9C 6804414400 push 00444104
:00401BA1 6888000000 push 00000088
:00401BA6 E81D700000 call 00408BC8
:00401BAB 5B pop ebx
:00401BAC 5E pop esi
:00401BAD 5F pop edi
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401B39(C)
|
:00401BAE 5D pop ebp
:00401BAF 59 pop ecx
:00401BB0 C20800 ret 0008
Всеволод Лукьянин не только с юмором, а еще и очень хитер
! Видите, как ловко он вплел показ баннеров в код?! После непродолжительного разглядывания данного куска становиться очевидно :), что от результата, возвращаемого процедурой в строке:00401B32 E8BF6B0000 call 004086F6
зависит относится ли данный вызов непосредственно к показу рекламы или нет (если нет, то возвращаемый результат равен 0, и соответственно после
:00401B37 84C0 test al, al
мы перепрыгиваем “через овечку” прямо в конец куска (перелетаем полностью через весь показ
баннеров). Сам переход происходит в строке:00401B39 7473 je 00401BAE
Записывай пока на бумажку адрес
00401B39.Теперь напряжемся и вместе подумаем: как же сделать так, чтобы
“перелет через показ баннера” происходил в любом случае ? Выхода здесь два: либо загружать al перед je нулем посредством xor-а (mov не меняет флаги), либо просто изменить “74 на EB” (74 – код команды je, EB – код команды jmp; эти коды, наряду с CD (int) и др. кодами ты должен знать как “отче наш”)Конечно же, мы выбираем второй вариант…
Где наш
HIEW ? Вот и он. Запускаем. Ищем и меняем байт по адресу 00401B39h. Кстати, небольшое лирическое отступление.Для того, чтобы не бегать в
HIEW по всему коду в поисках адреса 00401B39 мы в режиме decode (выбирается по F4) жмем F5 и набираем его в строке для быстрого перехода. Набрав 401B39 нас сразу же пошлют подальше, хотя реально это смещение в окне HIEW мы действительно можем наблюдать белым по синему. Так в чем же дело? А дело в том, что это не те смещения… :) Все эти адреса генерятся из заголовка EXE файла, а РЕАЛЬНОЕ смещение в файле, как оно есть, можно увидеть, нажав в любимом HIEW-е комбинацию клавиш alt+F1. Все. Теперь все смещения – реальные, на любое из них можно прыгнуть по F5. Но куда же нам, все таки, in hell прыгать? Возвращаемся в любимый WDASM. Наводим курсор на строку00401B39 7473 je 00401BAE
А вот внизу то что нам нада
:Line:1734 Pg 35 and 36 of 2788 Code Data … @offset 00000F39 in file…
Видишь
@offset in file… ? Все. Теперь в HIEW прыгаем на F39 и меняем “74 на EB”.ЗОЛОТОЕ ПРАВИЛО: всегда, перед тем как править файл в
HIEW ВСЕГДА сохраняй его копиюИ до чего же мы докатились
? Запускаем Shtirlitz, смотрим…
Вот зараза…
Такой подлости мы явно не ожидали… “Файл поврежден, переустановите программу с дистрибутива”. Что же произошло? А произошло то, что
shtirlitz при загрузке проверяет сам себя на вшивость (или “на измену”). Как он это делает ? А очень просто! Считывает сам себя в память (ф-ция ReadFile), затем с первого байта начинает сканировать сам себя, попутно манипулируя своим “телом” через регистры. Короче говоря, вычисляет контрольную сумму всех своих байт. (Контрольная сумма на деле оказывается не простой суммой, а результатом махинаций с регистрами, XOR-ами и MOV-ами). Вникать в алгоритм нет никакого желания да и не нужно нам это пока… Но запомните: взломать прогу “красиво” можно только полностью проникнувшись подобными алгоритмами.Итак, восстанавливаем из сохраненной копии
Shtirlitz.exe и опять в SoftIce. Просто взять и установить бряк на ReadFile будет глупо, т.к. данная API-шка после запуска shtirlitz.exe вызывается тучу раз, и какой именно нужен нам – непонятно. Будем действовать старым дедовским методом. Лезем в WDASM. Смотрим, есть ли чего нить, что отвечает за загрузку файла. В строке поиска поочередно перебираем возможные варианты: сначала openfile. Найдено GetOpenFileName. Не то. CreateFile. О! То что нада! CreateFileA!Несколько слов по поводу данной апишки… Все что нам нужно знать про нее – это то, что перед ее вызовом последним в стек ляжет адрес на имя загружаемого файла
. Вот его то нам и нужно отлавливать и контролировать, во избежание вызова “лже-CreateFile”.Back to the SoftIce…
Набиваем:bpx CreateFileA
Запускаем Штирлица и ждем
срабатывания бряка… Есть! Смотрим, чего у нас лежит в стеке:dd esp
В окне данных видим:
00407289 00910BB0 …
Когда
SI отлавливает вызов API, управление передается на первую команду этой самой API, поэтому сейчас мы оказались на самом первом байте кода ф-ции CreateFile.Чего же это там у нас в окне данных… Ну первое число – понятно, откуда произошел вызов, оно нам не нада, а вот второе – это и есть указатель на имя открываемого файла
(у вас это может быть другое число). Лезем по нему:d 00910BB0
Облом…
Shtirlitz.loc какой то… А нам нужен Shtirlitz.exe. Но ничего! Ждем следующего вызова CreateFile… Жмем F5. И вот буквально тут же! Повторяем уже знакомые операции (dd esp), вот оно второе число: 00910910. Заглянем и туда (d 910910) – yes! Вот он, родимый! Shtirlitz.exe!!! Ну все!!! ВОТ ТЕПЕРЬ можно ставить бряк на ReadFile! НЕ ВЫХОДЯ ИЗ SI пишем:bpx ReadFile
Теперь
жмем F5, ждем… Вот он долгожданный бряк по ReadFile! Смотрим стек (dd esp). Видим:00405B00 00000060 00E90020 000A9400 ….
нас интересуют первые четыре числа. Первое число – адрес возврата
(не нада), второе число – хэндл файла (не нужен), третье число – уже интереснее (адрес, куда надо считывать файл), четвертое – сколько байт нада считывать.Четвертое число вообще очень интересное… Кстати,
ebx тоже равен этому же числу… Запомним это. Смотрим на калькуляторе: A9400h=693246d. А теперь угадай с трех раз, сколько весит файл Shtirlitz.exe ? Теперь можно точно сказать, что происходит подсчет контрольной суммы ВСЕГО файла целиком… Но ты не сиди – записывай все числа на бумажку. С комментариями, ато потом заблудишься.Все. Пришло время заняться делом. Как только мы оказались в начале апишки
ReadFile и посмотрели стек – жмем F12 (сам увидишь как это связано с первым числом). Теперь поехали трейсить! Запомни: видишь call – жми F10, чтобы не влезать в него. В других случаях – жмешь F8. Теперь главное вовремя остановиться… :). По ходу пьесы тебе часто придется вываливаться из SI, хотя бы даже для заглядывания в данную статью, поэтому перед выходом тебе ПРИДЕТСЯ набивать bc* (убрать все бряки). Так вот, для возврата тебе придется опять два раза отлавливать CreateFile, потом ReadFile… запаришься! Поэтому вспомни, что ebx был равен четвертому числу – а это ключ!!! Зная это, просто пишешь:bpx ReadFile if ebx==A9400
и ты в нужном месте в нужное время…!
Итак, трейсим… через несколько
F8 и парочки F10 мы попадаем в загадочную область:00423B1E: movzx…
…
inc esi
cmp esi, ebx
mov [ebp-08], ecx
00423B5E: jb 00423B1E
00423B60: …
Это какой то заговор… Обрати внимание на тот факт, что
esi в начале цикла равен нулю, а ebx – A9400 (или размеру файла Штирлиц.exe); я нарочно выделил inc esi и последующее сравнение с ebx – тут даже койоту ясно, что идет подсчет контрольной суммы всего файла. Ну что ж, любители острых ощущений могут просидеть так пару дней, давя F8, я предпочитаю (и вам советую) сделать так:bpx 00423B60
Это есть бряк на следующую после
jb команду, а сюда управление вернется только после того, как выполнится A9400 итераций. (вообще желательно выписать на бумажку значения ВСЕХ регистров и ячейки ebp-08 в этом месте, т.к. и ежу понятно – это единственные правильные значения, которые могут иметь место (ведь если бы мы “исправили” файл в HIEW, то значения регистров на выходе оказались бы совершенно иными). Вот значения регистров для “девственного” shtirlitz.exeEAX=00000016
ECX=000048D2
EDX=00000020
EDI=00E90020
dword [ebp-08]=ECX=000048D2
Кстати, как многие уже догадались
48D2 – это и есть контрольная сумма, запомним это число.Что теперь? Пока ничего, трейсим дальше…
:) Здесь нам встретятся два call-а, перелетаем их. Ждем ret-а… И вот мы вернулись непонятно куда – на00423744: cmp ax,si
00423747: jz 0042376A
Любознательные могут сами залезть в те два
call-а, я же просто скажу: после того, как мы оказались на 00423744 в esi всегда будет лежать 48D2h (помните его?), а вот в ax – то, что получилось из нашего shtirlitz.exe, и если он только не равен 48D2… то… сами понимаете.Ну что, опять в
00423747 замена jz на jmp ? И сколько это будет продолжаться ? Пробуем… (00423747=22B47 in file)Запускаем
… Ну вот!!! Теперь еще круче!!! Вообще ничего!!! Мда…Пришло время пораскинуть мозгами. Очевидно, что единственное, что поменялось в самом процессе работы программы – значение регистров после вычисления контрольной суммы. С одной стороны, весь цикл (00423
B1E-00423B5E) можно заменить на код типа такого:mov ecx,48D2h
mov edx,20h
….
т.е. галимо подогнать значения всех регистров, зная какими они выглядят в “девственном” Штирлице.
exe. Но, во-первых, это уродливо, а во вторых - это нас не спасет… (можете попробовать). Стоит только отметить, что обращение к области памяти с E90020h (там, где лежит копия файла shtirlitz.exe) происходит еще минимум 4 раза !!! Разбираться и отлавливать их все нет никакого желания, Всеволод очень неплохо постарался…Поэтому пойдем по другому пути… Помнишь, в самом начале мы заменили по адресу
:00401B39 7473 je 00401BAE
je
на jmp ? Так вот, что если править код не в самом файле, а непосредственно в памяти ??? Тогда никакой возни с контрольной суммой не возникнет !!! Отлично ! Заодно можно проверить, по тому ли пути мы вообще идем… Итак, берем “девственный” shtirlitz.exe, ставим в SI бряк на readfile при ebx==A9400, запускаем shtirlitz.exe… Теперь, правим байт:eb 401B39 eb
Жмем
F5… Yes! Никаких баннеров !!! Мы победили… Но… Не будем же мы в самом деле каждый раз при запуске Штирлица править байт в памяти !!!Но это уже и не нужно !!! Запустите
shtirlitz.exe и убедитесь в этом сами !!! Вот он пресловутый “баг в защите” !!!Postlude
Существует еще как минимум два способа взлома данной программы. Сам автор на своем сайте в форуме признался, что если запустить Штирлица более 200 раз или с параметром –
banoff в командной строке, то баннеры исчезнут… Но эти ли способы достойны настоящих хакеров?Вот как раз с первым способом (запустить 200 раз) и связан баг, который мы обнаружили.
FAQ
-
После того, как я пишу hwnd я ничего не вижуА
addr XXXX ты не забыл ? Еще это может быть из за несовместимости версии SoftIce-а с установленной версией винды. Так, например, в SI из DriverStudio 2.5 в XP наблюдается именно этот баг, хотя по заявлениям SI 2.5 полностью поддерживает XP. В XP безгючно (почти!) работает ТОЛЬКО SI из DriverPack 2.6 (и вообще именно этот пак я и рекомендую всем)-
Хочу исправить байт в HIEW, а оно ругается: “read-only mode”Закрой
WDASM-
Теперь ругается SoftIce: Symbol not definedВот горе ты мое… Ищи файл
winice.dat (в NT лежит он здесь: c:\windows\system32)Ищи
строку: EXP=C:\WINDOWS\system32\comdlg32.dllПосле нее дописывай таким же манером пути к нужным библиотекам (где лежат нужные
API-шки). Какие это такие нужные библиотеки – см. в WDASM-е в самом начале идет список, впиши их все – не ошибешься. И будь внимателен с названием API-шек (SI различает CreateFile и CreateFileA)Опять
SoftIce пищит: Syntax errorВнимательно набирай команды!!!
bpx readfile if ebx=A9400
-
ошибка!!! Должно быть два значка “=”Ломать
– не строить(
народная мудрость)
Материалы находятся на сайте http://cracklab.narod.ru/doc/