/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A variable to be passed to the thread function.</param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread"/> class.</returns> public RemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true) { // Marshal the parameter var marshalledParameter = MarshalValue.Marshal(MemorySharp, parameter); //Create the thread var ret = ThreadCore.NtQueryInformationThread( ThreadCore.CreateRemoteThread(MemorySharp.Handle, address, marshalledParameter.Reference, ThreadCreationFlags.Suspended)); // Get the native thread previously created // Loop until the native thread is retrieved ProcessThread nativeThread; do { nativeThread = MemorySharp.Threads.NativeThreads.FirstOrDefault(t => ret.ClientIdStruct.UniqueThread.IsEqual(t.Id)); } while (nativeThread == null); // Find the managed object corresponding to this thread var result = new RemoteThread(MemorySharp, nativeThread, marshalledParameter); // If the thread must be started if (isStarted) { result.Resume(); } return(result); }
/// <summary> /// Executes the assembly code located in the remote process at the specified address. /// </summary> /// <param name="address">The address where the assembly code is located.</param> /// <param name="callingConvention">The calling convention used to execute the assembly code with the parameters.</param> /// <param name="parameters">An array of parameters used to execute the assembly code.</param> /// <returns>The return value is the exit code of the thread created to execute the assembly code.</returns> public T Execute <T>(IntPtr address, Native.Types.CallingConventions callingConvention, params dynamic[] parameters) { // Marshal the parameters var marshalledParameters = parameters.Select(p => MarshalValue.Marshal(Process, p)).Cast <IMarshalledValue>().ToArray(); // Start a transaction AssemblyTransaction t; using (t = BeginTransaction()) { // Get the object dedicated to create mnemonics for the given calling convention var calling = CallingConventionSelector.Get(callingConvention); // Push the parameters t.AddLine(calling.FormatParameters(marshalledParameters.Select(p => p.Reference).ToArray())); // Call the function t.AddLine(calling.FormatCalling(address)); // Clean the parameters if (calling.Cleanup == CleanupTypes.Caller) { t.AddLine(calling.FormatCleaning(marshalledParameters.Length)); } // Add the return mnemonic t.AddLine("retn"); } // Clean the marshalled parameters foreach (var parameter in marshalledParameters) { parameter.Dispose(); } // Return the exit code return(t.GetExitCode <T>()); }
public void MarshalChar() { // Arrange var sharp = Resources.MemorySharp; const char value = 'A'; // Act using (var pointer = MarshalValue.Marshal(sharp, value)) { // Assert Assert.AreEqual(0x41, pointer.Reference.ToInt32()); } Resources.EndTests(sharp); }
public void MarshalBoolean() { // Arrange var sharp = Resources.MemorySharp; const bool value = true; // Act using (var pointer = MarshalValue.Marshal(sharp, value)) { // Assert Assert.AreEqual(0x1, pointer.Reference.ToInt32()); } Resources.EndTests(sharp); }
public void MarshalFloat() { // Arrange var sharp = Resources.MemorySharp; const float value = 1024f; // Act using (var pointer = MarshalValue.Marshal(sharp, value)) { // Assert Assert.AreEqual(0x44800000, pointer.Reference.ToInt32()); } Resources.EndTests(sharp); }
public void MarshalInteger() { // Arrange var sharp = Resources.MemorySharp; const int value = 1024; // Act using (var pointer = MarshalValue.Marshal(sharp, value)) { // Assert Assert.AreEqual(value, pointer.Reference.ToInt32()); } Resources.EndTests(sharp); }
public void MarshalString() { // Arrange var sharp = Resources.MemorySharp; const string path = "If you read that, you're *really* like unit tests."; // Act using (var pointer = MarshalValue.Marshal(sharp, path)) { // Assert Assert.AreEqual(path, pointer.Allocated.ReadString(0)); } Resources.EndTests(sharp); }
public void Marshal_CustomStruct() { // Arrange var sharp = Resources.MemorySharp; var value = Resources.CustomStruct; // Act using (var pointer = MarshalValue.Marshal(sharp, value)) { // Assert Assert.AreEqual(Resources.CustomStruct.X, pointer.Allocated.Read <int>(0)); Assert.AreEqual(Resources.CustomStruct.Y, pointer.Allocated.Read <int>(4)); Assert.AreEqual(Resources.CustomStruct.Z, pointer.Allocated.Read <int>(8)); } Resources.EndTests(sharp); }
public RemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true) { var marshalledParameter = MarshalValue.Marshal(m_Process, parameter); ThreadHelper.CreateRemoteThread(m_Process.Handle, address, marshalledParameter.Reference, out int threadId, ThreadCreationFlags.Suspended); ProcessThread nativeThread; do { nativeThread = m_Process.Threads.NativeThreads.FirstOrDefault(t => t.Id == threadId); } while (nativeThread == null); var result = new RemoteThread(m_Process, nativeThread, marshalledParameter); if (isStarted) { result.Resume(); } return(result); }
/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A variable to be passed to the thread function.</param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread"/> class.</returns> public RemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true) { // Marshal the parameter var marshalledParameter = MarshalValue.Marshal(MemorySharp, parameter); //Create the thread var ret = ThreadCore.NtQueryInformationThread( ThreadCore.CreateRemoteThread(MemorySharp.Handle, address, marshalledParameter.Reference, ThreadCreationFlags.Suspended)); // Find the managed object corresponding to this thread var result = new RemoteThread(MemorySharp, MemorySharp.Threads.NativeThreads.First(t => t.Id == ret.ThreadId), marshalledParameter); // If the thread must be started if (isStarted) { result.Resume(); } return(result); }
/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A variable to be passed to the thread function.</param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread" /> class.</returns> public IRemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true) { // Marshal the parameter var marshalledParameter = MarshalValue.Marshal(_process, parameter); //Create the thread var ret = ThreadHelper.NtQueryInformationThread( ThreadHelper.CreateRemoteThread(_process.Handle, address, marshalledParameter.Reference, ThreadCreationFlags.Suspended)); // Find the managed object corresponding to this thread var result = new RemoteThread(_process, _process.ThreadFactory.NativeThreads.First(t => t.Id == ret.ThreadId), marshalledParameter); if (isStarted) { result.Resume(); } return(result); }
public T Execute <T>(IntPtr address, CallingConvention callingConvention, params dynamic[] parameters) { var marshalledParameters = parameters.Select(p => MarshalValue.Marshal(m_Process, p)).Cast <IMarshalledValue>().ToArray(); var calling = callingConvention == CallingConvention.Default ? CallingConventionSelector.Get(m_Process.Is64Bit ? CallingConvention.FastCall64 : CallingConvention.StdCall) : CallingConventionSelector.Get(m_Process.Is64Bit ? CallingConvention.FastCall64 : callingConvention); AssemblyTransaction t; using (t = BeginTransaction()) { t.Add(calling.FormatCall(address, marshalledParameters.Select(p => p.Reference).ToArray())); } foreach (var parameter in marshalledParameters) { parameter.Dispose(); } return(t.GetExitCode <T>()); }
/// <summary> /// Creates a thread that runs in the remote process. /// </summary> /// <param name="address"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A variable to be passed to the thread function.</param> /// <param name="isStarted">Sets if the thread must be started just after being created.</param> /// <returns>A new instance of the <see cref="RemoteThread" /> class.</returns> public IRemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true) { // Marshal the parameter var marshalledParameter = MarshalValue.Marshal(Process, parameter); //Create the thread var ret = ThreadHelper.NtQueryInformationThread( ThreadHelper.CreateRemoteThread(Process.Handle, address, marshalledParameter.Reference, ThreadCreationFlags.Suspended)); // Find the managed object corresponding to this thread // TODO (int) cast may be unnecessary and/or problematic. Suggest coming back for proper fix later var result = new RemoteThread(Process, NativeThreads.First(t => t.Id == (int)ret.ClientId.UniqueThread), marshalledParameter); // If the thread must be started if (isStarted) { result.Resume(); } return(result); }
/// <summary>Calls method <paramref name="method" /> in SuperMemo</summary> /// <param name="method">The method to call</param> /// <param name="parameters">The method's parameters to pass along with the call</param> /// <returns> /// The returned value (eax register) from the call to <paramref name="method" /> /// </returns> protected int CallNativeMethod(NativeMethod method, dynamic[] parameters) { SMA.Debug($"Executing native method {Enum.GetName(typeof(NativeMethod), method)}."); if (parameters == null) { OnException(new ArgumentNullException(nameof(parameters), $"CallNativeMethod: Called with null 'parameters' for method {method}")); return(-1); } // Possible null reference on parameters var marshalledParameters = new IMarshalledValue[parameters.Length]; for (var i = 0; i < parameters.Length; i++) { var p = parameters[i]; var dynMarshalled = MarshalValue.Marshal(_smProcess, p); if (dynMarshalled is IMarshalledValue marshalled) { marshalledParameters[i] = marshalled; } else { OnException(new ArgumentException($"CallNativeMethod: Parameter n°{i} '{p}' could not be marshalled for method {method}", nameof(p))); return(-1); } } try { switch (method) { case NativeMethod.AppendAndAddElementFromText: var elWdw = marshalledParameters[0].Reference.ToInt32(); var elType = marshalledParameters[1].Reference.ToInt32(); var elDesc = marshalledParameters[2].Reference.ToInt32(); // elWdw.AppendElement(elType, automatic: false); int elemId = Delphi.registerCall3(_callTable[NativeMethod.ElWdw_AppendElement], elWdw, elType, 0); if (elemId <= 0) { return(-1); } // elWdw.AddElementFromText(elDesc); int res = Delphi.registerCall2(_callTable[NativeMethod.ElWdw_AddElementFromText], elWdw, elDesc); return(res > 0 ? elemId : -1); case NativeMethod.PostponeRepetition: elWdw = marshalledParameters[0].Reference.ToInt32(); var interval = marshalledParameters[1].Reference.ToInt32(); // elWdw.ExecuteUncommittedRepetition(inclTopics: true, forceDisplay: false); Delphi.registerCall3(_callTable[NativeMethod.ElWdw_ExecuteUncommittedRepetition], elWdw, 1, 0); // elWdw.ScheduleInInterval(interval); Delphi.registerCall2(_callTable[NativeMethod.ElWdw_ScheduleInInterval], elWdw, interval); // elWdw.SetElementState(DisplayState.Display); //registerCall2(_callTable[NativeMethod.ElWdw_SetElementState], // elWdw, // 2); // elWdw.NextElementInLearningQueue() Delphi.registerCall1(_callTable[NativeMethod.ElWdw_NextElementInLearningQueue], elWdw); return(1); case NativeMethod.ForceRepetitionAndResume: elWdw = marshalledParameters[0].Reference.ToInt32(); interval = marshalledParameters[1].Reference.ToInt32(); var adjustPriority = marshalledParameters[2].Reference.ToInt32(); // elWdw.ForceRepetitionExt(interval, adjustPriority); Delphi.registerCall3(_callTable[NativeMethod.ElWdw_ForceRepetitionExt], elWdw, interval, adjustPriority); // elWdw.NextElementInLearningQueue(); Delphi.registerCall1(_callTable[NativeMethod.ElWdw_NextElementInLearningQueue], elWdw); // elWdw.RestoreLearningMode(); Delphi.registerCall1(_callTable[NativeMethod.ElWdw_RestoreLearningMode], elWdw); return(1); } switch (parameters.Length) { case 1: return(Delphi.registerCall1(_callTable[method], marshalledParameters[0].Reference.ToInt32())); case 2: return(Delphi.registerCall2(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32())); case 3: return(Delphi.registerCall3(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32())); case 4: return(Delphi.registerCall4(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32())); case 5: return(Delphi.registerCall5(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32())); case 6: return(Delphi.registerCall6(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32(), marshalledParameters[5].Reference.ToInt32())); default: throw new NotImplementedException($"No execution path to handle {parameters.Length} parameters."); } } finally { foreach (var param in marshalledParameters) { param.Dispose(); } } }
protected int CallNativeMethod(NativeMethod method, dynamic[] parameters) { var marshalledParameters = parameters.Select(p => MarshalValue.Marshal(_smProcess, p)) .Cast <IMarshalledValue>().ToArray(); try { switch (method) { case NativeMethod.AppendAndAddElementFromText: var elWdw = marshalledParameters[0].Reference.ToInt32(); var elType = marshalledParameters[1].Reference.ToInt32(); var elDesc = marshalledParameters[2].Reference.ToInt32(); // elWdw.AppendElement(elType, automatic: false); int elemId = Delphi.registerCall3(_callTable[NativeMethod.ElWdwAppendElement], elWdw, elType, 0); if (elemId <= 0) { return(-1); } // elWdw.AddElementFromText(elDesc); int res = Delphi.registerCall2(_callTable[NativeMethod.ElWdwAddElementFromText], elWdw, elDesc); return(res > 0 ? elemId : -1); case NativeMethod.PostponeRepetition: elWdw = marshalledParameters[0].Reference.ToInt32(); var interval = marshalledParameters[1].Reference.ToInt32(); // elWdw.ExecuteUncommitedRepetition(inclTopics: true, forceDisplay: false); Delphi.registerCall3(_callTable[NativeMethod.ElWdwExecuteUncommitedRepetition], elWdw, 1, 0); // elWdw.ScheduleInInterval(interval); Delphi.registerCall2(_callTable[NativeMethod.ElWdwScheduleInInterval], elWdw, interval); // elWdw.SetElementState(DisplayState.Display); //registerCall2(_callTable[NativeMethod.ElWdwSetElementState], // elWdw, // 2); // elWdw.NextElementInLearningQueue() Delphi.registerCall1(_callTable[NativeMethod.ElWdwNextElementInLearningQueue], elWdw); return(1); case NativeMethod.ForceRepetitionAndResume: elWdw = marshalledParameters[0].Reference.ToInt32(); interval = marshalledParameters[1].Reference.ToInt32(); var adjustPriority = marshalledParameters[2].Reference.ToInt32(); // elWdw.ForceRepetitionExt(interval, adjustPriority); Delphi.registerCall3(_callTable[NativeMethod.ElWdwForceRepetitionExt], elWdw, interval, adjustPriority); // elWdw.NextElementInLearningQueue(); Delphi.registerCall1(_callTable[NativeMethod.ElWdwNextElementInLearningQueue], elWdw); // elWdw.RestoreLearningMode(); Delphi.registerCall1(_callTable[NativeMethod.ElWdwRestoreLearningMode], elWdw); return(1); } switch (parameters.Length) { case 1: return(Delphi.registerCall1(_callTable[method], marshalledParameters[0].Reference.ToInt32())); case 2: return(Delphi.registerCall2(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32())); case 3: return(Delphi.registerCall3(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32())); case 4: return(Delphi.registerCall4(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32())); case 5: return(Delphi.registerCall5(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32())); case 6: return(Delphi.registerCall6(_callTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32(), marshalledParameters[5].Reference.ToInt32())); default: throw new NotImplementedException($"No execution path to handle {parameters.Length} parameters."); } } finally { foreach (var param in marshalledParameters) { param.Dispose(); } } }
protected int CallNativeMethod(NativeMethod method, dynamic[] parameters) { var marshalledParameters = parameters.Select(p => MarshalValue.Marshal(SMProcess, p)) .Cast <IMarshalledValue>().ToArray(); try { switch (method) { case NativeMethod.AppendAndAddElementFromText: var elWdw = marshalledParameters[0].Reference.ToInt32(); var elType = marshalledParameters[1].Reference.ToInt32(); var elDesc = marshalledParameters[2].Reference.ToInt32(); int elemId = registerCall3(CallTable[NativeMethod.ElWdwAppendElement], elWdw, elType, 0); if (elemId <= 0) { return(-1); } int res = registerCall2(CallTable[NativeMethod.ElWdwAddElementFromText], elWdw, elDesc); return(res > 0 ? elemId : -1); } switch (parameters.Length) { case 1: return(registerCall1(CallTable[method], marshalledParameters[0].Reference.ToInt32())); case 2: return(registerCall2(CallTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32())); case 3: return(registerCall3(CallTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32())); case 4: return(registerCall4(CallTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32())); case 5: return(registerCall5(CallTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32())); case 6: return(registerCall6(CallTable[method], marshalledParameters[0].Reference.ToInt32(), marshalledParameters[1].Reference.ToInt32(), marshalledParameters[2].Reference.ToInt32(), marshalledParameters[3].Reference.ToInt32(), marshalledParameters[4].Reference.ToInt32(), marshalledParameters[5].Reference.ToInt32())); default: throw new NotImplementedException($"No execution path to handle {parameters.Length} parameters."); } } finally { foreach (var param in marshalledParameters) { param.Dispose(); } } }