diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a3cff5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +ciadpi.exe \ No newline at end of file diff --git a/Makefile b/Makefile index c0f9f67..0530f05 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,13 @@ TARGET = ciadpi CC ?= gcc CFLAGS += -std=c99 -O2 -D_XOPEN_SOURCE=500 SOURCES = packets.c main.c conev.c proxy.c desync.c mpool.c extend.c +WIN_SOURCES = win_service.c all: $(CC) $(CFLAGS) $(SOURCES) -I . -o $(TARGET) windows: - $(CC) $(CFLAGS) $(SOURCES) -I . -lws2_32 -lmswsock -o $(TARGET).exe + $(CC) $(CFLAGS) $(SOURCES) $(WIN_SOURCES) -I . -lws2_32 -lmswsock -o $(TARGET).exe clean: rm -f $(TARGET) *.o diff --git a/dist/windows/byedpi.bat b/dist/windows/byedpi.bat new file mode 100644 index 0000000..8fb6023 --- /dev/null +++ b/dist/windows/byedpi.bat @@ -0,0 +1,4 @@ +@echo off +title ByeDPI + +ciadpi.exe --split 1+s --disorder 3+s --mod-http=h,d --auto --tlsrec 1+s \ No newline at end of file diff --git a/dist/windows/service_delete.bat b/dist/windows/service_delete.bat new file mode 100644 index 0000000..3f12aeb --- /dev/null +++ b/dist/windows/service_delete.bat @@ -0,0 +1,13 @@ +@echo off +title ByeDPI - Delete Service + +echo This script should be run with administrator privileges. +echo Right click - run as administrator. +echo Press any key if you're running it as administrator. +pause + +set svc_name="ByeDPI" + +sc stop %svc_name% +sc delete %svc_name% +pause \ No newline at end of file diff --git a/dist/windows/service_install.bat b/dist/windows/service_install.bat new file mode 100644 index 0000000..24c3b68 --- /dev/null +++ b/dist/windows/service_install.bat @@ -0,0 +1,24 @@ +@echo off +title ByeDPI - Install Service +pushd "%~dp0" + +echo This script should be run with administrator privileges. +echo Right click - run as administrator. +echo Press any key if you're running it as administrator. +pause + +set svc_name="ByeDPI" +set svc_desc="Local SOCKS proxy server to bypass DPI (Deep Packet Inspection)." + +:: Set up launch args (bypass methods) here. The "--service" arg is required; +:: without it, the program will not register itself as a Windows service! +set svc_bin="\"%cd%\ciadpi.exe\" --service --split 1+s --disorder 3+s --mod-http=h,d --auto --tlsrec 1+s" + +sc stop %svc_name% +sc delete %svc_name% +sc create %svc_name% binPath= %svc_bin% start= "auto" +sc description %svc_name% %svc_desc% +sc start %svc_name% + +popd +pause \ No newline at end of file diff --git a/main.c b/main.c index 01ea37d..23f0ffa 100644 --- a/main.c +++ b/main.c @@ -20,6 +20,7 @@ #include #else #include + #include "win_service.h" #define close(fd) closesocket(fd) #endif @@ -139,6 +140,9 @@ const struct option options[] = { #ifdef __linux__ {"md5sig", 0, 0, 'S'}, #endif + #ifdef _WIN32 + {"service", 0, 0, 'B'}, + #endif {"fake-data", 1, 0, 'l'}, {"tls-sni", 1, 0, 'n'}, #endif @@ -433,6 +437,8 @@ int main(int argc, char **argv) uniperror("WSAStartup"); return -1; } + + int as_winsvc = 0; #endif struct sockaddr_ina s = { .in = { @@ -459,7 +465,7 @@ int main(int argc, char **argv) int rez; int invalid = 0; - long val = 0; + ssize_t val = 0; char *end = 0; uint16_t port = htons(1080); @@ -475,6 +481,12 @@ int main(int argc, char **argv) argc, argv, opt, options, 0)) != -1) { switch (rez) { + #ifdef _WIN32 + case 'B': + as_winsvc = 1; + break; + #endif + case 'N': params.resolve = 0; break; @@ -803,6 +815,12 @@ int main(int argc, char **argv) return -1; } } + + #ifdef _WIN32 + if (as_winsvc && register_winsvc(argc, argv)) + return 0; + #endif + if (invalid) { fprintf(stderr, "invalid value: -%c %s\n", rez, optarg); clear_params(); diff --git a/win_service.c b/win_service.c new file mode 100644 index 0000000..6189d75 --- /dev/null +++ b/win_service.c @@ -0,0 +1,79 @@ +#include "win_service.h" +#include +#include + +#define SERVICE_NAME "ByeDPI" + +static SERVICE_STATUS ServiceStatus; +static SERVICE_STATUS_HANDLE hStatus; +static int svc_argc = 0; +static char **svc_argv = NULL; + +int main(int argc, char *argv[]); + +void service_ctrl_handler(DWORD request) +{ + switch(request) + { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + ServiceStatus.dwWin32ExitCode = 0; + ServiceStatus.dwCurrentState = SERVICE_STOPPED; + default: + break; + } + SetServiceStatus(hStatus, &ServiceStatus); + return; +} + +void service_main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) +{ + ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStatus.dwCurrentState = SERVICE_RUNNING; + ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + ServiceStatus.dwWin32ExitCode = 0; + ServiceStatus.dwServiceSpecificExitCode = 0; + ServiceStatus.dwCheckPoint = 1; + ServiceStatus.dwWaitHint = 0; + + hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)service_ctrl_handler); + if (hStatus == (SERVICE_STATUS_HANDLE)0) + { + // Registering Control Handler failed + return; + } + + SetServiceStatus(hStatus, &ServiceStatus); + + // Calling main with saved argc & argv + ServiceStatus.dwWin32ExitCode = (DWORD)main(svc_argc, svc_argv); + ServiceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(hStatus, &ServiceStatus); + return; +} + +int register_winsvc(int argc, char *argv[]) +{ + SERVICE_TABLE_ENTRY ServiceTable[] = { + {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main}, + {NULL, NULL} + }; + + // Save args passed to the program to use instead of the service args. + if (!svc_argc && !svc_argv) { + svc_argc = argc; + svc_argv = calloc((size_t)(argc + 1), sizeof(void*)); + for (int i = 0; i < argc; i++) + svc_argv[i] = strdup(argv[i]); + } + + int result = StartServiceCtrlDispatcher(ServiceTable); + + if (svc_argc && svc_argv) { + for (int i = 0; i < svc_argc; i++) + free(svc_argv[i]); + free(svc_argv); + } + + return result; +} \ No newline at end of file diff --git a/win_service.h b/win_service.h new file mode 100644 index 0000000..6c15d5d --- /dev/null +++ b/win_service.h @@ -0,0 +1 @@ +int register_winsvc(int argc, char *argv[]); \ No newline at end of file