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

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

Появилась новая версия библиотеки для работы с PE-файлами (0.1.5). Перекачайте и пересоберите ее.

Пришло время заняться обработкой такой важной вещи, как Thread Local Storage (TLS) - локальной памяти потока. Что она из себя представляет? Это небольшая структура, которая говорит загрузчику PE-файлов о том, где находятся данные, которые должны быть выделены в памяти для каждого потока. Загрузчиком также производится вызов функции TlsAlloc, и значение, возвращенное ей, записывается по адресу, также указанному в этой структуре (называется это индексом). Кроме того, эта же структура может содержать адрес массива, хранящего набор коллбэков (адресов функций), которые будут вызваны загрузчиком при загрузке файла в память или при создании нового потока в процессе.

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

Читать далее «Пишем упаковщик по шагам. Шаг шестой. TLS.»

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

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

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

Читать далее «Пишем упаковщик по шагам. Шаг пятый. Ресурсы.»

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

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

Появилась новая версия библиотеки для работы с PE-файлами (0.1.4). Перекачайте и пересоберите ее.

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

Читать далее «Пишем упаковщик по шагам. Шаг четвертый. Запускаем.»

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

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

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

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

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

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

Сразу скажу, что по мере написания этого цикла статей я кое-что правлю и дорабатываю в своей библиотеке для работы с PE-файлами. Поэтому вам стоит ее перекачать и пересобрать - сейчас уже есть версия 0.1.3.

И мы продолжаем написание собственного упаковщика. В этом шаге пора переходить непосредственно к упаковке PE-файла. Я достаточно давно выкладывал простенький упаковщик, который был малоэффективным по двум причинам: во-первых, он использовал стандартные Windows-функции для упаковки и распаковки данных, обладающие достаточно низкой степенью сжатия и скоростью, во-вторых, паковались все секции PE-файла по отдельности, что не очень-то оптимально. В этот раз я сделаю по-другому. Мы будем считывать данные всех секций сразу, слеплять их в один кусок и упаковывать. В результирующем файле, таким образом, будет только одна секция (на самом деле две, потом поясню, почему), в которой мы сможем разместить и ресурсы, и код распаковщика, и сжатые данные, и вспомогательные таблицы. Мы получаем некоторый выигрыш, потому что не нужно тратить размер на файловое выравнивание, кроме того, алгоритм LZO явно более эффективен, чем RtlCompressBuffer, во всех отношениях.

Читать далее «Пишем упаковщик по шагам. Шаг второй. Пакуем.»

Пишем упаковщик PE-файлов по шагам. Шаг первый.

Раз уж я закончил разработку библиотеки на C++ для работы с PE-файлами, грех не использовать ее в каком-то более-менее серьезном проекте. Поэтому я разработаю с ее помощью упаковщик, поясняя по шагам, что я делаю, а либа на C++ сильно упростит нам жизнь. Итак, с чего же начать разработку упаковщика? Наверное, с выбора какого-нибудь несложного бесплатного алгоритма сжатия. После непродолжительных поисков таковой был мной найден: LZO. Он поддерживает множество различных видов сжатия (можно считать, разновидностей), и LZO1Z999 - самая эффективная по степени сжатия из всех доступных. Это, конечно, не ZIP, но приближается к нему по эффективности: 550-килобайтный файл был сжат zip'ом с максимальной степенью сжатия в 174 килобайта, в то время как LZO сжал тот же файл до 185 килобайтов. Однако у LZO гораздо более быстрый распаковщик. Он также оказался базонезависимым, то есть, его можно разместить по любому виртуальному адресу, и он будет работать без всяких корректировок адресов. Размер распаковщика приятно удивил: Visual Studio с оптимизациями по размеру и отключением исключений и проверок буферов дала результат в 613 байтов кода! Этот алгоритм нам подойдет.

Читать далее «Пишем упаковщик PE-файлов по шагам. Шаг первый.»

Библиотека для работы с PE-файлами (C++)

Выкладываю более-менее завершенную библиотеку для работы с Portable Executable (PE) файлами - PE Bliss.

Основные фичи библиотеки:
[+] Чтение 32-разрядных и 64-разрядных PE-файлов (PE, PE+) для Windows, возможность единообразной работы с обоими форматами
[+] Создание PE/PE+ образов с чистого листа
[+] Пересборка 32-разрядных и 64-разрядных PE-файлов
[+] Работа с директориями и заголовками
[+] Конвертирование адресов
[+] Чтение и редактирование секций PE-файла
[+] Чтение и редактирование таблицы импортов
[+] Чтение и редактирование таблицы экспортов
[+] Чтение и редактирование таблиц релокаций
[+] Чтение и редактирование ресурсов
[+] Чтение и редактирование TLS
[+] Чтение конфигурации образа (image config)
[+] Чтение базовой информации .NET
[+] Чтение информации о привязанном импорте
[+] Чтение директории исключений (только PE+)
[+] Чтение отладочной директории с расширенной информацией
[+] Вычисление энтропии
[+] Изменение файлового выравнивания
[+] Изменение базового адреса загрузки
[+] Работа с DOS Stub'ом и Rich overlay
[+] Высокоуровневое чтение ресурсов: картинки, иконки, курсоры, информация о версии, строковые таблицы, таблицы сообщений
[+] Высокоуровневое редактирование ресурсов: картинки, иконки, курсоры, информация о версии

Словом, все, что вы хотели сделать с PE, но боялись спросить, как. Весь код библиотеки снабжен обильными комментариями на английском языке. В проект включено 25 примеров работы с библиотекой, которые показывают, как работать с той или иной частью библиотеки (комментарии на русском языке). Имеются солюшены для MSVC++ 2008 и 2010. Справочной информации пока нет, возможно, соберусь ее как-нибудь написать.

Библиотека не использует WinAPI или другие библиотеки, только STL.

Библиотека и примеры собираются под Windows x86 и x64, но для того, чтобы работать с PE+, собирать под x64 необязательно. Библиотека не исполняет считываемые файлы, не маппит их в память, поэтому с ее помощью можно спокойно открывать подозрительные исполняемые файлы и работать с ними. Теперь собирается еще и под Linux.

Проект залит на code.google.com на случай возможных правок и улучшений, так как сейчас библиотека в стадии альфа-версии.

Репозиторий: http://code.google.com/p/portable-executable-library/
Скачать архив с сорсами версии 0.1.11 (годятся для сборки упаковщика по ману, который тут в блоге есть): ZIP
Скачать архив с последними сорсами (1.0.0): ZIP

Жизненный RFID

Последний месяц выдался не слишком продуктивным, так как приходилось много ездить по разнообразным медицинским учреждениям. На вторую неделю поездок выяснилось, что большинство учреждений используют RFID-карты для разграничения доступа во внутренних помещениях. Таким образом, под конец месяца у меня набралось великое множество таких карт, что было дико неудобно: приехал в очередное место, открыл рюкзак, достал кипу карт и ищешь где именно та, которую тебе дали на прошлой неделе местные сотрудники. Ещё одним негативным моментом этих поездок было время, которое приходилось проводить в транспорте. В итоге я решил избавиться от одного из неудобств, а именно купить программатор и написать программу-менеджер, которая избавит от необходимости таскать с собой кучу карт (все равно ношу в рюкзаке нетбук, а программатор много веса не добавит) и позволит вести базу, по которой можно будет быстро найти карту от нужного помещения для заданного учреждения, записать идентификатор на болванку и воспользоваться им по назначению. Сказано - сделано, вчера, во время очередной серии поездок, написал соответствующую программку, которую далее и рассмотрю подробнее.
Также обозначим формат карт, который, как оказалось, является доминирующим по неведомой мне причине - это EM-4100. Мимоходом, в магазине со всякой электроникой, был куплен программатор китайского производства, к которому прилагались драйвера для USB-UART моста модели CP210x производства Silicon Laboratories и стремный софт с китайским интерфейсом (имеющий в своем арсенале только функции чтения и записи идентификатора карты), который все же пригодился в дальнейшем.
Читать далее «Жизненный RFID»

Игрища с USB в Windows (отслеживаем и контролируем)

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

Итак, в статье я расскажу, как:
[+] отследить появление новой флешки или USB-диска в системе (даже если это хитрожопая флешка, которая монтируется как CD-ROM+Flash, например, или флешка, разбитая на пару дисков)
[+] отслеживать безопасное извлечение флешек и манипулировать им
[+] самому безопасно извлечь любой извлекаемый USB-девайс по букве его диска
[+] отследить прочие события, а именно небезопасное извлечение флешки и отказ в безопасном извлечении

Само-собой, никаких драйверов, только уровень пользователя! Я также поделюсь с вами исходником класса на C++, который реализует все вышеописанные задачи. Давно я не писал годных толстых статей...
Читать далее «Игрища с USB в Windows (отслеживаем и контролируем)»

Прокси-ботнет из роутеров

В 2010 году, в период тестирования SSH Bruteforce'a одним хорошим человеком, я узнал, что на Европейских диапазонах IP-адресов попадается приличное количество SSH-доступов к всевозможным роутерам. Наиболее частыми среди них оказались роутеры с MIPS-процессором и известной кастомной прошивкой DD-WRT.
Казалось бы, особой пользы с них не извлечь, но ещё тогда был предложен вариант использования их в качестве прокси. До тестирования концепции на тот момент руки не дошли, а сегодня я как раз разбирал старые архивы и решил попробовать собрать рабочий пример под подобный роутер. Благо, у меня валяется парочка таких. Стоит отметить, что поднятие прокси-серверов на роутерах также обладает всем известной спецификой, которая заключается в том, что у провайдеров часто используются динамические IP, поэтому, естественно, прокси-сервер должен сообщать свой текущий IP некой веб-админке.
Читать далее «Прокси-ботнет из роутеров»