Club Delphi  
    Paypal   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 27-04-2008
Khronos Khronos is offline
Miembro
 
Registrado: abr 2007
Posts: 298
Poder: 20
Khronos Va por buen camino
Aquí tienes el código:

Código Delphi [-]

uses TlHelp32;

function EnabledDebugPrivilege(const Enabled : Boolean) : Boolean;
var
  hTk : THandle;
  rtnTemp : Dword;
  TokenPri : TOKEN_PRIVILEGES;
const
  SE_DEBUG = 'SeDebugPrivilege';
begin
  Result := False;
  if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,hTk)) then
  begin
    TokenPri.PrivilegeCount := 1;
    LookupPrivilegeValue(nil,SE_DEBUG,TokenPri.Privileges[0].Luid);
    if Enabled then
      TokenPri.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
    else
      TokenPri.Privileges[0].Attributes := 0;
    rtnTemp := 0;
    AdjustTokenPrivileges(hTk,False,TokenPri,sizeof(TokenPri),nil,rtnTemp);
    Result := GetLastError = ERROR_SUCCESS;
    CloseHandle(hTk);
  end;
end;
 
{Esta es una función muy importante que sirve para
obtener el ID de un proceso.}
function GetProcessID(Exename: string): DWORD; 
var
  hProcSnap: THandle;
  pe32: TProcessEntry32;
begin
  result := 0;
  hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
  if hProcSnap <> INVALID_HANDLE_VALUE then
  begin
    pe32.dwSize := SizeOf(ProcessEntry32);
    if Process32First(hProcSnap, pe32) = true then
    begin
      while Process32Next(hProcSnap, pe32) = true do
      begin
        if pos(Exename, pe32.szExeFile) <> 0 then
          result := pe32.th32ProcessID;
      end;
    end;
    CloseHandle(hProcSnap);
  end;
end;
 
function InjectTo(const Host, Guest: string): DWORD;
var
  hRemoteProcess: THandle;  
  dwRemoteProcessId: DWORD;  
  memSize: DWORD;        
  pszLibFileRemote: Pointer;  
  iReturnCode: Boolean;
  TempVar: DWORD;
  pfnStartAddr: TFNThreadStartRoutine; 
  pszLibAFilename: PwideChar;
begin
  Result := 0;
  EnabledDebugPrivilege(True);
  Getmem(pszLibAFilename, Length(Guest) * 2 + 1);
  StringToWideChar(Guest, pszLibAFilename, Length(Guest) * 2 + 1);
  dwRemoteProcessID:=GetProcessId(host);
 
  hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + PROCESS_VM_OPERATION +
      PROCESS_VM_WRITE,
      FALSE, dwRemoteProcessId);
  //abrimos el proceso basándonos en la Id de dicho proceso
  memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR)*2;
 
  pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE));
  TempVar := 0;
  iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, TempVar);
    if iReturnCode then
  begin
    pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
    TempVar := 0;
    Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
  end;
  Freemem(pszLibAFilename);
end;

Ejemplo de uso:

Código Delphi [-]
begin
  InjectTo('notepad.exe', 'C:\MyDll.dll');
end;

Nunca utilices un proceso critíco del sistema. Si tienes alguna duda, pregunta.


Salu2 y suerte.

Última edición por Khronos fecha: 27-04-2008 a las 15:30:41.
Responder Con Cita
  #2  
Antiguo 27-04-2008
rolandoj rolandoj is offline
Miembro
 
Registrado: abr 2007
Posts: 395
Poder: 20
rolandoj Va por buen camino
Muchas gracias. Primeras dudas

Hola,

Muchas gracias por el aporte.

Efectivamente es muy similar a lo que ya conocía de esa técnica, y la complejidad luce mayor a la copia directa de memoria a memoria. Voy a analizarlo con bastante calma; pero te adelanto dos temas que me saltan a la vista:

1. Veo que la memoria alocada en el proceso remoto no la liberas con VirtualFreeEx sino con FreeMem, como es posible si se supone que están en espacios de direcciones diferentes ?

2. No mencionas nada acerca de la función que se va a ejecutar remotamente. Lo que indicas es ejecutar la carga de la librería como tal. Que hay de las observaciones que yo hacía en mi primera nota acerca de las condiciones que debe cumplir una rutina para ejecutarse en el proceso remoto ?. Es que acaso aquí la lógica es que lo único que se ejecuta es la rutina de inicialización del DLL ?. Si es así, que hay del paso de parámetros desde el proceso principal a la rutina remota ?, sería solo vía mensajes registrados?

Bueno, aunque como obvio interes profesional pienso detallar tú código, sigo con mi idea de corregir el problema con lo que tengo, que funcionalmente ya me está trabajando bien. Alguna idea de porque puede fallar después de haber ejecutado bien todas las instrucciones en el cuerpo de la rutina ?. Quizás es algún problema por la convención de llamadas stdcall, tal como la limpieza de la pila ?

Una vez más muchas gracias y seguiremos en contacto.

Muchos saludos
Responder Con Cita
  #3  
Antiguo 27-04-2008
rolandoj rolandoj is offline
Miembro
 
Registrado: abr 2007
Posts: 395
Poder: 20
rolandoj Va por buen camino
El problema con VirtualFreeEx

Hola,

Las pruebas que he hecho ya me han confirmado que el problema surge cuando libero el código de la rutina con VirtualFreeEx. Una investigación en Internet me ha mostrado que ese problema le ha ocurrido a otros; pero, hasta ahora, en ninguno de los sitios que he visto que lo han reportado se ha dado una explicación t/o solución.

El código que uso para liberar es :

Código Delphi [-]
TheResult := VirtualFreeEx(AProcessHandle, TheExtFuncAddr, 0, MEM_RELEASE);
        If Not Assigned(TheResult) Then Begin
           ShowMessage('Error liberando la Función '+SysErrorMessage(GetLastError));
        End;

Ahora bien, la rutina no me devuelve error, o sea, mi programa sigue funcionando; pero el proceso externo dice generar errores y se cierra.

La liberación de memoria de la parte de datos la hago de manera idéntica; pero esa no genera ningún problema.

La función la reservo así :

Código Delphi [-]
TheExtFuncAddr := VirtualAllocEx(AProcessHandle,
                                      0,
                                      AFunctionSize,
                                      MEM_COMMIT or MEM_RESERVE,
                                      PAGE_EXECUTE_READWRITE);

Quedo atento a sugerencias
Responder Con Cita
  #4  
Antiguo 29-04-2008
rolandoj rolandoj is offline
Miembro
 
Registrado: abr 2007
Posts: 395
Poder: 20
rolandoj Va por buen camino
El impacto de no liberar la memoria

Hola Khronos,

Pués sigo estancado en el error. No ha habido forma de encontrar una explicación de la falla de los programas al liberar la memoria con VirtualFreeEx.

Ante eso, sin recurrir a tú solución, me queda la alternativa de no liberar la memoria. En principio, el impacto de ello parece despreciable, Mi rutina ocupa 56 bytes, por tanto, se necesitaría llamarla mil veces seguídas para generar un excedente de 56000 bytes en un proceso. Considerando la frecuencia con la que se llama, es casi imposible aproximarse a esa cifra sin que al menos se haya cerrado sesión.

Las pruebas que he hecho no indican que dejar esa memoria sin liberar pueda generar algún problema; por tanto, aunque burda, parece una solución viable. Sin embargo, no estoy tan convencido. Se te ocurre algo que pudiera pasar muy a largo plazo ?

Respecto a tú solución, como verás, el hecho de que no me anime mucho a usarla es, aparte de que obliga a recodificar, por la diferencia de eficiencia. Aquí solo paso 56 bytes al otro proceso; en el otro método hay que cargar y descargar DLLs.

Eso sí, encuentro muy interesantes algunos puntos de tú método; entre ellos EnabledDebugPrivilege. No he tenido tiempo de investigarla a fondo; pero, esta rutina aparentemente asigna privilegios al proceso actual, o sea a mi propio proceso. Lo que no entiendo es que impacto tiene en el método de cargar el DLL
Responder Con Cita
  #5  
Antiguo 29-04-2008
Khronos Khronos is offline
Miembro
 
Registrado: abr 2007
Posts: 298
Poder: 20
Khronos Va por buen camino
Hola rolandoj, perdona por no haber contestado antes pero estuve algo ocupado

En principio al no liberar la memoria, dudo mucho que provoques un desbordamiento de la memoria , supongo que otro proceso sobreescribirá esa zona..

Antes de intentar inyectar codigo en otros procesos mediante dlls, probé un método parecido al tuyo pero me saltaba el DEP (Prevención de ejecución de datos de Windows) y me paraba el proceso. El método que utilizaba funcionaba perfectamente con funciones de la API de windows como DeleteFile, Sleep.. pero con funciones propias se iba a la mierda . Por eso pensé que inyectando una dll entera conseguiría "saltarme" esa protección y me salí con la mia .

Información de DEP: http://www.microsoft.com/latam/techn.../depcnfxp.mspx

Si encuentro el código lo pongo. Por cierto, ¿podrías enseñarnos tu código para ver el método que usas?

PD: Tengo que hacer una ejemplo de inyecciones de procesos mediante dll y subirlo. No es tan díficil como te piensas y funciona perfecto.

Salu2

Última edición por Khronos fecha: 29-04-2008 a las 20:32:50.
Responder Con Cita
  #6  
Antiguo 29-04-2008
rolandoj rolandoj is offline
Miembro
 
Registrado: abr 2007
Posts: 395
Poder: 20
rolandoj Va por buen camino
Gracias por los aportes. Comentarios

Hola,

Muchas gracias por aportar al tema.

Colocar el código completo puede ser inconveniente porque resulta complicado de seguír debido a la cantidad de detalles. Si la idea es documentar para que a otros les quede más facil este tortuoso camino; epro potencialmente eficiente camino, creo mejor ir colocandolo por fragmentos y comentar en detalle esos fragmentos.

Tengo que salir ahora; pero, al final de la noche trataré de sacar un tiempo para empezar a explicar la teoría, al menos lo que yo sé. Lo ideal sería que más colegas se sumaran a esta discusión y pudieran aclarar aspectos que para mí aún son oscuros,
Responder Con Cita
  #7  
Antiguo 01-05-2008
rolandoj rolandoj is offline
Miembro
 
Registrado: abr 2007
Posts: 395
Poder: 20
rolandoj Va por buen camino
Smile Abrí un hilo para explicar la inyección directa de código

Hola Khronos,

Pensandolo bien, para no confundir temas, ya que aquí lo busco es averiguar porque falla la limpieza de código en mi rutina, he creado un nuevo tema para discutir el método de inyectar código a un proceso externo. Puedes leerlo aquí:

http://www.clubdelphi.com/foros/showthread.php?t=55924

Es un tema largo y complicado que amerita explicaciones claras en varios puntos; por eso, solo he colocado hasta ahora el inicio del mismo. Debido al tiempo que me toma escribir acerca de esto, pondré más a medida que vea que hay interés de los colegas.

Esperaré tús comentarios
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
ayuda ejecutando un proceso como "SYSTEM" y haciendo que no se pueda terminar lostprophets Varios 2 05-02-2008 02:28:50
ayuda "Detectando un proceso y ejecutando otro" lostprophets Varios 1 29-01-2008 23:54:03
Error de conexion a servidor Remoto con Firebird Gaim2205 Firebird e Interbase 5 18-09-2007 21:33:00
Error al conectar la base de datos en modo Remoto oscjae Firebird e Interbase 2 26-01-2006 11:19:33
Error de memoria con proceso de Data Pump burasu Conexión con bases de datos 4 22-11-2005 11:14:22


La franja horaria es GMT +2. Ahora son las 10:37:43.


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