Ver Mensaje Individual
  #27  
Antiguo 26-02-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Reputación: 24
seoane Va por buen camino
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;

// Ajustamos los privilegios
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.

Última edición por seoane fecha: 27-02-2007 a las 03:56:39.
Responder Con Cita