-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathmain.cpp
142 lines (112 loc) · 4.07 KB
/
main.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <windows.h>
// list all PIDs and TIDs
#include <tlhelp32.h>
#include <Psapi.h>
#include "ntinfo.h"
std::vector<DWORD> threadList(DWORD pid);
DWORD GetThreadStartAddress(HANDLE processHandle, HANDLE hThread);
int main(int argc, char** argv) {
std::string pid = argv[1];
DWORD dwProcID;
std::stringstream stringstream(pid);
stringstream >> std::dec >> dwProcID;
if (!dwProcID) {
std::cerr << pid << " is not a valid process id (PID)" << std::endl;
return EXIT_FAILURE;
}
HANDLE hProcHandle = NULL;
printf("PID %d (0x%x)\n", dwProcID, dwProcID);
std::cout << "Grabbing handle" << std::endl;
hProcHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcID);
if (hProcHandle == INVALID_HANDLE_VALUE || hProcHandle == NULL) {
std::cerr << "Failed to open process -- invalid handle" << std::endl;
std::cerr << "Error code: " << GetLastError() << std::endl;
return EXIT_FAILURE;
}
else {
std::cout << "Success" << std::endl;
}
std::vector<DWORD> threadId = threadList(dwProcID);
int stackNum = 0;
for (auto it = threadId.begin(); it != threadId.end(); ++it) {
HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, *it);
DWORD threadStartAddress = GetThreadStartAddress(hProcHandle, threadHandle);
printf("TID: 0x%04x = THREADSTACK%2d BASE ADDRESS: 0x%04x\n", *it, stackNum, threadStartAddress);
stackNum++;
}
return EXIT_SUCCESS;
}
std::vector<DWORD> threadList(DWORD pid) {
/* solution from http://stackoverflow.com/questions/1206878/enumerating-threads-in-windows */
std::vector<DWORD> vect = std::vector<DWORD>();
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (h == INVALID_HANDLE_VALUE)
return vect;
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
if (te.th32OwnerProcessID == pid) {
printf("PID: %04d Thread ID: 0x%04x\n", te.th32OwnerProcessID, te.th32ThreadID);
vect.push_back(te.th32ThreadID);
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
return vect;
}
DWORD GetThreadStartAddress(HANDLE processHandle, HANDLE hThread) {
/* rewritten from https://github.com/cheat-engine/cheat-engine/blob/master/Cheat%20Engine/CEFuncProc.pas#L3080 */
DWORD used = 0, ret = 0;
DWORD stacktop = 0, result = 0;
MODULEINFO mi;
GetModuleInformation(processHandle, GetModuleHandle("kernel32.dll"), &mi, sizeof(mi));
stacktop = (DWORD)GetThreadStackTopAddress_x86(processHandle, hThread);
/* The stub below has the same result as calling GetThreadStackTopAddress_x86()
change line 54 in ntinfo.cpp to return tbi.TebBaseAddress
Then use this stub
*/
//LPCVOID tebBaseAddress = GetThreadStackTopAddress_x86(processHandle, hThread);
//if (tebBaseAddress)
// ReadProcessMemory(processHandle, (LPCVOID)((DWORD)tebBaseAddress + 4), &stacktop, 4, NULL);
/* rewritten from 32 bit stub (line3141)
Result: fail -- can't get GetThreadContext()
*/
//CONTEXT context;
//LDT_ENTRY ldtentry;
//GetModuleInformation(processHandle, LoadLibrary("kernel32.dll"), &mi, sizeof(mi));
//
//if (GetThreadContext(processHandle, &context)) {
//
// if (GetThreadSelectorEntry(hThread, context.SegFs, &ldtentry)) {
// ReadProcessMemory(processHandle,
// (LPCVOID)( (DWORD*)(ldtentry.BaseLow + ldtentry.HighWord.Bytes.BaseMid << ldtentry.HighWord.Bytes.BaseHi << 24) + 4),
// &stacktop,
// 4,
// NULL);
// }
//}
CloseHandle(hThread);
if (stacktop) {
//find the stack entry pointing to the function that calls "ExitXXXXXThread"
//Fun thing to note: It's the first entry that points to a address in kernel32
DWORD* buf32 = new DWORD[4096];
if (ReadProcessMemory(processHandle, (LPCVOID)(stacktop - 4096), buf32, 4096, NULL)) {
for (int i = 4096 / 4 - 1; i >= 0; --i) {
if (buf32[i] >= (DWORD)mi.lpBaseOfDll && buf32[i] <= (DWORD)mi.lpBaseOfDll + mi.SizeOfImage) {
result = stacktop - 4096 + i * 4;
break;
}
}
}
delete buf32;
}
return result;
}