-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathThreadFactory.cs
More file actions
201 lines (182 loc) · 7.54 KB
/
Copy pathThreadFactory.cs
File metadata and controls
201 lines (182 loc) · 7.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Process.NET.Marshaling;
using Process.NET.Native.Types;
using Process.NET.Utilities;
namespace Process.NET.Threads
{
/// <summary>
/// Class providing tools for manipulating threads.
/// </summary>
public class ThreadFactory : IThreadFactory
{
/// <summary>
/// The reference of the <see cref="Process" /> object.
/// </summary>
protected readonly IProcess Process;
/// <summary>
/// Initializes a new instance of the <see cref="ThreadFactory" /> class.
/// </summary>
/// <param name="process">The reference of the <see cref="Process" /> object.</param>
public ThreadFactory(IProcess process)
{
// Save the parameter
Process = process;
}
/// <summary>
/// Gets the main thread of the remote process.
/// </summary>
public IRemoteThread MainThread
{
get
{
return new RemoteThread(Process,
NativeThreads.Aggregate((current, next) => next.StartTime < current.StartTime ? next : current));
}
}
/// <summary>
/// Gets the native threads from the remote process.
/// </summary>
public IEnumerable<ProcessThread> NativeThreads
{
get
{
// Refresh the process info
Process.Native.Refresh();
// Enumerates all threads
return Process.Native.Threads.Cast<ProcessThread>();
}
}
/// <summary>
/// Gets the threads from the remote process.
/// </summary>
public IEnumerable<IRemoteThread> RemoteThreads
{
get { return NativeThreads.Select(t => new RemoteThread(Process, t)); }
}
/// <summary>
/// Gets the thread corresponding to an id.
/// </summary>
/// <param name="threadId">The unique identifier of the thread to get.</param>
/// <returns>A new instance of a <see cref="RemoteThread" /> class.</returns>
public IRemoteThread this[int threadId]
{
get { return new RemoteThread(Process, NativeThreads.First(t => t.Id == threadId)); }
}
/// <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;
}
/// <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="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, bool isStarted = true)
{
//Create the thread
var ret = ThreadHelper.NtQueryInformationThread(
ThreadHelper.CreateRemoteThread(Process.Handle, address, IntPtr.Zero, ThreadCreationFlags.Suspended));
// Find the managed object corresponding to this thread
var result = new RemoteThread(Process, Process.ThreadFactory.NativeThreads.First(t => t.Id == ret.ThreadId));
// If the thread must be started
if (isStarted)
result.Resume();
return result;
}
/// <summary>
/// Creates a thread in the remote process and blocks the calling thread until the thread terminates.
/// </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>
/// <returns>A new instance of the <see cref="RemoteThread" /> class.</returns>
public IRemoteThread CreateAndJoin(IntPtr address, dynamic parameter)
{
// Create the thread
var ret = Create(address, parameter);
// Wait the end of the thread
ret.Join();
// Return the thread
return ret;
}
/// <summary>
/// Creates a thread in the remote process and blocks the calling thread until the thread terminates.
/// </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>
/// <returns>A new instance of the <see cref="RemoteThread" /> class.</returns>
public IRemoteThread CreateAndJoin(IntPtr address)
{
// Create the thread
var ret = Create(address);
// Wait the end of the thread
ret.Join();
// Return the thread
return ret;
}
/// <summary>
/// Releases all resources used by the <see cref="ThreadFactory" /> object.
/// </summary>
public void Dispose()
{
// Nothing to dispose... yet
}
/// <summary>
/// Gets a thread by its id in the remote process.
/// </summary>
/// <param name="id">The id of the thread.</param>
/// <returns>A new instance of the <see cref="RemoteThread" /> class.</returns>
public IRemoteThread GetThreadById(int id)
{
return new RemoteThread(Process, NativeThreads.First(t => t.Id == id));
}
/// <summary>
/// Resumes all threads.
/// </summary>
public void ResumeAll()
{
foreach (var thread in RemoteThreads)
thread.Resume();
}
/// <summary>
/// Suspends all threads.
/// </summary>
public void SuspendAll()
{
foreach (var thread in RemoteThreads)
thread.Suspend();
}
}
}