Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   API de Windows (https://www.clubdelphi.com/foros/forumdisplay.php?f=7)
-   -   Como saber si la aplicación fue ejecutada desde Delphi (https://www.clubdelphi.com/foros/showthread.php?t=88594)

Nipx4215 01-07-2015 02:39:13

Como saber si la aplicación fue ejecutada desde Delphi
 
Dando seguimiento a este hilo Saber si la aplicación fue ejecutada desde Delphi creo que eso ya no funciona mas con Windows Vista en Adelante.

El problema es que con UpdateProcThreadAttribute lanzan el programa con CreateProcessW en la creencia de que fué lanzado por Windows

Info vista en
Hay manera de detectar aún esto?

nlsgarcia 01-07-2015 04:18:48

Nipx4215,

¡Bienvenido al Club Delphi! :D

Nelson.

nlsgarcia 01-07-2015 07:00:50

Nipx4215,

Cita:

Empezado por Nipx4215
...Como saber si la aplicación fue ejecutada desde Delphi...

:rolleyes:

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellAPI, TlHelp32, PsAPI;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetParentProcess(PID : DWORD) : String;
var
   SnapShot : THandle;
   ProcessEntry32 : TProcessEntry32;
   PPID : DWORD;
   PPHandle : THandle;
   PPPath : PChar;

begin

   SnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   GetMem(PPPath, MAX_PATH);

   if SnapShot <> INVALID_HANDLE_VALUE then
   begin
      ProcessEntry32.dwSize := SizeOf(ProcessEntry32);
      if Process32First(SnapShot, ProcessEntry32) then
      repeat
         if ProcessEntry32.th32ProcessID = PID then
         begin
            PPID := ProcessEntry32.th32ParentProcessID;
            PPHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False,PPID);
            if PPHandle <> 0 then
            begin
               GetModuleFileNameEx(PPHandle, 0, PPPath, MAX_PATH);
               Result := PPPath;
            end
            else
               Result := EmptyStr;
            CloseHandle(PPHandle);
            Break;
         end;
      until not Process32Next(SnapShot, ProcessEntry32);
      CloseHandle(SnapShot);
   end;

   FreeMem(PPPath);

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   MessageDlg(GetParentProcess(GetCurrentProcessId),mtInformation,[mbOK],0);
end;

end.
El código anterior en Delphi 7 sobre Windows 7 Professional x32, Obtiene la ruta y nombre del proceso padre de la aplicación lo cual permite determinar desde donde fue ejecutada la misma, como se muestra en la siguiente imagen:



Espero sea útil :)

Nelson.

escafandra 02-07-2015 00:43:19

Resisa también este tema: Saber si la aplicación fue ejecutada desde Delphi

Saludos.

escafandra 02-07-2015 01:35:02

Aclaración: Ese código, funciona en Win8.1

Saludos.

Nipx4215 02-07-2015 02:06:34

Gracias por sus respuestas.

Cuando abrimos un programa con doble click el que lo lanza es el explorer.exe y con el código que mencionan se puede checar que no sea lanzado de otra aplicacion, con una simple verificacion del P.I.D. del proceso padre. El problema es que a partir de Windows vista hay unas nuevas apis que permiten indicarle al proceso lanzado cual es tu proceso padre
Cita:

Ver esta web que lo explica mas claro : Launching a non-child process
Ejemplo, alguien puede crear algo que llamaremos "programa1" y con OpenProces abrir el explorer.exe para a su vez aplicarle los atributos y lanzar una nueva aplicación que llamaremos "programa2" indicando que su procesopadre es el explorer.exe, cuando en realidad es el "programa1". Lo anterior compromete la seguridad del "programa2" aunque protejamos nuestra aplicacion, porque con el "programa1" pueden modificar nuestro código en memoria.

Espero haberme explicado, ya que pretendo detectar esto cuando ha sido lanzado mi "programa2" por "programa1" y cuando en realidad por el explorer, algun rastro debe quedar de ello

nlsgarcia 02-07-2015 02:23:21

Nipx4215,

Cita:

Empezado por Nipx4215
...pretendo detectar...cuando ha sido lanzado mi "programa2" por "programa1" y cuando en realidad por el explorer...

:rolleyes:

Pregunto : ¿Revisastes el código sugerido en el Msg #3?, en dicho mensaje se muestra desde conde se ha lanzado la aplicación.

Espero sea útil :)

Nelson.

Nipx4215 02-07-2015 02:28:05

Cita:

Empezado por nlsgarcia (Mensaje 493882)
Nipx4215,


:rolleyes:

Pregunto : ¿Revisastes el código sugerido en el Msg #3?, en dicho mensaje se muestra desde conde se ha lanzado la aplicación.

Espero sea útil :)

Nelson.


Si Gracias, desafortunadamente solo funciona en WIndows 32 bits


Edito: Perdón, me confundí el que estoy seguro que no va en 64 bits es "TH32CS_SNAPMODULE" , checaré con TH32CS_SNAPPROCESS

nlsgarcia 02-07-2015 06:14:48

Nipx4215,

Cita:

Empezado por nlsgarcia
...¿Revisastes el código sugerido en el Msg #3?...

Cita:

Empezado por Nipx4215
...desafortunadamente solo funciona en Windows 32 bits...

:rolleyes:

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellAPI, TlHelp32, PsAPI;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  function QueryFullProcessImageName(hProcess : THandle;
                                     dwFlags : DWORD;
                                     lpExeName : Pchar;
                                     lpdwSize : PDWORD) : Bool; stdCall;  external('Kernel32.dll') name 'QueryFullProcessImageNameA';

  function IsWow64Process(hProcess: THandle; Wow64Process : PBool) : Bool; stdCall; external('Kernel32.dll');

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetParentProcess(PID : DWORD) : String;
var
   SnapShot : THandle;
   ProcessEntry32 : TProcessEntry32;
   PPID : DWORD;
   PPHandle : THandle;
   PPPath : PAnsiChar;
   Size : Integer;
   IsWow64 : BOOL;

begin

   SnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if SnapShot <> INVALID_HANDLE_VALUE then
   begin

      GetMem(PPPath, MAX_PATH);
      Size := MAX_PATH;

      ProcessEntry32.dwSize := SizeOf(ProcessEntry32);

      if Process32First(SnapShot, ProcessEntry32) then
      repeat

         if ProcessEntry32.th32ProcessID = PID then
         begin

            PPID := ProcessEntry32.th32ParentProcessID;
            PPHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False,PPID);

            if PPHandle <> 0 then
            begin

               isWow64Process(GetCurrentProcess, @IsWow64);

               if IsWow64 then
                  QueryFullProcessImageName(PPHandle, 0, PPPath, @Size)
               else
                  GetModuleFileNameEx(PPHandle, 0, PPPath, Size);

               Result := PPPath;

            end
            else
               Result := EmptyStr;

            CloseHandle(PPHandle);
            Break;

         end;

      until not Process32Next(SnapShot, ProcessEntry32);

      CloseHandle(SnapShot);
      FreeMem(PPPath);

   end;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   MessageDlg(GetParentProcess(GetCurrentProcessId),mtInformation,[mbOK],0);
end;

end.
El código anterior en Delphi 7 sobre Windows 7 Professional x64, Obtiene la ruta y nombre del proceso padre de la aplicación lo cual permite determinar desde donde fue ejecutada la misma, como se muestra en la siguiente imagen:



Notas:

1- El código identifica si se esta ejecutando una aplicación de 32 bits en WOW64 para determinar como obtener la ruta y nombre del proceso padre.

2- El código fue probado en Windows 7 Professional x32 y Windows 7 Professional x64, funcionando correctamente según lo esperado.

3- Esta versión es una mejora del código propuesto en el Msg #3.

Revisa esta información:
Espero sea útil :)

Nelson.

escafandra 03-07-2015 00:54:23

Cita:

Empezado por Nipx4215 (Mensaje 493881)
...Cuando abrimos un programa con doble click el que lo lanza es el explorer.exe y con el código que mencionan se puede checar que no sea lanzado de otra aplicacion, con una simple verificacion del P.I.D. del proceso padre. El problema es que a partir de Windows vista hay unas nuevas apis que permiten indicarle al proceso lanzado cual es tu proceso padre...

Nipx4215, tienes razón. EXTENDED_STARTUPINFO_PRESENT permite en Win Vista y posteriores saltarse el UAC y ejecutar un proceso "engañando" atribuyéndolo a otro proceso padre falso.
La bandera EXTENDED_STARTUPINFO_PRESENT fuerza el uso de una estructura como esta:
Código Delphi [-]
  STARTUPINFOEX = packed record
    StartupInfo: TStartupInfo;
    lpAttributeList: PPROC_THREAD_ATTRIBUTE_LIST;
  end;
  PSTARTUPINFOEX = ^STARTUPINFOEX;

y con las APIs InitializeProcThreadAttributeList y UpdateProcThreadAttribute Crear la lista de atributos (atributo PROC_THREAD_ATTRIBUTE_PARENT_PROCESS) que permitirá a CreateProcess engañar al sistema.

He escrito una pequeña aplicación que permite realizarlo, he contrastado el código de cHackAll y el aportado por nlsgarcia, ninguno encuentra el verdadero padre del proceso hijo.
Hasta el momento no he encontrado el antídoto, aclarar que el ProcessExplorer de Sysinternals también es engañado.
Código Delphi [-]
const
  EXTENDED_STARTUPINFO_PRESENT = $00080000;
  PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = $00020000;

type
  PPROC_THREAD_ATTRIBUTE_LIST = Pointer;

  STARTUPINFOEX = packed record
    StartupInfo: TStartupInfo;
    lpAttributeList: PPROC_THREAD_ATTRIBUTE_LIST;
  end;
  PSTARTUPINFOEX = ^STARTUPINFOEX;

  function InitializeProcThreadAttributeList(lpAttributeList: PPROC_THREAD_ATTRIBUTE_LIST;
                                             dwAttributeCount, dwFlags: DWORD;
                                             var lpSize: Cardinal): Boolean; stdcall; external 'kernel32.dll';

  function UpdateProcThreadAttribute(lpAttributeList: PPROC_THREAD_ATTRIBUTE_LIST;
                                     dwFlags, Attribute: DWORD;
                                     var pValue: DWORD;
                                     cbSize: Cardinal;
                                     pPreviousValue: Pointer;
                                     pReturnSize: PCardinal): BOOL; stdcall; external 'kernel32.dll';

  procedure DeleteProcThreadAttributeList(lpAttributeList: PPROC_THREAD_ATTRIBUTE_LIST); stdcall; external 'Kernel32.dll';

function GetProcessId(FileName: String): DWORD;
var
   proc: TProcessEntry32;
   hSysSnapshot: THandle;
begin
   proc.dwSize := SizeOf(TProcessEntry32);
   hSysSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   if (hSysSnapshot <> INVALID_HANDLE_VALUE) and Process32First(hSysSnapshot, proc) then
   begin
     repeat
       if String(proc.szExeFile) = FileName then
       begin
         Result:= proc.th32ProcessID;
         break;
       end;
     until not (Process32Next(hSysSnapshot, proc));
   end;
   CloseHandle(hSysSnapshot);
end;

function CeateChildProcess(ExeName, ParentProcess: string): BOOL;
var
  pi: TProcessInformation;
  si: STARTUPINFOEX;
  Size: Cardinal;
  hParent: Cardinal;
begin
  Result:= false;

  FillChar(si, SizeOf(si), 0);
  si.StartupInfo.cb := sizeof(si);
  FillChar(pi, sizeof(pi), 0);
      
  Size := 0;
  InitializeProcThreadAttributeList(nil, 1, 0, Size);
  si.lpAttributeList:= HeapAlloc(GetProcessHeap(), 0, Size);
  InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, Size);
  hParent := OpenProcess(PROCESS_ALL_ACCESS, False, GetProcessID(ParentProcess));
  UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, hParent, sizeof(hParent), nil, nil);

  if CreateProcess(nil, PChar(ExeName), nil, nil, False, EXTENDED_STARTUPINFO_PRESENT, nil, nil, (PSTARTUPINFO(@si))^, pi) then
  begin
    Result:= true;
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  end;

  DeleteProcThreadAttributeList(si.lpAttributeList);
  HeapFree(GetProcessHeap(), 0, si.lpAttributeList);
end;
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  CeateChildProcess(Edit1.Text, 'Explorer.exe');
end;

Subo un binario compilado para pruebas, he elegido que el padre sea Explorer.exe porque es lo más habitual en procesos de escritorio: ExecuteWithParent

Cita:

Empezado por Nipx4215 (Mensaje 493881)
...Lo anterior compromete la seguridad del "programa2" aunque protejamos nuestra aplicacion, porque con el "programa1" pueden modificar nuestro código en memoria...

En realidad un proceso puede modificar la memoria de otro, independientemente de quién lo haya creado. Pero si pretendes basar una protección de algún componente en el hecho de que se ejecute o no desde el IDE, quizás estés en un apuro, a no ser que exista una solución al problema de encontrar el verdadero padre de la criatura. De todas formas ten en cuenta que siempre se podrá encontrar un antídoto para dicha protección.


Saludos.

escafandra 03-07-2015 01:36:58

Se me olvidaba un detalle importante, el código anterior no funciona si se ejecuta desde el IDE, una vez compilado debe ser ejecutado desde el mismo explorer.


Saludos.

Nipx4215 03-07-2015 01:46:53

Gracias a ambos, sigo haciendo pruebas

@escafandra solo que debe ser explorer.exe en lugar de Explorer.exe porque si no falla

tambien hay una manera mas fiable de encontrar al explorer real, porque explorer puede haber muchos que no son precisamente explorer, digamos abrir con openprocess el proceso padre de ExecuteWithParent.exe y automáticamente sería el explorer

sigo investigando, les cuento si encuentro algo

Nipx4215 03-07-2015 06:26:42

Cita:

MSDN
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
Los atributos heredados del proceso especificado incluyen handles, device map, processor affinity, priority, quotas, process token y job object. (Algunos atributos, como el debug port vendrán del proceso de creación, no el proceso especificado por este handle.)
La pregunta sería que otros atributos no se heredan por esta forma, msdn no especifica más

nlsgarcia 03-07-2015 08:10:38

escafandra,

Cita:

Empezado por escafandra
...el código anterior no funciona si se ejecuta desde el IDE, una vez compilado debe ser ejecutado desde el mismo explorer...

:rolleyes:

En las pruebas realizadas con Delphi 7 sobre Windows 7 Professional x32 con el código del Msg #10, este funciono correctamente desde el IDE y de forma independientemente, con la salvedad de que el ParentProcess en este caso debe ser explorer.exe en lugar de Explorer.exe

Saludos,

Nelson.

nlsgarcia 03-07-2015 08:18:06

Nipx4215,

Cita:

Empezado por escafandra
...En realidad un proceso puede modificar la memoria de otro, independientemente de quién lo haya creado...

Cita:

Empezado por escafandra
...si pretendes basar una protección de algún componente en el hecho de que se ejecute o no desde el IDE, quizás estés en un apuro, a no ser que exista una solución al problema de encontrar el verdadero padre...

Cita:

Empezado por Nipx4215
...sigo investigando...

:rolleyes:

Pregunto : ¿Has considerado hacer un hash a explorer.exe y verificar el mismo en tu proceso? :confused:

Revisa este código:
Código Delphi [-]
  unit Unit1;
  
  interface
  
  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls, IdHashMessageDigest, IdHash, IdHashSHA1;
  
  type
    TForm1 = class(TForm)
      Button1: TButton;
      Button2: TButton;
      procedure Button1Click(Sender: TObject);
      procedure Button2Click(Sender: TObject);
    private
      { Private declarations }
    public
      { Public declarations }
    end;
  
  var
    Form1: TForm1;
  
  implementation
  
  {$R *.dfm}
  
  function GetMD5(const FileName : String): String;
  var
     MD5 : TIdHashMessageDigest5;
     FS : TFileStream;
  begin
     Result := EmptyStr;
     MD5 := TIdHashMessageDigest5.Create;
     FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
     try
        Result := MD5.HashStreamAsHex(FS);
     finally
        MD5.Free;
        FS.Free;
     end;
  end;
  
  function GetSHA1(const FileName : String): String;
  var
     SHA1 : TIdHashSHA1;
     FS : TFileStream;
  begin
     Result := EmptyStr;
     SHA1 := TIdHashSHA1.Create;
     FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
     try
        Result := SHA1.HashStreamAsHex(FS);
     finally
        SHA1.Free;
        FS.Free;
     end;
  end;
  
  procedure TForm1.Button1Click(Sender: TObject);
  var
     FileName : String;
     MsgUsr, Title : String;
  begin
     FileName := 'C:\Windows\explorer.exe';
     MsgUsr := GetMD5(FileName);
     Title := 'MD5 ' + FileName;
     MessageBox(Handle, PChar(MsgUsr), PChar(Title), MB_OK + MB_ICONINFORMATION);
  end;
  
  procedure TForm1.Button2Click(Sender: TObject);
  var
     FileName : String;
     MsgUsr, Title : String;
  begin
     FileName := 'C:\Windows\explorer.exe';
     MsgUsr := GetSHA1(FileName);
     Title := 'SHA1 ' + FileName;
     MessageBox(Handle, PChar(MsgUsr), PChar(Title), MB_OK + MB_ICONINFORMATION);
  end;
  
  end.
El código anterior en Delphi 2010 sobre Windows 7 Professional x32, Permite calcular un Hash MD5 y SHA1 a un archivo seleccionado, como se muestra en la siguiente imagen:



Nota: La idea en este caso particular, es calcular el hash de explorer.exe y guardarlo dentro de la aplicación para que esta pueda verificar si efectivamente corresponde al hash del proceso padre actual.

Revisa esta información:
Espero sea útil :)

Nelson.

escafandra 03-07-2015 12:46:09

Cita:

Empezado por Nipx4215 (Mensaje 493923)
...escafandra solo que debe ser explorer.exe en lugar de Explorer.exe...
...explorer puede haber muchos que no son precisamente explorer...

Tienes razón, el tema fue experimentar con distintos procesos padre y no supeditarlo solo a explorer. Un cambio a última hora me llevó a poner Explorer. Explorer hay muchos pero para experimentar es irrelevante quien sea el padre, a no ser que tengas un interés especial en el tema.

Cita:

Empezado por nlsgarcia (Mensaje 493932)
...En las pruebas realizadas con Delphi 7 sobre Windows 7 Professional x32 con el código del Msg #10, este funciono correctamente desde el IDE y de forma independientemente...

En delphi7 bajo Win 8.1 no me ha funcionado, probablemente por las opciones de compatibilidad del nuevo S.O. es por lo que avisé de no correr bajo IDE

Cita:

Empezado por nlsgarcia (Mensaje 493933)
¿Has considerado hacer un hash a explorer.exe y verificar el mismo en tu proceso?

Puede ser una buena idea, pero el archivo no va a ser el mismo según la versión del S.O. y además no se está a salvo de que M$ lo cambie en una actualización. Por otro lado, no sabemos lo que pretende realmente Nipx4215, si descartar como padre al explorer u otro proceso, en cuyo caso quizás es hash sea más "estable"...:rolleyes:, o no.


Lo ideal sería encontrar el verdadero padre.


Saludos.

nlsgarcia 04-07-2015 05:54:54

Nipx4215,

Cita:

Empezado por escafandra
...Lo ideal sería encontrar el verdadero padre...

Es correcto ^\||/

Cita:

Empezado por escafandra
...Por otro lado, no sabemos lo que pretende realmente Nipx4215, si descartar como padre al explorer u otro proceso...

:rolleyes:

Pregunto:

1- ¿Que versión de Delphi y Windows (x32/x64) vas a utilizar para el problema en cuestión?.

2- ¿Puedes describir que tipo de aplicación utilizara este tipo de verificación y por que es necesaria?.

Espero sea útil :)

Nelson.

Nipx4215 04-07-2015 20:47:25

Hola

1.-Sería delphi 7, win7 x64
2.-Es solo evitar que sea lanzado con un programa diferente al explorer, hasta ahorita al programa no han podido desempacarlo, y la única manera que lo pueden atacar es en memoria. Por eso se quiere evitar esto.

nlsgarcia 04-07-2015 21:41:01

Nipx4215,

Cita:

Empezado por Nipx4215
...hasta ahorita al programa no han podido desempacarlo, y la única manera que lo pueden atacar es en memoria...

:rolleyes:

Pregunto:

1- ¿Que significa que no han podido desempacarlo? :confused:

2- ¿Podrías explicar cual es la función de esta aplicación?.

Espero sea útil :)

Nelson.

escafandra 04-07-2015 21:49:15

Añado otra pregunta: ¿Deseas evitar que lo lancen con un depurador (debugger)?

Saludos.


La franja horaria es GMT +2. Ahora son las 18:09:12.

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