Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Dll injection [D7, Win2k, WinXP]


Страницы:   1 2

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.
После снятия хука твоя длл-ка выгрузится.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо