Убираем баннеры в "Штирлице" или Баг в защите — Архив WASM.RU
Штирлиц шел по лесу и напоролся на сук.
- "Шли бы вы домой, девочки, война все-таки!"Из личного дела:
Код (Text):
Имя: Штирлиц 4.01 Вес: 738 кило Дата рождения: 2001 год Отец: Всеволод ЛукьянинPrelude
Наверное, нет такого человека, который никогда бы ничего не слышал о Штирлице. И речь в данной статье пойдет не о В. Тихонове, и не об анекдотах, а о лучшем в своем роде расшифровщике-трансляторе, вернее, о доведении оного до совершенства .
Любому из нас приходилось получать загадочные письма из сети, содержащие в себе прелюбопытные наборы значков и черточек. Разнообразие стандартов и кодировок породило на свет огромное количество перекодировщиков. Во всем этом безобразном разнообразии отчетливо обозначились несколько особо продвинутых программулин. Мне почему то особенно запомнились только две – Bred и Штирлиц. И если первая ничем не достает и не просит на "покушать", то вторая изрядно выводит из себя своим "рекламным окошком", которое по заявлению самого автора "не мешает работать программе" (Лукьянин вообще парень с юмором). Но, ближе к делу...
С чего начинается родина…
Родина, безусловно, начинается с отладчика, и не с простого, а с большой буквы. Как вы уже догадались – это SoftIce, Многие из вас уже испугались и начали выводить кресты, однако я просто советую вам поставить на свою машину именно этот отладчик и пользуясь данным руководством в конце пути вы просто пожмете ему руку и... больше никуда не отпустите. Еще ОЧЕНЬ пригодится дизаcмер (я рекомендую ТОЛЬКО WDASM) и HIEW (который, как окажется в последствии, совершенно не понадобится, но в педагогических целях его неплохо бы заиметь).
Больше нам реально ничего не понадобится... Ах да, разве что еще ваш любимый выходной набор "мозги + прямые руки". И конечно, листик с ручкой (запомните, ни один серьезный взлом не обходится без листика с ручкой, а еще лучше завести для этого дела специальную тетрадь, но это уже для извращенцев).
Go Go Go...!
Итак, поехали! Запускаем Shtirlitz.exe для того чтобы окончательно понять, чего же мы все таки хотим. А хотим мы убрать этот чертов баннер, ато он $%@##$ уже достал внатуре !!!
Где же он ?! Вот он, сидит себе в углу, моргает. Подожди же, зараза...
SoftIce у нас уже конечно же запущен…
Сразу же жмем ctrl-D, осмотримся, чего же у нас творится в данный момент... Оказавшись в любимом окне набиваем:
Код (Text):
addrВ ответ получим загадочную последовательность запущенных на данный момент процессов. Где-то в самом конце списка (на всякий случай, перемещение по списку – клавиши [вверх] и [вниз]) мы просто обязаны увидеть строку такого содержания:
Код (Text):
Addr PID NAME ………… ………… …… ………. xxxxxxxx xxxxxxxx xxxx Shtirlitzгде вместо "х"-ов будут hex-цифры.
Вот он, родимый!!! Привяжемся же к нему всей душой!!!
Набиваем:
Код (Text):
addr xxxxгде вместо иксов подставляем соотв. значение из колонки PID.
Теперь, повторно набрав в строке addr убеждаемся, что Штирлиц стал текущим процессом (т.е. голубым .
Далее. Добившись того, чтобы Shtirlitz стал текущим процессом, можно смело узнать про него много всего полезного. Набиваем:
Код (Text):
hwnd Shtirlitz(Shtirlitz, кстати, в данном случае берется из колонки NAME)
И что мы видим ? А видим мы длинный список инфы про нашего пациента. Чего мы вообще хотим? Убрать баннеры... Смотрим, чего тут можно нарыть по нашей проблеме... Ага!!! Вот оно!!! Первой же строкой!!! И не стыдно...?
Shtirlitz.banner ... запомним.
Теперь запускаем WDASM. Грузим Shtirlitz.exe. Пошарим по файлу (теперь мы знаем чего искать). В строке поиска пишем banner. Ждем... Вуаля!
Код (Text):
* 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Всеволод Лукьянин не только с юмором, а еще и очень хитер! Видите, как ловко он вплел показ баннеров в код?! После непродолжительного разглядывания данного куска становиться очевидно , что от результата, возвращаемого процедурой в строке
Код (Text):
:00401B32 E8BF6B0000 call 004086F6зависит относится ли данный вызов непосредственно к показу рекламы или нет (если нет, то возвращаемый результат равен 0, и соответственно после
Код (Text):
:00401B37 84C0 test al, alмы перепрыгиваем "через овечку" прямо в конец куска (перелетаем полностью через весь показ баннеров). Сам переход происходит в строке
Код (Text):
: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. Наводим курсор на строку
Код (Text):
00401B39 7473 je 00401BAEА вот внизу то что нам нада:
Код (Text):
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... Набиваем:
Код (Text):
bpx CreateFileAЗапускаем Штирлица и ждем срабатывания бряка... Есть! Смотрим, чего у нас лежит в стеке:
Код (Text):
dd espВ окне данных видим:
Код (Text):
00407289 00910BB0 ...Когда SI отлавливает вызов API, управление передается на первую команду этой самой API, поэтому сейчас мы оказались на самом первом байте кода ф-ции CreateFile.
Чего же это там у нас в окне данных... Ну первое число – понятно, откуда произошел вызов, оно нам не нада, а вот второе – это и есть указатель на имя открываемого файла (у вас это может быть другое число). Лезем по нему:
Код (Text):
d 00910BB0Облом... Shtirlitz.loc какой то... А нам нужен Shtirlitz.exe. Но ничего! Ждем следующего вызова CreateFile… Жмем F5. И вот буквально тут же! Повторяем уже знакомые операции (dd esp), вот оно второе число: 00910910. Заглянем и туда (d 910910) – yes! Вот он, родимый! Shtirlitz.exe!!! Ну все!!! ВОТ ТЕПЕРЬ можно ставить бряк на ReadFile! НЕ ВЫХОДЯ ИЗ SI пишем:
Код (Text):
bpx ReadFileТеперь жмем F5, ждем... Вот он долгожданный бряк по ReadFile! Смотрим стек (dd esp). Видим:
Код (Text):
00405B00 00000060 00E90020 000A9400 ...нас интересуют первые четыре числа. Первое число – адрес возврата (не нада), второе число – хэндл файла (не нужен), третье число – уже интереснее (адрес, куда надо считывать файл), четвертое – сколько байт нада считывать.
Четвертое число вообще очень интересное... Кстати, ebx тоже равен этому же числу... Запомним это. Смотрим на калькуляторе: A9400h=693246d. А теперь угадай с трех раз, сколько весит файл Shtirlitz.exe? Теперь можно точно сказать, что происходит подсчет контрольной суммы ВСЕГО файла целиком... Но ты не сиди – записывай все числа на бумажку. С комментариями, ато потом заблудишься.
Все. Пришло время заняться делом. Как только мы оказались в начале апишки ReadFile и посмотрели стек – жмем F12 (сам увидишь как это связано с первым числом). Теперь поехали трейсить! Запомни: видишь call – жми F10, чтобы не влезать в него. В других случаях – жмешь F8. Теперь главное вовремя остановиться... . По ходу пьесы тебе часто придется вываливаться из SI, хотя бы даже для заглядывания в данную статью, поэтому перед выходом тебе ПРИДЕТСЯ набивать bc* (убрать все бряки). Так вот, для возврата тебе придется опять два раза отлавливать CreateFile, потом ReadFile... запаришься! Поэтому вспомни, что ebx был равен четвертому числу – а это ключ!!! Зная это, просто пишешь:
Код (Text):
bpx ReadFile if ebx==A9400и ты в нужном месте в нужное время...!
Итак, трейсим... через несколько F8 и парочки F10 мы попадаем в загадочную область:
Код (Text):
00423B1E: movzx... ... inc esi cmp esi, ebx mov [ebp-08], ecx 00423B5E: jb 00423B1E 00423B60: ...Это какой то заговор... Обрати внимание на тот факт, что esi в начале цикла равен нулю, а ebx – A9400 (или размеру файла Штирлиц.exe); я нарочно выделил inc esi и последующее сравнение с ebx – тут даже койоту ясно, что идет подсчет контрольной суммы всего файла. Ну что ж, любители острых ощущений могут просидеть так пару дней, давя F8, я предпочитаю (и вам советую) сделать так:
Код (Text):
bpx 00423B60Это есть бряк на следующую после jb команду, а сюда управление вернется только после того, как выполнится A9400 итераций. (вообще желательно выписать на бумажку значения ВСЕХ регистров и ячейки ebp-08 в этом месте, т.к. и ежу понятно – это единственные правильные значения, которые могут иметь место (ведь если бы мы "исправили" файл в HIEW, то значения регистров на выходе оказались бы совершенно иными). Вот значения регистров для "девственного" shtirlitz.exe:
Код (Text):
EAX=00000016 ECX=000048D2 EDX=00000020 EDI=00E90020 dword [ebp-08]=ECX=000048D2Кстати, как многие уже догадались 48D2 – это и есть контрольная сумма, запомним это число.
Что теперь? Пока ничего, трейсим дальше... Здесь нам встретятся два call-а, перелетаем их. Ждем ret-а... И вот мы вернулись непонятно куда – на
Код (Text):
00423744: cmp ax,si 00423747: jz 0042376AЛюбознательные могут сами залезть в те два call-а, я же просто скажу: после того, как мы оказались на 00423744 в esi всегда будет лежать 48D2h (помните его?), а вот в ax – то, что получилось из нашего shtirlitz.exe, и если он только не равен 48D2... то... сами понимаете.
Ну что, опять в 00423747 замена jz на jmp ? И сколько это будет продолжаться ? Пробуем... (00423747=22B47 in file)
Запускаем... Ну вот!!! Теперь еще круче!!! Вообще ничего!!! Мда...
Пришло время пораскинуть мозгами. Очевидно, что единственное, что поменялось в самом процессе работы программы – значение регистров после вычисления контрольной суммы. С одной стороны, весь цикл (00423B1E-00423B5E) можно заменить на код типа такого:
Код (Text):
mov ecx,48D2h mov edx,20h ...т.е. галимо подогнать значения всех регистров, зная какими они выглядят в "девственном" Штирлице.exe. Но, во-первых, это уродливо, а во вторых - это нас не спасет... (можете попробовать). Стоит только отметить, что обращение к области памяти с E90020h (там, где лежит копия файла shtirlitz.exe) происходит еще минимум 4 раза!!! Разбираться и отлавливать их все нет никакого желания, Всеволод очень неплохо постарался...
Поэтому пойдем по другому пути... Помнишь, в самом начале мы заменили по адресу
Код (Text):
:00401B39 7473 je 00401BAEje на jmp ? Так вот, что если править код не в самом файле, а непосредственно в памяти??? Тогда никакой возни с контрольной суммой не возникнет!!! Отлично! Заодно можно проверить, по тому ли пути мы вообще идем... Итак, берем "девственный" shtirlitz.exe, ставим в SI бряк на readfile при ebx==A9400, запускаем shtirlitz.exe... Теперь, правим байт:
Код (Text):
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" - ошибка!!! Должно быть два значка "=".Ломать – не строить!
(C) Народная мудрость. © Broken Sword
Убираем баннеры в "Штирлице" или Баг в защите
Дата публикации 14 авг 2002