![]() |
Сырая загрузка DLL(скрытая)
Вложений: 1
// To Moderators. Если что, то можете перекинуть в статьи.
// Для Кодинга - слишком много написано // Для Статей - хз. тема не очень, просто познавательная. // Короче, решать вам ) (С) SLESH 2009 Сырая загрузка DLL (скрытая) ВВЕДЕНИЕ: Иногда появляется такая необходимость чтобы скрытно загрузить и использовать определенную DLL, но не всегда это удается сделать. Существует 3 основных способа подгрузить в своё адресное пространство какую либо DLL: 1) Использование таблицы импорта - самый паливный способ, потому как о загрузке этой DLL будут знать все 2) Использование функции LoadLibrary и GetProcAddress - Дают намного лучше результат, но всё равно DLL можно обнаружить в списке загруженных модулей. 3) Второй способ + манипулирование с системными структурами, для удаления DLL из списка. Способ хорош, но есть один недостаток - При хуке LoadLibrary сразу будет вычислена эта DLL. Так же эти способы обладают большим недостатком - нельзя удалить файл DLL не прекратив работу с ней. Но существует довольно специфический механизм основанный на ручной загрузке DLL в память, не используя существующих функций предназначенных для этой цели. Вот как раз этот метод и будет рассмотрен. АЛГОРИТМ: Теперь можно рассмотреть алгоритм загрузки, использования и выгрузки DLL 1) Считываем заголовки из DLL (DOS + PE + SERCTIONS) 2) На основании данных в этих заголовках выделяем память под нашу DLL 3) Загружаем все секции и заголовки 4) Обрабатываем релоки 5) Обрабатываем таблицу импорта. 6) Передаем управление на точку входа в DLL с флагом указывающим что мы подгружаем DLL 7) т.к. система ничего не знает о нашей DLL то придется самому получать адреса функций из таблицы экспорта. 8) получаем вручную адрес функции и используем её 9) уведомляем DLL и том, что мы её выгружаем 10) освобождаем память. С виду кажется что очень много необходимо сделать, хотя на практике это всё занимает строчек 300-350. Для реализации всего будет использован Си компилятор от VS++ 2008. И так нам необходимо теперь написать 3 функции. HideLoadLibrary - для загрузки DLL HideGetProcAddress - для поиска адресов HideFreeLibrary - для выгрузки DLL Также нам предварительно понадобятся следующие типы Код:
#define MAX_SECTIONS 10 // максимальное кол-во секций в файлеSTEP 1: Загрузка DLL Код:
HMODULE __stdcall HideLoadLibrary(char * LibFileName)Код:
// обработка релоковКод:
// Обработчик импортаВажно отметить, что нельзя использовать функцию GetProcAddress для DLL загруженных через HideLoadLibrary. Это связанно с тем, что система предварительно проверяет факт загрузки DLL итд итп. По этому необходимо будет использовать собственную функцию - HideGetProcAddress, которая является полным аналогом GetProcAddress. Но при этом умеет искать адреса в DLL, которые загруженные не только через HideLoadLibrary, но и даже через LoadLibrary. Также после загрузки DLL можно вообще удалить её файл. Как видно из кода, его быстро можно переписать так, чтобы можно было загружать DLL сразу из памяти. Это будет удобно для реализации дополнительной защиты программ. STEP 2: Поиск адресов Как уже было выше сказано – функция HideGetProcAddress находит адреса в DLL. При этом не важно, каким образом была загружена DLL в память, главное чтобы она была корректно загружена (обработка импорта и релоков). Также как GetProcAddress, данная функция может принимать в качестве параметров не только имя функции, но и её ординал. Код функции HideGetProcAddress Код:
FARPROC _stdcall HideGetProcAddress(HMODULE hModule, char* lpProcName)Если в процессе работы нам уже не нужна DLL, то мы можем её выгрузить по средствам функции HideFreeLibrary. Важно отметить, что нестоит выгружать через данную функцию DLL загруженные через LoadLibrary. Хоть эта функция и является аналогом FreeLibrary, но всё же она далека от неё. Код HideFreeLibrary: Код:
// функция выгрузки DLLДля теста попробуем подгрузить копию user32.dll. Найти в ней адрес функции MessageBoxA и вызвать её. Для начала скопируем библиотеку с новым именем: Windows\system32\user32.dll к примеру в e:\u32.dll Код тестовой программы (консольный проект): Код:
// переменная для адреса MessageBoxA1) Загружаются спокойно DLL написанные на С, FASM и Delphi (остальные не проверял) 2) Многие системные DLL (kernel32.dll, user32.dll) – тоже загружаются без проблем 3) Проблема возникла лишь при загрузке ws2_32.dll. Т.е. сама DLL загрузилась без проблем, а также без проблем были найдены адреса функций. Но функция WSAStartup возвращала значение об ошибке: Цитата:
ЛИТЕРАТУРА Для полного понимания этого всего, советую почитать следующие вещи 1) ФОРМАТ ИСПОЛНЯЕМЫХ ФАЙЛОВ PortableExecutables (PE) // Hard Wisdom Это txt файл (PEFMT003.TXT) в котором описаны основные структуры PE файла. Находится в аттаче. 2) Путь воина – внедрение в pe/coff файлы // Крис Касперски Хорошее описание PE файлов, особенно таблиц импорта и экспорта. Находится по адресу http://www.insidepro.com/kk/019/019r.shtml P.S. В аттаче найдете исходники всего этого и файл PEFMT003.TXT (С) SLESH 2009 |
А еще один вариант: прописаться в TLS'e загрузить либу, выполнить нужный код и выгрузиться.
|
Очень познавательно. Неплохо было бы в разделе кодинг сделать подраздел статьи и перенести туда самые стоящие темы, тем более такие есть...
имхо в разделе "Наши статьи" они затеряются.. |
Ну куда переносить - это дело модераторов )
2 s0l_ir0n в любом случае где-бы ты не выполнял код, всё равно ты будеш юзать LoadLibrary которую можно похукать. Тем более можно скрыто хукать - в ntdll через LdrpLoadModule |
Нет ее лучше оставить тут, потому что раздел статьи это куча мусора, а это раздел кодинга тут как раз, слэш позновательные вещи пишешь) попробуй перекинуть еще на васм)
|
А я там не зареган )
|
Цитата:
|
Спасибо
|
UPDATE 1
Нашел вот небольшой баг в функции Обработки импорта, в частности глюки при работе с импортом по ординалам. Исправил. Вот нова версия функции Код:
ULONG ProgressImport(ULONG filebase) |
зобыл копюрайты напесать ;)
|
а копирайты на первой странице )
|
[offtop] на васме кстати подобный метод описан (в виде нжекта)
http://wasm.ru/article.php?article=apihook_2 |
Ну вот вечно так, сначало напишу, а потом оказывается что ктото это уже сделал до меня (
Кстати говоря, если компилить это без отладочный инфы, с оптимизацией + без дефолтовых либ, то код получает очень маленький, что очень удобно для юзанья во всяком малваре. |
msrem - классный кодер, и копатель ядра NT был...
куда он делся? никто не знает? |
2 flacs официальные неподтвержденные данные - не справился с управлением и разбился.
Но неофициальный, неподтвержденным данным - это было лишь прикрытие для ухода. И это всеголишь смерть ника Ms-Rem |
Загрузка dll из памяти
Понадобилось загружать dll из памяти сразу вот переделал несколько функцию :)
Код:
// непосредственно функция загрузки DLL из памяти by Gar|k |
Дллка открывается(файл),но не подгружается.На вызове ProgressImport вылазит ERROR_MOD_NOT_FOUND,проблема втом что эту ф-цию построчно перебрал и так непонял где оишбка вылазит :confused: В какую сторону копать?
ЗЫ:на морозе закаментил Код:
else if (!ProgressImport(retadr))// обработаем импорт |
Цитата:
[CODE] // -- cutted -- AddressTable = (PADDRESS_TABLE)(*(ULONG*)RVA + filebase); // получаем адрес структуры где хранится HINT NAME if ((ULONG)AddressTable Name[0]) // если импорт по имени { addr = (ULONG)GetProcAddress(lib, AddressTable->Name); // найдем адрес } else // если импорт по ординалу { addr = (ULONG)GetProcAddress(lib, (char*)((USHORT)AddressTable & 0xFFFF)); // |
| Время: 23:55 |