Пишем упаковщик по шагам. Шаг третий. Распаковываем.

Предыдущий шаг здесь.

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

Начнем мы вот с чего. Для работы распаковщика нам стопроцентно потребуются две WinAPI-функции: LoadLibraryA и GetProcAddress. В своем старом упаковщике я писал стаб распаковщика на MASM32 и вообще не создавал таблицу импорта. Я искал адреса этих функций в ядре, что несколько сложно и хардкорно, кроме того, это может вызвать неиллюзорные подозрения у антивирусов. Давайте в этот раз создадим обычную таблицу импортов и сделаем так, чтобы загрузчик сам нам сообщил адреса этих функций! Разумеется, набор из двух этих функций в таблице импорта так же подозрителен, как и полное их отсутствие, но ничто нам не мешает в будущем добавить еще другие левые случайные импорты из различных DLL-файлов. Куда загрузчик будет записывать адреса этих двух функций? Пора расширить нашу структуру packed_file_info!

Я добавил в структуру три поля. В первые два загрузчик впишет адреса функций LoadLibraryA и GetProcAddress из kernel32.dll. Последнее поле указывает на конец адресной таблицы импорта (import address table, IAT), и в него мы запишем ноль, чтобы дать понять загрузчику, что больше никаких функций нам не надо. Про это я еще расскажу немного дальше.

Теперь необходимо создать новую таблицу импорта. В этом нам сильно поможет моя библиотека для работы с PE. (На старую оригинальную мы пока что наплюем).

Начало кода понятно - создали импорт библиотеки, добавили к ней пару функций, создали список импортируемых библиотек из одной-единственной kernel32.dll. Поясню строку, где мы устанавливаем RVA к IAT (kernel32.set_rva_to_iat). Я уже раньше писал кое-что об импортах PE-файла. Расскажу вкратце еще разок. Для каждой импортируемой библиотеки в таблице импортов создается следующая структура:

Загрузчик записывает адреса импортируемых функций в Import Address Table (IAT) для каждой импортируемой DLL, а имена или ординалы импортируемых функций он берет из Original Import Address Table (или, по-другому, Import Lookup Table). Можно обойтись и без последней, например, все компиляторы Borland всегда так делают, плевать они хотели на Import Lookup Table. В этом случае у нас в единственной таблице Import Address Table содержатся сразу ординалы или имена импортируемых функций, и туда же, поверх этих данных, загрузчик запишет адреса непосредственно импортированных функций. Мы тоже не будем делать Original Import Address Table, обойдемся без нее (меньше места импорт займет), поэтому отключаем эту опцию в пересборщике импортов.

Вызов settings.save_iat_and_original_iat_rvas настраивает пересборщик таким образом, что он не будет создавать свои собственные IAT и Original IAT, а запишет все по тем адресам, которые уже указаны в каждой библиотеке (помните вызов kernel32.set_rva_to_iat?).

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

Теперь запустим получившийся бинарник в OllyDbg и убедимся, что загрузчик записал адреса двух нужных нам функций туда, куда надо:

Как видно, по адресам 0x1009 и 0x100D записались именно те адреса, которые нам нужны, значит, все сделано правильно. (Адрес точки входа пока что совершенно левый, и нет никакого распаковщика, поэтому файл по-прежнему не запустится, но мы уже достигли многого).

Идем дальше. Необходимо подготовить наши сорсы для написания распаковщика. Вынесем все структуры из файла main.cpp в файл structs.h, его содержимое будет таким:

Тут пояснять ничего не нужно, мы просто перенесли код. В main.cpp, в свою очередь, подключим этот файл:

И наступает время хардкора! Будем писать распаковщик. Немного поразмыслив, я решил не использовать MASM32, а писать его на C с элементами C++ и ассемблерными вставками - читаемость кода будет выше. Итак, создаем новый проект в солюшене и называем его unpacker. Добавляем к нему файлы unpacker.cpp и parameters.h (создаем). Далее в настройках выставляем всё то же самое, что мы делали с проектом lzo-2.06 в самом первом шаге, чтобы сборка была самой минимальной по размеру и базонезависимой. Точку входа (Linker - Advanced - Entry Point) выставляем в unpacker_main. Далее, в Configuration Manager'е (см. шаг 1) выставляем, чтобы этот проект всегда собирался в конфигурации Release:

Проставим у проекта simple_pe_packer зависимость от проекта unpacker (Project Dependencies, как в шаге 1) и добавим файл parameters.h в инклюды проекта упаковщика - в этот файл мы будем вписывать необходимые параметры для сборки распаковщика:

Теперь начнем писать сам распаковщик. Открываем файл unpacker.cpp...

Итак, начинаю разъяснения. Сначала мы подключили файл, содержащий объявления структур упаковщика - в распаковщике они нам пригодятся. Далее мы создаем точку входа - процедуру unpacker_main. Обратите внимание, что это особо объявленная функция - naked. Это говорит компилятору о том, что не нужно создавать для этой функции пролог и эпилог (стековый фрейм) автоматически. Нам это необходимо сделать вручную, а зачем - поясню в следующем уроке. Пока что мы создаем точь-в-точь такие же пролог и эпилог, которые делает сам компилятор MSVC++. Строка "sub esp, 128" выделяет на стеке 128 байтов - этого нам пока должно хватить для подручных нужд. В этом шаге распаковщик не будет делать чего-то серьезного. Пролог и эпилог нужны нам, чтобы мы могли выделять память на стеке без лишних проблем. В самом конце мы пишем инструкцию ret - возврат в ядро. Теперь напишем самое простое тело упаковщика. Пусть он будет просто приветствовать нас, выдавая Message Box с текстом "Hello!".

Здесь мы объявили две локальные переменные. Первая будет содержать действительный адрес загрузки образа, а вторая - относительный адрес самой первой секции, в которую, как вы помните, мы кладем всю необходимую для распаковщика информацию и сами упакованные данные. Вместо чисел 0x11111111 и 0x22222222 мы с помощью упаковщика будем записывать реальные значения.

Здесь, кажется, все понятно. В начале первой секции упакованного файла лежит структура packed_file_info, которую мы создаем в упаковщике. В ней есть еще три поля, заполняемые самим загрузчиком - мы так устроили таблицу импортов, как вы помните. Из этих полей мы получаем адреса функций LoadLibraryA и GetProcAddress. Вы еще можете спросить, зачем я сначала объявляю все переменные, и только позже присваиваю им значения, ведь я мог бы это делать одной строкой. Все дело в том, что в naked-функциях нельзя одновременно объявить переменную и сразу же присвоить ей значение.

И последняя (пока что) часть кода распаковщика:

Здесь в целом тоже все должно быть понятно, кроме странного заполнения строк. Мы выделили буфер buf на стеке. Строки все у нас также должны быть исключительно на стеке - мы ничего не можем писать в секцию данных, так как это неизбежно приведет к появлению релокаций, и код станет базозависимым. Именно поэтому мы так нелепо по 4 байта записываем строки непосредственно в стековый буфер. Нужно еще помнить про обратный порядок байтов, с которым работает архитектура x86, а мы именно под нее пишем код, поэтому буквы в кусках строк по 4 байта расположены в обратном порядке.

Сначала мы загружаем библиотеку user32.dll, затем получаем из нее адрес процедуры MessageBoxA, а затем вызываем ее. Вот и всё с распаковщиком!

Но осталась еще одна вещь - нам надо код распаковщика каким-то образом вставить в упакованный файл и настроить. Я решил это дело автоматизировать. Для этого добавим новый проект с именем unpacker_converter в солюшен. Цель этого проекта такова: он будет открывать получающийся после компиляции распаковщика файл unpacker.exe, считывать данные из его единственной секции (по сути, код) и преобразовывать его в h-файл, который мы заинклюдим в проекте simple_pe_packer. Пропишем в проекте unpacker_converter include-директорию как в проекте simple_pe_packer, чтобы можно было подключать h-файлы библиотеки для работы с PE-файлами, добавим в проект файл main.cpp и начнем писать код.

Не буду детально описывать этот код - многое вам уже будет знакомо. Скажу только, что он просто формирует из файла unpacker.exe файл unpacker.h вида:

Эти данные являются шестнадцатеричным представлением данных первой и единственной секции кода распаковщика. Он у нас пока совсем простой и маленький. Как же сделать, чтобы unpacker_converter автоматически генерировал для нас такой h-файл при пересборке распаковщика? Необходимо поправить настройку проекта unpacker (Build Events - Post-Build Event):

Почему я в этой настройке не использовал макрос $(Configuration)? Потому что он для проекта unpacker всегда будет раскрываться в "Release", так как и в дебаге, и в релизе этот проект собирается как Release (мы это меняли ранее в Configuration Manager'е). Поэтому мы просто будем копировать файл unpacker_converter.exe из ЕГО текущей конфигурации в корень проекта, и оттуда его уже сможет взять проект unpacker. Таким образом, последнее, что мы делаем, это правим конфигурацию проекта unpacker_converter (Build Events - Post-Build Event):

Осталось расставить зависимости (Project Dependencies): unpacker от unpacker_converter (вохможно, это не совсем логично, ну да ладно). После этого у нас все будет собираться и в Release, и в Debug-конфигурации.

Поясню, что мы запишем в файл parameters.h. Его содержимое будет таким:

Мы пишем смещения относительно начала кода распаковщика (в собранном бинарном виде) двух чисел - 0x11111111 и 0x22222222. Эти числа будут перезаписываться упаковщиком, а смещения 0xC (12) и 0x13 (19) просчитываются в любом HEX-редакторе или с помощью автогенеренного файла unpacker.h. Меняться они уже вряд ли будут, так как код перед двумя ассемблерными командами mov в распаковщике мы больше дописывать не будем.

Добавим в include проекта simple_pe_packer автогенеренный файл unpacker.h:

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

Теперь будем вставлять туда код распаковщика и настраивать его:

Всё! Теперь распаковщик будет настраиваться и добавляться в упакованный файл! Давайте убедимся в этом. Как всегда, упакуем сами себя, получив на выходе файл packed_simple_pe_packer.exe. Запустим его и увидим долгожданное окошко, ради которого было проделано столько работы!

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

Как всегда, прикладываю полный солюшен (кроме библиотеки для работы с PE-файлами) упаковщика: Own PE packer step 3

Пишем упаковщик по шагам. Шаг третий. Распаковываем.: 11 комментариев

      1. Спасибо за обзор. Почему написал, что винда читает иконку по секции .rsrc? Ведь можно вообще затереть имена и от этого иконка не исчезнет.

  1. dx, проблемы при сборке unpacker_converter:

    1>------ Построение начато: проект: unpacker_converter, Конфигурация: Debug Win32 ------
    1>Построение начато 25.09.2013 19:40:36.
    1>InitializeBuildStatus:
    1> Обращение к "Debug\unpacker_converter.unsuccessfulbuild".
    1>ClCompile:
    1> Для всех выходных данных обновления не требуется.
    1>ManifestResourceCompile:
    1> Для всех выходных данных обновления не требуется.
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: void __thiscall std::basic_ios<char,struct std::char_traits >::setstate(int,bool)" (?setstate@?$basic_ios@DU?$char_traits@D@std@@@std@@QAEXH_N@Z) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: class std::basic_streambuf<char,struct std::char_traits > * __thiscall std::basic_ios<char,struct std::char_traits >::rdbuf(void)const " (?rdbuf@?$basic_ios@DU?$char_traits@D@std@@@std@@QBEPAV?$basic_streambuf@DU?$char_traits@D@std@@@2@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: void __thiscall std::_Container_base12::_Orphan_all(void)" (?_Orphan_all@_Container_base12@std@@QAEXXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: __thiscall std::_Container_base12::_Container_base12(void)" (??0_Container_base12@std@@QAE@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12@std@@QAE@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: class std::locale::facet * __thiscall std::locale::facet::_Decref(void)" (?_Decref@facet@locale@std@@QAEPAV123@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: bool __thiscall std::ios_base::good(void)const " (?good@ios_base@std@@QBE_NXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: int __thiscall std::ios_base::flags(void)const " (?flags@ios_base@std@@QBEHXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: void __thiscall std::locale::facet::_Incref(void)" (?_Incref@facet@locale@std@@QAEXXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: class std::basic_ostream<char,struct std::char_traits > & __thiscall std::basic_ostream<char,struct std::char_traits >::flush(void)" (?flush@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV12@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: int __thiscall std::basic_streambuf<char,struct std::char_traits >::sputc(char)" (?sputc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAEHD@Z) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: __int64 __thiscall std::basic_streambuf<char,struct std::char_traits >::sputn(char const *,__int64)" (?sputn@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAE_JPBD_J@Z) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "protected: char * __thiscall std::basic_streambuf<char,struct std::char_traits >::gptr(void)const " (?gptr@?$basic_streambuf@DU?$char_traits@D@std@@@std@@IBEPADXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "protected: char * __thiscall std::basic_streambuf<char,struct std::char_traits >::_Gninc(void)" (?_Gninc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@IAEPADXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: void __thiscall std::basic_ostream<char,struct std::char_traits >::_Osfx(void)" (?_Osfx@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEXXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: class std::basic_ostream<char,struct std::char_traits > * __thiscall std::basic_ios<char,struct std::char_traits >::tie(void)const " (?tie@?$basic_ios@DU?$char_traits@D@std@@@std@@QBEPAV?$basic_ostream@DU?$char_traits@D@std@@@2@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "protected: char * __thiscall std::basic_streambuf<char,struct std::char_traits >::_Pninc(void)" (?_Pninc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@IAEPADXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_base.obj) : error LNK2005: "public: __thiscall std::locale::id::operator unsigned int(void)" (??Bid@locale@std@@QAEIXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_32_64.obj) : error LNK2005: "public: __thiscall std::_Container_base12::_Container_base12(void)" (??0_Container_base12@std@@QAE@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_32_64.obj) : error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12@std@@QAE@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_32_64.obj) : error LNK2005: "public: void __thiscall std::_Container_base12::_Orphan_all(void)" (?_Orphan_all@_Container_base12@std@@QAEXXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_32_64.obj) : error LNK2005: "public: void __thiscall std::basic_ios<char,struct std::char_traits >::setstate(int,bool)" (?setstate@?$basic_ios@DU?$char_traits@D@std@@@std@@QAEXH_N@Z) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>pe_lib.lib(pe_32_64.obj) : error LNK2005: "public: class std::basic_streambuf<char,struct std::char_traits > * __thiscall std::basic_ios<char,struct std::char_traits >::rdbuf(void)const " (?rdbuf@?$basic_ios@DU?$char_traits@D@std@@@std@@QBEPAV?$basic_streambuf@DU?$char_traits@D@std@@@2@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(syserror.obj) : error LNK2005: "public: __thiscall std::_Container_base12::_Container_base12(void)" (??0_Container_base12@std@@QAE@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(syserror.obj) : error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12@std@@QAE@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(syserror.obj) : error LNK2005: "public: void __thiscall std::_Container_base12::_Orphan_all(void)" (?_Orphan_all@_Container_base12@std@@QAEXXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(ios.obj) : error LNK2005: "public: class std::locale::facet * __thiscall std::locale::facet::_Decref(void)" (?_Decref@facet@locale@std@@QAEPAV123@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(locale0.obj) : error LNK2005: "private: static void __cdecl std::locale::facet::_Facet_Register(class std::locale::facet *)" (?_Facet_Register@facet@locale@std@@CAXPAV123@@Z) уже определен в msvcprtd.lib(locale0_implib.obj)
    1>libcpmtd.lib(locale0.obj) : error LNK2005: "public: class std::locale::facet * __thiscall std::locale::facet::_Decref(void)" (?_Decref@facet@locale@std@@QAEPAV123@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(locale0.obj) : error LNK2005: "private: static class std::locale::_Locimp * __cdecl std::locale::_Getgloballocale(void)" (?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(locale0.obj) : error LNK2005: "public: void __thiscall std::locale::facet::_Incref(void)" (?_Incref@facet@locale@std@@QAEXXZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(xlock.obj) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>libcpmtd.lib(xlock.obj) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) уже определен в msvcprtd.lib(MSVCP100D.dll)
    1>LIBCMTD.lib(setlocal.obj) : error LNK2005: __configthreadlocale уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(dbgheap.obj) : error LNK2005: __free_dbg уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(dbgheap.obj) : error LNK2005: __CrtSetCheckCount уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(dbghook.obj) : error LNK2005: __crt_debugger_hook уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(invarg.obj) : error LNK2005: __invalid_parameter уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(invarg.obj) : error LNK2005: __invoke_watson уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(mlock.obj) : error LNK2005: __lock уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(mlock.obj) : error LNK2005: __unlock уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: _exit уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __exit уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __cexit уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __amsg_exit уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __initterm_e уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(winxfltr.obj) : error LNK2005: __XcptFilter уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(crt0.obj) : error LNK2005: _mainCRTStartup уже определен в MSVCRTD.lib(crtexe.obj)
    1>LIBCMTD.lib(errmode.obj) : error LNK2005: ___set_app_type уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xi_a уже определен в MSVCRTD.lib(cinitexe.obj)
    1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xi_z уже определен в MSVCRTD.lib(cinitexe.obj)
    1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xc_a уже определен в MSVCRTD.lib(cinitexe.obj)
    1>LIBCMTD.lib(crt0init.obj) : error LNK2005: ___xc_z уже определен в MSVCRTD.lib(cinitexe.obj)
    1>LIBCMTD.lib(hooks.obj) : error LNK2005: "void __cdecl terminate(void)" (?terminate@@YAXXZ) уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(dbgrptw.obj) : error LNK2005: __CrtDbgReportW уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(_file.obj) : error LNK2005: __lock_file уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(_file.obj) : error LNK2005: __unlock_file уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LIBCMTD.lib(fflush.obj) : error LNK2005: _fflush уже определен в MSVCRTD.lib(MSVCR100D.dll)
    1>LINK : warning LNK4098: библиотека по умолчанию "MSVCRTD" противоречит использованию других библиотек; используйте параметр /NODEFAULTLIB:library
    1>LINK : warning LNK4098: библиотека по умолчанию "LIBCMTD" противоречит использованию других библиотек; используйте параметр /NODEFAULTLIB:library
    1>C:\Users\user1\Documents\Visual Studio 2010\Projects\portable_executable_library\simple_pe_packer\simple_pe_packer\Debug\unpacker_converter.exe : fatal error LNK1169: обнаружен многократно определенный символ - один или более
    1>
    1>СБОЙ построения.
    1>
    1>Затраченное время: 00:00:03.26
    ========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========

    Что делать?

    1. Видимо, какой-то из проектов солюшена собирается со статическими рантаймами, а какой-то с динамическими. Проблемно будет что-то собрать, не зная, как пользоваться компилятором... Проще скачать собранное.

  2. Как можно исправить это:

    1> All outputs are up-to-date.
    1> unpacker.vcxproj -> D:\Главное\SandBox\C++\Lib\Joni\Release\unpacker.exe
    1>PostBuildEvent:
    1> ""..\unpacker_converter.exe"" не является внутренней или внешней
    1> командой, исполняемой программой или пакетным файлом.
    1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: The command ""..\unpacker_converter.exe" "..\Release\unpacker.exe" "..\Joni\unpacker.h"
    1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :VCEnd" exited with code 9009.
    1>
    1>Build FAILED.

    1. Здесь что-то с PostBuild-событием (работа, которая выполняется после сборки проекта). Надо посмотреть, где лежит файл unpacker_converter.exe и собрался ли он вообще. Если собрался, то убедиться, что в PostBuildEvent в Visual Studio указан корректный путь к нему и к аргументам командной строки, которые ему передаются.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *