segunda-feira, 4 de abril de 2011

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 :)

Nenhum comentário:

Postar um comentário

Postagens populares

Marcadores

delphi (60) C# (31) poo (21) Lazarus (19) Site aos Pedaços (15) sql (13) Reflexões (10) .Net (9) Humor (9) javascript (9) ASp.Net (8) api (8) Básico (6) Programação (6) ms sql server (5) Web (4) banco de dados (4) HTML (3) PHP (3) Python (3) design patterns (3) jQuery (3) livros (3) metaprogramação (3) Ajax (2) Debug (2) Dicas Básicas Windows (2) Pascal (2) games (2) linguagem (2) música (2) singleton (2) tecnologia (2) Anime (1) Api do Windows (1) Assembly (1) Eventos (1) Experts (1) GNU (1) Inglês (1) JSON (1) SO (1) datas (1) developers (1) dicas (1) easter egg (1) firebird (1) interfaces (1) introspecção (1) memo (1) oracle (1) reflexão (1)