Cita:
Empezado por Nipx4215
...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
...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.