Unconfigured Ad Widget

Collapse

Anúncio

Collapse
No announcement yet.

Code Injection

Collapse
X
 
  • Filter
  • Tempo
  • Show
Clear All
new posts

  • Font Size
    #1

    Tutorial Code Injection

    1) O que é Code Injetion??

    Code injection é o ato de introduzir rotinas a um processo remoto, de modo a mudar o sua funcionabilidade. No caso, nós simplesmente iremos introduzir uma rotina e fazer o processo remoto executá-la, sem interferir em sua funcionabilidade.


    2) Entendendo a lógica


    Bom, para os que não estão muito familiarizados com manipulação de memória eu sugiro que estudem um pouco mais antes de tentar entender completamente o conceito de Code Injection. Bom, como estaremos mexendo com a memória de outro processo, quando formos usar algum parametro que está em NOSSO programa, não podemos simplesmente tentar chamá-lo de um processo para outro. Então nós escreveremos na memória do target (tratarei o processo remoto como "target" por questão de conveniência ao escrever) tudo que ele for usar que está em nosso processo.

    A rotina que injetaremos no target deve estar numa DLL e sendo exportada.

    Outro fator importante são os privilégios necessários para o nosso programa executar essa ação. Se tentarmos fazer isso com privilégios normais, é provável que, em algum momento do código, haja problemas de permissão. Para evitar quaisquer eventuais problemas, definiremos o privilégio como o de debug.

    Depois de executada a rotina, não temos mais porque deixar os parametros utilizados na execução da mesma no target, isso só iria ocupar espaço, então nós liberaremos toda a memória escrita no processo remoto.


    3) O código

    Bom, antes de mais nada, vamos criar a estrutura que armazenará os parametros utilizados na execução da rotina. Mas que parametros são esses afinal??

    Esses parametros devem incluir as funções LoadLibraryA (para carregar a DLL na memória) e GetProcAddress (para saber o endereço de memória da nossa rotina quando for injetada no target). Além dessas funções, também devemos por nessa estrutura os parametros de cada uma: o nome da DLL e o nome da rotina. Tendo isso em mente, definam a estrutura do seguinte modo:
    Código:
    type
      TInjectParams = record
        LoadLibrary: function (lpLibFileName: PAnsiChar): Cardinal; stdcall;
        LibName: PAnsiChar;
        GetProcAddress: function (hModule: Cardinal; lpProcName: PAnsiChar): Pointer; stdcall;
        ProcName: PAnsiChar;
      end;
      PInjectParams = ^TInjectParams;
    Agora, como na função final do Code Injection o usuário irá apenas especificar o nome do processo, da dll e da rotina a ser injetada, precisaremos de uma função que pega o Handle do processo a partir do nome dele. Para isso adicionem "tlhelp32" no uses e utilizem o seguinte método:
    Código:
    function GetProcess(proc: string): Cardinal;
    var
    Snap: THandle;
    pe: TProcessEntry32;
    begin
    Snap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if Snap = 0 then Exit;
    if Process32First(Snap,pe) then
      begin
      repeat
        if proc = pe.szExeFile then
          begin
          Result:=pe.th32ProcessID;
          break;
          end;
      until not Process32Next(Snap,pe)
      end
    end;


    * Notificar esta Mensagem
    * Responder com citação

    [TUTORIAL]Code Injection

    Mensagempor ace_ventura » 24 Mar 2009, 13:43
    1) O que é Code Injetion??

    Code injection é o ato de introduzir rotinas a um processo remoto, de modo a mudar o sua funcionabilidade. No caso, nós simplesmente iremos introduzir uma rotina e fazer o processo remoto executá-la, sem interferir em sua funcionabilidade.


    2) Entendendo a lógica

    Bom, para os que não estão muito familiarizados com manipulação de memória eu sugiro que estudem um pouco mais antes de tentar entender completamente o conceito de Code Injection. Bom, como estaremos mexendo com a memória de outro processo, quando formos usar algum parametro que está em NOSSO programa, não podemos simplesmente tentar chamá-lo de um processo para outro. Então nós escreveremos na memória do target (tratarei o processo remoto como "target" por questão de conveniência ao escrever) tudo que ele for usar que está em nosso processo.

    A rotina que injetaremos no target deve estar numa DLL e sendo exportada.

    Outro fator importante são os privilégios necessários para o nosso programa executar essa ação. Se tentarmos fazer isso com privilégios normais, é provável que, em algum momento do código, haja problemas de permissão. Para evitar quaisquer eventuais problemas, definiremos o privilégio como o de debug.

    Depois de executada a rotina, não temos mais porque deixar os parametros utilizados na execução da mesma no target, isso só iria ocupar espaço, então nós liberaremos toda a memória escrita no processo remoto.


    3) O código

    Bom, antes de mais nada, vamos criar a estrutura que armazenará os parametros utilizados na execução da rotina. Mas que parametros são esses afinal??

    Esses parametros devem incluir as funções LoadLibraryA (para carregar a DLL na memória) e GetProcAddress (para saber o endereço de memória da nossa rotina quando for injetada no target). Além dessas funções, também devemos por nessa estrutura os parametros de cada uma: o nome da DLL e o nome da rotina. Tendo isso em mente, definam a estrutura do seguinte modo:

    Código: Selecionar tudo
    type
    TInjectParams = record
    LoadLibrary: function (lpLibFileName: PAnsiChar): Cardinal; stdcall;
    LibName: PAnsiChar;
    GetProcAddress: function (hModule: Cardinal; lpProcName: PAnsiChar): Pointer; stdcall;
    ProcName: PAnsiChar;
    end;
    PInjectParams = ^TInjectParams;



    Agora, como na função final do Code Injection o usuário irá apenas especificar o nome do processo, da dll e da rotina a ser injetada, precisaremos de uma função que pega o Handle do processo a partir do nome dele. Para isso adicionem "tlhelp32" no uses e utilizem o seguinte método:

    Código: Selecionar tudo
    function GetProcess(proc: string): Cardinal;
    var
    Snap: THandle;
    pe: TProcessEntry32;
    begin
    Snap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if Snap = 0 then Exit;
    if Process32First(Snap,pe) then
    begin
    repeat
    if proc = pe.szExeFile then
    begin
    Result:=pe.th32ProcessID;
    break;
    end;
    until not Process32Next(Snap,pe)
    end
    end;



    Como dito acima, será necessário escrever na memória do target os parametros e a rotina em si. Para isso vamos criar duas funções, uma para escrever os parametros (WriteString) e uma para escrever a rotina (WriteData). Notem que elas são funções e não procedimentos pois precisamos do endereço de memória onde esses dados foram escritos para chamá-los a partir do target.
    Código:
    function WriteString(Process: Cardinal; s: string): Pointer;
    var
    bytes: Cardinal;
    begin
    Result:=VirtualAllocEx(Process, nil, length(s) + 1, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(Process, Result , pchar(s), length(s) + 1, bytes);
    end;
    Código:
    function WriteData(Process, dwSize: Cardinal; RemoteData: pointer): pointer;
    var
    bytes: Cardinal;
    begin
    Result:=VirtualAllocEx(Process, nil, dwSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(Process, Result, RemoteData, dwSize, bytes);
    end;
    Agora precisaremos de uma rotina para executar a rotina injetada no target. Vamos chamá-la de RemoteFunction. Essa rotina precisará dos parametros injetados no target para executar a rotina desejada e, como os parametros já estarão definidos na memória, utilizaremos PInjectParams para pegar os valores.
    Código:
    procedure RemoteFunction(Parametros: PInjectParams); stdcall;
    var
    proc: procedure; stdcall;
    begin
    proc:=Parametros^.GetProcAddress(Parametros^.LoadLibrary(Parametros^.LibName),Parametros^.ProcName);
    proc;
    end;
    Agora precisaremos de um método para saber o tamanho dessa rotina descrita acima, pois na hora de escrevê-la no target é necessário por o tamanho. Para isso faremos outro método logo abaixo desse, e depois é só pegar o endereço dele e subtrair do endereço da rotina "RemoteFunction".
    Código:
    procedure RemoteFunctionEnd; stdcall;
    begin;
    end;
    Como já disse anteriormente, é necessário mudar o privilégio para evitar eventuais problemas. Utilizem o seguinte método:
    Código:
    procedure ChangePrivilege(szPrivilege: PChar; fEnable: Boolean);
    var
      NewState: TTokenPrivileges;
      luid: TLargeInteger;
      hToken: THandle;
      ReturnLength: DWord;
    begin
      OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken);
      LookupPrivilegeValue(nil, szPrivilege, luid);
    
      NewState.PrivilegeCount := 1;
      NewState.Privileges[0].Luid := luid;
      if (fEnable) then
        NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
      else
        NewState.Privileges[0].Attributes := 0;
    
      AdjustTokenPrivileges(hToken, False, NewState, SizeOf(NewState), nil, ReturnLength);
      CloseHandle(hToken);
    end;
    Pronto, agora só falta montar a função final, mas depois de tudo isso, para quem realmente entendeu a lógica fica fácil. Não vou comentar parte por parte dela no post, pois o código já está comentado.
    Código:
    procedure Inject(process, dll, code: string);
    var
    PID, hProcess, ThreadId, ThreadHandle: Cardinal;
    RemoteData,RemoteFunc,LibFileName,ProcName: pointer;
    Parametros: TInjectParams;
    begin
    {Pega o Handle do processo}
    PID:=GetProcess(Process);
    
    {Seta o privilégio de debug}
    ChangePrivilege('SeDebugPrivilege', True);
    
    {Abre o processo}
    hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
    
    {Define os parâmetros que serão usados para executar a procedure}
    LibFileName:=WriteString(hProcess, dll);
    ProcName:=WriteString(hProcess, code);
    Parametros.LoadLibrary:=GetProcAddress(GetModuleHandle('kernel32'), 'LoadLibraryA');
    Parametros.LibName:=LibFileName;
    Parametros.GetProcAddress:=GetProcAddress(GetModuleHandle('kernel32'), 'GetProcAddress');
    Parametros.ProcName:=ProcName;
    
    {Abre um novo espaço de memória para guardar os parâmetros}
    RemoteData:=WriteData(hProcess, sizeof(Parametros), @Parametros);
    
    {Abre um novo espaço de memória para guardar a procedure}
    RemoteFunc:=WriteData(hProcess, integer(@RemoteFunctionEnd) - integer(@RemoteFunction), @RemoteFunction);
    
    {Cria a thread que executará a procedure}
    ThreadHandle:=CreateRemoteThread(hProcess, nil, 0, RemoteFunc, RemoteData, 0, ThreadId);
    WaitForSingleObject(ThreadHandle, 3000);
    
    {Libera as memórias criadas}
    VirtualFreeEx(hProcess,LibFileName,0,MEM_RELEASE);
    VirtualFreeEx(hProcess,ProcName,0,MEM_RELEASE);
    VirtualFreeEx(hProcess,RemoteFunc,0,MEM_RELEASE);
    VirtualFreeEx(hProcess,RemoteData,0,MEM_RELEASE);
    end;

    3) Pondo tudo em prática


    Criem uma DLL e adicionem uma rótina simples, como:
    Código:
    procedure Msg;
    begin
    MessageBox(0,'Teste','Code Injected',mb_ok);
    end;
    **Não esqueçam de declarar "windows" no uses

    Depois exportem essa função. Digitem o seguinte abaixo de todas as eventuais rotinas que sua DLL tem:
    Código:
    exports
       Msg;
    Compilem essa DLL com um nome 'qualquer.DLL'. Depois criem um projeto novo e coloquem um botão, além de todo o procedimento descrito acima. No onClick desse botão coloquem:
    Código:
    Inject('notepad.exe','C:\Projects\qualquer.DLL','Msg');
    --------------------------------------------------------------------------------------------------------

    O motivo que eu postei foi para ajudar as pessoas que realmente se interessam em aprender... Eu, particularmente, quando realmente entendi a lógica desse algoritmo, fiquei maravilhado com a inteligencia de seu criador...

    Espero sinceramente que alguém faça proveito desse source do jeito que eu fiz quando aprendi, esse é o primeiro passo para Api hook, que é o primeiro passo para rootkit... =)
    sigpic

  • Font Size
    #2
    Eu me amarro nesses assuntos. Estou pensando em fazer meu TCC sobre algo do genero.

    Um futuro bem proximo

    Poxa valeu, parabéns ae

    Comment

    X
    Working...
    X