Api hooking para mudar o usuário logado

Já está nas bancas a revista Clube Delphi 127 com meu primeiro artigo sobre a madShi Collection. Neste artigo eu explico o básico sobre API Hooking.

Neste post falarei sobre um exemplo que não se encontra no artigo, que é o hooking da API GetUserName.
Os motivos que levam a hookar essa API podem ser variados, e todos eles nada éticos a meu ver. Você pode desde tentar enganar um produto registrado para um usuário acessando-o como outro usuário ou simplesmente para tapear um usuário administrador, que quando olhar quem está logado verá um nome diferente (supondo que isso funcione, não testei).

A idéia é que dá para mudar a resposta que outros programas recebem quando perguntam quem é o usuário logado. Para isso é necessário conhecer quais são as api's que fazem isso e como interceptá-las.

O código dessa postagem mostra como usar a madCodeHook para interceptar a api GetUserName da api do windows.

Primeiro de tudo criei um programa que mostra o nome do usuário corrente:


function NomeUsuario: string;
var
  I: DWord;
begin
  I := 255;
  SetLength(Result, I);
  Windows.GetUserName(PChar(Result), I);
  Result := string(PChar(Result));
end;



procedure TForm2.btTestarClick(Sender: TObject);

begin
  Edit1.Text := NomeUsuario;
end;



Esse programa simplesmente mostra o usuário logado. Depois de injetada a DLL que faz o hook a chamada a GetUserName terá seu resultado mudado.
É preciso salientar que existe outra api chamada GetUserNameEx que não está mapeada na unit windows.pas e que aceita mais parâmetros, e devolve mais resultados.

Interceptar essas duas API's é certeza de que mudará os resultados às suas relativas chamadas. Não é garantia nenhuma de que será possível abrir um arquivo para o qual seu usuário atual não tem autorização, mas não custa nada tentar.

Como pôde ser visto nos artigos que escrevi para a Revista Clube Delphi, eis o código da dll a ser injetada.

Essa dll intercepta apenas a função GetUserName, deixo a cargo do leitor a GetUserNamneEx, que é mais complexa. Num post futuro trataremos da GetUserNameEx. Deixo apenas o esqueleto para quem quiser se aventurar.

Lembre-se de que se estiver usando a versão trial/demo da madCollectionHook deverá manter mchEvaluation rodando para que o hooking funcione.

library hook;

uses
  SysUtils,
  windows,
  Classes,
  madcodehook;

{$R *.res}


const
  USUORIGINAL =  'vitorrubio';    //       vitorrubio --> meu user
  USUTROCA = 'Administrador';       //       Administrador--> quem quero ser




var
  GetUserNameWNext:  function (lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall;
  GetUserNameANext:  function (lpBuffer: PAnsiChar; var nSize: DWORD): BOOL; stdcall;


function GetUserNameWCallback (lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall;
begin

  Result := GetUserNameWNext(lpBuffer, nSize);
  if (trim(string(lpBuffer)) = USUORIGINAL) then
  begin
    StrCopy(lpBuffer, USUTROCA);
    nSize := Length(USUTROCA);
  end;

end;

function GetUserNameACallback (lpBuffer: PAnsiChar; var nSize: DWORD): BOOL; stdcall;
begin

  Result := GetUserNameANext(lpBuffer, nSize);
  if (trim(AnsiString(lpBuffer)) = AnsiString(USUORIGINAL)) then
  begin
    StrCopy(lpBuffer, USUTROCA);
    nSize := Length(USUTROCA);
  end;

end;

begin
  HookAPI('advapi32.dll', 'GetUserNameW',  @GetUserNameWCallback, @GetUserNameWNext);
  HookAPI('advapi32.dll', 'GetUserNameA',  @GetUserNameACallback, @GetUserNameANext);
end.


Agora o código para injetar, desinjetar e testar a dll:

procedure TForm1.btInjetarClick(Sender: TObject);
begin
  InjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'hook.dll');
end;

procedure TForm1.btTestarClick(Sender: TObject);
begin
  Edit1.Text := NomeUsuario;
end;

procedure TForm1.btDesinjetarClick(Sender: TObject);
begin
  UninjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'hook.dll');
end;

Crie uma form com 3 botões e um edit e teste. Lembre-se de todas as medidas de segurança necessárias para se trabalhar com API hooking e lembre-se que toda a api do windows se invoca com stdcall.

Coloque a dll e o testador em um mesmo project group para facilitar.

É importante salientar que qualquer processo que use a GetUserNameEx para identificar o usuário não sofrerá nenhum efeito desse hooking. Além disso o windows tem outras formas, de baixo nível, para descobrir o usuário logado.

Have fun :)

Comentários

Postagens mais visitadas deste blog

Detectar o encoding de um arquivo para não corromper ao transformá-lo

erro "ora-12154: tns: não foi possível resolver o identificador de conexão especificado"

Quebras de linha no Delphi 2010