![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Dll injection [D7, Win2k, WinXP]
nomshar © (2004-09-26 17:46:00)Внедрил свою dll в SysListView32 (для тех, кто не знает, иерархия такая: Progman -> SHELLDLL_DefView -> SysListView32). Все нормально, хук установился, оконная процедура заменилась. В общем, работает. Одна только проблема. Как выгрузить эту dll-ку, не перезагружая explorer.exe.
Бился я довольно-таки долго. Даже предка менял (SetParent), но ничего не помогло, хотя и не могло помочь. У каждого процесса хендл одной и той же библиотеки разный.
Есть вариант внедрения в код explorer.exe и выгрузка уже из него этой самой библиотеки. Но как это сделать? А может есть и другие варианты. Обратился к Рихтеру. У него по этому поводу ничего не сказано.
Может кто-нибудь уже сталкивался с этой проблемой и решил ее или есть какие-нибудь идеи. Подскажите, буду благодарен. Тема очень интересная и веселая, особенно, когда пользователь видит, что знакомая ему с "ранних лет" программа чудит что-то невообразимое. :)
Digitman (2004-09-30 10:10:00) [21]содрал конечно ... причем совершенно бездумно
Cobalt (2004-09-30 10:08:00) [22]2 Digitman ©
Я же намекаю - взял он её откуда-то ;)
<offtopic>
Таки я был прав насчёт освобождения памяти под интерфейс?
</offtopic>
Digitman (2004-09-30 08:26:00) [23]
> способ перехвата событий
не событий, а сообщений
> Да его надо обязательно ставить из dll
не обязательно. зависит от типа хука.
> свою библиотеку внедряю в другой процесс
если ты ее внедряешь явно (т.е. не средствами установки глоб.хука), то это совершенно иной вопрос
myHook:= SetWindowsHookEx(WH_GETMESSAGE, @myHookProc, hInstance, ProcId);
уже здесь несуразица.
с параметрами.
обо всем остальном рассуждать смысла не имеет.
ты читал вообще справку к ф-ции ?
Cobalt (2004-09-29 22:36:00) [24]> Я так понял, ты имеешь в виду способ внедрения с двуями dll.
Нет, отчего же - с одной длл-кой.
что снимай, хук, не снимай, библиотека все равно не выгрузится - на нее есть ссылка в explorer.exe.
ты же сам загружаешь её -
if loadLibrary('injectdll.dll') <> 0 then
А вот без этой загрузки у тебя бы при снятии хука окно Проводника упало бы - потому что оконная процедура указывала бы на недействительную - выгруженную - память.
Так вот - тебе надо добавить такую вещь - что бы при постановке хука оконная процедура не заменяла "родную" на свою, а наоборот.
И рекомендуется пользоваться для хранения переменных в длл-ках с хуками в отображаемых в память файлах - посмотри статью здесь на сайте.
P.S. Сдаётся мне, откуда-то ты взял эту длл-ку ;)
nomshar (2004-09-29 18:38:00) [25]Таким образом получается, что снимай, хук, не снимай, библиотека все равно не выгрузится - на нее есть ссылка в explorer.exe. Рихтер, к сожалению, о том, как можно выгрузить dll в таком случае ничего не говорит. Однако он привел (в своем четвертом издании) пример внедрения в чужой код. Но опять же, метод создан для внедрения в dll и только с подменой конкретной (известной функции; Рихтер подменял MessageBoxA). Здесь этот метод не подходит. Надо каким-то образом внедриться в код explorer.exe и на каком-то шаге его исполнения перевести управления на свою функцию, которая от его имени и выгрузит dll.
Кстати, по этому поводу родился вопрос. Преположим, я внедрил dll в процесс, запущенный с правами SYSTEM (пусть я таких прав не имею). Вопрос такой (вернее их два). 1. Процесс "А" внедряет dll в процесс "В". Процесс "А" имеет права ниже прав процесса "В". Возможно ли в этом случае внедрение.
2. Если внедрение возможно, то может ли процесс "А" посредством внедренной dll дать себе или еще кому права, аналогичные процессу "В"?
nomshar (2004-09-29 18:28:00) [26]> Digiman. Извини, но ты несколько не прав. Что такое хук?! Это всего лишь способ перехвата событий. Да его надо обязательно ставить из dll. Это правильно. Но я же свою библиотеку внедряю в другой процесс. И, скажем так, вынедрить ее может только он сам. В данном случаей explorer.exe.
> Cobalt. Я так понял, ты имеешь в виду способ внедрения с двуями dll. Я же использую всего лишь одну: в ней и ставиться хук, и подменяется оконная процедура.
Про твой вопрос.
Привожу код dll.
library injectdll;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Classes,
messages,
windows,
ShellAPI;
const
SUCCESS = 10100;
FAILED = 10101;
UNNABLE_TO_LOAD_DLL = 10110;
PAINTED = 10111;
{$R *.res}
var
Injected: boolean = false;
myHook: HHOOK;
SavedProc: pointer;
ButtonCreated: boolean = false;
function GethWnd: HWND;
begin
result:= FindWindowEx(0, 0, 'Progman', nil);
result:= FindWindowEx(result, 0, 'SHELLDLL_DefView', nil);
result:= FindWindowEx(result, 0, 'SysListView32', nil);
end;
// Взято из Delphi World!
function GetOSInfo: string;
var
Platform: string;
BuildNumber: Integer;
begin
case Win32Platform of
VER_PLATFORM_WIN32_WINDOWS:
begin
Platform := 'Windows 95';
BuildNumber := Win32BuildNumber and $0000FFFF;
end;
VER_PLATFORM_WIN32_NT:
begin
Platform := 'Windows NT';
BuildNumber := Win32BuildNumber;
end;
else
begin
Platform := 'Windows';
BuildNumber := 0;
end;
end;
if (Win32Platform = VER_PLATFORM_WIN32_WINDOWS) or (Win32Platform = VER_PLATFORM_WIN32_NT) then
begin
if Win32CSDVersion = '' then
result := Format('%s %d.%d (Build %d)', [Platform, Win32MajorVersion, Win32MinorVersion, BuildNumber])
else
result := Format('%s %d.%d (Build %d: %s)', [Platform, Win32MajorVersion, Win32MinorVersion, BuildNumber, Win32CSDVersion]);
end
else
result := Format('%s %d.%d', [Platform, Win32MajorVersion, Win32MinorVersion])
end;
procedure DoSomething(myWnd: HWND);
var r: TRect;
dc: HDC;
str: string;
BtnWnd: HWND;
begin
r:= Rect(0, 0, 0, 0);
dc:= GetDC(myWnd);
SetTextColor(dc, rgb(255, 255, 255));
SetBkMode(dc, TRANSPARENT);
GetWindowRect(myWnd, r);
m.dwLength:= sizeOf(m);
str:= 'Your system is: ' + GetOSInfo;
DrawText(dc, PChar(str), Length(str), r, DT_TOP or DT_RIGHT);
ReleaseDC(myWnd, dc);
end;
procedure CreateButton;
var h: HWND;
r: TRect;
begin
if not ButtonCreated then
begin
r:= Rect(0, 0, 0, 0);
GetWindowRect(GethWnd, r);
h:= CreateWindow('BUTTON', 'ClickMe', WS_CHILD or BS_PUSHBUTTON,
r.Right - 85, r.Top + 50, 75, 25, GethWnd, hMenu(123), 0, 0);
ShowWindow(h, SW_SHOW);
ButtonCreated:= true;
end;
end;
function MyWndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
DoSomething(hWnd);
CreateButton;
case Msg of
WM_PAINT: PostMessage(FindWindow(0, 'Form1'), WM_USER + 100, 0, PAINTED);
end;
if ButtonCreated then
begin
case Msg of
WM_COMMAND: begin
case HiByte(wParam) of
BN_CLICKED:
PostMessage(FindWindow(0, 'Form1'), WM_USER + 100, 0, 123);
end;
end;
end;
end;
result:= CallWindowProc(SavedProc, hWnd, Msg, wParam, lParam);
end;
procedure SetWndProc(hWnd: HWND);
begin
if pointer(GetWindowLong(hWnd, GWL_WNDPROC)) <> @myWndProc then
begin
SavedProc:= pointer(SetWindowLong(hWnd, GWL_WNDPROC, cardinal(@myWndProc)));
end;
end;
function myHookProc(nCode: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if not Injected then
begin
if loadLibrary('injectdll.dll') <> 0 then
SetWndProc(GethWnd)
else
PostMessage(FindWindow(0, 'Form1'), WM_USER + 100, 0, UNNABLE_TO_LOAD_DLL);
Injected:= true;
end;
result:= CallNextHookEx(myHook, nCode, wParam, lParam);
end;
procedure Install;
var ProcId: Cardinal;
begin
ProcId:= GetWindowThreadProcessId(GethWnd, nil);
myHook:= SetWindowsHookEx(WH_GETMESSAGE, @myHookProc, hInstance, ProcId);
if myHook <> 0 then
PostMessage(FindWindow(0, 'Form1'), WM_USER + 100, 0, SUCCESS)
else
PostMessage(FindWindow(0, 'Form1'), WM_USER + 100, 0, FAILED);
end;
procedure Uninstall;
begin
UnHookWindowsHookEx(myHook);
end;
exports Install, Uninstall;
begin
end.
kaZaNoVa (2004-09-27 22:14:00) [27]это похоже на то, что я раньше делал - внедрял длл и стартовал поток ...
- в потоке loadlibrary, после снятия хука dll НЕ выгружалась .. :)
Cobalt (2004-09-27 14:41:00) [28]2 nomshar (27.09.04 13:49) [2]
Тут получается - не совсем сама себя - её система выгрузит.
А про FreeLibrary - ты ведь, после того, как хук поставил и сменил оконную процедуру - сделал LoadLibrary для длл (чтобы после снятия хука функция из длл-ки осталась в АП процесса) и снял хук?
Digitman (2004-09-27 13:59:00) [29]
> nomshar
чего ты мудришь ?
снимай свой глоб.хук вызовом UnhookWindowsHookEx - и всех делов-то ! ... при снятии хука образы хук-ДЛЛ будут выгружены из АП всех процессов, куда они были загруженгы при соотв.установке хука
nomshar (2004-09-27 13:49:00) [30]> Cobalt. То есть ты хочешь сказать, что мне необходимо внедрить ее одну dll-ку?!
Плюс, dll-ка сама себя выгрузить не может.
Cobalt (2004-09-26 20:35:00) [31]Клин клином вышибают.
Хуком внедрил - хуком и выгружай.
Точно также меняй процедуру окна и делай FreeLibrary.
После снятия хука твоя длл-ка выгрузится.