public static HookRegistry Get() { if (_instance == null) { _instance = new HookRegistry(); _instance.LoadRuntimeHooks(); } return _instance; }
// Remove a hook listener public static void Unregister(Callback cb) { HookRegistry.Get().callbacks.Remove(cb); }
public static void RegisterDeclaringType(RuntimeTypeHandle typeHandle) { HookRegistry.Get().declaringTypes.Add(typeHandle); }
// Add a hook listener public static void Register(Callback cb) { HookRegistry.Get().callbacks.Add(cb); }
// First function called by modified libraries. // Return the response coming from the hook, because it's needed by the original library code ! important public static object OnCall(RuntimeMethodHandle rmh, object thisObj, object[] args) { return(HookRegistry.Get().Internal_OnCall(rmh, thisObj, args)); }
object OnCall(string typeName, string methodName, object thisObj, object[] args, IntPtr[] refArgs, int[] refIdxMatch) { if (typeName != "System.Net.Sockets.Socket" || (methodName != "EndSend" && methodName != "EndReceive")) { return(null); } // Socket is a low-level construct so we must guard ourselves robustly against race conditions. if (!ReentrantEnter(thisObj)) { return(null); } /* Actual hook code */ bool isOutgoing = methodName.EndsWith("Send"); int OPResult = 0; var dumpServer = DumpServer.Get(); // True if we need to feedback the error code returned by the proxy method. bool feedbackErrorCode = false; var thisSocket = thisObj as Socket; if (thisSocket == null) { HookRegistry.Panic("SocketHook - `thisObj` is NOT a Socket object"); } // We expect 1 referenceArgument, which makes the total passed argument equal to 2. // The argument in question is `out SocketError` if (refArgs != null && refArgs.Length == 1) { if (args.Length != 2 || refIdxMatch == null || refIdxMatch[0] != 1) { string message = String.Format("SocketHook - {0} - Got 1 reference argument, but total arguments don't match: {1} <=> 2", thisSocket.GetHashCode(), args.Length); HookRegistry.Panic(message); } else { HookRegistry.Debug("SocketHook - {0} - Valid referenced argument!", thisSocket.GetHashCode()); feedbackErrorCode = true; } } dumpServer.PreparePartialBuffers(thisSocket, false); // Fetch the asyncModel early to prevent it being cleaned up // directly after operation end. var asyncResult = args[0] as IAsyncResult; if (asyncResult == null) { HookRegistry.Panic("SocketHook - asyncResult == null"); } if (isOutgoing) { int sentBytes = (int)ProxyEndWrite(thisObj, ref args); // buffer holds the transmitted contents. // requestedBytes holds the amount of bytes requested when starting the operation. // => This amount gets decreased, towards 0, each time bytes are sent. // => The actual amount of bytes sent are found inside sentBytes. // offset is the starting offset, within buffer, of data to be written when starting // the operation. // => This amount gets increased, towards orignal value of size, each time bytes are sent. // => The actual offset would then be (offset-sentBytes)! OPResult = sentBytes; //processedBytes = sentBytes; // Update offset parameter. //offset = offset-sentBytes; } else { int readBytes = (int)ProxyEndRead(thisObj, ref args); OPResult = readBytes; //processedBytes = readBytes; } // These variables have a different meaning depending on the operation; read or write. byte[] buffer = GetAsyncBuffer(asyncResult); // Offset in buffer where relevant data starts. int offset = GetAsyncOffset(asyncResult); int requestedBytes = GetAsyncRequestedBytes(asyncResult); // Amount of bytes actually processed by the operation. int processedBytes = OPResult; if (buffer != null) { if (offset + processedBytes > buffer.Length) { offset -= processedBytes; } // HookRegistry.Log("SocketHook - {0} - writing", thisSocket.GetHashCode()); dumpServer.PartialData(thisSocket, !isOutgoing, buffer, offset, processedBytes, isWrapping: false, singleDecode: false); } else { HookRegistry.Log("SocketHook - {0} - buffer == null", thisSocket.GetHashCode()); } if (feedbackErrorCode == true) { var errorCode = (SocketError)args[1]; IntPtr errorCodePtr = refArgs[0]; HookRegistry.Debug("SocketHook - {0} - Writing `{1}` to refPtr", thisSocket.GetHashCode(), errorCode.ToString()); Marshal.StructureToPtr(errorCode, errorCodePtr, true); } ReentrantLeave(thisObj); return(OPResult); }
public ExampleHook() { HookRegistry.Register(OnCall); }
public GwentHook() { HookRegistry.Register(OnCall); }
object OnCall(string typeName, string methodName, object thisObj, object[] args, IntPtr[] refArgs, int[] refIdxMatch) { if (typeName != "System.Net.Security.SslStream" || (methodName != "EndWrite" && methodName != "EndRead")) { return(null); } if (_reentrant == true) { return(null); } /* Actual hook code */ _reentrant = true; bool isWriting = methodName.EndsWith("Write"); object OPresult = null; var dumpServer = DumpServer.Get(); int readBytes = -1; Socket underlyingSocket = GetUnderlyingSocket(thisObj); dumpServer.PreparePartialBuffers(underlyingSocket, true); // Fetch the asyncModel early to prevent it being cleaned up // directly after operation end. var asyncResult = args[0] as IAsyncResult; if (asyncResult == null) { HookRegistry.Panic("SslStreamHook - asyncResult == null"); } if (isWriting) { OPresult = ProxyEndWrite(thisObj, args); // Buffer holds written data, // offset holds offset within buffer where writing started, // count holds amount of written bytes. } else { readBytes = (int)ProxyEndRead(thisObj, args); OPresult = readBytes; // Buffer holds read data, // offset holds offset within buffer where reading started, // count holds size of buffer. //count = readBytes; // Reassigned } // These variables have a different meaning depending on the operation; read or write. byte[] buffer = GetAsyncBuffer(asyncResult); // Offset in buffer where relevant data starts. int offset = GetAsyncOffset(asyncResult); // Amount of bytes encoding the relevant data (starting from offset). int count = GetAsyncCount(asyncResult); if (!isWriting) { count = readBytes; } // We can assume the async operation succeeded. if (buffer != null) { // HookRegistry.Log("SslStreamHook - {0} - writing", underlyingSocket.GetHashCode()); dumpServer.PartialData(underlyingSocket, !isWriting, buffer, offset, count, isWrapping: true, singleDecode: false); } else { HookRegistry.Log("SslStreamHook - {0} - buffer == null!", underlyingSocket.GetHashCode()); } // Short circuit original method; this prevents executing the method twice. _reentrant = false; return(OPresult); }
public BackendSwitcher() { HookRegistry.Register(OnCall); }
public SSLDisable() { HookRegistry.Register(OnCall); }
public PacketLog() { HookRegistry.Register(OnCall); }