![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
"Вклиниться" в адр. пространство библиотеки до выполнения Dllmain [Win2k]
BiN © (2004-03-11 12:38:00)Добрый день, уважаемые мастера!
Возможно ли выполнить сабж без создания своего загрузчика.
Надеюсь, вы не подумаете, что здесь ведется разработка трояна - скорее наоборот.
pasha_golub (2004-03-22 13:46:00) [1]Напишите, пожалуйста, статью по этому поводу и код исходный на pavel.golub@farata.kr.ua киньте, пожалуйста.
Игорь Шевченко (2004-03-22 13:26:00) [2]Да, нашел. Называется LdrpCallInitRoutine. В этом случае действительно DLL готова к выполнению функции инициализации.
BiN (2004-03-22 12:16:00) [3]
...ты же перехватываешь не то место, где вызывается DLLMain, а перехватываешь вызов той процедуры, которая вызывает DllMain внутри себя
Совершенно верно
... а не вызывается ли настройка импорта (или еще чего-нибудь важного) в промежутке между адресом, который ты перехватил, и точкой вызова DllMain ?
эта процедура в ntdll w2ksp4 в переводе на паскаль выглядит примерно так (ассемблерный код можно посмотреть самому):
function LdrpDllEntryPointCaller(DllEntryPoint:TDllEntryPoint; hinstDLL:HMODULE; fdwReason:DWORD; lpvReserved:Pointer):BOOL; stdcall;
begin
Result:=DllEntryPoint(hinstDll, fdwReason, lpvReserved);
end;
Причем, никаких иных действий эта функция не производит. Она же получает управление и для вызова Dllmain при выгрузке библиотеки. Следовательно, логично предположить, что в ней не будет происходить какие-либо изменения IAT - зачем при выгрузке библиотеки настраивать таблицу импорта.
Следует отметить, что описанный в предыдущих постах пример не затрагивает перехват Dllmain при вызове FreeLibrary и т.п., в этом просто нет необходимости.
Игорь Шевченко (2004-03-22 11:52:00) [4]BiN © (22.03.04 11:13)
> Обязательно настроены, ведь без этого работа самой Dllmain
> была бы некорректна.
Э....ты же перехватываешь не то место, где вызывается DLLMain, а перехватываешь вызов той процедуры, которая вызывает DllMain внутри себя, если я правильно в коде разобрался. Или прокомментируй каждую команду в процедуре, начинающуюся с
{$O-} {<-- на всякий случай}
Я хочу сказать, а не вызывается ли настройка импорта (или еще чего-нибудь важного) в промежутке между адресом, который ты перехватил, и точкой вызова DllMain ?
BiN (2004-03-22 11:13:00) [5]Игорь Шевченко © (22.03.04 10:28) [66]
... как можно убедиться в перехваченной точке, что DLL загружена и ее разделы импорта настроены нужным образом
Обязательно настроены, ведь без этого работа самой Dllmain была бы некорректна.
Насколько я понял, ты перехватываешь вызов той программы, которая вызывает внутри себя DllMain.
Немного путано, но попробую разобраться... Дело в том, что этот метод можно использовать не только при внедрении своего кода в другие процессы, а, например, для защиты от всё того же внедрения.
В данном же случае требуется перехватить любые попытки вызова функции A, как в a) теле программы так и в b) теле DllMain при динамической загрузке. Это решается просто, если исследуемый процесс создавать самим, т.е. использовать отработанную схему:
CREATE_SUSPENDED
внедрение нашей длл, в кот. происходит:
правка IAT
правка адреса в ntdll, кот-ю, кстати, возможно придется делать в новом потоке, а не изнутри процедуры точки входа нашей внедренной длл - я, к сожалению, пока не тестировал все варианты.
ResumeThread
Или, может, я не до конца понял вопрос?
Игорь Шевченко (2004-03-22 10:28:00) [6]BiN © (22.03.04 09:39)
Проверил я, как и обещал в письме, все работает, но мне до сих пор непонятно одно - как можно убедиться в перехваченной точке, что DLL загружена и ее разделы импорта настроены нужным образом.
Насколько я понял, ты перехватываешь вызов той программы, которая вызывает внутри себя DllMain. Идея интересная, но вопрос остается...
BiN (2004-03-22 09:39:00) [7]SPeller © (21.03.04 17:01) [62]
Здесь можно посоветовать почитать статью, где описываются минимальные действия по созданию загрузчика на дельфи, но даже там в результате получается несколько ущербный вариант.
http://rsdn.ru/article/baseserv/peloader.xml
Alexander666 (2004-03-21 22:50:00) [8]А на адрес alexj_8@hotmail.com тоже можно отправить?
Игорь Шевченко (2004-03-21 22:39:00) [9]SPeller © (21.03.04 17:01)
Это называется - написать свой загрузчик. Я там ссылочку на MSDN RE давал, почитай, чем занимается загрузчик.
SPeller (2004-03-21 17:01:00) [10]Товарищи, если я что-то не догоняю, то извините пожалуйста. Если можно, то расскажите мне, бестолковому, что мешает загрузить библиотеку через CreateFileMapping, сделать все нужные поправки, о которых я говорил ранее, и после этого вызвать DllMain ?
Игорь Шевченко (2004-03-19 10:18:00) [11]Код на whitefranz@hotmail.com не затруднит отправить ?
BiN (2004-03-18 20:20:00) [12]Проведенное тестирование на MS Windows XP Professional SP1, позволяет с уверенностью утверждать, что предложенный мной метод увпешно работает и на этой ОС.
BiN (2004-03-18 17:53:00) [13]... LdrpLoadDll не начинается с той шапки
в том-то и дело, что в моем методе нет зависимости от LdrpLoadDll, т.к. она вызывается где-то "посередине" иерархии вложенных функций . Что ж, из принципа придется сегодня ставить XP :)
Игорь Шевченко (2004-03-18 17:43:00) [14]
> Так как нужно определить всего лишь вторую ссылку, то и
> вероятность ошибки довольно мала. Точнее, этот метод будет
> работать железно при условии(!), что вызывающая Dllmain
> функция начинается с вышеуказанной шапки.
Это все будет работать до Windows XP (и, соответственно, всех более поздних версий). Свен Шрайбер не зря ведь рекомендует пользоваться символьной информацией.
> элементарно осуществив его с конца, из недр своей подгружаемой
> библиотеки. Другими словами, функция определяющая адрес
> находится не в теле программы, а в библиотеке, что может
> создавать некоторые неудобства, но не тем кто, кто хочет
> осуществлять перехват в адресном пространстве другого процесса
Идея интересная. Но LdrpLoadDll не начинается с той шапки в указанных мной версиях Windows.
BiN (2004-03-18 17:21:00) [15]Готовый проект я позже выложу где-нибудь в инете, а принцип объяснить могу и сейчас - к тому же он оказался прост до безобразия :). Как уже упоминалось, все сводится к изменению адреса в инструкции вызова в одной из вложеных в LdrLoadDll функций.
Сама LdrLoadDll выглядит примерноо так в переводе на дельфи :)
function LdrLoadDll(PathToFile:Pchar;
Flags:ULONG;
ModuleFileName:PNICODE_STRING;
var ModuleHandle:DWORD); stdcall;
begin
MapDataAndCreateIAT; <<Более подробно можно посмотреть по
ссылке, указанной в [47]
...
call offset // где offset - это смещение на функцию
LdrpDllEntryPointCaller см [47]
end;
Этот последний вызов и требуется найти и изменить. Здесь и возникают проблемы с несовместимостью OS и как следствие, со сдвигами адресов и т.д. Свен Шнайбер борется с этим с помощью отладочных файлов, кто-то еще находу анализирует код LdrLoadDll и патчит его начало.
Но ведь можно сократить наш поиск, элементарно осуществив его с конца, из недр своей подгружаемой библиотеки. Другими словами, функция определяющая адрес находится не в теле программы, а в библиотеке, что может создавать некоторые неудобства, но не тем кто, кто хочет осуществлять перехват в адресном пространстве другого процесса. На данный момент требуемый адрес находится по ссылкам оставляемым в стеке "шапками" процедур вида
push ebp
mov ebp, esp
Так как нужно определить всего лишь вторую ссылку, то и вероятность ошибки довольно мала. Точнее, этот метод будет работать железно при условии(!), что вызывающая Dllmain функция начинается с вышеуказанной шапки. Вуаля.
Aleksey Pavlov (2004-03-18 15:59:00) [16]>> BiN:
можно полученный в результате код посмотреть?
164142@_NO_SPAM_PLZ_mail.ru
BiN (2004-03-18 15:32:00) [17]Удалено модератором
Примечание: Дубль
BiN (2004-03-18 15:31:00) [18]>> SPeller ©
конечно же, сам образ библиотеки отображается в памяти до вызова DllMain - это очевидно хотя бы потому, что в качестве одного из параметров передается адрес (или хэндл) загруженного модуля.
Метод, предложеный тобой в [46] работать не будет по той причине, что ты собираешься править код в уже загруженной библиотеке и после вызова точки входа.
Игорь Шевченко (2004-03-18 15:13:00) [19]SPeller © (18.03.04 14:51)
> Да ну?
Ну да. MSDN RE второй сигнальный номер: внутри загрузчика Windows NT
SPeller (2004-03-18 14:51:00) [20]
> В том-то и дело, что он отображается в памяти, когда уже
> полностью загружен и как правило _после_ вызова Dllmain
Да ну?