-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathGRETunnel.cpp
194 lines (158 loc) · 5.21 KB
/
GRETunnel.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
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
#include <iostream>
#include <winsock2.h>
#include <wintun.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include <mstcpip.h>
#include <WS2tcpip.h>
#include <thread>
#include <filesystem>
#include <Dbghelp.h>
#include "include/wintun.h"
#include "wintun_helper.h"
#include "GRE.h"
#include "easylogging++.h"
#include "wintun.h"
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Iphlpapi.lib")
bool reset_adapter = false;
GRE* gre;
WINTUN_ADAPTER_HANDLE Adapter;
WINTUN_SESSION_HANDLE Session;
void configure_logging() {
el::Configurations conf;
conf.setToDefault();
conf.set(el::Level::Global, el::ConfigurationType::ToFile, "true");
conf.set(el::Level::Global, el::ConfigurationType::Filename, "./gre.log");
conf.setGlobally(el::ConfigurationType::Format, "%datetime{%d/%M/%Y %H:%m:%s} [%level] %msg");
el::Loggers::reconfigureLogger("default", conf);
}
void make_minidump(EXCEPTION_POINTERS* e)
{
auto hDbgHelp = LoadLibraryA("dbghelp");
if (hDbgHelp == nullptr)
return;
auto pMiniDumpWriteDump = (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if (pMiniDumpWriteDump == nullptr)
return;
char name[MAX_PATH];
{
auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH);
SYSTEMTIME t;
GetSystemTime(&t);
wsprintfA(nameEnd - strlen(".exe"),
"_%4d%02d%02d_%02d%02d%02d.dmp",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
}
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return;
MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = e;
exceptionInfo.ClientPointers = FALSE;
auto dumped = pMiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
e ? &exceptionInfo : nullptr,
nullptr,
nullptr);
CloseHandle(hFile);
return;
}
LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e)
{
make_minidump(e);
return EXCEPTION_CONTINUE_SEARCH;
}
INITIALIZE_EASYLOGGINGPP
int main(int argc, char* argv[])
{
SetUnhandledExceptionFilter(unhandled_handler);
std::cout << "GRE Tunnel for Windows" << std::endl << std::endl;
if (argc < 5 || argc > 7) {
std::cerr << "At least 2 arguments must be given" << std::endl <<
"Arguments: gre_tunnel.exe GRE_BIND_IP GRE_SERVER INTERFACE_IP GATEWAY_IP [CIDR (30)] [ADAPTER_NAME]" << std::endl;
return 0;
}
configure_logging();
LOG(DEBUG) << "Starting GRE Application";
const char* gre_bind_ip = argv[1];
const char* server_ip = argv[2];
const char* bind_ip = argv[3];
const char* gateway_ip = argv[4];
const wchar_t* adapter_name;
const char* _adapter_name;
int cidr;
// Default CIDR is 30
if (argc >= 6) {
cidr = atoi(argv[5]);
if (cidr == 0) LOG(FATAL) << "CIDR " << cidr << " is invalid.";
}
else
cidr = 30;
if (argc == 7)
{
adapter_name = GetWC(argv[6]);
_adapter_name = argv[6];
}
else
{
adapter_name = L"GRE_Tunnel";
_adapter_name = "GRE_Tunnel";
}
std::cout << "My IP on the GRE network: " << bind_ip << "/" << cidr << std::endl <<
"GRE server IP : " << server_ip << std::endl <<
"GRE server IP (Gateway) : " << gateway_ip << std::endl <<
"GRE binding IP : " << gre_bind_ip << std::endl;
std::wcout << L"Adapter name : " << adapter_name << std::endl << std::endl;
if (!validateIpAddress(bind_ip) || !validateIpAddress(gre_bind_ip) || !validateIpAddress(server_ip)
|| !validateIpAddress(gateway_ip)) {
LOG(FATAL) << "Failed to parse IPv4";
}
HMODULE MWintun = wt_LoadModule();
if (!InitializeWintun(MWintun)) {
LOG(FATAL) << "Failed to initialize WinTun: " << GetLastError() << std::endl << "Please make sure that wintun.dll exists";
return 0;
}
Adapter = WintunCreateAdapter(adapter_name, L"GRE_Tunnel", NULL);
if (!Adapter) {
LOG(FATAL) << "Failed to create Wintun adapter: " << GetLastError();
return 0;
}
SetConsoleCtrlHandler(exit_handler, TRUE);
MIB_UNICASTIPADDRESS_ROW AddressRow;
InitializeUnicastIpAddressEntry(&AddressRow);
WintunGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid);
AddressRow.Address.Ipv4.sin_family = AF_INET;
inet_pton(AF_INET, bind_ip, &AddressRow.Address.Ipv4.sin_addr.S_un.S_addr);
AddressRow.OnLinkPrefixLength = cidr;
AddressRow.DadState = IpDadStatePreferred;
auto LastError = CreateUnicastIpAddressEntry(&AddressRow);
if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS)
{
LOG(FATAL) << "Failed to assign IP: " << LastError;
WintunCloseAdapter(Adapter);
return 0;
}
Session = WintunStartSession(Adapter, WINTUN_MAX_RING_CAPACITY);
if (!Session)
{
LOG(FATAL) << "Failed to create adapter";
WintunCloseAdapter(Adapter);
return 0;
}
char comm[256];
sprintf_s(comm, 256, "netsh interface ip set address name=\"%s\" static %s 255.255.255.252 %s 300", _adapter_name, bind_ip, gateway_ip);
LOG(INFO) << comm;
system(comm);
memset(comm, '0', 256);
sprintf_s(comm, 256, "netsh interface ip set subinterface \"%s\" mtu=1476 store=persistent", _adapter_name);
LOG(INFO) << comm;
system(comm);
gre = new GRE(server_ip, gre_bind_ip);
std::thread t1(wintun_receive_loop);
gre->receiver(MWintun);
}