Bueno, pues al final parece que sale bien inyectando código. Aquí os dejo el código, lo acabo de hacer así que esta un poco "sucio", pero creo que debe de funcionar bien.
Por una parte tenemos una dll, que es la que vamos a inyectar en el winlogon. Esta librería se inyecta sola
, exporta dos funciones Inject y Eject, la primera inyecta la dll en el winlogon y la segunda la vuelve a sacar. La dll por su parte, una vez que detecta que ha sido inyectada, sustituye el bucle de mensajes de la ventana "SAS window" e intercepta el mensaje WM_HOTKEY.
Código de la librería:
Código Delphi
[-]
library Injection;
uses
Windows, Sysutils, Messages, Psapi;
const
strTarget = '\winlogon.exe';
strWindowName = 'SAS window';
strWindowClass = 'SAS window class';
var
Injected: Boolean;
ModuleHandle: DWORD;
WindowHandle: THandle;
OldWindowProc: Pointer;
function WindowProc(hWnd: HWND; Msg: UINT; WParam: WPARAM; LParam: LPARAM):
LRESULT; stdcall;
begin
if (Msg = WM_HOTKEY) then
Result:= 0
else
Result:= CallWindowProc(OldWindowProc,hWnd,Msg,WParam,lParam);
end;
function EnablePrivilege(PrivilegeName: PChar; Enable: Boolean): Boolean;
var
hToken: THandle;
Tp: TOKEN_PRIVILEGES;
Luid: TLargeInteger;
begin
Result:= FALSE;
if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or
TOKEN_QUERY or TOKEN_READ, hToken) then
if LookupPrivilegeValue(nil,PrivilegeName,Luid) then
begin
Tp.PrivilegeCount:= 1;
Tp.Privileges[0].Luid:= Luid;
if Enable then
Tp.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED
else
Tp.Privileges[0].Attributes:= 0;
Result:= AdjustTokenPrivileges(hToken,FALSE,Tp,0,nil,PDWORD(nil)^);
CloseHandle(hToken);
end;
end;
procedure Inject(LibPath: PChar); stdcall;
var
Procesos: array[1..1024] of DWORD;
Needed, i: DWORD;
Process, Thread: THandle;
ModName, Target: array[0..MAX_PATH] of Char;
RemLibPath: PChar;
begin
if ModuleHandle = 0 then
if EnablePrivilege('SeDebugPrivilege', TRUE) then
begin
FillChar(Target,Sizeof(Target),#0);
GetSystemDirectory(@Target,Sizeof(Target)-1);
StrLCat(Target,strTarget,Sizeof(Target)-1);
if EnumProcesses(@Procesos, SizeOf(Procesos), Needed ) then
begin
for i:= 1 to (Needed div Sizeof(DWORD)) do
begin
Process := OpenProcess(PROCESS_ALL_ACCESS, FALSE,Procesos[i]);
if Process <> 0 then
begin
if GetModuleFileNameEx(Process,0,ModName,SizeOf(ModName)-1) > 0 then
begin
if AnsiStrPos(ModName,Target) <> nil then
begin
RemLibPath:= VirtualAllocEx(Process, nil,StrLen(LibPath)+1,
MEM_COMMIT, PAGE_READWRITE);
if RemLibPath <> nil then
begin
if WriteProcessMemory(Process, RemLibPath, LibPath,
StrLen(LibPath),PDWORD(nil)^) then
begin
Thread:= CreateRemoteThread(Process, nil, 0,
GetProcAddress(GetModuleHandle('Kernel32'),'LoadLibraryA'),
RemLibPath, 0, PDWORD(nil)^);
if Thread <> 0 then
begin
WaitForSingleObject(Thread,INFINITE );
GetExitCodeThread(Thread,ModuleHandle);
CloseHandle(Thread);
end;
end;
VirtualFreeEx(Process,RemLibPath,StrLen(LibPath)+1,MEM_RELEASE);
end;
end;
end;
CloseHandle(Process);
end;
end;
end;
EnablePrivilege('SeDebugPrivilege', FALSE);
end;
end;
procedure Eject; stdcall;
var
Procesos: array[1..1024] of DWORD;
Needed, i: DWORD;
Process, Thread: THandle;
ModName, Target: array[0..MAX_PATH] of Char;
begin
if ModuleHandle <> 0 then
if EnablePrivilege('SeDebugPrivilege', TRUE) then
begin
FillChar(Target,Sizeof(Target),#0);
GetSystemDirectory(@Target,Sizeof(Target)-1);
StrLCat(Target,strTarget,Sizeof(Target)-1);
if EnumProcesses(@Procesos,SizeOf(Procesos),Needed) then
begin
for i:= 1 to (Needed div Sizeof(DWORD)) do
begin
Process := OpenProcess(PROCESS_ALL_ACCESS, FALSE,Procesos[i]);
if Process <> 0 then
begin
if GetModuleFileNameEx(Process,0,ModName,SizeOf(ModName)-1)>0 then
begin
if AnsiStrPos(ModName,Target) <> nil then
begin
Thread:= CreateRemoteThread(Process, nil, 0,
GetProcAddress(GetModuleHandle('Kernel32'),'FreeLibrary'),
Pointer(ModuleHandle), 0, PDWORD(nil)^);
if Thread <> 0 then
begin
WaitForSingleObject(Thread,INFINITE );
CloseHandle(Thread);
ModuleHandle:= 0;
end;
end;
end;
CloseHandle(Process);
end;
end;
end;
EnablePrivilege('SeDebugPrivilege', FALSE);
end;
end;
procedure ProcessAttach; stdcall;
var
Process: THandle;
ModName: array[0..MAX_PATH] of Char;
Target: array[0..MAX_PATH] of Char;
begin
Injected:= FALSE;
ModuleHandle:= 0;
OldWindowProc:= nil;
WindowHandle:= 0;
Process := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE,
GetCurrentProcessId);
if Process <> 0 then
begin
if GetModuleFileNameEx(Process, 0, ModName,SizeOf(ModName)-1) > 0 then
begin
FillChar(Target,Sizeof(Target),#0);
GetSystemDirectory(@Target,Sizeof(Target)-1);
StrLCat(Target,strTarget,Sizeof(Target)-1);
if AnsiStrPos(ModName,Target) <> nil then
begin
WindowHandle := FindWindow(strWindowClass,strWindowName);
if WindowHandle <> 0 then
begin
OldWindowProc := Pointer(SetWindowLong(WindowHandle,GWL_WNDPROC,
LongInt(@WindowProc)));
Injected:= TRUE;
Windows.Beep(500,100);
end;
end;
end;
CloseHandle(Process);
end;
end;
procedure ProcessDetach; stdcall;
begin
if Injected and (OldWindowProc <> nil) and (WindowHandle <> 0)then
begin
SetWindowLong(WindowHandle,GWL_WNDPROC,LongInt(OldWindowProc));
Windows.Beep(500,100);
end else
Eject;
end;
procedure DLLEntryPoint(Reason: integer);
begin
case Reason of
Dll_Process_Detach: ProcessDetach;
Dll_Process_Attach: ProcessAttach;
end;
end;
exports
Inject, Eject;
begin
ProcessAttach;
DLLProc:= @DLLEntryPoint;
end.
Un ejemplo de como usar la librería seria la siguiente aplicación de consola, donde se supone que la librería se encuentra en la misma carpeta que la aplicación.
Código Delphi
[-]
program Injector;
{$APPTYPE CONSOLE}
uses Windows, SysUtils;
procedure Inject(LibPath: PChar); stdcall; external 'Injection.dll';
procedure Eject; stdcall; external 'Injection.dll';
var
LibPath: String;
begin
LibPath:= ExtractFilePAth(ParamStr(0)) + 'Injection.dll';
Inject(PChar(LibPath));
Writeln;
Writeln('Pulsa (Enter) para terminar ...');
Readln;
Eject;
end.
Bueno, una cosa mas que tacho en mi lista
EDITO: Modifique un poco el código para ponerlo bonito.