Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 02-08-2013
Jais Jais is offline
Miembro
NULL
 
Registrado: jul 2013
Posts: 12
Poder: 0
Jais Va por buen camino
Inyeccion DLL[Duda]

Hola

Este es mi primer post en el foro.

Estoy estudiando la inyección de DLL en un proceso.
Hasta el momento he conseguido hacer un Hook (metodo trampolin) a un MessageBox.

La duda que tengo es la siguiente.

Yo tengo un programa de este estilo, pero con mucho más código:

Código:
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils,Windows;

Var
  i: Integer;
  Cuenta: String;

begin
  { TODO -oUser -cConsole Main : Insert code here }
  Cuenta := '';
  For i:=0 To 10 Do
    Begin
      Cuenta := Cuenta + IntToStr(i);
    End;

  MessageBox(0,PAnsiChar(Cuenta),'Cuenta',64);
end.
Y lo que no se como hacer, es inyectar este programa, haciendo uso de la inyección con DLL, en un proceso como notepad.exe, calc.exe, ... (el proceso sinceramente no me importa cual sea).

Espero me puedan ayudar.

Muchísimas gracias de antemano.

Un saludo
Responder Con Cita
  #2  
Antiguo 02-08-2013
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
En el foro tienes ejemplos de como inyectar una dll. De entrada, necesitas tener una dll que inyectar y tu código no lo es.


Saludos.
Responder Con Cita
  #3  
Antiguo 05-08-2013
Jais Jais is offline
Miembro
NULL
 
Registrado: jul 2013
Posts: 12
Poder: 0
Jais Va por buen camino
Hola escafandra

Gracias por tu respuesta. La DLL que quiero inyectar es esta:

Código:
library Sumar;

{$APPTYPE CONSOLE}

uses
  SysUtils,Windows;

Var
  i: Integer;
  Cuenta: String;

begin
  { TODO -oUser -cConsole Main : Insert code here }
  Cuenta := '';
  For i:=0 To 10 Do
    Begin
      Cuenta := Cuenta + IntToStr(i);
    End;

  MessageBox(0,PAnsiChar(Cuenta),'Cuenta',64);
end.
Llevo tiempo leyendo tutoriales, tanto los que mencionas como otros, pero no tengo muy claro el funcionamiento.

Ahora mismo estoy trabajando con este codigo, que me funciona en Windows XP:

Código:
procedure InjectDll(PID: dword;  DLL: pChar);
var
  BytesWritten, hProcess, hThread, TID: Cardinal;
  Parameters: pointer;
  pThreadStartRoutine: Pointer;
begin
  // Abrimos el proceso
  hProcess := OpenProcess(PROCESS_ALL_ACCESS,  False,  PID);
  // Creamos espacio en el proceso
  Parameters := VirtualAllocEx( hProcess, nil, Length(DLL)+1, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  // Escribimos en el proceso la ruta de nuestra DLL
  WriteProcessMemory(hProcess,Parameters,Pointer(DLL  ),Length(DLL)+1,BytesWritten);
  // Obtenemos la direccion de LoadLibrary con GetProcAddress
  pThreadStartRoutine := GetProcAddress(GetModuleHandle('KERNEL32.DLL'), 'LoadLibraryA');
  // Creamos un Thread en el proceso remoto que ejecute nuestra dll
  hThread := CreateRemoteThread(hProcess,  nil,  0,  pThreadStartRoutine,  Parameters,  0,  TID);
  // Cerramos el hProcess abierto
  CloseHandle(hProcess);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  InjectDll(Aqui pongo el PID del notepad o de la calculadora,PAnsiChar('C:\Sumar.dll'));
end;
He probado este codigo tanto con el PID de un notepad y con el de la calculadora y con los dos me ha funcionado.

Tengo unas dudas, ¿porque obtenemos la dirección de LoadLibrary?
He leido el algun tutorial, pero no se porque motivo es, que este codigo no funciona en Sistemas Operativos de 64 bits. ¿Por que razon no funciona? Yo no le podido probar en sistemas operativos de 64 bits porque no tengo.

Muchisimas gracias de antemano.

Saludos
Responder Con Cita
  #4  
Antiguo 07-08-2013
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Aclarando dudas:
Cita:
Empezado por Jais Ver Mensaje
¿porque obtenemos la dirección de LoadLibrary?
Estudia la API CreateRemoteThread, el 4 parámetro precisa un puntero a una función y el 5 es un puntero que se pasará a la dicha función.

LoadLibrary es la API que se usa para cargar una dll en el proceso actual y usa un parámetro que es el nombre de la dll. La inyección se basa en obligar a otro proceso a cargar una dll, CreateRemoteThread hace esa función ejecutando en el proceso anfitrión LoadLibrary con el nombre de la dll que queremos inyectar. Por eso necesitamos conocer un puntero a Loadlíbrary y reservar memoria en el espacio de direcciones del priceso anfitrión para escribir el nombre de la dll que pasaremos a LoadLibrary. El truco se basa en que las direcciones de las APIs del sistema son idénticas para todos los procesos.

Cita:
Empezado por Jais Ver Mensaje
...este codigo no funciona en Sistemas Operativos de 64 bits. ¿Por que razon no funciona?
Un proceso compilado para 32bits no puede usar una dll compilada para 32bits, por lo tanto
no se puede inyectar código compilado para 32bits en un proceso 64bits.


Saludos.
Responder Con Cita
  #5  
Antiguo 09-08-2013
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Perdón por la errata:
Cita:
Empezado por escafandra Ver Mensaje
Un proceso compilado para 32bits no puede usar una dll compilada para 32bits, por lo tanto
no se puede inyectar código compilado para 32bits en un proceso 64bits.
debe decir:
Un proceso compilado para 64bits no puede usar una dll compilada para 32bits, por lo tanto
no se puede inyectar código compilado para 32bits en un proceso 64bits.


Saludos.
Responder Con Cita
  #6  
Antiguo 10-08-2013
Jais Jais is offline
Miembro
NULL
 
Registrado: jul 2013
Posts: 12
Poder: 0
Jais Va por buen camino
Hola escafandra

Referente a la API CreateRemoteThread me ha quedado todo muy claro. Ahora si lo que entiendo muy bien. Sinceramente, muchisimas gracias escafandra.

El tema de 32 bits y 64 bits también, creo , que me ha quedado claro. Esto es lo que he entendido:
- Para utilizar una DLL en 32 bits, se deberá crear esa DLL en una arquitectura 32 bits. Ejemplo: Windows Vista 32 bits,...
- Para utilizar una DLL en 64 bits, se deberá crear esa DLL en una arquitectura 64 bits. Ejemplo: Windows 7 64 bits,...

Espero haberlo entendido bien.

Una vez entendido el tema de la inyección DLL bastante bien, quería aprender el tema de Hook API porque aunque algo hecho todavía no lo entiendo del todo bien.

El código con el que he estado trabajando es el siguiente(Autor: Robert Milan ):

Aplicación Test:

Código:
procedure TForm1.Button1Click(Sender: TObject);
begin
MessageBoxA(Self.Handle,                         // Application Handle
              PAnsiChar(AnsiString(Edit1.Text)),   // Message in messagebox
              PAnsiChar(Self.Caption),             // Title of messagebox
              $00000040);                          // Information Icon
end;
Inyector:

Código:
procedure TForm1.Button1Click(Sender: TObject);
begin
InjectDLL('notepad.exe', Ruta de la DLL);
end;

function GetProcessIdByName(s : String) : Cardinal;
var
   { Process Vars }
   hProcessSnap : THandle;
   PE32         : ProcessEntry32;
begin
	{ Init. Result }
  	Result := 0;

  	{ Take a snapshot of all the processes in the system }
  	hProcessSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  	if (hProcessSnap = INVALID_HANDLE_VALUE) then exit;

  	{ Size of the ProcessEntry32 Structure }
  	PE32.dwSize := SizeOf(TProcessEntry32);

  	{ Unable to retreive information about the first process }
  	if not (Process32First(hProcessSnap, PE32)) then
  	begin
    	PE32.dwSize := 0;
    	CloseHandle(hProcessSnap);
    	exit;
  	end;

  	{ Iterate through the process list }
  	while not (Process32Next(hProcessSnap, PE32) = false) do
  	begin
   	if (Lowercase(PE32.szExeFile) = Lowercase(s)) then
    	begin
         Result := PE32.th32ProcessID;
      	break;
    	end;
  	end;

   { Cleanup the ProcessEntry32 struct. }
   with PE32 do
   begin
      dwSize := 0;
      cntUsage := 0;
      th32ProcessID := 0;
      th32DefaultHeapID := 0;
      th32ModuleID := 0;
      cntThreads := 0;
      th32ParentProcessID := 0;
      pcPriClassBase := 0;
      dwFlags := 0;
      szExeFile := '';
   end;

   { Freeup allocated memory }
   CloseHandle(hProcessSnap);
end;

function InjectDLL(Process: AnsiString; Dll: AnsiString) : Integer;
var
   PID          : Cardinal; { Process ID }

   hProcess     : THandle;  { Process Object }
   hThread      : THandle;  { Remote Thread Handle }

   dwThreadID   : DWORD;    { Remote Thread ID }

   BaseAddr     : PChar;    { Memory Address }

   BytesWritten : LongWord; { Total Bytes Written }
begin
   { Search for process id }
	PID := GetProcessIdByName(Process);

   { Process wasn't found }
   if (PID = 0) then
   begin
   	Result := -1;
   	exit;
   end;

   { Something went wrong, we can't find the process }
   if (PID = 0) then
   begin
      Result := -1;
      exit;
   end;

   { Open the process }
   hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or { For Token, Exit code and more }
                           PROCESS_CREATE_THREAD or     { For CreateRemoteThread }
                           PROCESS_VM_OPERATION or      { For VirtualAllocEx/VirtualFreeEx }
                           PROCESS_VM_WRITE,            { For WriteProcessMemory }
                           false, PID);


   { Allocate some extra memory in the target process }
   BaseAddr := PChar(VirtualAllocEx(hProcess, nil, strlen(PChar(DLL)) + 1 * sizeof(Char), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE));

   { Inject dll into memory }
   if not (BaseAddr = nil) then
   begin
      WriteProcessMemory(hProcess, BaseAddr, PChar(DLL), Length(DLL), BytesWritten);
   end else
   begin
      { No need to continue, we couldn't write the dll into memory }
      Result := -1;
      exit;
   end;

   { Create a thread, force the process to load the dll }
   hThread := CreateRemoteThread(hProcess, nil, 0, GetProcAddress(LoadLibrary('Kernel32.dll'), 'LoadLibraryA'), BaseAddr, 0, dwThreadID);

   { Wait for the thread to execute }
   WaitForSingleObject(hThread, INFINITE);

   { Free allocated memory }
   VirtualFreeEx(hProcess, BaseAddr, 0, MEM_RELEASE);
   CloseHandle(hProcess);

   Result := 0;
end;
DLL:

Código:
(************************************************************)
(* Win32 API Hooking Library                                *)
(* by Robert Milan (03/23/13)                               *)
(************************************************************)
(* This code is provided "as is" without express or         *)
(* implied warranty of any kind. Use it at your own risk.   *)
(************************************************************)

library prjHook;

uses
  Windows,
  SysUtils,
  StrUtils,
  Classes,
  Dialogs,
  Winsock;

var
   { Original API }
   TMessageBoxA : function (Handle : hWnd; lpText : PAnsiChar; lpCaption : PAnsiChar; uType : Cardinal) : Integer; stdcall;

{$R *.res}

{ Duplicate of the original api }
function OMessageBoxA(Handle : hWnd; lpText : PAnsiChar; lpCaption : PAnsiChar; uType : Cardinal) : Integer; stdcall;
begin

   { Here we will edit the api in any way that we want. }


   { Edit the message for the MessageBox }
   lpText := PAnsiChar('Message text edited!');

   { Change the icon type to exclamation }
   uType := $00000030;

   { Call the original api }
   Result := TMessageBoxA(Handle, lpText, lpCaption, uType);
end;

{
   This function will take a api call from a dll and create a
      unconditional JMP to the functions address in this dll.

   If the "REAL" function address is "0x00AA0F00" and the address to
      our replacement is "0x00FFFFFF" then the JMP will replace a JMP
      right before we reach the "REAL" address to the replacement address.
}

// Example: InterceptAPI('USER32.dll', 'MessageBoxA', @OMessageBoxA, @TMessageBoxA);
function InterceptAPI(lpModuleName : PAnsiChar; lpProcName: PAnsiChar; PCallBack : Pointer; var PTrampoline : Pointer) : Integer; stdcall;
var
   hMod      : HMODULE;
   FuncAddr  : Pointer;
   FuncOrg   : Pointer;
   dwProtect : DWORD;
begin
   { Dynamic Link Library }
   hMod := GetModuleHandle(lpModuleName);
   if (hMod = 0) then
   begin
      Result := 0;
      exit;
   end;

   { Address to api function }
   FuncAddr := GetProcAddress(hMod, lpProcName);
   if (FuncAddr = nil) then
   begin
      Result := 0;
      exit;
   end;

   VirtualProtect(FuncAddr, 5, PAGE_WRITECOPY, dwProtect);
   GetMem(FuncOrg, 10);
   CopyMemory(FuncOrg, FuncAddr, 5);

   { Create a unconditional JMP to the address of our replacement api}
   Byte(Pointer(DWORD(FuncOrg) + 5)^) := $E9;
   DWORD(Pointer(DWORD(FuncOrg) + 6)^) := (DWORD(FuncAddr) - (DWORD(FuncOrg) + 5));

   { Create a trampoline so that we can replace the replacement api back with the original }
   PTrampoline := FuncOrg;

   Byte(FuncAddr^) := $E9;
   DWORD(Pointer(DWORD(FuncAddr) + 1)^) := DWORD(PCallback) - (DWORD(FuncAddr) + 5);

   VirtualProtect(FuncAddr, 5, dwProtect, dwProtect);
   FlushInstructionCache(GetCurrentProcess(), Nil, 0);

   Result := 1;
end;

procedure DllMain(reason: integer);
begin
   case reason of
      DLL_PROCESS_ATTACH:   // DLL Loaded
      begin
         InterceptAPI('USER32.dll', 'MessageBoxA', @OMessageBoxA, @TMessageBoxA);
      end;

      DLL_PROCESS_DETACH:  // DLL Unloaded
      begin
         // Do something while dll is being unloaded.
      end;
   end;
end; { DllMain }

begin
   { Set the dll entry point and call it }
   DllProc := @DllMain;
   DllProc(DLL_PROCESS_ATTACH);
end.
Hace uso de la tecnica "Trampolin" que tambien utilizaste tu escafandra aqui: delphiaccess.com/forum/tutoriales/hook-a-la-api-en-delphi-(trampolin)

Mas o menos entiendo que hace el codigo y en que consiste la tecnica del trampolin.
Pero tengo unas dudas:
- Como se que $E9 hace referencia a JMP.
- Y la operación inversa. Como sacar que "codigo hexadecimal" tiene JMP.

Mirando google he visto otros codigos que hacen uso de la funcion SetWindowsHookEx, CallNextHookEx y UnhookWindowsHookEx para hacer un Hook.

Quería saber la diferencia que hay entre hacer un hook con el metodo trampolin y el hacer el hook utilizando las 3 apis de arriba. Tengo un codigo que hacer un hook del 2º tipo, pero sinceramente no lo entiendo.
Estudiando y leyendo, creo que la respuesta es que el metodo trampolin hace un hook INDIVIDUAL a una api de un UNICO proceso, mientras que con SetWindowsHookEx se hace un hook GLOBAL que es procesado por un UNICO proceso, pero sinceramente no estoy seguro de si es correcto lo que he dicho.

Muchisimas gracias escafandra por la ayuda!!!

Siento lo largo que me ha quedado el post y espero que me haya explicado con claridad.

Saludos
Responder Con Cita
  #7  
Antiguo 19-08-2013
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por Jais Ver Mensaje
Mas o menos entiendo que hace el codigo y en que consiste la tecnica del trampolin.
Pero tengo unas dudas:
- Como se que $E9 hace referencia a JMP.
- Y la operación inversa. Como sacar que "codigo hexadecimal" tiene JMP.
E9h es el opcode de la instrucción JMP en ensamblador. Es así en la familia de microprocesadores intel desde el Z80.

Cita:
Empezado por Jais Ver Mensaje
Mirando google he visto otros codigos que hacen uso de la funcion SetWindowsHookEx, CallNextHookEx y UnhookWindowsHookEx para hacer un Hook.

Quería saber la diferencia que hay entre hacer un hook con el metodo trampolin y el hacer el hook utilizando las 3 apis de arriba. Tengo un codigo que hacer un hook del 2º tipo, pero sinceramente no lo entiendo.
Ese segundo tipo Hook no es a la API, sino de Windows, tienes amplia documentación: Hook Functions

Saludos.
Responder Con Cita
  #8  
Antiguo 19-08-2013
Jais Jais is offline
Miembro
NULL
 
Registrado: jul 2013
Posts: 12
Poder: 0
Jais Va por buen camino
Ok, Muchísimas gracias Escafandra!!

¿Y donde puedo mirar o como puedo saber que JMP es E9?¿Y saber que E9 es JMP?

Un saludo
Responder Con Cita
  #9  
Antiguo 20-08-2013
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por Jais Ver Mensaje
¿Y donde puedo mirar o como puedo saber que JMP es E9?¿Y saber que E9 es JMP?
Con un ensamblador-desensamblador. Por ejemplo con el programa de consola debug.
El desensamblador de delphi también te serviría.
También puedes consultar tablas de opcodes como esta.


Saludos.
Responder Con Cita
  #10  
Antiguo 22-08-2013
Jais Jais is offline
Miembro
NULL
 
Registrado: jul 2013
Posts: 12
Poder: 0
Jais Va por buen camino
ok, muchísimas gracias escafandra!!

Seguro que me ayuda para entender mejor los opcodes.

Saludos
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Inyeccion SQL RebeccaGL MySQL 10 30-04-2012 17:15:43
ataques de inyección de sql hogol SQL 5 17-10-2011 23:00:37
Formas de inyección de procesos aeff API de Windows 8 27-10-2007 19:25:25
Inyeccion de sql richy08 PHP 0 19-10-2007 01:08:41
evitar inyeccion de html reevil PHP 2 21-12-2006 03:26:08


La franja horaria es GMT +2. Ahora son las 01:19:06.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi