forked from katlogic/bindip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bindip.c
409 lines (386 loc) · 11.8 KB
/
bindip.c
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
#include "common.h"
#include "resource.h"
static HKEY registry;
static IP_ADAPTER_INFO adapters[256];
#if 0
static BOOL (*wow64_disable)(void **old);
static BOOL (*wow64_enable)(void *old);
#endif
__declspec(dllimport) BOOL wow64_disable(void **old);
__declspec(dllimport) BOOL wow64_enable(void *old);
// add unique list item
static void adduniq(HWND list, char *s)
{
// dont add duplicate names and empty strings
if (!s[0]) return;
if (SendMessage(list, LB_FINDSTRINGEXACT, 0, (LPARAM)s)==LB_ERR)
SendMessage(list, LB_ADDSTRING, 0, (LPARAM)s);
}
// enumerate running processes and add to the list
static void enumproc(HWND list)
{
int i,t;
char subname[MAX_PATH];
DWORD subsize = sizeof(subname);
PROCESSENTRY32 lpe;
lpe.dwSize = sizeof(lpe);
for (i=0;(t=RegEnumValue(registry, i, subname, &subsize, NULL, NULL, NULL, NULL))==ERROR_SUCCESS;i++,subsize=sizeof(subname))
adduniq(list, subname);
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL entry = Process32First(snap, &lpe);
while (entry) {
if (PathMatchSpec(lpe.szExeFile, "*.exe"))
adduniq(list, lpe.szExeFile);
lpe.dwSize = sizeof(lpe);
entry = Process32Next(snap, &lpe);
}
CloseHandle(snap);
}
// add network interfacess to list
static void enumintf(HWND list)
{
IP_ADAPTER_INFO *ada;
adduniq(list, "(default route)");
for (ada = adapters; ada; ada = ada->Next)
adduniq(list, ada->Description);
}
// react to user clicks in exe/intf list boxes
// il=1 if clicked on interface list
static void process_selections(HWND parent, HWND exe, HWND intf, int il)
{
static int sels[16384];
static TCHAR buf[512], buf2[512];
IP_ADAPTER_INFO *ada, *curada = NULL;
long nsel;
int i, j, curif = -1;
// Clicked on exelist, go through selected exes
nsel = SendMessage(exe, LB_GETSELITEMS, 16384, (LPARAM)sels);
if (!il) for (i = 0; i < nsel; i++) {
DWORD len = sizeof(buf2);
SendMessage(exe, LB_GETTEXT, sels[i], (LPARAM)buf);
if (RegQueryValueEx(registry, buf,NULL,NULL, (LPBYTE)buf2, &len)!=ERROR_SUCCESS) {
// undefined key -> no adapter, default route, shortcut
curif = 0;
curada = NULL;
break;
}
// and check they have all interfaces in common
for (j = 1, ada = adapters; ada; ada = ada->Next, j++)
if (!strcmp(ada->AdapterName, buf2)) {
// mismatch in selected group -> reset default route
if (curif >= 0 && curif != j) {
curif = 0;
curada = NULL;
goto out;
}
// otherwise keep as current interface
curif = j;
curada = ada;
break;
}
}
out:;
if (!il) {
// clicked exe list
if (curif < 0) curif = 0;
SendMessage(intf, LB_SETCURSEL, curif, 0);
} else {
// clicked interface list
curif = SendMessage(intf, LB_GETCURSEL,0,0);
// resolve index to name
for (i = curif, ada = adapters; ada && i--; ada = ada->Next)
curada = ada;
}
// in curif we have corresponding interface index, 0 if default
// in curada we have interface, null if default
// in sels[] we have exes this aplies to
for (i = 0; i < nsel; i++) {
SendMessage(exe, LB_GETTEXT, sels[i], (LPARAM)buf);
if (curif > 0) { // assign new interface
RegSetValueExA(registry, buf, 0, REG_SZ, (LPBYTE)curada->AdapterName, strlen(curada->AdapterName)+1);
} else { // no interface, delete it
RegDeleteValue(registry, buf);
}
}
strcpy(buf, "Default interface");
strcpy(buf2, "Default source ip");
if (curif > 0 && curada) {
BYTE *mac = curada->Address;
char *pip = curada->IpAddressList.IpAddress.String;
wnsprintf(buf, sizeof(buf), "%02x-%02x-%02x-%02x-%02x-%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
strcpy(buf2, pip);
}
SendMessage(GetDlgItem(parent, IDC_MAC), WM_SETTEXT, 0, (LPARAM)buf);
SendMessage(GetDlgItem(parent, IDC_IP), WM_SETTEXT, 0, (LPARAM)buf2);
}
static int check_system_dlls(char *buf, int len32)
{
return !(GetFileAttributesA(buf) == INVALID_FILE_ATTRIBUTES || GetFileAttributesA(buf+len32) == INVALID_FILE_ATTRIBUTES);
}
// locate dlls in system directory
static int get_system_dlls(char *buf)
{
int len32;
void *sav=NULL;
wow64_disable(&sav);
if (!SHGetSpecialFolderPathA(NULL, buf, CSIDL_SYSTEMX86, 0))
SHGetSpecialFolderPathA(NULL, buf, CSIDL_SYSTEM, 0);
strcat(buf, "\\bindip.dll");
len32 = strlen(buf)+1;
SHGetSpecialFolderPathA(NULL, buf + len32, CSIDL_SYSTEM, 0);
strcat(buf + len32, "\\bindip.dll");
wow64_enable(sav);
return len32;
}
// locate dlls in all places
static int locate_dlls(char *buf, int sys)
{
char tbuf[MAX_PATH];
int i,len32 = 0;
void *sav=NULL;
wow64_disable(&sav);
if (sys) {
len32 = get_system_dlls(buf);
if (check_system_dlls(buf, len32))
goto out;
}
for (i = 0; i < 3; i++) {
switch(i) {
case 2:
ExpandEnvironmentStringsA("%PROGRAMFILES(X86)%\\BindIP", tbuf, sizeof(tbuf));
break;
case 1:
ExpandEnvironmentStringsA("%PROGRAMFILES%\\BindIP", tbuf, sizeof(tbuf));
break;
case 0:
GetModuleFileNameA(NULL, tbuf, sizeof(tbuf));
PathRemoveFileSpecA(tbuf);
break;
}
len32 = wnsprintf(buf, 2048, "%s\\bindip.dll", tbuf)+1;
wnsprintf(buf + len32, 2048, "%s\\64\\bindip.dll", tbuf);
if (GetFileAttributesA(buf) != INVALID_FILE_ATTRIBUTES || GetFileAttributesA(buf+len32) != INVALID_FILE_ATTRIBUTES)
goto out;
}
out:;
wow64_enable(sav);
return len32;
}
// configure global filter winsock
static int dll_config(HWND dlg, int enable)
{
HKEY reg;
char buf[MAX_PATH*2], buf2[MAX_PATH*2];
static char const orig[] = "%SystemRoot%\\System32\\wshtcpip.dll";
DWORD buf2len, buflen = sizeof buf;
int e;
void *sav=NULL;
if ((e=RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Winsock", 0, KEY_ALL_ACCESS, ®))) {
if (dlg) {
Button_Enable(dlg, 0);
}
return 0;
}
wow64_disable(&sav);
if (RegQueryValueExA(reg, "HelperDllName", 0, NULL, (BYTE*)buf, &buflen)) {
enable = 0;
goto out;
}
if (!strcmp(buf+buflen-11, "bindip.dll")) {
if (enable) {
enable = 1;
goto out;
}
// request to disable
buflen=sizeof(orig);
if (RegSetValueExA(reg, "HelperDllName", 0, REG_EXPAND_SZ, (BYTE*)orig, buflen)) {
enable = 1; // Failed to disable..
} else { // Disabled, delete dlls too
buflen = get_system_dlls(buf);
DeleteFile(buf);
DeleteFile(buf+buflen);
}
} else if (enable == 1) {
enable = 0;
// request to enable
buflen = get_system_dlls(buf);
if (!check_system_dlls(buf, buflen)) {
buf2len = locate_dlls(buf2, 0);
CopyFile(buf2+buf2len, buf+buflen, FALSE);
CopyFile(buf2, buf, FALSE);
// Re-check that the files are ok now
if (!check_system_dlls(buf, buflen))
goto out;
}
enable = !RegSetValueExA(reg, "HelperDllName", 0, REG_EXPAND_SZ, (BYTE*)buf+buflen, strlen(buf+buflen)+1);
} else enable = 0; // Otherwise disabled
out:
RegCloseKey(reg);
wow64_enable(sav);
return enable;
}
// configure shell button registry
// -1 - just query status
static int shell_config(int enable)
{
HKEY reg, reg2;
RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Classes\\exefile\\shell", 0, KEY_ALL_ACCESS, ®);
if (enable == -1) {
if (RegQueryValue(reg, "Open with BindIP", NULL, NULL)==ERROR_SUCCESS)
enable = 1;
else
enable = 0;
} else if (enable == 1) {
char myname[MAX_PATH];
char pbuf[MAX_PATH];
GetModuleFileName(NULL, myname, sizeof(myname));
RegCreateKeyExA(reg, "Open with BindIP\\command", 0, NULL, 0, KEY_ALL_ACCESS, NULL, ®2, NULL);
enable = !RegSetValueExA(reg2, NULL, 0, REG_SZ, (BYTE*)pbuf,wnsprintf(pbuf, sizeof(pbuf), "\"%s\" \"%%1\"", myname)+1);
RegCloseKey(reg2);
}
if (enable == 0)
SHDeleteKeyA(reg, "Open with BindIP");
RegCloseKey(reg);
return enable;
}
// dialog handler
static INT_PTR CALLBACK dialog_wproc(HWND dlg, UINT msg, WPARAM w, LPARAM l)
{
HWND exe = GetDlgItem(dlg, IDC_EXELIST);
HWND intf = GetDlgItem(dlg, IDC_INTLIST);
HWND appinit = GetDlgItem(dlg, IDC_APPINIT);
HWND shell = GetDlgItem(dlg, IDC_SHELL);
int il = 0;
switch (msg) {
case WM_INITDIALOG:
enumproc(exe);
enumintf(intf);
Button_SetCheck(shell, shell_config(-1));
Button_SetCheck(appinit, dll_config(appinit,-1));
SetFocus(exe);
SendMessage(exe, LB_SETSEL, TRUE, 0);
process_selections(dlg,exe,intf, 0);
return TRUE;
case WM_CLOSE:
EndDialog(dlg, 0);
return TRUE;
case WM_COMMAND: switch (LOWORD(w)) {
case IDC_REFRESH:
enumproc(exe);
return TRUE;
case IDC_DONE:
EndDialog(dlg, 0);
return TRUE;
case IDC_INTLIST:
il = 1;
case IDC_EXELIST:
if (HIWORD(w) == LBN_SELCHANGE)
process_selections(dlg, exe,intf,il);
return TRUE;
case IDC_ADD: {
char filebuf[MAX_PATH];
filebuf[0] = 0;
OPENFILENAME ofn = {
.lStructSize = sizeof(OPENFILENAME),
.hwndOwner = dlg,
.lpstrFile = filebuf,
.nMaxFile = sizeof(filebuf),
.lpstrFilter = "EXE\0*.exe\0COM\0*.com\0SCR\0*.scr\0",
};
if (GetOpenFileName(&ofn)) {
PathStripPathA(filebuf);
adduniq(exe, filebuf);
SendMessage(exe, LB_SETSEL, FALSE, (LPARAM)-1);
SendMessage(exe, LB_SETSEL, TRUE, SendMessage(exe, LB_FINDSTRINGEXACT, 0, (LPARAM)filebuf));
SetFocus(exe);
process_selections(dlg,exe,intf, 0);
}
return TRUE;
}
case IDC_SHELL:
Button_SetCheck(shell, shell_config(Button_GetCheck(shell)));
return TRUE;
case IDC_URL:
ShellExecute(NULL, "open", "http://lua.cz/bindip/1", NULL, NULL, SW_SHOWNORMAL);
return TRUE;
case IDC_APPINIT:
Button_SetCheck(appinit, dll_config(appinit, Button_GetCheck(appinit)));
return TRUE;
} // WM_COMMAND
} // msg
return FALSE;
}
__declspec(dllimport) char *inject(HANDLE hp, HANDLE ht, char *dll32, int len32);
__declspec(dllimport) void cpiw_init();
static void run_preloaded(WCHAR *cmd)
{
DWORD ecode = 0;
char dlls[MAX_PATH*2];
STARTUPINFOW si = {0};
PROCESS_INFORMATION pi = {0};
int len32 = locate_dlls(dlls, 0);
if (len32) {
// Triggers our patched CreateProcessInternal
dlls[len32-1] = ';';
SetEnvironmentVariable("BINDIP_CHAINHOOK", dlls);
cpiw_init(); // Patch createprocess
}
si.cb = sizeof(si);
// Pass console handles
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
// Spawn
if (!CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
MessageBoxA(NULL, serr(), "CreateProcess", MB_ICONERROR|MB_OK);
goto err;
}
if (WaitForInputIdle(pi.hProcess, INFINITE) == WAIT_FAILED) {
// Console process, setup break handler
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &ecode);
} else {
// GUI app, close console
FreeConsole();
}
err:;
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
ExitProcess(ecode);
}
void winMain()
{
// Skip over exe name
WCHAR *cmd = GetCommandLineW();
int quot = *cmd++ == L'"';
while (*cmd && (quot || (cmd[0]>L' ')))
if (*cmd++ == L'"')
quot ^= 1;
while (*cmd && *cmd<= L' ')
cmd++;
// Request to launch specified program
//static WCHAR fake[MAX_PATH] = L"nc.exe -h";
//cmd = fake;
if (*cmd) {
run_preloaded(cmd);
} else {
ULONG len = sizeof(adapters);
DWORD disp;
// Otherwise gui
FreeConsole();
RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\BindIP\\Mapping", 0, NULL, 0, KEY_ALL_ACCESS, NULL, ®istry, &disp);
if (disp == REG_CREATED_NEW_KEY) {
// Run for the first time - enable shell, delete system dlls if possible
shell_config(1);
dll_config(NULL, 0);
} else if (shell_config(-1)) // Shell enabled, re-enable again to update exe path in registry
shell_config(1);
GetAdaptersInfo(adapters, &len);
// And fire up dialog
DialogBox(NULL, MAKEINTRESOURCE(IDD_FORMVIEW), NULL, dialog_wproc);
RegCloseKey(registry);
}
ExitProcess(0);
}