Показать сообщение отдельно

  #1662  
Старый 30.05.2008, 21:03
cash$$$
Banned
Регистрация: 06.01.2008
Сообщений: 413
Провел на форуме:
1301036

Репутация: 1334
По умолчанию

Для загрузки библиотеки можно использовать функцию LdrLoadDll из ntdll.dll.
Код:
function LdrLoadDll(szcwPath: PWideChar;
                    pdwLdrErr: dword;
                    pUniModuleName: PUnicodeString;
                    pResultInstance: PDWORD): NTSTATUS;
                       stdcall; external 'ntdll.dll';
Нас интересует параметр pUniModuleName представляющий из себя указатель на строку типа UnicodeString в которой передается имя загружаемой DLL. По указателю pResultInstance будет сохранен адрес MZ заголовка загруженной DLL (параметр hInstance).
Следующий код загружает DLL аналогично функции kernel32 LoadLibraryW:
Код:
Function MyLoadLibrary(lpLibFileName: PWideChar): HMODULE;
var
 uName: TUnicodeString;
begin
 RtlInitUnicodeString(@uName, lpLibFileName);
 if (LdrLoadDll(nil, 0, @uName, @Result) > 0) then Result := 0;
 RtlFreeUnicodeString(@uName);
end;
Для получения адреса функции cледует использовать LdrGetProcedureAddress.
Код:
function LdrGetProcedureAddress(hModule: dword;
                                dOrdinal: DWORD;
                                 psName: PAnsiString;
                                 ppProcedure: ppointer): NTStatus;
                                  stdcall; external 'ntdll.dll';
Если необходимо обеспечить максимальную скрытность перехвата, то вообще лучше использовать во внедряемом коде только функции Native API.
Процедура копирования участка памяти в процесс:
Код:
function InjectMemory(Process: dword; Memory: pointer; Size: dword): pointer;
var
  BytesWritten: dword;
begin
  Result := VirtualAllocEx(Process, nil, Size, MEM_COMMIT or MEM_RESERVE,
                           PAGE_EXECUTE_READWRITE);
  WriteProcessMemory(Process, Result, Memory, Size, BytesWritten);
end;
Эта процедура предельно проста, она принимает хэндл открытого процесса, указатель на данные в текущем процессе и размер данных, а возвращает указатель на данные в целевом процессе.

Внедрение процедуры в целевой процесс:
Код:
program InjectCode;

uses
  Windows,
  advApiHook;

type
  TRemoteInfo = record
    LoadLibrary: function(lpLibFileName: PChar): HMODULE; stdcall;
    GetProcAddress: function(hModule: HMODULE;
                             lpProcName: LPCSTR): FARPROC; stdcall;
    Kernel32    : array[0..16] of Char;
    User32      : array[0..16] of Char;
    MessageBoxA : array[0..16] of Char;
    nExitThread : array[0..16] of Char;
    Text        : array[0..16] of Char;
    Title       : array[0..16] of Char;
  end;

{ Процедура внедряемая в процесс }
procedure RemoteThread(RemoteInfo: pointer); stdcall;
var
 MessageBox: function(hWnd: HWND; lpText,
                      lpCaption: PChar; uType: UINT): Integer; stdcall;
 ExitThread: procedure(uExitCode: UINT); stdcall;
begin
  with TRemoteInfo(RemoteInfo^) do
  begin
    @MessageBox := GetProcAddress(LoadLibrary(User32), MessageBoxA);
    @ExitThread := GetProcAddress(LoadLibrary(Kernel32), nExitThread);
    MessageBox(0, Text, Title, 0);
    ExitThread(0);
  end;
end;
procedure RemoteThreadEnd; begin end; //метка конца кода 

var
  RemoteInfo: TRemoteInfo;
  pInfo, CodeAdr: pointer;
  TID: dword;
  Process: dword;
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;

begin
  //Запускаем процесс
  ZeroMemory(@StartInfo, SizeOf(TStartupInfo));
  StartInfo.cb := SizeOf(TStartupInfo);
  CreateProcess(nil, 'notepad.exe', nil, nil, False, 0,
                nil, nil, StartInfo, ProcInfo);
  Process := ProcInfo.hProcess;
  //Заполняем структуру передаваемую внедряемому коду
  lstrcpy(RemoteInfo.User32, 'user32.dll');
  lstrcpy(RemoteInfo.Kernel32, 'kernel32.dll');
  lstrcpy(RemoteInfo.MessageBoxA, 'MessageBoxA');
  lstrcpy(RemoteInfo.nExitThread, 'ExitThread');
  lstrcpy(RemoteInfo.Text, 'Hello World!');
  lstrcpy(RemoteInfo.Title, 'Injected MessageBox');
  //получаем адреса используемых API
  @RemoteInfo.LoadLibrary    := GetProcAddress(GetModuleHandle('kernel32.dll'),
                                               'LoadLibraryA');
  @RemoteInfo.GetProcAddress := GetProcAddress(GetModuleHandle('kernel32.dll'),
                                               'GetProcAddress');
  //копируем в процесс структуру с данными
  pInfo := InjectMemory(Process, @RemoteInfo, SizeOf(TRemoteInfo));
  //копируем в процесс внедряемый код
  CodeAdr := InjectMemory(Process, @RemoteThread,
                          dword(@RemoteThreadEnd) - dword(@RemoteThread));
  //запускаем внедренный код
  CreateRemoteThread(Process, nil, 0, CodeAdr, pInfo, 0, TID);
end.
Перед внедрением кода процедуры, необходимо скопировать в память целевого процесса структуру с данными используемыми внедряемым кодом. В этой структуре необходимо передать адреса функций LoadLibary и GetProcAddress, через которые внедряемый код будет загружать используемые библиотеки и получать адреса используемых функций.
введем еще одну процедуру:
Код:
function InjectThread(Process: dword; Thread: pointer; Info: pointer;
                      InfoLen: dword; Results: boolean): THandle;
var
  pThread, pInfo: pointer;
  BytesRead, TID: dword;
begin
  pInfo   := InjectMemory(Process, Info, InfoLen);
  pThread := InjectMemory(Process, Thread, SizeOfProc(Thread));
  Result  := CreateRemoteThread(Process, nil, 0, pThread, pInfo, 0, TID);
  if Results then
    begin
      WaitForSingleObject(Result, INFINITE);
      ReadProcessMemory(Process, pInfo, Info, InfoLen, BytesRead);
    end;
end;
Эта процедура копирует в целевой процесс внедряемый код и структуру с данными для него, после чего запускает внедренный код.
Принимаемые параметры:
Process - хэндл открытого процесса.
Thread - указатель на внедряемый код в текущем процессе.
Info - указатель на структуру с данными.
InfoLen - размер структуры с данными.
Results - необходимость возврата результата. (если true, то функция ожидает завершения удаленного потока и копирует обратно структуру с данными) .
 
Ответить с цитированием