Underground InformatioN Center [&articles] 
[network & security news] [RSS & Twitter] [articles, programing info] [books] [links, soft & more...] [soft archive][home]

Взлом программ, защищенных с помощью криптоалгоритма Blowfish

Внимание!!!
   Статья написана ТОЛЬКО для образовательных целей. Прочитавший ее не сможет украсть миллиарды Билла Гейтса или научиться управлять Боингом. Статья абсолютно безвредна и рекомендована для прочтения даже грудным детям и беременным женщинам.

Итак, приступим...

Пациент
Winsim Design II v.8.хх, (17мб)

Инструменты

  • SoftICE (любая версия)
  • IDA (любая версия)
  • Компилятор С. Я использовал MSVC++ v.6.0
  • Исходники для blowfish из криптобиблиотеки openssl. Используются: blowfish.h, bf_pi.h, bf_skey.c, bf_locl.h, bf_enc.c, bf_ecb.c, opensslv.h, opensslconf.h
  • Ручка, бумага

    Первый взгляд
       Замечаем файл с интересным именем - d2licens.exe. Запускаем.. Ага, как и предполагалось этот файлик проверяет регистрацию.
    Дизасмим его. После дизассемблирования замечаем несколько интересных строк:

    'COULD NOT MALLOC BLOWFISHKEY'
    'The password must be 16 characters !'
    'Could not find the hardware key on any port !'
    'Please check your Serial Number and Password to ensure that they are
    entered correctly.'
    'If this is a hardware locking password then please check your hardware
    key using KEYIDW32.'
    'If this is a software locking password then please check your Computer
    ID value'
    'If this is a password lock only then please check your Name and
    Location to ensure that they are
    'entered correctly.'

    Интересно. Даже очень. Такое впечатление что здесь несколько типов регистрации для разных продуктов. Так как в помощи к программе ничего не сказано об электронном ключе логично предположить что тут или "software locking password" или "password lock only". Очень мило, что не надо соображать какой алгоритм используется - все и так написано.

    Blowfish
       Blowfish - 64 битный блочный шифр. Подробное его описание есть в книге "Applied Cryptography" by Bruce Schneier. Я очень коротенько постараюсь обьяснить суть. Для шифрования/дешифрования нам нужны: текст(text) и ключ(key). Сначала с помощью ключа генерятся подключи(subkeys) - P-array состоящий из 18-ти 32-битных подключей и четыре S-boxes. Каждый S (S1, S2, S3, S4) состоит в свою очередь из 256-ти 32-битных подключей. Вместе P-array и S-boxes представляют собой массив длиной в 4168 байт. Расположение в этом массиве такое:
    P-array+S1_box+S2_box+S3_box+S4_box. То есть сначала Р-array и потом все остальное. Изначально этот массив имеет фиксированные значения и называется pi-array. С помощью ключа этот массив модифицируется.

    Я не хочу раздувать статью, так что алгоритм шифрования обьяснять не буду. В "Applied Cryptography" все доступно обьяснено.

    Ищем, ищем и находим
       Если в программе используется blowfish, то где-то должна быть процедура генерации подключей и, соответственно, pi-array. Или ключ используется один и подключи просчитаны программером заранее - тогда должны быть подключи.
    В любом случае где-то в коде программы будет массив подключей. Проверим.
    Вводим Password , Name, Serial number, Location. Так как я предполагаю, что алгоритм - blowfish, то Password и Serial number будут состоять только из вот этих символов (0123456789ABCDEF). Это так потому, что введеный пароль или серийник будет переведен в DWORD. То есть была строка "1234567890ABCDEF", а получится "1234567890ABCDEFh".
    С теорией покончено, теперь в SoftIce. Расставляем обычные бряки - bpx GetDlgItemTextA, быстренько опускаемся сюда:

    040A86F    mov     ecx, [ebp+var_208]
    0040A875   call    MFC42_3098
    0040A87A   lea     ecx, [ebp+var_80]
    0040A87D   push    ecx
    0040A87E   call    sub_408702
    0040A883   add     esp, 4
    0040A886   call    sub_4077A7 ;!!!
    0040A88B   mov     [ebp+var_104], eax
    0040A891   cmp     [ebp+var_104], 3039h
    0040A89B   jnz     short loc_40A8AA
    Нас интересует call sub_4077A7. Заходим в него. Чуть ниже видим:
    0040786D   lea     ecx, [ebp+var_80]
    00407870   push    ecx
    00407871   lea     edx, [ebp+var_108]
    00407877   push    edx
    00407878   mov     eax, [ebp+var_84]
    0040787E   push    eax
    0040787F   lea     ecx, [ebp+var_208]
    00407885   push    ecx
    00407886   lea     edx, [ebp+var_288]
    0040788C   push    edx
    0040788D   call    sub_4069E6  ;!!!
    00407892   add     esp, 14h
    00407895   test    eax, eax
    00407897   jz      short loc_4078A2

    В процедуру 4069E6 передаются все наши введенные параметры а на выходе проверяется eax. Очень смахивает на проверку. Заходим в нее. Интересный кусок кода:

    0406B65    loc_406B65:  ; CODE XREF: sub_4069E6+15A_j
    00406B65   mov     ecx, dword_413C7C
    00406B6B   push    ecx
    00406B6C   push    38h
    00406B6E   push    offset a8_38_38_3Versi ; "8.3 8.3 8.3 Version
                                              ; 8.3 of DESIGN II fo"...
    00406B73   call    sub_401000
    00406B78   add     esp, 0Ch
    На что похож этот бред - "8.3 8.3 8.3 Version 8.3 of DESIGN II for Windows 8.3 8.3"? Для меня это похоже на ключ. Проверим это. Заходим внутрь call sub_401000.
    040102C    mov     [ebp+var_104C], 243F6A88h
    00401036   mov     [ebp+var_1048], 85A308D3h
    00401040   mov     [ebp+var_1044], 13198A2Eh
    0040104A   mov     [ebp+var_1040], 3707344h
    00401054   mov     [ebp+var_103C], 0A4093822h
    0040105E   mov     [ebp+var_1038], 299F31D0h
    00401068   mov     [ebp+var_1034], 82EFA98h
    00401072   mov     [ebp+var_1030], 0EC4E6C89h
    0040107C   mov     [ebp+var_102C], 452821E6h
    00401086   mov     [ebp+var_1028], 38D01377h
    00401090   mov     [ebp+var_1024], 0BE5466CFh
    0040109A   mov     [ebp+var_1020], 34E90C6Ch
    004010A4   mov     [ebp+var_101C], 0C0AC29B7h
    004010AE   mov     [ebp+var_1018], 0C97C50DDh
    004010B8   mov     [ebp+var_1014], 3F84D5B5h
    и так далее...

    Это pi-array. Значит это процедера генерации подключей, а та большая строка и есть ключик. Вот на этом этапе я понял что буду не патчить программу, а писать кейген. Ключ нам известен, текст для шифрования мы введем сами, следовательно у нас есть все что нужно. Пионерский привет всем программерам, втыкающим в свои проги криптоалгоритмы даже не разобравшись в них. Идем дальше.
    Переименовываем процедурку 401000 в "Subkeys_Calculation". Просто для наглядности :)

    00406B82   push    10h
    00406B84   lea     eax, [ebp+var_98]  ; Password
    00406B8A   push    eax
    00406B8B   call    sub_405216
    Тут у нас Password плавно превращается прeвращается в HEX. Дальше смотрим сюда:
    00406BBE   mov     eax, dword_413C7C  
    00406BC3   push    eax
    00406BC4   lea     ecx, [ebp+var_A4]
    00406BCA   push    ecx
    00406BCB   lea     edx, [ebp+var_A4]
    00406BD1   push    edx
    00406BD2   call    sub_403A7C

    dword_413C7C - subkeys, в есх и еdx заносятся половинки Рassword. Значит call sub_403A7C это либо Encrypt либо Decrypt. Третьего не дано :) Заходим в этот call

    00403BD1 xor eax, [edx+ecx*4]

    Если смотреть на это под SoftIce то станет понятно что тут у нас decrypt, так как еах хоr-ится с последним элементом p-array. При encrypt был бы первый.

    00406C07 call sub_40505D ; HEX to ASCII

    Дальше идет проверка на то, что первый символ полученной строки должен быть (1..7).
    00406C3B   cmp     dword_413C88, 1
    00406C42   jl      short loc_406C4D
    00406C44   cmp     dword_413C88, 7
    00406C4B   jle     short loc_406C70
    00406C4D                     
    00406C4D   loc_406C4D:    ; CODE XREF: sub_4069E6+25C_j
    00406C4D   mov     dword_413C88, 0
    00406C57   push    offset aTheTypeOfSec_2 ; "The type of security
                                              ; is NO GOOD !"

    Ага, это если я (1..7) введу то не взломают а если (8..0F) то да. Идиотизм. Дальше идут разные условия для нашей строки, получившейся в результате дешифрования. Они легко просматриваются при помощи SoftIce так что я их не буду подробно обьяснять. Важно понять саму идею, алгоритм. Введенный пользователем Password расшифровывается, затем расшифрованный пароль проверяется на наличие 7 первым символом, второй символ отвечает за тип лицензии(их там несколько). Последние 4 символа отвечают за срок регистрации. Остальные зависят от Name, Location и Serial Number.

    Итак для ключегена нам надо иметь Name, Location и Serial Number. Зная все условия мы сможем составить строку, которую зашифруем и получим Password. Вот так все просто.

    Вот тут кусок исходника на VC. Я писал его когда ломал эту программу так, что исходник этот похож на ассемблер, записанный в операторах С :-). Но тем не менее все работает.

    Ну и в заключение хочу сказать, что все программы используюшие для защиты Blowfish однотипны. Ключ может быть одним, как в нашем случае или генерится в зависимости от имени юзера. Но ключ все равно будет присутствовать. И значит программу все равно можно закейгенить.

    Примечание: С 01.01.2002 WinSim Inc. стали пользовать twofish в своем продукте Winsim Design, так что статья теперь имеет чисто научное значение :)

    Исходник и файл d2licens.exe можно скачать здесь. (Скачано 3974 раз)

    Линки
    OpenSSL - http://www.openssl.org
    Applied Cryptography - http://www.cacr.math.uwaterloo.ca/hac/

    C пионерским приветом,
    Сorbio (corbio@mail.ru).
    uinC Member
    [c]uinC

    Статья написана специально для UInC (http://www.uinc.ru).

    Все документы и программы на этом сайте собраны ТОЛЬКО для образовательных целей, мы не отвечаем ни за какие последствия, которые имели место как следствие использования этих материалов\программ. Вы используете все вышеперечисленное на свой страх и риск.

    Любые материалы с этого сайта не могут быть скопированы без разрешения автора или администрации.


  • [network & security news] [RSS & Twitter] [articles, programing info] [books] [links, soft & more...] [soft archive][home]
     Underground InformatioN Center [&articles] 
    2000-2015 © uinC Team