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

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

Загрузка и выгрузка dll в чужой процесс


Страницы:   1 2

bar ©   (2004-07-08 15:16:00) 

Загружаю свой дллку в процесс explorer`a с помощью хука на WH_GETMESSAGE. Загрузка проходит нормально. Но потом не могу выгрузить эту библиотеку. Хотя по идеи всё должно быть OK. Дескриптор загруженной в эксплорер библиотеки я первоночально сохранял в FileMapping и потом пытался выгрузить дллку по этому дескриптору из хука эксплорера(адресного пространства). Потом заметил, что при очередной загрузки loadlibrary возвращает одинаковый дескриптор уже загруженной дллки и использовал это для выяснения дескриптора библиотеки в адреснов пространстве explorer`а, но все равно не выгружается. Ж:-(
Помогите кто понял суть проблемы, может предложите другой мметод загрузки и выгрузки библиотеки в чужой процесс или объясните где у меня ошибка.

Пример кода из библиотеки хука.
type
   PGlobalDLLData = ^TGlobalDLLData;
   TGlobalDLLData = packed record
       SysHook: HWND; // дескриптор установленной ловушки
       MyAppWnd: HWND; // дескриптор нашего приложения
       Flag: Boolean;
       HLIB: THANDLE;
   end;
var
   GlobalData: PGlobalDLLData;
   MMFHandle: THandle;
   H: THAndle;
   GetAndSet: procedure(h: integer); stdcall; // процедура из 2-ой ДЛЛки, которая заменит оконную процедуру часов.

..............

//Процедура хука
function CallWndProc(
   nCode: integer; // hook code
   wParam: WPARAM; // current-process flag
   lParam: LPARAM // address of structure with message data
   ): LRESULT; stdcall;
var
   hl: THAndle;
   ok, a: boolean;
begin
   if nCode = HC_ACTION then
   begin
       ok := false;
       if tmsg(pointer(lparam)^).hwnd = H then
       begin
           ok := true;
           if GlobalData^.Flag then
{ Если GlobalData^.Flag=true загружаем дллку в процесс окна с хендлом H}
           begin
               GlobalData^.HLIB := loadlibrary(remdll);
               @GetAndSet := nil;
               if GlobalData^.HLIB > HINSTANCE_ERROR then
               begin
                   @GetAndSet := GetProcAddress(GlobalData^.HLIB, 'GetAndSet');
                   if @GetAndSet <> nil then
                       GetAndSet(H)
               end else
           end else
           begin{ Если GlobalData^.Flag=false загружаем дллку в процесс окна с хендлом H}
               PostMessage(H, WM_User + 456, 0, 0);
               sleep(1000);
               hl := loadlibrary(remdll);
               repeat
                   a := FreeLibrary(Hl);
                   PostMessage(GlobalData^.MyAppWnd,
                       WM_MYCMD, $55, HL);
                   PostMessage(GlobalData^.MyAppWnd,
                       WM_MYCMD, $56, integer(a));
               until a;
           end;
       end;
       result := CallNextHookex(GlobalData^.SysHook, ncode, wparam, lparam);
       if ok then

           UnHookWindowsHookEx(GlobalData^.SysHook);
   end
   else
       result := CallNextHookex(GlobalData^.SysHook, ncode, wparam, lparam);
   //
end;
......


Игорь Шевченко   (2004-07-09 11:30:00) [21]


> Все-таки - где доказательство того, что kernel32.dll всегда
> по одному адресу?


Практика - критерий истины


Тимохов   (2004-07-09 11:27:00) [22]


>
> Digitman ©   (09.07.04 11:16) [13]
> неправильно понимаешь
> поточная ф-ция вызывает FreeLibrary

Да?
У рихтера пример имеено с передачей FreeLibrary в качестве поточной функции

    // Get the real address of LoadLibraryW in Kernel32.dll
     PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
        GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
     if (pfnThreadRtn == NULL) __leave;

     // Create a remote thread that calls LoadLibraryW(DLLPathname)
     hThread = CreateRemoteThread(hProcess, NULL, 0,
        pfnThreadRtn, me.modBaseAddr, 0, NULL);
     if (hThread == NULL) __leave;


Все-таки - где доказательство того, что kernel32.dll всегда по одному адресу? Понимаю, что вопрос не совсем практичен, т.к. это и так ясно - но все же документальное подтверждение было бы не лишним.


Digitman   (2004-07-09 11:23:00) [23]


> bar   (09.07.04 11:20) [14]


ну держи, не жалко

на авторство не претендую, текст этот взят когда-то где-то только для анализа варианта решения


//
// внедрение dll в чужой процесс с помощью CreateRemoteThread.
// работать будет только там, где эта самая CreateRemoteThread реализована,
// а это nt/w2k/xp
// использовать так:
//   loader.exe идентификатор_процесса  полный_путь_и_имя_dll
// paul_shmakov@mail.ru
//
program loader;

{$APPTYPE CONSOLE}

uses
Windows, Messages, SysUtils;

function SetDebugPriv: Boolean;
var
Token: THandle;
tkp: TTokenPrivileges;
begin
Result := false;
if OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then
begin
  if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), tkp.Privileges[0].Luid) then
  begin
    tkp.PrivilegeCount := 1;
    tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    Result := AdjustTokenPrivileges(Token, false, tkp, 0, PTokenPrivileges(nil)^, PDWord(nil)^);
  end;
end;
end;

function Start(ProcessID: Cardinal; DllFileName: string): Boolean;
var
hProcess, hTh: THandle;
BytesWritten, ThreadID, DllNameLen: Cardinal;
LoadLibraryProc, MemPtr: Pointer;
ExitCode: DWord;
begin
Result := false;

//
// этот вызов нужен только для внедрения в системные процессы
// btw, нужны привилегии администратора
//
SetDebugPriv();

hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE,
  true, ProcessID);

if hProcess <> 0 then
begin
  DllNameLen := Length(DllFileName) + 1;

  MemPtr := VirtualAllocEx(hProcess, nil, DllNameLen, MEM_COMMIT, PAGE_READWRITE);

  if MemPtr <> nil then
  begin
    if WriteProcessMemory(hProcess, MemPtr, PChar(DllFileName), DllNameLen, BytesWritten) then
    begin
      LoadLibraryProc := GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryA');

      hTh := CreateRemoteThread(hProcess, nil, 0, LoadLibraryProc, MemPtr, 0, ThreadID);

      if hTh <> 0 then
      begin
        if (WaitForSingleObject(hTh, INFINITE) = WAIT_OBJECT_0) and
          GetExitCodeThread(hTh, ExitCode) then
          Result := ExitCode <> 0;

        CloseHandle(hTh);
      end;
    end;

    VirtualFreeEx(hProcess, MemPtr, 0, MEM_RELEASE);
  end;

  CloseHandle(hProcess);
end;

end;

var
ProcessID: Cardinal;
DllName: string;
begin
if ParamCount < 2 then
begin
  WriteLn('usage: loader.exe process_id dll_full_path_and_name');
  Exit;
end;

ProcessID := StrToInt(ParamStr(1));
WriteLn('process id: ' + IntToStr(ProcessID));

DllName := ParamStr(2);
WriteLn('dllname: ' + DllName);

if ProcessID <> 0 then
begin
  if Start(ProcessID, DllName) then
    WriteLn('success')
  else
    WriteLn('fail');
end;
end.


bar   (2004-07-09 11:20:00) [24]

Я думал Вам просто дать пример. Или ссылку хорошую по теме.
Ну ладно буду искать.

см http://www.delphimaster.ru/cgi-bin/forum.pl?id=1089275745&n=5
А первоисточники на русском не посоветуете. Лучше в инете.


Digitman   (2004-07-09 11:16:00) [25]


> Тимохов ©   (09.07.04 10:50) [11]
> Это не офф, т.к. в струе вопроса.
>
> > Digitman ©   (09.07.04 10:42) [10]
>
> Я так понимаю, что Вы имеете в виду стартовать удаленный
> поток с поточкной функцией, равной FreeLibrary


неправильно понимаешь
поточная ф-ция вызываетFreeLibrary

> bar   (09.07.04 11:12) [12]
> >>Digitman ©   (09.07.04 10:42) [10]
> А пример можно пожалуйста. А то я с WriteProcessMemory не
> общался.


а почитать для начала справку и первоисточники ?


bar   (2004-07-09 11:12:00) [26]

>>Digitman ©   (09.07.04 10:42) [10]
А пример можно пожалуйста. А то я с WriteProcessMemory не общался.


Тимохов   (2004-07-09 10:50:00) [27]

Это не офф, т.к. в струе вопроса.

> Digitman ©   (09.07.04 10:42) [10]

Я так понимаю, что Вы имеете в виду стартовать удаленный поток с поточкной функцией, равной FreeLibrary. Но при этом должна быть уверенность в том, что kernel32.dll загружена по тому же базовому адресу. По факту оказывается именно так - kernel32.dll загруже всегда по одному и тому же базовому адресу. Я уже подинмал этот вопрос, но тогда ответа не получил  - где факт того, что kernel32.dll загружена по одному адресу описан в msdn?


Digitman   (2004-07-09 10:42:00) [28]


> bar   (09.07.04 10:14) [6]


> как её потом выгрузить


все просто - вновь стартуй удаленный трэд, который выполнит freelibrary()


Тимохов   (2004-07-09 10:41:00) [29]

не совсем въехал про что тут говорится (квалификации не хватает), но про запуск потока в другом прочессе через загрузку/выгрузку библиоткb подробно рассказывается в главе 21, 22 или 23 рихтера 4 издание (ключевое слово для поиска CreateRemoteThread).


bar   (2004-07-09 10:38:00) [30]

>>DeadMeat ©   (09.07.04 10:23) [7]
Ну да, скоприровал откуда-то и подправил для свох нужд.
Но скопировал не с xakep.ru
Кстати а там про выгрузку длл есть инфа. Пойду посмотрю.


DeadMeat   (2004-07-09 10:23:00) [31]


> Нет не процесс невидимка

Ну извини... Просто код взят из этой статьи...

---
...Death Is Only The Begining...


bar   (2004-07-09 10:14:00) [32]

>>DeadMeat ©   (08.07.04 23:50) [1]
Нет не процесс невидимка. Просто нужно отловить некоторые сообщения SHELLDLL_DefView, а хук на него не работает(Runtime error 216 at FF640227 при нажатии win+d )( см ветку)
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1089095680&n=5
Кстати кто нибудь знает что такое Runtime error 216 ?

>>Digitman ©   (09.07.04 08:49) [4]
Знаю. Делал загрузку dll-ки в процесс в момент загрузки библиотеки хука, результат такой же, даже гдето глюков больше (скорее всего код корявый)а с WH_GETMESSAGE это второй более отлаженный вариант. Кроме того разве влияет то кога грузить dll.?
>>Digitman ©   (09.07.04 08:41) [3]
а как её потом выгрузить

>>Kerk ©   (09.07.04 08:31) [2]
Попробуй GetModuleHandle / FreeLibrary
В каком процессе? В споем приложении пробовал http://delphiworld.narod.ru/base/kill_dll.htmlне работает. В процессе explorer`a сейчас попробую.


SammIk   (2004-07-09 09:50:00) [33]

Дескриптор возвращаемыи лоадлиброри, это адрес
куда грузится библеотека.
А винлоадер старается грузить их в одно место,
по этому возвращает один хендл


Digitman   (2004-07-09 08:49:00) [34]


> bar   (08.07.04 15:16)  


а если уж пошел методом глоб.хука, то выкрутасы с обработкой WH_GETMESSAGE и иже с ним вовсе не нужны для этой цели

в момент загрузки хук-модуля в АП процесса эксплорера процедура иниц-ции хук-модуля получает управление, и в этот момент как раз и можно выполнить loadlibrary() ... но перед тем как выполнить loadlibrary() процедура иниц-ции хук-модуля должна проанализировать имя тек.процесса и выполнить loadlibrary() лишь в том случае, если вызов GetModuleFileName вернул именно explorer.exe, иначе библ-ка будет загружена во все GUI-процессы, а не только в эксплорер


Digitman   (2004-07-09 08:41:00) [35]


> bar   (08.07.04 15:16)  


открой процесс эксплорера (см. OpenProcess)

запроси в АП эксплорера блок вирт.памяти c параметром защиты страниц PAGE_EXECUTE_READWRITE под дальнейшее размещение там кода поточной ф-ции (см. VirtualAllocEx)

скопируй в этот блок памяти код поточной ф-ции (см. WriteProcessMemory)

стартуй в АП эксплорера удаленный кодовый поток вызовом CreateRemoteThread(), в качестве параметра, указывающего адрес поточной ф-ции, передай адрес точки входа в скопированную поточную ф-цию в АП эксплорера

при удаленном старте потока поточная ф-ция получает управление и загружает твою библиотеку в АП эксплорера, после чего завершается


Kerk   (2004-07-09 08:31:00) [36]

Попробуй GetModuleHandle / FreeLibrary


DeadMeat   (2004-07-08 23:50:00) [37]

Дай угадаю... Ты прочитал статью на xakep.ru, про невидимый процесс?? Просто интересно...

---
...Death Is Only The Begining...


Страницы:   1 2

Наверх

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