me gustaria que mi programa este a la espera hasta que un proceso determinado es llamado, una vez detectado poder modificar los argumentos que se le dan, si es que se le da alguno
¿En que lenguaje de programación lo piensas llevar a cabo?, no somos adivinos...
La tarea que pides sería extremadamente fácil de llevar a cabo con los métodos y/o componentes del lenguaje en cuestión si no fuese por que además de interceptar la llamada quieres modificar los argumentos, y eso implica técnicas de hooking, o mejor dicho
API Hooking, debes hookear la pre-llamada de la función "CreateProcess" de la librería "Kernel32.dll" de la API de Windows,
en la pre-llamada a la función debes traducir/interpretar los parámetros enviados por esta función y modificarlos, donde cómo se explica la documentación oficial de la MSDN, el parámetro '
lpCommandLine' (de tipo String) contiene los argumentos commandline:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspxNota: El primer argumento (o argumento 0) siempre debe ser la ruta del proceso.
( Quizás debas hookear también la función 'ShellExecute' de la librería 'shell32.dll' para controlar la ejecución de un proceso en ciertas circunstancias )
Existen librerías para facilitar el enrutamiento de las funciones de la API de Windows, cómo por ejemplo
Microsoft Detours para C/C++, y
EasyHook o
Nektra Deviare para C#/VB.Net;
pero si piensas llevar a cabo la tarea sin ayuda de una librería de terceros entonces te advierto que se convertirá en una tarea horriblemente laboriosa y tediosa, y, por ejemplo en lo referente a la programación .Net requerirás un nivel medio-avanzado de conocimientos sobre el P/Invoking y el hooking, cómo Delegados, Callbacks, Marshalling, e indiferentemente del lenguaje que sea tampoco etsaría demás saber utilizar técnicas de programación asíncrónicas.
A continuación te muestro un ejempo que he desarrollado en Vb.Net utilizando la librería
Deviare,
el siguiente código es un hook que se adjunta a las instancias activas del proceso "explorer.exe" y a sus procesos hijos para interceptar las llamadas a la función "CreateProcess" realizadas desde dichos procesos, si el nombre del proceso es "Notepad.exe" entonces modifico los argumentos del notepad para indicarle que cargue un archivo de texto ("C:\File.txt").
Nota: No es necesario interceptar la post-llamada de la función, pero deberías hacerlo para comprobar si hubo un error evaluando el valor de retorno de la función 'GetLastError' de la librería 'kernel32.dll" (si lo piensas hacer desde .Net entonces debes comprobar el valor de la función
GetLastWin32Error de la Class '
Marshal')
Nota 2: El código de abajo es solo un ejemplo, el hook no es persistente, es decir, si reinicias el proceso Explorer.exe dejará de funcionar.
' Nektra Deviare: "CreateProcess" hook example, By Elektro.
Imports Nektra.Deviare2
Imports System.IO
Public NotInheritable Class Form1
Public WithEvents SpyMgr As NktSpyMgr
Public Hook As NktHook
ReadOnly processesToAttach As IEnumerable(Of Process) =
Process.GetProcessesByName("explorer") '.Concat(Process.GetProcessesByName("cmd"))
ReadOnly processToIntercept As String = "notepad.exe"
ReadOnly processArgs As String = "C:\File.txt" ' Notepad will try to load that filepath.
' "CreateProcess" API reference:
' http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx
Dim libName As String = "kernel32.dll"
Dim funcName As String = "CreateProcessW" ' Unicode
Dim hookFlags As eNktHookFlags = eNktHookFlags.flgOnlyPreCall Or
eNktHookFlags.flgAutoHookChildProcess
Private Sub Test() Handles MyBase.Load
Me.SpyMgr = New NktSpyMgr()
Me.SpyMgr.Initialize()
Me.Hook = SpyMgr.CreateHook(String.Format("{0}!{1}", libName, funcName), hookFlags)
Me.Hook.Hook(sync:=True)
For Each proc As Process In processesToAttach
Me.Hook.Attach(procOrId:=proc.Id, sync:=True)
Next proc
End Sub
<MTAThread>
Private Sub OnCreateProcess_Called(ByVal hook As NktHook,
ByVal proc As NktProcess,
ByVal callInfo As NktHookCallInfo) Handles SpyMgr.OnFunctionCalled
Dim lpApplicationNameParam As NktParam = DirectCast(callInfo.Params(0), NktParam)
Dim lpCommandLineParam As NktParam = DirectCast(callInfo.Params(1), NktParam)
If Path.GetFileName(lpApplicationNameParam.Value.ToString).Equals(processToIntercept, StringComparison.OrdinalIgnoreCase) Then
lpCommandLineParam.Value = String.Format("""{0}"" ""{1}""", lpApplicationNameParam.Value.ToString, Me.processArgs)
End If
End Sub
End Class
Y, si lo que quieres es evitar que un proceso invocado mediante la función "CreateProcess" se inicie, entonces debes modificar el valor de retorno (result) de la función y despues saltar la llamada, con
Deviare puedes hacerlo así:
Private Sub OnCreateProcess_Called(ByVal hook As NktHook,
ByVal proc As NktProcess,
ByVal callInfo As NktHookCallInfo) Handles SpyMgr.OnFunctionCalled
With callInfo
If .IsPreCall Then ' Skip precall. Avoid process creation.
.Result.Value = 1
.SkipCall()
End If
End With
End Sub
Nota: Cada función de la API de Windows tiene sus valores de retorno y debes documentarte primero para saber cómo va a afectar al SO el valor de retorno que utilices.
Saludos.