Blog. Just Blog

Расшифровка языковых файлов Download Master

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Темная сторона Силы | Автор: ManHunter
Расшифровка языковых файлов Download Master
Расшифровка языковых файлов Download Master

Уже много лет я пользуюсь удобным менеджером закачек Download Master от компании WestByte Software, и за это время покрутил его со всех сторон, в том числе и изнутри. По сути Download Master является бесплатной (если не считать баннеры) версией другого коммерческого продукта этой же компании - Internet Download Accelerator, который ориентирован на зарубежных покупателей. А чтобы было нельзя использовать Download Master с зарубежными локализациями интерфейса, все языковые файлы в нем хранятся в шифрованном виде. То есть нельзя взять, например, французский языковой файл от платного Internet Download Accelerator, подложить его в бесплатный Download Master и получить полноценную бесплатную французскую версию программы.

Раз есть что-то зашифрованное, то почему бы не попробовать это расшифровать? Лично мне вполне хватает русского интерфейса Download Master, поэтому исследование проводилось "just for fun", без каких-либо конкретных целей. Забегая вперед скажу, что алгоритмы шифрования не меняются, программа часто обновляется, поэтому привязки к какой-то версии не будет, главное понять сам принцип.

Скачаем дистрибутив портативной версии, распакуем его куда-нибудь на диск. Ну а для примера возьмем украинский файл локализации.

Меню выбора языка
Меню выбора языка

Сперва отправим исполняемый файл dmaster.exe в дизассемблер и поищем что-нибудь, связанное со строкой "Ukrainian". Первым же попаданием найдется вот такой блок кода:
  1. CODE:00639E62                 mov     eax, [ebp+var_8]
  2. ; Сравнить что-то со строкой "Ukrainian"
  3. CODE:00639E65                 mov     edx, offset _str_Ukrainian.Text
  4. CODE:00639E6A                 call    @System@@LStrCmp$qqrv
  5. ; System::__linkproc__ LStrCmp(void)
  6. CODE:00639E6F                 jnz     short loc_639ED4
  7. CODE:00639E71                 mov     eax, ds:off_734550
  8. CODE:00639E76                 mov     eax, [eax]
  9. CODE:00639E78                 mov     edx, [eax+0D34h]
  10. CODE:00639E7E                 lea     eax, [ebp+var_24]
  11. ; Задействовать файл "dmaster1.dat"
  12. CODE:00639E81                 mov     ecx, offset _str_dmaster1_dat.Text
  13. CODE:00639E86                 call    @System@@LStrCat3$qqrv
  14. ; System::__linkproc__ LStrCat3(void)
  15. CODE:00639E8B                 mov     eax, [ebp+var_24]
  16. ; Проверить наличие этого файла
  17. CODE:00639E8E                 call    @Sysutils@FileExists$qqrx17System
  18. ; Sysutils::FileExists(System::AnsiString)
  19. CODE:00639E93                 test    al, al
  20. CODE:00639E95                 jz      short loc_639ED4
  21. CODE:00639E97                 lea     eax, [ebp+var_28]
  22. CODE:00639E9A                 push    eax
  23. CODE:00639E9B                 mov     eax, ds:off_734550
  24. CODE:00639EA0                 mov     eax, [eax]
  25. CODE:00639EA2                 mov     edx, [eax+0D34h]
  26. CODE:00639EA8                 lea     eax, [ebp+var_2C]
  27. CODE:00639EAB                 mov     ecx, offset _str_dmaster1_dat.Text
  28. CODE:00639EB0                 call    @System@@LStrCat3$qqrv
  29. ; System::__linkproc__ LStrCat3(void)
  30. CODE:00639EB5                 mov     eax, [ebp+var_2C]
  31. CODE:00639EB8                 xor     ecx, ecx
  32. CODE:00639EBA                 mov     edx, 73110h
  33. CODE:00639EBF                 call    sub_4AA750
  34. CODE:00639EC4                 mov     edx, [ebp+var_28]
  35. CODE:00639EC7                 mov     eax, [ebp+var_10]
  36. CODE:00639ECA                 mov     ecx, [eax]
  37. CODE:00639ECC                 call    dword ptr [ecx+2Ch]
Уже по исходному тексту можно примерно выяснить, что тут делается. Из настроек берется название выбранного языка интерфейса, сравнивается со строкой "Ukrainian", если совпало, то вычисляется путь к папке с установленной программой и проверяется наличие в ней файла "dmaster1.dat". Если посмотреть, то такой файл там действительно есть, а кроме него еще "dmaster2.dat", "dmaster3.dat" и "dmaster.dat", аккурат по количеству доступных языков в меню настроек. Теперь нам надо узнать, как же это все шифруется и расшифровывается. Наибольшее подозрение у меня вызывает вот этот кусочек кода.
  1. CODE:00639EB5                 mov     eax, [ebp+var_2C]
  2. CODE:00639EB8                 xor     ecx, ecx
  3. CODE:00639EBA                 mov     edx, 73110h
  4. CODE:00639EBF                 call    sub_4AA750
Почему именно он? Смотрите сами: в регистр EAX записывается путь до файла (можете проверить под отладчиком), в регистр EDX записывается какая-то константа 73110h, которая не является ни адресом, ни указателем, ни строкой. А после этого вызывается какая-то функция. Давайте посмотрим на нее поближе.
  1. CODE:004AA750                 push    ebp
  2. CODE:004AA751                 mov     ebp, esp
  3. CODE:004AA753                 add     esp, 0FFFFFFE8h
  4. CODE:004AA756                 push    ebx
  5. CODE:004AA757                 push    esi
  6. CODE:004AA758                 push    edi
  7. CODE:004AA759                 xor     ebx, ebx
  8. CODE:004AA75B                 mov     [ebp+var_18], ebx
  9. CODE:004AA75E                 mov     [ebp+var_14], ebx
  10. CODE:004AA761                 mov     [ebp+var_9], cl
  11. CODE:004AA764                 mov     [ebp+var_8], edx
  12. CODE:004AA767                 mov     [ebp+var_4], eax
  13. CODE:004AA76A                 mov     eax, [ebp+var_4]
  14. CODE:004AA76D                 call    @System@@LStrAddRef$qqrpv
  15. ; System::__linkproc__ LStrAddRef(void *)
  16. CODE:004AA772                 xor     eax, eax
  17. CODE:004AA774                 push    ebp
  18. CODE:004AA775                 push    offset loc_4AA8C7
  19. CODE:004AA77A                 push    dword ptr fs:[eax]
  20. CODE:004AA77D                 mov     fs:[eax], esp
  21. CODE:004AA780                 mov     eax, [ebp+arg_0]
  22. CODE:004AA783                 call    @System@@LStrClr$qqrpv
  23. ; System::__linkproc__ LStrClr(void *)
  24. CODE:004AA788                 mov     eax, [ebp+var_4]
  25. CODE:004AA78B                 call    @Sysutils@FileExists$qqrx17System
  26. ; Sysutils::FileExists(System::AnsiString)
  27. CODE:004AA790                 test    al, al
  28. CODE:004AA792                 jz      loc_4AA8A4
  29. CODE:004AA798                 xor     eax, eax
  30. CODE:004AA79A                 push    ebp
  31. CODE:004AA79B                 push    offset loc_4AA89A
  32. CODE:004AA7A0                 push    dword ptr fs:[eax]
  33. CODE:004AA7A3                 mov     fs:[eax], esp
  34. CODE:004AA7A6                 xor     edx, edx
  35. CODE:004AA7A8                 mov     eax, [ebp+var_4]
  36. CODE:004AA7AB                 call    @Sysutils@FileOpen$qqrx17System
  37. ; Sysutils::FileOpen(System::AnsiString,uint)
  38. CODE:004AA7B0                 mov     ebx, eax
  39. CODE:004AA7B2                 mov     ecx, 2          ; dwMoveMethod
  40. CODE:004AA7B7                 xor     edx, edx        ; lDistanceToMove
  41. CODE:004AA7B9                 mov     eax, ebx        ; hFile
  42. CODE:004AA7BB                 call    sub_40DA70
  43. CODE:004AA7C0                 mov     esi, eax
  44. CODE:004AA7C2                 xor     ecx, ecx        ; dwMoveMethod
  45. CODE:004AA7C4                 xor     edx, edx        ; lDistanceToMove
  46. CODE:004AA7C6                 mov     eax, ebx        ; hFile
  47. CODE:004AA7C8                 call    sub_40DA70
  48. CODE:004AA7CD                 lea     eax, [esi+1]
  49. CODE:004AA7D0                 call    @Sysutils@AllocMem$qqrui
  50. ; Sysutils::AllocMem(uint)
  51. CODE:004AA7D5                 mov     [ebp+lpBuffer], eax
  52. CODE:004AA7D8                 xor     eax, eax
  53. CODE:004AA7DA                 push    ebp
  54. CODE:004AA7DB                 push    offset loc_4AA889
  55. CODE:004AA7E0                 push    dword ptr fs:[eax]
  56. CODE:004AA7E3                 mov     fs:[eax], esp
  57. CODE:004AA7E6                 mov     edx, [ebp+lpBuffer] ; lpBuffer
  58. CODE:004AA7E9                 mov     ecx, esi
  59. ; nNumberOfBytesToRead
  60. CODE:004AA7EB                 mov     eax, ebx        ; hFile
  61. CODE:004AA7ED                 call    sub_40DA18
  62. CODE:004AA7F2                 mov     esi, eax
  63. CODE:004AA7F4                 mov     eax, ebx        ; hObject
  64. CODE:004AA7F6                 call    sub_40DAB4
  65. CODE:004AA7FB                 lea     eax, [ebp+var_14]
  66. CODE:004AA7FE                 call    @System@@LStrClr$qqrpv
  67. ; System::__linkproc__ LStrClr(void *)
  68. CODE:004AA803                 cmp     [ebp+var_9], 0
  69. CODE:004AA807                 jz      short loc_4AA813
  70. ...
С первой половиной функции трудностей быть не должно. Проверяется и открывается для чтения файл, под него выделяется память и затем его содержимое читается в память. То есть сейчас у нас в памяти содержится зашифрованный языковой файл. Логично предположить, что дальше будет его расшифровка. Для наглядности лучше всего пройти вторую половину функции под отладчиком, я именно так и сделал, поэтому оставлю только задействованный код:
  1. ; Ключ расшифровки - та самая загадочная константа, которая была
  2. ; передана в функцию расшифровки
  3. CODE:004AA818                 mov     edx, [ebp+var_8]
  4. ...
  5. ; Указатель на начало прочитанного файла
  6. CODE:004AA823                 xor     edi, edi
  7. CODE:004AA825 loc_4AA825:
  8. CODE:004AA825                 mov     eax, [ebp+lpBuffer]
  9. ; Взять следующий зашифрованный байт
  10. CODE:004AA828                 mov     bl, [eax+edi]
  11. ...
  12. CODE:004AA841 loc_4AA841:
  13. ; Вычислить байт для расшифровки
  14. CODE:004AA841                 mov     eax, 0FFh
  15. CODE:004AA846                 call    unknown_libname_41
  16. ; Расшифровать байт
  17. CODE:004AA84B                 xor     al, bl
  18. CODE:004AA84D                 mov     ebx, eax
  19. CODE:004AA84F loc_4AA84F:
  20. CODE:004AA84F                 lea     eax, [ebp+var_18]
  21. CODE:004AA852                 mov     edx, ebx
  22. ; Преобразовать байт в символ
  23. CODE:004AA854                 call    unknown_libname_76
  24. ; BDS 2005-2007 and Delphi6-7 Visual Component Library
  25. CODE:004AA859                 mov     edx, [ebp+var_18]
  26. CODE:004AA85C                 lea     eax, [ebp+var_14]
  27. ; Сохранить расшифрованный символ
  28. CODE:004AA85F                 call    @System@@LStrCat$qqrv
  29. ; System::__linkproc__ LStrCat(void)
  30. CODE:004AA864                 inc     edi
  31. CODE:004AA865                 dec     esi
  32. CODE:004AA866                 jnz     short loc_4AA825
Еще требует уточнения загадочная функция unknown_libname_41:
  1. CODE:00403C44 unknown_libname_41 proc near
  2. CODE:00403C44                 push    ebx
  3. CODE:00403C45                 xor     ebx, ebx
  4. ; Умножить текущее значение ключа на 8088405h
  5. CODE:00403C47                 imul    edx, ds:dword_720008[ebx], 8088405h
  6. ; Увеличить текущее значение ключа на 1
  7. CODE:00403C51                 inc     edx
  8. CODE:00403C52                 mov     ds:dword_720008[ebx], edx
  9. CODE:00403C58                 mul     edx
  10. CODE:00403C5A                 mov     eax, edx
  11. CODE:00403C5C                 pop     ebx
  12. CODE:00403C5D                 retn
  13. CODE:00403C5D unknown_libname_41 endp
Алгоритм расшифровки более-менее вырисовывается. Файл расшифровывается побайтно, при каждой итерации DWORD ключа модифицируется, затем байт файла расшифровывается командной XOR с младшим байтом ключа. Потом расшифрованный байт преобразуется в символ и записывается куда следует. Под отладчиком это все хорошо видно. Если совсем наводить красоту, то расшифровка сводится вот к такой компактной функции:
  1.         ; Начальный ключ расшифровки
  2.         mov     [key],73110h
  3.  
  4.         xor     esi,esi
  5. loc_decrypt:
  6.         ; Модифицировать ключ расшифровки
  7.         mov     eax,0FFh
  8.         imul    edx,[key],8088405h
  9.         inc     edx
  10.         mov     [key],edx
  11.         mul     edx
  12.  
  13.         ; Расшифровать байт
  14.         xor     byte [buff+esi],dl
  15.  
  16.         ; Следующий байт
  17.         inc     esi
  18.         cmp     esi,[file_size]
  19.         jb      loc_decrypt
Для разных языковых файлов используется одна и та же функция расшифровки, меняется только ключ. Например:
  1. ; Транслит
  2. CODE:00639F27                 mov     eax, [ebp+var_38]
  3. CODE:00639F2A                 xor     ecx, ecx
  4. CODE:00639F2C                 mov     edx, 8D87AFh
  5. CODE:00639F31                 call    sub_4AA750
  1. ; Белорусский язык
  2. CODE:00639F99                 mov     eax, [ebp+var_44]
  3. CODE:00639F9C                 xor     ecx, ecx
  4. CODE:00639F9E                 mov     edx, 31FA2Fh
  5. CODE:00639FA3                 call    sub_4AA750
Кстати, раз команда XOR обратимая, то файл можно при первом проходе расшифровать, а затем при втором проходе снова зашифровать. Что нам это дает? А то, что во-первых мы можем вносить любые изменения в языковые файлы, а во-вторых можем использовать любые языковые файлы от Internet Download Accelerator, о чем я говорил в начале статьи.

Download Master с испанским интерфейсом
Download Master с испанским интерфейсом

Вот, к примеру, по этому алгоритму был зашифрован испанский языковой файл от Internet Download Accelerator, после чего им был заменен оригинальный файл dmaster1.dat в папке Download Master. В языковых настройках Download Master выбираем "Ukrainian", а именно он соответствует этому файлу, и через несколько секунд получаем бесплатный Download Master, но уже на испанском языке.

Поделиться ссылкой ВКонтакте
Просмотров: 7254 | Комментариев: 11

Метки: реверсинг
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Иван (26.02.2018 в 01:10):
Уважаемый ManHunter.

К теме статьи мой вопрос не имеет абсолютно никакого отношения.
Просто в поиске информации набрел на эту страницу, и поскольку мой вопрос на форуме, посвященном DM проигнорировали, решил задать его здесь. И получил исчерпывающий ответ. Спасибо.
ManHunter (25.02.2018 в 13:01):
\Application Data\DMBackUp\
Просто скопировать нужный файл оттуда. Только какое отношение это имеет к теме статьи?
Иван (25.02.2018 в 12:13):
Доброго времени суток!

Также давно пользуюсь Dowload master. Хорошая программа.
Но вот на днях случилась катавасия. Накопил в списке закачек около 400 ссылок и не сохранял. Надеялся на программу, которая даже после аварийного завершения Windows автоматически загружала список обратно. Но в последний раз сам DM аварийно завершил работу из-за нехватки памяти (работал в VMWare) и после перезапуска выдал окно в вопросом "Список закачек пуст, восстановить его из резервной копии?". Надо было конечно ответить положительно, но, замкнуло и ответил "нет". И, конечно, список не восстановился. И вот такой вопрос: где находится этот резервный список закачек? Или он очистился после отрицательного ответа на вопрос? И каким можно снова заставить DM задать вопрос о восстановлении списка закачек, например, через какой-либо параметр в файле настроеr dmaster.ini. У меня DM v6.01 portable.
ManHunter (17.07.2014 в 11:17):
Удаляем папку temp и получаем один, но постоянный баннер Download Master. Это не считая всяких кнопок "разместить рекламу", "мнение о закачке" и прочий хлам. Патчи пишутся и применяются не от нефиг делать.
Жека (17.07.2014 в 01:07):
Soso, удаляем папку temp со всем содержимым, в директории установленной программа и вот и весь патч для удаления рекламы.
Soso (17.12.2013 в 04:55):
>"На руборде мой патч" - хочется увидить обновленную версию с добавлением новых и эТой опций !)

Спасибо и Удачи .
DimitarSerg (24.11.2013 в 15:42):
>Еще требует уточнения загадочная функция unknown_libname_41:
Это Random (еще точнее procedure _RandInt) же стандарный дельфовский, где dword_720008 -  RandSeed.
Использьование данной функции в качестве функции шифровки/дешифровки видел в регистрационной схеме TurboLaunch, а также в кастомном шифре Total Commander'a (сразу после rsa-расшифровки данных ключа).
ManHunter (02.11.2013 в 13:20):
На руборде мой патч против рекламы выложен аж с 2006 года.
hoper (02.11.2013 в 13:19):
Еще-бы и рекламу убрать.
ManHunter (31.10.2013 в 17:27):
Если я не ошибаюсь, то для этого достаточно будет зaNOPить две команды в исходном файле:

CODE:004AA84B   xor     al, bl
CODE:004AA84D   mov     ebx, eax

И все, файл будет читаться как есть и не расшифровываться, можно будет подкладывать нешифрованные файлы. Только это придется делать после каждого обновления DM.
Compiller (31.10.2013 в 17:23):
А можно просто убрать шифрование и заставить DownloadMaster работать с незашифрованным языковым файлом?
И полученные таким образом файлы локализации работают с неломанной версией?

Добавить комментарий

Заполните форму для добавления комментария
Комментарии отключены администратором сайта
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0065 сек.) / Память: 4.5 Mb
Наверх