I'm a first traveler coding in WinApi, Hooks, COM objects. Then, I made a dll to inject (EasyHook) this in the target SIEMENS Step7 process and modify the software code at runtime: Maybe I want some opinion about this kind of practices, hooking, injection, file system driver, kernel hook, modify .exe vtable before init, interprocess-communication, etc. This code gets the `DataSource` from a Grid GUI(COM Object) when the user do a determined "Force" action through menu. using EasyHook; using Octtos.S7ussapx.Injected.COM.Interfaces; using Octtos.S7ussapx.Injected.Step7.COM.Interfaces; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; namespace Octtos.S7ussapx.Injected { public class Main : IEntryPoint { private ClientCallbackHandler _callbackHandler; [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] unsafe delegate int IDispatchInvokeDelegate(IntPtr pthis, int dispIdMember, ref Guid riid, uint lcid, ushort wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, void* ppvResult, ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo, IntPtr[] pArgErr); #region CoGetClassObject ole32.dll private LocalHook _coGetClassObjectHook; private LocalHook _S7StatusOCXIClassFacttoryCreateInstanceHook; private LocalHook _S7VarServer50IClassFacttoryCreateInstanceHook2; private bool _s7StatusOCXCOMHookCreated = false; private bool _s7VarServer50COMHookCreated = false; private IntPtr _S7StatusOCXIClassFacttoryCreateInstanceMethodPtr; private IntPtr _S7VarServer50IClassFacttoryCreateInstanceMethodPtr; private delegate uint CoGetClassObjectDelegate(ref Guid rclsid, int dwClsContext, IntPtr pServerInfo, ref Guid riid, out IntPtr ppv); [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] private delegate int IClassFactoryCreateInstanceDelegate(IntPtr pThis, IntPtr pUnkOuter, ref Guid riid, out IntPtr ppv); private static unsafe uint CoGetClassObject_Hook(ref Guid clsid, int dwClsContext, IntPtr pServerInfo, ref Guid iid, out IntPtr ppv) { var me = (Main)HookRuntimeInfo.Callback; var classObjectInstance = CoGetClassObject(ref clsid, dwClsContext, pServerInfo, ref iid); ppv = Marshal.GetIUnknownForObject(classObjectInstance); var iclassFactory = classObjectInstance as IClassFactory; if (!me._s7StatusOCXCOMHookCreated) { if (iclassFactory != null && clsid == typeof(IS7StatusOcx).GUID) { var method = typeof(IClassFactory).GetMethod("CreateInstance"); var methodVTableIdx = Marshal.GetComSlotForMethodInfo(method); int** comVTable = *(int***)ppv.ToPointer(); int* hMethod = comVTable[methodVTableIdx]; me._S7StatusOCXIClassFacttoryCreateInstanceMethodPtr = new IntPtr(hMethod); me._S7StatusOCXIClassFacttoryCreateInstanceHook = LocalHook.Create(me._S7StatusOCXIClassFacttoryCreateInstanceMethodPtr, new IClassFactoryCreateInstanceDelegate(S7StatusOCXCreateInstance_Hook), me); me._S7StatusOCXIClassFacttoryCreateInstanceHook.ThreadACL.SetExclusiveACL(new int[0]); me._s7StatusOCXCOMHookCreated = true; } } if (!me._s7VarServer50COMHookCreated) { if (iclassFactory != null && clsid == typeof(IS7VarServer50).GUID) { var method = typeof(IClassFactory).GetMethod("CreateInstance"); var methodVTableIdx = Marshal.GetComSlotForMethodInfo(method); int** comVTable = *(int***)ppv.ToPointer(); int* hMethod = comVTable[methodVTableIdx]; me._S7VarServer50IClassFacttoryCreateInstanceMethodPtr = new IntPtr(hMethod); me._S7VarServer50IClassFacttoryCreateInstanceHook2 = LocalHook.Create(me._S7VarServer50IClassFacttoryCreateInstanceMethodPtr, new IClassFactoryCreateInstanceDelegate(S7VarServer50CreateInstance_Hook), me); me._S7VarServer50IClassFacttoryCreateInstanceHook2.ThreadACL.SetExclusiveACL(new int[0]); me._s7VarServer50COMHookCreated = true; } } Marshal.ReleaseComObject(classObjectInstance); return 0; } #endregion #region S7StatusOCX IClassFactory.Create ole32.dll private IS7StatusOcxDispatch _currentInstance; [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] private delegate int IClassFactoryCreateInstanceDelegate2(IntPtr pThis, IntPtr pUnkOuter, ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object obj); private static unsafe int S7StatusOCXCreateInstance_Hook(IntPtr pThis, IntPtr pUnkOuter, ref Guid riid, out IntPtr ppv) { var me = (Main)HookRuntimeInfo.Callback; var baseMethod = (IClassFactoryCreateInstanceDelegate2)Marshal.GetDelegateForFunctionPointer(me._S7StatusOCXIClassFacttoryCreateInstanceMethodPtr, typeof(IClassFactoryCreateInstanceDelegate2)); object objInstance; var hr = baseMethod(pThis, pUnkOuter, ref riid, out objInstance); me._currentInstance = (IS7StatusOcxDispatch)objInstance; var ppv2 = Marshal.GetIUnknownForObject(objInstance); Marshal.QueryInterface(ppv2, ref riid, out ppv); return hr; } #endregion #region S7VarServer50 IClassFactory.Create ole32.dll private LocalHook _s7VarServer5IDispatchHook; private IntPtr _s7VarServer50IDispatchInvokeMethodPtr; private bool _S7VarServer50CreateInstanceHookCreated = false; private IDictionary<IntPtr, IS7StatusOcxDispatch> _s7StatusOCXDispatchInstances = new Dictionary<IntPtr, IS7StatusOcxDispatch>(); private static unsafe int S7VarServer50CreateInstance_Hook(IntPtr pThis, IntPtr pUnkOuter, ref Guid riid, out IntPtr ppv) { var me = (Main)HookRuntimeInfo.Callback; var baseMethod = (IClassFactoryCreateInstanceDelegate2)Marshal.GetDelegateForFunctionPointer(me._S7VarServer50IClassFacttoryCreateInstanceMethodPtr, typeof(IClassFactoryCreateInstanceDelegate2)); object objInstance; var hr = baseMethod(pThis, pUnkOuter, ref riid, out objInstance); var ppv2 = Marshal.GetIUnknownForObject(objInstance); Marshal.QueryInterface(ppv2, ref riid, out ppv); if (objInstance is IS7VarServer50Dispatch) { Guid iidIDispatch = typeof(IDispatch).GUID; IntPtr ppv3; Marshal.QueryInterface(ppv2, ref iidIDispatch, out ppv3); if (me._s7StatusOCXDispatchInstances.ContainsKey(ppv3)) { me._s7StatusOCXDispatchInstances[ppv3] = me._currentInstance; } else { me._s7StatusOCXDispatchInstances.Add(ppv3, me._currentInstance); } me._currentInstance = null; if (!me._S7VarServer50CreateInstanceHookCreated) { var methodVTableIdx = Marshal.GetComSlotForMethodInfo(typeof(IDispatch).GetMethod("Invoke")); int** comVTable = *(int***)ppv3.ToPointer(); int* hMethod = comVTable[methodVTableIdx]; me._s7VarServer50IDispatchInvokeMethodPtr = new IntPtr(hMethod); me._s7VarServer5IDispatchHook = LocalHook.Create(me._s7VarServer50IDispatchInvokeMethodPtr, new IDispatchInvokeDelegate(S7VarServer50IDispatch_Invoke_Hook), me); me._s7VarServer5IDispatchHook.ThreadACL.SetExclusiveACL(new int[0]); me._S7VarServer50CreateInstanceHookCreated = true; } } return hr; } //Por que esse IDispatch tem IntPtr pThis como primeiro parâmetro? Se na DOC o primeiro parâmetro dessa função é o dispIdMember?! //http://msdn.microsoft.com/en-us/library/aa912367.aspx unsafe static int S7VarServer50IDispatch_Invoke_Hook(IntPtr pthis, int dispIdMember, ref Guid riid, uint lcid, ushort wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, void* ppvResult, ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo, IntPtr[] pArgErr) { var me = (Main)HookRuntimeInfo.Callback; switch (dispIdMember) { case 14: me._callbackHandler.WriteLine("CreateForceJob() called"); break; case 15: me._callbackHandler.WriteLine("StartForceJob() called"); IS7StatusOcxDispatch instance; if (me._s7StatusOCXDispatchInstances.TryGetValue(pthis, out instance)) { string varList; instance.GetVariableList(out varList, false); var bytes = Encoding.Unicode.GetBytes(varList); var str = Encoding.Default.GetString(bytes); me._callbackHandler.WriteLine(str); } else { me._callbackHandler.WriteLine("ERROR!!! Tentou pegar uma instancia que não existia. Por que essa instância não existe?"); } break; default: break; } var baseMethod = (IDispatchInvokeDelegate)Marshal.GetDelegateForFunctionPointer(me._s7VarServer50IDispatchInvokeMethodPtr, typeof(IDispatchInvokeDelegate)); return baseMethod(pthis, dispIdMember, ref riid, lcid, wFlags, ref pDispParams, ppvResult, ref pExcepInfo, pArgErr); } #endregion public Main(RemoteHooking.IContext ctx, string channelId) { _callbackHandler = RemoteHooking.IpcConnectClient<ClientCallbackHandler>(channelId); } public unsafe void Run(RemoteHooking.IContext ctx, string arg1) { try { _coGetClassObjectHook = LocalHook.Create(LocalHook.GetProcAddress("ole32.dll", "CoGetClassObject"), new CoGetClassObjectDelegate(CoGetClassObject_Hook), this); _coGetClassObjectHook.ThreadACL.SetExclusiveACL(new int[0]); RemoteHooking.WakeUpProcess(); _callbackHandler.InjectStart(); while (true) { _callbackHandler.SetIsAlive(true); Thread.Sleep(TimeSpan.FromSeconds(2)); } } catch (Exception ex) { throw; } } [DllImport("ole32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] [return: MarshalAs(UnmanagedType.Interface)] private static extern object CoGetClassObject(ref Guid rclsid, int dwClsContext, IntPtr pServerInfo, ref Guid riid); } }