Шустрый

Профиль
Группа: Участник
Сообщений: 94
Регистрация: 5.6.2010
Репутация: нет Всего: нет
|
Так ведь и прикол то весь в том что для каждого консольного окна которое я запускаю. нужен СВОЙ заголовок. Нашёл из этого выход, подгружать dll внутрь процесса(грузится, меняет заголовок и выгружается). Код dll: | Код | Library HookDLL;
const kernel32='kernel32.dll'; DLL_PROCESS_ATTACH = 1;
type BOOL = LongBool; DWORD = LongWord;
function SetConsoleTitle(lpConsoleTitle: PChar): BOOL; stdcall; external kernel32 name 'SetConsoleTitleA'; procedure FreeLibraryAndExitThread(hLibModule: HMODULE; dwExitCode: DWORD); stdcall; external kernel32 name 'FreeLibraryAndExitThread'; function GetModuleHandle(lpModuleName: PChar): HMODULE; stdcall; external kernel32 name 'GetModuleHandleA';
procedure DLLEntryPoint(dwReason: DWORD); begin case dwReason of DLL_PROCESS_ATTACH: begin SetConsoleTitle('THE BEST of the test!'); FreeLibraryAndExitThread(GetModuleHandle('hooklib.dll'), 0); ExitCode := 0; end; end; end;
begin DLLProc := @DLLEntryPoint; DLLEntryPoint(DLL_PROCESS_ATTACH); end.
|
Код программы: | Код | //////////////////////////////////////////////////////////////////////////////// // // **************************************************************************** // * Project : Inject/Eject Library Demo // * Unit Name : main // * Purpose : Демонстрационный пример внедрения // * : библиотеки через CreateRemoteThread // * Author : Александр (Rouse_) Багель // * Version : 1.01 // * HomePage : http://rouse.drkb.ru // **************************************************************************** //
unit main;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, TlHelp32;
resourcestring BTN_INJECT = 'Inject'; BTN_EJECT = 'Eject'; const DLLName = 'hooklib.dll';
type TfrmMain = class(TForm) btnInjectEject: TButton; GroupBox: TGroupBox; lbStatus: TListBox; cbProcess: TComboBox; Label1: TLabel; procedure btnInjectEjectClick(Sender: TObject); procedure FormCreate(Sender: TObject); private UnloadAddrOffset: DWORD; procedure FillProcessCombo; function InjectLib(const ProcessID: DWORD): Boolean; function EjectLib(const ProcessID: DWORD): Boolean; end;
var frmMain: TfrmMain;
implementation
{$R *.dfm}
{ TfrmMain }
// Обработчик кнопки на внедрение/выгрузку библиотеки // ============================================================================= procedure TfrmMain.btnInjectEjectClick(Sender: TObject); var PID: Integer; begin PID := DWORD(cbProcess.Items.Objects[cbProcess.ItemIndex]); if InjectLib(PID) then lbStatus.Items.Add('Library injected succes.') else lbStatus.Items.Add('Library injected fail.'); end;
// Пока наш процесс не получит отлабочные привилегии, // весь этот код работать не будет // ============================================================================= function SetDebugPriv: Boolean; var Token: THandle; tkp: TTokenPrivileges; ReturnLength: DWORD; begin Result := false; // Получаем токен текущего процесса if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then try // Получаем Luid привилегии 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, nil, ReturnLength); end; finally CloseHandle(Token); end; end;
// Функция внедряет библиотеку в удаленный процесс с PID равным ProcessID // Для успешного внедрения нужно передать адрес функции LoadLibraryA // и путь к загружаемой библиотеке. // Строку с путем необходимо разместить в алресном пространстве удаленного процесса // ============================================================================= function TfrmMain.InjectLib(const ProcessID: DWORD): Boolean; var Process: HWND; ThreadRtn: FARPROC; DllPath: String; RemoteDll: Pointer; BytesWriten: DWORD; Thread: DWORD; ThreadId: DWORD; begin // Устанавливаем отладочные привилегии для нашего процесса Result := SetDebugPriv; if not Result then Exit; Process := 0; Thread := 0; try // Открываем процесс Process := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE, True, ProcessID); if Process = 0 then Exit; // Выделяем в нем память под строку DllPath := ExtractFilePath(ParamStr(0)) + DLLName; RemoteDll := VirtualAllocEx(Process, nil, Length(DllPath), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE); if RemoteDll = nil then Exit; // Пишем путь к длл в его адресное пространство if not WriteProcessMemory(Process, RemoteDll, PChar(DllPath), Length(DllPath), BytesWriten) then Exit; if BytesWriten <> DWORD(Length(DllPath)) then Exit; // Получаем адрес функции из Kernel32.dll ThreadRtn := GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA'); if ThreadRtn = nil then Exit; // Запускаем удаленный поток Thread := CreateRemoteThread(Process, nil, 0, ThreadRtn, RemoteDll, 0, ThreadId); if Thread = 0 then Exit; // Ждем пока удаленный поток отработает... if (WaitForSingleObject(Thread, INFINITE) = WAIT_OBJECT_0) then Result := True; finally // Удаленный поток свою задачу выполнил и загрузил нашу библиотеку, // можно освобождать занятую память... if RemoteDll <> nil then VirtualFreeEx(Process, @RemoteDll, 0, MEM_RELEASE); if Thread <> 0 then CloseHandle(Thread); if Process <> 0 then CloseHandle(Process); end; end;
// Данная функция запускает в удаленном процессе поток // который стартует с инструкции JMP [EBX] // В EBX будет лежать адрес функции SelfUnload, // который будет выгружать библиотеку. // Адрес функции рассчитывается отдельно и равен // адресу загрузки библиотеки + смещение на саму функцию // ============================================================================= function TfrmMain.EjectLib(const ProcessID: DWORD): Boolean; var hModuleSnap: THandle; ModuleEntry: TModuleEntry32; Process: HWND; BytesWriten: DWORD; Thread: DWORD; ThreadId: DWORD; ExitCode: DWORD; PLibHandle: PDWORD; OpCode: PWORD; CurrUnloadAddrOffset: DWORD; begin Result := False; // Находим адрес библиотеки hModuleSnap := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessID); if hModuleSnap <> INVALID_HANDLE_VALUE then try FillChar(ModuleEntry, SizeOf(TModuleEntry32), #0); ModuleEntry.dwSize := SizeOf(TModuleEntry32); if not Module32First(hModuleSnap, ModuleEntry) then Exit; repeat if AnsiUpperCase(ModuleEntry.szModule) = AnsiUpperCase(DLLName) then begin // Получаем адрес функции CurrUnloadAddrOffset := ModuleEntry.hModule + UnloadAddrOffset; Break; end; until not Module32Next(hModuleSnap, ModuleEntry); finally CloseHandle(hModuleSnap); end;
// Устанавливаем отладочные привилегии для нашего процесса Result := SetDebugPriv; if not Result then Exit;
Process := 0; Thread := 0; try // Открываем процесс Process := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE, True, ProcessID); if Process = 0 then Exit;
// Пишем опкод jmp [ebx] OpCode := VirtualAllocEx(Process, nil, 2, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE); ModuleEntry.hModule := $23FF; if not WriteProcessMemory(Process, OpCode, @ModuleEntry.hModule, 2, BytesWriten) then Exit;
// Пишем адрес функции выгрузки (он будет лежать в EBX при старте потока) PLibHandle := VirtualAllocEx(Process, nil, 4, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE); if not WriteProcessMemory(Process, PLibHandle, @CurrUnloadAddrOffset, 4, BytesWriten) then Exit;
// запускаем поток Thread := CreateRemoteThread(Process, nil, 0, OpCode, PLibHandle, 0, ThreadId);
if Thread = 0 then Exit; // Ждем пока удаленный поток отработает... if (WaitForSingleObject(Thread, INFINITE) = WAIT_OBJECT_0) then if GetExitCodeThread(Thread, ExitCode) then Result := ExitCode = 0; finally // Удаленный поток свою задачу выполнил и загрузил нашу библиотеку, // можно освобождать занятую память... if OpCode <> nil then VirtualFreeEx(Process, @OpCode, 0, MEM_RELEASE); if PLibHandle <> nil then VirtualFreeEx(Process, @PLibHandle, 0, MEM_RELEASE); if Thread <> 0 then CloseHandle(Thread); if Process <> 0 then CloseHandle(Process); end; end;
type PSYSTEM_THREADS = ^SYSTEM_THREADS; SYSTEM_THREADS = packed record KernelTime: LARGE_INTEGER; UserTime: LARGE_INTEGER; CreateTime: LARGE_INTEGER; WaitTime: ULONG; StartAddress: Pointer; UniqueProcess: DWORD; UniqueThread: DWORD; Priority: Integer; BasePriority: Integer; ContextSwitchCount: ULONG; State: Longint; WaitReason: Longint; end;
PSYSTEM_PROCESS_INFORMATION = ^SYSTEM_PROCESS_INFORMATION; SYSTEM_PROCESS_INFORMATION = packed record NextOffset: ULONG; ThreadCount: ULONG; Reserved1: array [0..5] of ULONG; CreateTime: FILETIME; UserTime: FILETIME; KernelTime: FILETIME; ModuleNameLength: WORD; ModuleNameMaxLength: WORD; ModuleName: PWideChar; BasePriority: ULONG; ProcessID: ULONG; InheritedFromUniqueProcessID: ULONG; HandleCount: ULONG; Reserved2 : array[0..1] of ULONG; PeakVirtualSize : ULONG; VirtualSize : ULONG; PageFaultCount : ULONG; PeakWorkingSetSize : ULONG; WorkingSetSize : ULONG; QuotaPeakPagedPoolUsage : ULONG; QuotaPagedPoolUsage : ULONG; QuotaPeakNonPagedPoolUsage : ULONG; QuotaNonPagedPoolUsage : ULONG; PageFileUsage : ULONG; PeakPageFileUsage : ULONG; PrivatePageCount : ULONG; ReadOperationCount : LARGE_INTEGER; WriteOperationCount : LARGE_INTEGER; OtherOperationCount : LARGE_INTEGER; ReadTransferCount : LARGE_INTEGER; WriteTransferCount : LARGE_INTEGER; OtherTransferCount : LARGE_INTEGER; ThreadInfo: array [0..0] of SYSTEM_THREADS; end;
function NtQuerySystemInformation( SystemInformationClass: DWORD; SystemInformation : Pointer; SystemInformationLength : DWORD; var ReturnLength: DWORD ): DWORD; stdcall; external 'ntdll.dll';
procedure TfrmMain.FillProcessCombo; const SystemProcessesAndThreadsInformation = 5; STATUS_INFO_LENGTH_MISMATCH = $C0000004; var SystemInformation, Temp: PSYSTEM_PROCESS_INFORMATION; ReturnLength: DWORD; begin cbProcess.Items.BeginUpdate; try cbProcess.Items.Clear; ReturnLength := 0; // Запрашиваем размер требуемой памяти if NtQuerySystemInformation( SystemProcessesAndThreadsInformation, nil, 0, ReturnLength) <> STATUS_INFO_LENGTH_MISMATCH then Exit; if ReturnLength > 0 then begin // Выделяем память GetMem(SystemInformation, ReturnLength); try // Получаем список процессов if NtQuerySystemInformation(SystemProcessesAndThreadsInformation, SystemInformation, ReturnLength, ReturnLength) = 0 then begin // Бежим по списку и заносим каждый в список Temp := SystemInformation; repeat // Добавляем все процессы за исключение системного и IDLE if (Temp^.ModuleName <> nil) and (Temp^.ProcessID <> 4) then cbProcess.Items.AddObject( Temp^.ModuleName, Pointer(Temp^.ProcessID)); Temp := Pointer(DWORD(Temp) + Temp^.NextOffset); until Temp^.NextOffset = 0; end; finally FreeMem(SystemInformation); end; end; finally cbProcess.Items.EndUpdate; end; end;
procedure TfrmMain.FormCreate(Sender: TObject); var hLibHandle: THandle; begin // Находим адрес функции FillProcessCombo; hLibHandle := LoadLibraryEx( PChar(ExtractFilePath(ParamStr(0)) + DLLName), 0, DONT_RESOLVE_DLL_REFERENCES); try UnloadAddrOffset := DWORD(GetProcAddress(hLibHandle, 'SelfUnload')) - hLibHandle; if UnloadAddrOffset = -hLibHandle then Exit; finally FreeLibrary(hLibHandle); end; end;
end.
|
Теперь вопрос: Как из моей программы, передать DLL нужный мне текст.
|