Загрузчик PE-файлов
От: Максим М. Гумеров Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 19.03.03 13:43
Оценка: 700 (24) +1
Статья:
Загрузчик PE-файлов
Автор(ы): Максим М. Гумеров
Дата: 20.03.2003
Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL (написанной на VC++). То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.


Авторы:
Максим М. Гумеров

Аннотация:
Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL (написанной на VC++). То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.
Специалист — это варвар, невежество которого не всесторонне :)
Так и не понял смысла статьи
От: BiAlix Украина  
Дата: 28.03.03 09:17
Оценка:
Что конкретно автор собирался сделать? Зачем?
%%%
То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.
%%%

И что и в чем такая сложность?

%%%
Как сделать так, чтобы никто не заметил рядом с исполнимым файлом эту DLL? Ясно, что распространять ее вместе с файлом нельзя.
%%%

Распространять вместе с файлом нельзя? Это как? А вручную делать ее из ресурсов самого файла можно? Какой смысл, если все равно без нее работать приложение не будет?
Если для целей защиты от пиратства, так хороший хакер все равно найдет эту вашу ДЛЛ-ку под каким-нибудь отладчиком ядра и дизассемблирует ее прямо в памяти процесса.

Это больше похоже на умственную зарядку для души. Личное имхо.
bialix
признано решением, недостойным программиста
От: Alexey Chen Чили  
Дата: 21.03.03 16:12
Оценка: 7 (2)
#define QUOTE
Как сделать так, чтобы никто не заметил рядом с исполнимым файлом эту DLL? Ясно, что распространять ее вместе с файлом нельзя. Создание файла DLL из информации, хранимой в самом приложении (например, в виде ресурса) в %TEMP% или где-нибудь в GetTempXXX было признано решением, недостойным программиста.
#undef QUOTE

А с чего бы это? Использование недокументированных возможностей достойно?
Ни кто не мешает сделать темпоральный файл ТОЛЬКО С ОПИСАНИЕМ СЕКЦИЙ и на лету поместить в эти секции код, при этом все будет совершенно законно и точно по спецификации. А если уж использовать недокументируемые возможности то вполне можно было поместить модуль в список загруженных. Это двусвязный список, лежит он в PEB. Если интересно могу прислать код который это делает. НО надо помнить что это НЕ БУДЕТ работать в Win9x, в отличии от варианта с временным файлом.
Сильно сказано.
От: Аноним  
Дата: 20.03.03 13:43
Оценка:
Жалко, что на Паскале.
Re: Так и не понял смысла статьи
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 28.03.03 12:06
Оценка: 1 (1) +1
В чем-то Вы правы. Помимо прочего, это еще и зарядка. И анализ материала по PE-формату. И новая точка зрения на DLL — не "когда-она-уже-загружена", а наоборот.

И еще — так лучше понимаешь, как работает (или почему не работает ;) ) твоя DLL. Принципы загрузки лучше все же знать, чем не знать, согласны?

А вообще, данная работа имела вполне определенную практическую направленность. К сожалению, Вам я о ней прилюдно рассказать не могу.

>> И что и в чем такая сложность?

Если бы Вы знали, сколько раз я слышал эту фразу... Часто тянет ответить: что ж тогда на эту тему нет никакой цельной, законченной информации? Может, конечно, я сейчас препираюсь с гуру, которому и впрямь море по колено... Так, что ли?
Возможно, Вы просто не вчитались в контекст (см. дальше):

>>Распространять вместе с файлом нельзя? Это как?

См. предыдущую фразу статьи: нужно, чтобы DLL никто не заметил.
Специалист — это варвар, невежество которого не всесторонне :)
Re: Сильно сказано.
От: siv Украина  
Дата: 22.03.03 15:13
Оценка:
Очень полезная статья! Спасибо.
Солидарен на все 100% на счет Паскаля;-) Хотелось бы иметь этот загрузчик на С++. Жаль, что времени пока нет переписать самому...
Re: признано решением, недостойным программиста
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 22.03.03 06:33
Оценка:
Да понятно все с PEB. В другом дело (кстати, Вы верно заметили, что это будет несовместимо с 9x). Просто у меня там фактически лишь один undoc используется, да и тот, возможно, где-то все же описан — не все же, кто про него писали, сидели и дизассемблировали виндоус. А вообще — я принципиально против undoc'ов. Вот и все объяснение.

+++
Ни кто не мешает сделать темпоральный файл ТОЛЬКО С ОПИСАНИЕМ СЕКЦИЙ
+++
Ага. Давайте теперь, когда нужно из BLOB-поля вытащить doc-файл и внедренно его открыть, сохранять его в Temp, а потом грузить из файла. Так ведь и правда проще :)
Специалист — это варвар, невежество которого не всесторонне :)
Переучивайся! 8-)
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 20.03.03 16:08
Оценка:
А если серьезно — уж на что я плохо на C пишу, так и то могу перевести готовый код с C на Pascal... Думаю, и тебе будет не сложнее в обратную сторону перевести.
Специалист — это варвар, невежество которого не всесторонне :)
Глупости про язык + вопрос
От: Vamp Россия  
Дата: 24.03.03 08:54
Оценка:
Тебе алгоритма недостаточно, чтобы его хоть на Перле написать, хоть на VB? Ценность статьи — в алгоритме, а не в коде. У меня другой вопрос — не удалось разобраться (хотя бы на уровне UNDOC), что именно мешает гетпросадрес загружать адреса функций?
Да здравствует мыло душистое и веревка пушистая.
Все, убедили...
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 22.03.03 16:29
Оценка:
Напишу параллельную линейку кода на C.
Только не прямо сегодня.
Специалист — это варвар, невежество которого не всесторонне :)
Re: Глупости про язык + вопрос
От: siv Украина  
Дата: 25.03.03 08:39
Оценка:
>Тебе алгоритма недостаточно
Не достаточно. Скажем так, алгоритм, в общих чертах, был известен давно по разрозненным источникам + голова... А вот времени на его реализацию, действительно, не было и не предвидется;-)
>Ценность статьи — в алгоритме
Не только! Еще и в том, что упомянутые источники были сведены вместе, систематизированы и критически проанализированы;-)
Удалось
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 24.03.03 15:02
Оценка:
То же, что мешает и GetModuleHandle. То есть GetProcAddress, в отличие от функций работы с ресурсами, резет сверяться с PEBшными структурами системного загрузчика и очень удивляется тому, что он там обнаруживает. Точнее, чего он не обнаруживает :)
По совету Alexey Chen я скоро выложу новую версию, где для желающих добавлю фрагмент кода для обновления PEB.
Да и сейчас это не проблема — просто при настройке таблицы импорта можно вместо GetProcAddress вписать свою функцию-замену. Правда, все API так не наперехватываешься...
Специалист — это варвар, невежество которого не всесторонне :)
Re: Загрузчик PE-файлов
От: Аноним  
Дата: 05.09.03 06:16
Оценка:
Здравствуйте, Максим М. Гумеров, Вы писали:

ММГ>Статья:

ММГ>Загрузчик PE-файлов

ММГ>Авторы:

ММГ> Максим М. Гумеров

ММГ>Аннотация:

ММГ>Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL (написанной на VC++). То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.

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


Необходимо отметить следующий факт: RawDataSize может быть как меньше, так и больше VirtualSize (разумеется, возможно и равенство). Меньше бывает только в случае, когда секция содержит неинициализированные данные (т.е. такие, для которых в секции отводится место, но значения не загружаются из исходного файла, а устанавливаются равными 0).

Больше же может быть из-за того, что RawDataSize округляется вверх до ближайшего числа, кратного FileAlignment. Например, если размер секции 4090, а FileAlignment=512, и в секции нет неинициализированных данных, то VirtualSize=4090, тогда как RawDataSize=4096.

Поэтому при чтении инициализирующих секцию данных необходимо читать из исходного файла min(VirtualSize, RawDataSize) байт данных.


Почему?!
Поправьте меня, но насколько я правильно понял: VirtualSize — Размер данных в секции, до округления по верхней границе, SizeOfRawData — то же, но уже после округления, PointerToRawData — RVA для инициализирующих данных, VirtualAddress — RVA самой секции. Для неинициализированных данных отводится только место. Отводится оно в VirtualSize, затем округляется до SizeOfRawData. И как тогда SizeOfRawData может быть меньше VirtualSize?! Или SizeOfRawData это округление только инициализированных данных? И зачем нам тогда фактически 2 одинаковых адреса (VirtualAddress, PointerToRawData)? Есть еще мысль, что неиниц. данные располагаются сразу по VirtualAddress, а иниц. по PointerToRawData И SizeOfRawData -- округленные иниц данные. Только не кидайте в мануал, плиз, я там чуть-чуть запутался...


Ps. А если еще кто-то на С всю программу перевел -- слава ему и почет!
Re[2]: Загрузчик PE-файлов
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 18.09.03 18:06
Оценка:
Извиняюсь, что поздно отвечаю — не увидел вопроса.

Поясняю.

Например, если размер секции 4090, а FileAlignment=512, и в секции нет неинициализированных данных, то VirtualSize=4090, тогда как RawDataSize=4096.

А если секция содержит, кроме того, еще и неинициализированные данные после этих инициализированных, то VirtualSize может быть хоть 111111 при том же RawDataSize, т.к. RawDataSize — это объем того, что вшито в PE-образ, т.е. в данном случае — округленный вверх объем инициализированной части секции. Вот вам как раз случай, когда RawDataSize<VirtualSize.

Понятно рассказал или только все запутал?

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re: Загрузчик PE-файлов
От: Аноним  
Дата: 14.01.04 05:29
Оценка:
Здравствуйте, Максим М. Гумеров,

Статья очень интересная, и с познавательной стороны и с практической (вот только если бы было не на Паскале

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

У меня к Вам вопрос. Будет ли вот такой псевдо-код работать?

{
HMODULE hLib =LoadLibrary ("hidden.dll") ;


// Делаем копию иимджа начиная с адреса hLib

// Останавливаем все потоки в процессе : SuspendThread() , чтобы кто-нибудь не занял виртуальную память

FreeLibrary(hLib) ;

DeleteFile ("hidden.dll") ;

// Выделяем память по адресу hLib в нужном кол-ве

memcopy ((void*) hLib , (void*) saved_image , sizeof(saved_image ) );

// Обратно запускаем все потоки: ResumeThread()


}

Идея следующая. Пусть штатный загрузчик сделает всю работу сам, затем мы сделаем копию памяти и выгрузим библиотеку — тогда уже никто не сможет "увидеть" с помощью ProcessBrowser или других spy что ваш процесс грузит такую то dll.
Потом снова выделяем память по тому же адресу и снова в нее пишем содержимое имиджа.
Чтобы какой-нибудь поток в промежутке между этими действами случайно не занял нужный нам кусочек памяти — останавливаем все потоки на короткое время.

Работоспособен ли данный метод или есть какие-то подводные камни?

Еще раз спасибо!
Re[2]: Так и не понял смысла статьи
От: c-smile Канада http://terrainformatica.com
Дата: 14.01.04 07:23
Оценка: :)
Здравствуйте, Slicer [Wirkwood], Вы писали:

SW>См. предыдущую фразу статьи: нужно, чтобы DLL никто не заметил.


Что значит никто? ... Детский сад, младшая группа.

Агенство по авторским правам ищет по сигнатурам которые предоставляют сами авторы.
В том числе анализируется и паттерны исполняемых функций.

Лучше стать автором чего полезного. Интереснее.
И денег больше в разы. Проверено.

Trust me.

Re[3]: Так и не понял смысла статьи
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 14.01.04 10:34
Оценка:
Отвечаю с конца.

CS>Лучше стать автором чего полезного. Интереснее.

CS>И денег больше в разы. Проверено.
Стараюсь. Trust me. Но и исследованиями кто-то должен заниматься.

SW>>См. предыдущую фразу статьи: нужно, чтобы DLL никто не заметил.

CS>Что значит никто? ... Детский сад, младшая группа.
Кому как. Если знать, что искать — конечно, шансы найти большие. А если не знать? Насчет сигнатур — нет НИЧЕГО элементарнее, чем приделать криптование. После этого останется только уже в памяти искать. А вообще, у меня была конкретная задача, в детали вдаваться, само собой, не буду — и подход себя оправдал на 100%. И, судя по письмам, что приходят ко мне на ящик, такая надобность возникла не только у меня, и люди готовы юзать предложенную схему даже несмотря на все ограничения.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[2]: Загрузчик PE-файлов
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 14.01.04 10:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Статья очень интересная, и с познавательной стороны и с практической (вот только если бы было не на Паскале

Ну извиняйте, с чем в основном работаю, на том и написал. Делал бы на C, багов было бы больше

А>Идея следующая. Пусть штатный загрузчик сделает всю работу сам, затем мы сделаем копию памяти и выгрузим библиотеку — тогда уже никто не сможет "увидеть" с помощью ProcessBrowser или других spy что ваш процесс грузит такую то dll.


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

Так что просто не вижу выигрыша. Да и самое главное — файл при этом появляется, хоть и ненадолго! А если у аккаунта, под которым запущена программа, нет прав писать в TEMP? (не знаю, бывает ли так, но теоретически, думаю, возможна ситуация, когда TEMP лежит на C, а C — R/O для всех, кроме админов).

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[3]: Загрузчик PE-файлов
От: Аноним  
Дата: 14.01.04 12:44
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM>Далее, наша либа вполне может выгружать все используемые ею dllки.



Насколько я понимаю, при выгрузке нашей dll вызываются и FreeLibrary для связанных модулей. FreeLibrary decrements the reference count of the loaded dynamic-link library, т.е. это не значит что модуль сейчас же будет выгружен, просто на него уменьшится счетчик ссылок.

Кстати, сейчас парралельно возникла еще одна ветка :
http://www.rsdn.ru/Forum/Message.aspx?mid=506011&amp;only=1
Автор: c-smile
Дата: 14.01.04


что еще раз подтверждает "полезность" идеи. Это интересно как с точки зрения "защиты" своего кода, так и незаметного использования чужого.
Re[4]: Так и не понял смысла статьи
От: c-smile Канада http://terrainformatica.com
Дата: 14.01.04 23:16
Оценка: 1 (1) +3
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM>Отвечаю с конца.


CS>>Лучше стать автором чего полезного. Интереснее.

CS>>И денег больше в разы. Проверено.
SM>Стараюсь. Trust me. Но и исследованиями кто-то должен заниматься.

SW>>>См. предыдущую фразу статьи: нужно, чтобы DLL никто не заметил.

CS>>Что значит никто? ... Детский сад, младшая группа.
SM>Кому как. Если знать, что искать — конечно, шансы найти большие. А если не знать? Насчет сигнатур — нет НИЧЕГО элементарнее, чем приделать криптование. После этого останется только уже в памяти искать. А вообще, у меня была конкретная задача, в детали вдаваться, само собой, не буду — и подход себя оправдал на 100%. И, судя по письмам, что приходят ко мне на ящик, такая надобность возникла не только у меня, и люди готовы юзать предложенную схему даже несмотря на все ограничения.

SM>Slicer


"Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL"

1) Сама концепция этой фразы этически не вяжется с духом RSDN (Это я уже модераторам свое ИМХО сообщаю)
2) Апликация испльзующая такой DLL embedding не для продаж за пределами России и Китая. Т.е. финансовый выход — ноль. Т.е. можно конечно сделать разовый проект для какого-нибудь заказчика в России. Но ему, этому заказчику, до фени вообще какие там DLL у тебя, верно? Тогда в чем сермяжность?

Т.е. практическая ценность исследований такого рода ассимптотически стремится к нулю.

Если же ты делаешь нечто на продажу, то гораздо(!) выгоднее и во времени и в нервах потратить 15-30 минут на следующее письмо авторам сокрываемой DLL примерно такого содержания:

Dear sir/madam.

Я собираюсь выпустить апликацию А в которой я бы хотел использовать Ваш компонент Б. Уж сильно он мне нравится бла-бла-бла....
К сожалению финансовые обстоятельства не позволяют мне в настоящее время оплатить....
Возможно ли...
И т.д.

Могу тебя заверить 99% авторов отнесутся с пониманием и станут тебя уважать заранее.
Причем сие уважение как бы качеством повыше чем "Слышь, пацан, ну ты крутой хакер".
Т.к. позволяет к тому же наладить партнерские отношения и пр. и пр.
Заодно чуть повысишь имидж российских разработчиков. Заодно заявишь серьезность намерений и пр.

Типа того. Это, кстати, из моего личного опыта.

Успехов в Пути.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.