-
Notifications
You must be signed in to change notification settings - Fork 8
/
threading.cpp
125 lines (104 loc) · 3.73 KB
/
threading.cpp
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
#include "pch.h"
#include "threading.h"
SAVE_DEBUG_REGISTERS Threading::ArrayDebugRegister[100] = { 0 };
// TODO: Terminate thread if he's gonna be suspended only.
HANDLE Threading::CreateFakeThread(LPVOID thread) {
CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_FULL;
HANDLE tHand = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)0x0, NULL, CREATE_SUSPENDED, NULL);
if (tHand == NULL)
return NULL;
HMODULE ntdllModule = GetModuleHandleA("ntdll.dll");
if (ntdllModule == NULL) {
return NULL;
}
FARPROC getContextThread = GetProcAddress(ntdllModule, "NtGetContextThread");
if (getContextThread == NULL) {
return NULL;
}
NTSTATUS status = ((__NtGetContextThread__)(getContextThread))(tHand, &ctx);
if (status != STATUS_SUCCESS)
return NULL;
ctx.Eax = (DWORD)thread;
SetThreadContext(tHand, &ctx);
ResumeThread(tHand);
return tHand;
}
void Threading::ThreadDebugContextRemoveEntry(const int index) {
Threading::ArrayDebugRegister[index].dwThreadId = 0;
}
void Threading::ThreadRetrieveSavedContext(PCONTEXT threadContext, const int index) {
threadContext->Dr0 = Threading::ArrayDebugRegister[index].Dr0;
threadContext->Dr1 = Threading::ArrayDebugRegister[index].Dr1;
threadContext->Dr2 = Threading::ArrayDebugRegister[index].Dr2;
threadContext->Dr3 = Threading::ArrayDebugRegister[index].Dr3;
threadContext->Dr6 = Threading::ArrayDebugRegister[index].Dr6;
threadContext->Dr7 = Threading::ArrayDebugRegister[index].Dr7;
}
void Threading::ThreadDebugContextSaveContext(const int index, const PCONTEXT threadContext) {
Threading::ArrayDebugRegister[index].dwThreadId = HandleToULong(GetCurrentThreadId());
Threading::ArrayDebugRegister[index].Dr0 = threadContext->Dr0;
Threading::ArrayDebugRegister[index].Dr1 = threadContext->Dr1;
Threading::ArrayDebugRegister[index].Dr2 = threadContext->Dr2;
Threading::ArrayDebugRegister[index].Dr3 = threadContext->Dr3;
Threading::ArrayDebugRegister[index].Dr6 = threadContext->Dr6;
Threading::ArrayDebugRegister[index].Dr7 = threadContext->Dr7;
}
void Threading::ClearThreadContext(PCONTEXT threadContext) {
threadContext->Dr0 = 0;
threadContext->Dr1 = 0;
threadContext->Dr2 = 0;
threadContext->Dr3 = 0;
threadContext->Dr6 = 0;
threadContext->Dr7 = 0;
}
int Threading::ThreadDebugContextFindExistingSlotIndex() {
for (int i = 0; i < _countof(Threading::ArrayDebugRegister); i++) {
if (Threading::ArrayDebugRegister[i].dwThreadId != 0) {
if (Threading::ArrayDebugRegister[i].dwThreadId == HandleToULong(GetCurrentThreadId())) {
return i;
}
}
}
return -1;
}
int Threading::ThreadDebugContextFindFreeSlotIndex() {
for (int i = 0; i < _countof(Threading::ArrayDebugRegister); i++) {
if (Threading::ArrayDebugRegister[i].dwThreadId == 0) {
return i;
}
}
return -1;
}
uint32_t Threading::GetCurrentBreakpointAddress(const PCONTEXT threadContext) {
DWORD contextDr6 = threadContext->Dr6;
DWORD firstDrAddress = (DWORD)&threadContext->Dr0;
for (int index = 0; index < 4; index++) {
if (((contextDr6 >> index) & 1) == 1) {
return *((DWORD*)(firstDrAddress + (index * sizeof(DWORD))));
}
}
return 0;
}
int Threading::GetCurrentBreakpointIndex(const PCONTEXT threadContext) {
DWORD contextDr6 = threadContext->Dr6;
for (int index = 0; index < 4; index++) {
if (((contextDr6 >> index) & 1) == 1) {
return index;
}
}
return -1;
}
void Threading::Sleep(int milliseconds) {
clock_t time_end;
time_end = clock() + milliseconds * CLOCKS_PER_SEC / 1000;
while (clock() < time_end) {
}
}
DWORD Threading::GetProcessIdByThreadHandle(HANDLE hThread) {
THREAD_BASIC_INFORMATION tbi;
if (NT_SUCCESS(NtQueryInformationThread(hThread, (THREADINFOCLASS)ThreadBasicInformation, &tbi, sizeof(THREAD_BASIC_INFORMATION), 0))) {
return HandleToULong(tbi.ClientId.UniqueProcess);
}
return 0;
}