◄— Предыдущая Следующая —►

Полная перекомпиляция программы write.exe
или тестируем демо-версию IdaPro 5.6

by Erfaren
http://erfaren.narod.ru
erfaren@rambler.ru


  • Загрузить Erfaren-001-Recompilation-write-exe.pdf - 746 Кб
  • Загрузить IdaPro56Test.001 - 801 Кб
  • Загрузить IdaPro56Test.txt - 801 Кб

  • (замените расширение на zip в IdaPro56Test.*)

    Введение

    В настоящее время существует широко известный и достаточно высококачественный интеллектуальный дизассемблер IdaPro от выпускника мехмата МГУ Ильфака Гильфанова (Ilfak Guilfanov). Всегда интересно знать, насколько хорош этот инструмент. Например, как много и что именно нужно изменить в декомпилированном коде, выдаваемом IdaPro, скажем для простейшей GUI программы, которую можно найти в папке Windows, чтобы скомпилированная версия этой программы заработала снова, практическим ничем не отличаясь от исходной программы? Т.е., чем меньше телодвижений нужно делать, чтобы перекомпилировать дизассемблерный файл в работающее приложение, тем, очевидно, более качественен инструмент нашего Ильфака Улыбка. Ну и конечно эти телодвижения не должны быть слишком уж изощренными, по крайней мере для небольших программ.

    Естественно, тестировать можно любую версию дизассемблера. Но поскольку, на данный момент, на сайте разработчика доступна уже демо-версия 5.6, то мы и воспользуемся ею, тем более что нам достаточно будет даже ограниченных возможностей этой версии.

    Главное ограничение демо-версии, это отсутствие возможности сохранения ассемблерного кода в файл, что не позволит использовать интерактивные возможности «Иды» длительное время, однако для наших целей тестирования это не очень актуально. Тем не менее, IdaPro оставила нам лазейку сохранения листинга кода в файл через буфер обмера (Ctrl-Ins или Ctrl-C / Shift-Ins или Ctrl-V). Правда, при этом сохраняются и адреса команд, но их очень легко убрать в полученном файле листинга. К этому мы еще вернемся, а пока займемся настройками «Иды».

    Мы выберем наименьшую GUI-шную программу, которую можно найти на наших компьютерах под управлением Windows NT. У меня это программа write.exe (обёртка для WordPad.exe из каталога по умолчанию \Program Files\Windows NT\Accessories\).

    Для тестирования у меня было три системы. Две под управлением XPюши, с сервис паком 3, но разных сборок и одна под Windows 2003 Server. У XPюши write.exe имел одну и ту же версию 5.1.2600.0, но был разных размеров 5632 и 22528 байт. Как оказалось, «лишние» байты занимал не вирус или троян Улыбка, а данные ресурсов. В данном случае вместо двух иконок для первого файла мы имеем четыре иконки для второго. Общий размер ресурсов (вместе с версионной информацией), соответственно, 2092 и 18692 байт.

    Для Windows 2003 у write.exe версия 5.2.3790.0, размером 5632 байта. Кстати, этот файл отличается от подобного файла XPюши практически на треть (и не только за счет ресурсов). Так что испытывать мы будем все эти версии, но начнем с меньшей версии из Windows XP.

    Настройка IdaPro v. 5.6

    Для максимальной эффективности декомпиляции воспользуемся следующими настройками.

    На странице «Welcome to the PE executable file loading Wizard» отмечаем галку в опции «Analysis options». Если мы хотим, чтобы эта галка стояла по умолчанию, то тогда просто заменяем в файле \IDAPro56\cfg\kernel.xml строку

    <checkbox X="analysis_c" caption="Analysis options" onClick="onClick_analysis_c">
    

    на

    <checkbox checked="true" X="analysis_c" caption="Analysis options" onClick="onClick_analysis_c">
    

    Однако изменять файл kernel.xml следует в последнюю очередь, так как после этого становятся недоступны некоторые страницы настроек.

    Следующую страницу Визарда «Segment Creation» оставляем без изменений (сегмент импорта создаем, а сегмент ресурсов – нет).

    Далее, на странице «Kernel Options» нам надо снять галку по умолчанию с опции «Automatically hide library functions», так как нам не незачем скрывать функции, которые мы собираемся перекомпилировать. Чтобы не делать это постоянно, надо отредактировать файл \IDAPro56\cfg\ida.cfg. Там мы видим следующее определение:

    #define AF2_HFLIRT      0x0004  // Automatically hide library functions
    

    Это значение входит в содержимое переменной ANALYSIS2, которое нам следует уменьшить на 4. Однако это переменная встречается в данном файле несколько раз, определяя по умолчанию различные настройки для разных процессоров. Можно изменить их все (заменим последнюю шестнадцатеричную цифру D на 9), а можно найти только нужный нам случай. Это будет секция:

    #ifdef __PC__             // INTEL 80x86 PROCESSORS
    . . .
    ANALYSIS2 = 0x3FFD        // Enable 'noret' analysis. Enable SP analysis
    #endif // __PC__
    

    Вместо исходной строки пишем:

    ANALYSIS2 = 0x3FF9
    

    Следующие страницы настроек Визарда будут «PC Processor Options» и «File loading». Их мы оставляем без изменений. Проверяем, смотрим. Все как надо. Теперь можно поменять и файл kernel.xml, описанный выше. После этого страницы «Kernel Options» и «PC Processor Options» станут недоступными, но тем лучше для нас. Нужные нам настройки там останутся, а лишних кликов мышью делать придется меньше Улыбка.

    Дизассемблинг write.exe

    Загрузим нашего «подопытного кролика», в данном случае, файл \WINDOWS\system32\write.exe версии 5.1.2600.0, размером 5632 байта, в дизассемблер IdaPro v. 5.6. Работаем под управлением XPюши. Интернет доступен.

    Думаю, что процесс загрузки достаточно очевиден, и мы можем, наконец-то лицезреть вожделенный ассемблерный листинг (рис. 1).

    Дизассемблерный листинг программы write.exe
    Рис. 1. Дизассемблерный листинг программы write.exe.

    Однако сразу бросается в глаза отсутствие прототипов структур write.exe на вкладке Structures (рис. 2) и «облегченное» использование прототипов функций в секции .idata (рис. 4).

    Отсутствие структур в IdaPro 5.6 для программы write.exe
    Рис. 2. Отсутствие структур в IdaPro 5.6 для программы write.exe.

    Как оказалось, со структурами просто вышел глюк. Если удалить вкладку со структурами (Alt-F3) и затем снова восстановить ее (через меню, либо по Shift-F9), то все нужные структуры появятся (рис. 3). Только не забудьте прокрутить окно вверх, а то будет казаться, что восстановлена только одна структура вместо трех необходимых.

    Восстановление структур после переоткрытия окна
    Рис. 3. Восстановление структур после переоткрытия окна.

    Кстати, эти структуры можно сразу сохранить в файл (предварительно раскрыв их «серым» плюсом) через буфер обмена, скажем, в файл write.lst.

    «Облегченное» использование прототипов функций в секции .idata
    Рис. 4. «Облегченное» использование прототипов функций в секции .idata.

    По поводу прототипов, IdaPro, например, пишет:

    ; Imports from SHELL32.dll
    ; HINSTANCE __stdcall ShellExecuteA(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, 
    ; LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)
    
    extrn ShellExecuteA:dword
    
    В данном случае правильной будет запись (так как мы имеем 6 параметров, каждый размером 4 байта, всего 6*4 = 24 байта)
    extrn ShellExecuteA@24:dword
    
    либо
    extrn _imp__ShellExecuteA@24:dword
    

    В таком виде (плюс лидирующий символ подчеркивания «_», который добавляет компилятор) эти имена функций присутствуют в библиотечных lib-файлах, которые нам нужно будет подгружать при компиляции ассемблерного кода. Понятно, что мы может внести все нужные изменения вручную, но зачем, если по-хорошему, то это задача «Иды».

    Конкретно, это означает, что отладочная информация из соответствующих pdb-файлов не была автоматически загружена из Интернета (с сайта microsoft.com). По этому поводу Ильфак Гильфанов пишет в своей документации, что в этом случае, он типа не виноват, это все происки зловредной Виндозы. Мол, он грузит отладочные символы из Интернета или локально не сам, а через системную \WINDOWS\system32\imagehlp.dll. А она де может отказать в загрузке, по только ей известным причинам. Но мы то верим в это с большим трудом, так как в предыдущей версии IdaPro 5.5 (ее уже нет на сайте Ильфака, но при желании можно найти в бескрайних просторах Сети) отладочные pdb-файлы прекрасно грузятся автоматом из Интернета, даже через прокси-сервер. Но не будем ради этого возвращаться на предыдущую версию. Ситуация в нашем случае такова. Под Windows XP (разных сборок) демо-версия «Иды» категорически отказывается подгружать автоматом или пулеметом Улыбка, то бишь, вручную отладочные символы, а Windows 2003 Server «соглашается» делать это только локально, т.е. загружать pdb-файлы с жесткого диска. «Ида» при этом ругается, на сервере:

    pdb(. . .\IDApro56\Temp\write.exe): Unknown error, code: 0x806D0012,
    
    а в русскоговорящей XPюше:
    pdb(. . .\IDApro56\Temp\write.exe): Класс не зарегистрирован.
    

    Но поскольку лезть во внутренности «Иды», в нашу задачу не входит, то мы продолжим наши исследования в серверной ОСи и расскажем, как можно работать без отладочных символов, если они, по каким-либо причинам, недоступны.

    Заметим, что в Masm32 прототипы функций определяются по-другому. Тот же пример функции ShellExecuteA там (в Include\shell32.inc) описан следующим образом:

    ShellExecuteA PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
    ShellExecute equ <ShellExecuteA>
    

    а сам файл прототипов подключается к проекту с помощью инструкции:

    include Include\shell32.inc
    

    Ничто не мешает нам использовать уже готовые файлы прототипов функций (стиль Iczelion'a). Это, кстати, уменьшает зависимость от pdb-файлов. Однако, лично мне кажется, что для наших целей вариант с использованием директивы extrn (или extern) более предпочтителен. Впрочем, окончательный выбор за вами.

    Загрузка pdb-файлов из Интернета

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

    Для Windows XP, sp. 3 инсталяк pdb-файлов занимает 214 Мб, а для Windows 2003 Server, sp. 2 – около 160 Мб. Можно, конечно, пытаться делать это индивидуально для конкретных файлов. Версия 5.5 «Иды» посылает следующий Get запрос, для XP-шной версии:

    srv*d:\Temp\Ida*http://msdl.microsoft.com/download/symbols/write.pdb/3b7d841d1/write.pdb
    
    Для серверной ОСи, аналогичный запрос:
    srv*d:\Temp\Ida*http://msdl.microsoft.com/download/symbols/write.pdb/3e8000e61/write.pdb
    

    Хотя это и Get запрос, только бесполезно передавать его непосредственно в браузере. По-видимому, нужно еще обмениваться файлами cookie с мелкософтом. Короче, геморно, это все. Проще скачать всю упаковку (или даже несколько) с символами и не париться. Что мы и сделаем.

    Итак, обе упаковки с отладочными символами получены (в виде pdb-файлов) для обеих, рассматриваемых нами, операционных систем.

    Ручная подгрузка pdb-файлов в IdaPro 5.6

    Вручную это можно сделать двумя способами.

    Первый способ заключается в том, чтобы положить файл write.pdb рядом с файлом write.exe. По крайней мере, серверная ОСь понимает это правильно, и подгружает сама нужный нам файл, в результате чего мы получаем то, к чему стремились (рис. 5).

    Прототипы функций после загрузки отладочных символов
    Рис. 5. Прототипы функций после загрузки отладочных символов.

    Вот! Теперь мы вполне удовлетворены полученным результатом. Распознавание прототипов функций осуществлено успешно. Теперь, быстренько (так как время работы одного сеанса демо-версии ограниченно и составляет порядка 30 минут) выделяем весь полученный листинг и сохраняем в тот же файл write.lst, вставив ассемблерный листинг после описания структур.

    Второй способ ручного использования pdb-файлов заключается в его непосредственном выборе из IdaPro через пункт меню File / Load file / PDB file . . . Мы просто указываем путь, выбрав маску файлов (*.*) для нужного файла символов. Заметим только, что выбор не того файла приведет к непредсказуемым последствиям по перекодировке ассемблерного листинга.

    Напомним, что в двух различных сборках XPюши, «Ида» отказывается это делать, мотивируя тем, что «класс не определен». Какой класс и чего, нам объяснять не считают нужным. Можно только предположить, что это глюки самой демо-версии 5.6 либо ее плагина pdb.plw, хотя на серверной ОСи этот плагин вполне успешно работает в предыдущей версии «Иды» (и даже автоматом грузит символы из Интернета, в том числе, через прокси-сервер).

    На случай, если нет интернета или файла write.pdb, покажем, как вручную сделать замену символов в рассматриваемом листинге write.lst. Для этого во всем файле нужно сделать замену строк из левого столбца таблицы на соответствующие строки из правого.

    Таблица 1. Ручная замена символов в листинге write.lst
    До заменыПосле заменыМодуль dll
    1GetStartupInfoA_imp__GetStartupInfoA@4Kernel32.dll
    2GetCommandLineA_imp__GetCommandLineA@0Kernel32.dll
    3GetModuleHandleA_imp__GetModuleHandleA@4Kernel32.dll
    4ShellExecuteA_imp__ShellExecuteA@24shell32.dll
    5_exit_imp___exitmsvcrt.dll
    6__imp__XcptFilter_imp___XcptFiltermsvcrt.dll
    7_cexit_imp___cexitmsvcrt.dll
    8exit_imp__exitmsvcrt.dll
    9_acmdln_imp___acmdlnmsvcrt.dll
    10__getmainargs_imp____getmainargsmsvcrt.dll
    11_c_exit_imp___c_exitmsvcrt.dll
    12__setusermatherr_imp____setusermatherrmsvcrt.dll
    13_adjust_fdiv_imp___adjust_fdivmsvcrt.dll
    14__p__commode_imp____p__commodemsvcrt.dll
    15__p__fmode_imp____p__fmodemsvcrt.dll
    16__set_app_type_imp____set_app_typemsvcrt.dll
    17__imp__controlfp_imp___controlfpmsvcrt.dll
    18__imp__except_handler3_imp___except_handler3msvcrt.dll
    19__imp__initterm_imp___inittermmsvcrt.dll

    В данном случае, это основная суть того, что делает «Ида», подгружая файл с отладочными символами. Как видим, не очень много и, может быть, не стоило бы так заморачиваться с pdb-файлами. Однако, для больших проектов, без отладочных символов трудоемкость работы может существенно возрасти.

    Получение из файла листинга ассемблерного файла

    Полученный файл дизассемблерного листинга после копирования через буфер обмена, содержит не нужные, для целей компиляции, адреса строк кода, перед собственно кодом ассемблера (рис. 6).

    Файл дизассемблерного листинга, полученный через буфер обмена
    Рис. 6. Файл дизассемблерного листинга, полученный через буфер обмена.

    В общем-то, столбец с адресами можно попытаться удалить вручную. Так, например, многие редакторы (лучше с моноширинным шрифтом) поддерживают выделения столбца текста с помощью Alt + левая кнопка мыши, либо Shift + Alt + управление стрелками / PageUp / PageDown / Home / End. Но нам это делать как-то лениво , поэтому мы лучше напишем небольшой скрипт, который будет выполнять за нас всю эту «черную» работу. Лично мне привычен FoxPro, который, на уровне ядра, очень неплох, для любых версий. Однако в данном случае это неважно. Вы можете наваять собственный скрипт, на любом удобном вам языке.

    Вот пример файла lst.prg, выполняющийся под управлением Visual FoxPro:

    ******************************************************************************
    CLEAR
    SET TALK OFF
    SET SAFETY OFF
    
    filename = "write"
    
    infile = filename + ".lst"
    outfile = filename + ".asm"
    
    file1 = FOPEN(infile)
    
    IF file1 < 0
      WAIT 'Не могу открыть файл: ' + infile
      QUIT
    ENDIF
    
    file2 = FCREATE(outfile)
    
    IF file2 < 0
      WAIT 'Не могу создать файл: ' + outfile
      QUIT
    ENDIF
    
    End1 = FSEEK(file1, 0, 2)  && Определяем размер файла
    Top1 = FSEEK(file1, 0)  && Идем в начало. Сама переменная не нужна
    
    IF End1 <= 0  && Если файл пуст
      MESSAGEBOX('Пустой файл: ' + infile)
      QUIT
    ENDIF
    
    pos = 0
    
    strline = FGETS(file1)
    
    DO WHILE NOT EOF(file1)  && На самом деле мы не можем доверять этой проверке
      Curpos1 = FSEEK(file1, 0, 1)
      
      IF Curpos1 >= End1  && Достигнут конец файла?
        pos = AT(" ", strline)
        FPUTS(file2, SUBSTR(strline, pos + 1))    
        EXIT
      ENDIF
    
      IF LEFT(strline, 1) = " "
        FPUTS(file2, strline)
        LOOP
      ENDIF
      
      pos = AT(" ", strline)
      
      IF pos > 0
        FPUTS(file2, SUBSTR(strline, pos + 1))
      ELSE
        FPUTS(file2, "")
      ENDIF
    
      strline = FGETS(file1)
    ENDDO
    
    CLOSE ALL
    QUIT
    ******************************************************************************
    ******************************************************************************
    

    Итак, в нашем распоряжении ассемблерный файл write.asm (рис. 7), который уже можно пытаться компилировать. Поэтому сейчас самое время поговорить о способах компиляции asm кода.

    Файл write.asm
    Рис. 7. Файл write.asm.

    Компиляция ассемблерного кода

    Есть множество версий разного рода ассемблеров и соответствующих программных компиляторов. Также немало и всевозможной документации по этим вопросам. Но лично мне кажется, что начинать нужно с классики жанра – знаменитого туториала от Iczelion'a и используемого им пакета Masm32.

    Пакет Masm32 (на сегодня 10-я версия) на самом деле имеет компилятор макро ассемблера ml.exe от 1999 года. Т.е. он много лет практически не меняется. Возможно это последняя бесплатная версия, ибо более поздние компиляторы ml.exe принадлежат Microsoft и входят в состав продуктов MS Visual Studio, по крайней мере, начиная с 7-й версии (2000 год). Так что, если у вас есть MS VC7 или выше из VS, то вы можете воспользоваться более новой версией ассемблерного компилятора.

    В принципе нас устраивает любая версия Masm32, хоть бесплатная, хоть от MS. Поэтому, для чистоты эксперимента будем работать с Masm32 и компилятором от 1999 года.

    Вот перечень файлов, которые нам понадобятся. Они (или аналогичные) есть также и в Visual C++ из MS Visual Studio.

    Каталог Bin:

    ml.exe – компилятор макро ассемблера;
    ml.err – пустой текстовый файл, для вывода ошибок компилятора;
    link.exe – линковшик;
    rc.exe – компилятор ресурсов;
    rcdll.dll – библиотека компилятора ресурсов;
    cvtres.exe – дополнительный компилятор ресурсов;
    mspdb50.dll – общая библиотека поддержки.

    Каталог Lib (для наших целей достаточно):

    kernel32.lib
    shell32.lib
    msvcrt.lib

    Выше этих каталогов мы будем располагать следующие файлы:

    write.asm – полученный с помощью IdaPro ассемблерный листинг программы write.exe;
    headers.inc – файл заголовка для write.asm, описан ниже;
    write.res – файл ресурсов для write.asm, описан ниже;
    asm.bat – командный файл, описан ниже.

    Опишем используемые нами дополнительные файлы.

    Файл заголовка headers.inc

    Поскольку нам нужны будут в обязательном порядке lib-файлы, для используемых в ассемблерном коде функций из системных dll-лек, то сразу вставим строку

    include headers.inc
    

    после строки

    .model flat
    

    в файле write.asm. Содержимым файла headers.inc будут строки:

    ;============================================================================
    
    includelib Lib\kernel32.lib
    includelib Lib\shell32.lib
    includelib Lib\msvcrt.lib
    
    ;============================================================================
    

    Командный файл asm.bat

    Вот пример командного файла asm.bat, который мы будем использовать для наших целей:

    SET FILENAME=write
    
    :: Компиляция ресурсов (не нужна, если мы берем готовый res-файл от Resource Builder)
    :: Bin\rc /r /v %FILENAME%.rc >a.a
    
    :: Компиляция ассемблерного кода
    Bin\ml /c /coff /Cp /Cx /Zp1 /Gz /Zm %FILENAME%.asm > b.a
    :: /c – компиляция без линковки
    :: /coff – обязательная опция для формата объектного (obj) файла
    :: /Cp – резервирование регистра для пользовательских идентификаторов
    :: /Cx – резервирование регистра для глобальных и экспортируемых символов
    :: /Zp[n] – установить выравнивание структур в n
    :: /Gz – применение вызова функций типа Stdcall
    :: /Zm – совместимость с версией MASM 5.10
    
    :: Линковка (создание exe-файла)
    Bin\link /BASE:0x1000000 %FILENAME%.obj %FILENAME%.res /subsystem:windows >c.a
    :: /BASE:0x1000000 – поскольку в листинге «Иды» указана эта база
    :: Первоначально текст %FILENAME%.res можно убрать, для компиляции без ресурсов
    
    del *.obj
    :: del *.res
    

    Здесь в текстовых файлах a.a, b.a и c.a записываются сообщения о выполнении процессов компиляции и линковки данного кода. Описание ошибок, которые мы сейчас начнем разбирать, находятся в файле b.a.

    Разбор ошибок

    В основном работа с ошибками будет заключаться в удалении ненужного (fake) кода. Будем исходить из случая, когда используются отладочные символы. Если мы делали замену символов вручную, на основе таблицы 1, но некоторых ошибок не будет.

    Итак, компилятор ругается на строки вида:

    extrn _KERNEL32_NULL_THUNK_DATA:byte:4
    . . .
    extrn _SHELL32_NULL_THUNK_DATA:byte:4
    . . .
    extrn _msvcrt_NULL_THUNK_DATA:byte:4
    

    Эти экспортируемые переменные не используются в нашем коде. Зачем они вставлены из pdb-файлов, непонятно. Ну, да ладно, сносим их не глядя.

    Далее, в нашем коде есть строка:

    align 1000h
    

    которая явно не нравиться компилятору. Максимум, что готов принять компилятор это значение вида

    align 10h
    

    так что этот вариант и оставим.

    Также не любит компилятор строки вида:

    mov     eax, large fs:0
    

    Экспериментально выяснилось, что его смущает директива large. Убираем ее полностью, делая автозамену по всему файлу. Тем самым уменьшаем общее количество ошибок на три.

    Остальные ошибки, как оказалось, связаны с директивой rva, которая встречается много раз. Например, в коде:

    ; ---------------------------------------------------------------------------
    align 4
    __IMPORT_DESCRIPTOR_SHELL32 dd rva off_10013D8 ; Import Name Table
    dd 0FFFFFFFFh           ; Time stamp
    dd 0FFFFFFFFh           ; Forwarder Chain
    dd rva aShell32_dll      ; DLL Name
    dd rva __imp__ShellExecuteA@24 ; Import Address Table
    . . .  
    

    Однако этот и оставшийся код (до конца секции) _text

    . . .  
    db 'GetModuleHandleA',0
    align 4
    dd 29h dup(0)
    dd 280h dup(?)
    _text           ends
    

    связан со старой таблицей импорта, которая в нашем случае будет формироваться заново. Поэтому лучшим решением будет удалить этот блок кода полностью. Что мы и делаем, избавляясь заодно от последних ошибок компилятора. Однако для успокоения совести добавим вместо него другой код:

    align 10h
    

    Ура! Компилятор согласился с нашими довольно радикальными операциями и скомпилировал объектный код в виде write.obj. Однако теперь настала очередь ругаться линковщику Улыбка (файл с.а). Практически ему не нравятся все имена функций перечисленных в правой части таблицы 1, к которым, оказались, добавлены лидирующие символы подчеркивания (как в lib-файле), т.е. перед префиксом imp два символа нижнего подчеркивания «__» (а в описании ошибок линковщика даже три), а не один, как у нас. Но это уже не проблема, а всего лишь задача, как говорят студенты Улыбка, которая решается в два хлопка автозаменой «__imp» на «_imp» в файле write.asm. Короче, хлопаем в ладоши, лишние символы удаляются, и наш код прекрасно собирается в exe-шник write.exe. И о, чудо! Программа запускается и можно работать с вызванным ею редактором WordPad (рис. 8).

    Запуск перекомпилированного файла write.asm
    Рис. 8. Запуск перекомпилированного файла write.asm – обёртки для WordPad.

    В данном случае, мы проигнорировали линковку бинарного файла ресурсов write.res, в командном файле asm.bat, так как пока у нас нет этого файла, что однако не помешало запуститься нашей конфетке (в смысле обёртке Улыбка) .

    Работа с ресурсами

    Теперь, когда мы добились принципиальной работоспособности нашего рекомпиляционного кода, можно, после небольшого перекура (быстренько два часа отдохнем, потом пять минут пор-р-р-работаем, пор-р-р-работаем Улыбка), заняться ресурсами. Ибо не факт, что и любая другая подопытная программа, после декомпиляции, будет также хорошо работать без собственных ресурсов.

    IdaPro позволяет создавать сегмент ресурсов (но мы то специально эту галку не ставили). Только это будет что-то вроде секции данных, что не очень удобно для анализа. Лучше найти подходящий редактор ресурсов, который позволит извлекать ресурсы из исполнимых файлов в нужном нам виде. И такой редактор сейчас действительно есть. Речь идет о такой чудесной программе как Resource Builder, триальную версию которой вы можете скачать отсюда. Для демонстрации наших исследований ее возможностей вполне достаточно.

    Мы не будем описывать принципы работы с Resource Builder. В программе поддерживается русский язык, и документации у нее хватает. Достаточно сказать, что мы можем извлечь с помощью нее нужные нам ресурсы, как в бинарном виде write.res, так и в виде описания сценариев ресурсов – файл write.rc. Заодно мы потренируемся в модификации манифеста ресурсов. Для этого изменим, например, строку описания программы (рис. 9). Затем компилируем измененные ресурсы во внешние файлы, которыми можно будет уже воспользоваться.

    Извлечение и модификация ресурсов write.asm
    Рис. 9. Извлечение и модификация ресурсов write.asm с помощью Resource Builder.

    Для наших целей мы можем воспользоваться либо уже готовым для применения бинарным файлом write.res, либо, после небольшого редактирования, файлом сценариев write.rc. В последнем случае нам надо будет раскомментировать строку:

    Bin\rc /r /v %FILENAME%.rc >a.a
    

    в файле asm.bat.

    Изменения в файле описания ресурсов write.rc касаются, в основном, явных определений используемых констант (которые можно найти в h-файлах MS VC++) и редактирования пути для иконки write.ico, которая также создается Resource Builder’ом. Приведем конечное его содержание:

    /*********************************************
    File: WRITE.RC
    Generated by Resource Builder (3.0.3.25).
    *********************************************/
    /*
    OutputExt=res
    */
    
    //MS Visual C++ compatible header
    //  #define APSTUDIO_READONLY_SYMBOLS
    //  #include "afxres.h"
    //  #undef APSTUDIO_READONLY_SYMBOLS
    //end of MS Visual C++ compatible header
    
    // Наши определения, взятые в MS Visual C++
    #define LANG_ENGLISH           0x09
    #define VOS_NT_WINDOWS32       0x00040004L
    #define VFT_APP                0x00000001L
    
    // Иконку, полученную в Resource Builder, переименовываем в write.ico и помещаем рядом с write.asm
    LANGUAGE LANG_ENGLISH, 1
    1 ICON "write.ico"
    
    // Version Info
    1 VERSIONINFO
    FILEVERSION 5, 1, 2600, 0
    PRODUCTVERSION 5, 1, 2600, 0
    FILEOS VOS_NT_WINDOWS32
    FILETYPE VFT_APP {
      BLOCK "StringFileInfo" {
        BLOCK "040904B0" {
          VALUE "CompanyName", "Microsoft Corporation"
          VALUE "FileDescription", "Windows Write - Обёртка для WordPad"
          VALUE "FileVersion", "5.1.2600.0 (xpclient.010817-1148)"
          VALUE "InternalName", "write"
          VALUE "LegalCopyright", "© Microsoft Corporation. All rights reserved."
          VALUE "OriginalFilename", "write"
          VALUE "ProductName", "Microsoft® Windows® Operating System"
          VALUE "ProductVersion", "5.1.2600.0"
        }
      }
    
      BLOCK "VarFileInfo"  {
        VALUE "Translation", 1033, 1200
      }
    }
    

    Компиляция с явным использованием ресурсного скрипта также проходит успешно. Раньше о подобных возможностях приходилось только мечтать! В Total Commander'е можно посмотреть параметры сгенерированного нами файла write.exe (рис. 10). Действительно, внесенные нами изменения имеют место. При желании можно также поменять и иконку. Но это оставим вам, в качестве домашнего задания .

    Просмотр свойств нового write.exe
    Рис. 10. Просмотр свойств нового write.asm с помощью Total Commander.

    Заметим, что размер нашего нового файла в MASM32 v.10ml.exe 1999 года), получился не намного больше исходного exe-шника (разница всего 512 байт). Можно, конечно пытаться уменьшать размер результирующего файла, но это уже не принципиально для наших целей, ибо главную задачу мы выполнили.

    Перекомпиляция других версий write.exe

    Для полноты картины нам еще нужно перекомпилировать XP-шную версию write.exe (который мы переименуем в write2.exe) с исходным размером 22528 байт и версию write.exe от Win2003 (который мы переименуем в write3.exe), размером также 5632 байта.

    Рекомпиляция write2.exe прошла абсолютно по тому же сценарию, что и первый случай. Даже pdb-файл мы не меняли. Разницей оказались, как уже упоминалось, другие иконки (4 штуки). В коде явных различий не обнаружено. Поэтому сразу перейдем к третьему случаю.

    Рекомпиляция write3.exe, несмотря на небольшое отличие в коде (связанного в основном со сканированием собственного PE-заголовка и выбора Image Base, отличного по умолчанию) также прошла успешно.

    Таким образом, все поставленные перед собой задачи мы полностью выполнили.

    Заключение

    Теперь можно подвести итоги нашего тестирования демо-версии IdaPro 5.6 на примере простейшего GUI-приложения write.exe.

    Как дизассемблер (отладочные способности мы не тестировали) IdaPro 5.6 вполне хорош, если не считать его глюки с загрузкой pdb-файлов. Будем надеяться, что Ильфак Гильфанов обратит на это внимание. Но даже ручная правка отладочных символов (или, как альтернатива, использование стиля программирования Iczelion'a) не портит впечатления от «Иды». Это действительно высококачественный продукт. Интересно будет еще попробовать мощь IdaPro на других приложениях, в качестве «подопытного кролика», но на более сложных, чем используемое нами.

    Вот примерный перечень GUI-приложений (для XPюши) – потенциальных кандидатов на тестирование:

    ПриложениеРазмер
    regedt32.exe3584 байт
    winver.exe5632 байт
    dcomcnfg.exe6144 байт
    winhlp32.exe8192 байт
    control.exe8192 байт
    eventvwr.exe8704 байт
    winmsd.exe11776 байт

    и другие.

    (Оказывается, regedt32.exe имеет даже меньший размер, чем write.exe, но обнаружил это я только сейчас Улыбка.)

    Примечание

    К данному тексту приложен файл IdaPro56Test.zip ( http://erfaren.narod.ru/Asm/IdaPro56Test.001 - измените расширение в zip), с результатами тестирования. Можно также посмотреть html версию этой статьи ( http://erfaren.narod.ru/Asm/Erfaren001.htm ) либо ее pdf-файл ( http://erfaren.narod.ru/Asm/Erfaren-001-Recompilation-write-exe.pdf ).


    ◄— Предыдущая Следующая —►


    Hosted by uCoz