From 241813e827cc4894ebb1e59f34421abea885b453 Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Sun, 22 Apr 2018 18:21:19 +0900 Subject: [PATCH] Preventing the Win32 API LoadLibrary() current directory DLL injection issue. When loading the DLL file by the LoadLibrary() function in Windows VPN programs, we changed the behavior not to search the current directory. Based on this improvement, even if there are untrusted DLL files in the calendar directory, it is now safe to avoid the problem of unexpected security problem caused by the default loading behavior of Windows. Acknowledgments: This is based on a report by Herman Groeneveld, aka Sh4d0wman. --- src/Mayaqua/Mayaqua.c | 14 ++++++++++++++ src/Mayaqua/Mayaqua.h | 3 +++ src/Mayaqua/Microsoft.c | 37 +++++++++++++++++++++++++++++++++++++ src/Mayaqua/Microsoft.h | 1 + src/vpnbridge/vpnbridge.c | 2 ++ src/vpnclient/vpncsvc.c | 2 ++ src/vpncmd/vpncmd.c | 2 ++ src/vpncmgr/vpncmgr.c | 2 ++ src/vpndrvinst/vpndrvinst.c | 2 ++ src/vpninstall/vpninstall.c | 1 + src/vpnserver/vpnserver.c | 2 ++ src/vpnsetup/vpnsetup.c | 2 ++ src/vpnsmgr/vpnsmgr.c | 2 ++ 13 files changed, 72 insertions(+) diff --git a/src/Mayaqua/Mayaqua.c b/src/Mayaqua/Mayaqua.c index 5bc06b86..b2ecdf54 100644 --- a/src/Mayaqua/Mayaqua.c +++ b/src/Mayaqua/Mayaqua.c @@ -154,7 +154,19 @@ static UINT64 probe_start = 0; static UINT64 probe_last = 0; static bool probe_enabled = false; +// The function which should be called once as soon as possible after the process is started +static bool init_proc_once_flag = false; +void InitProcessCallOnce() +{ + if (init_proc_once_flag == false) + { + init_proc_once_flag = true; +#ifdef OS_WIN32 + MsInitProcessCallOnce(); +#endif // OS_WIN32 + } +} // Calculate the checksum USHORT CalcChecksum16(void *buf, UINT size) @@ -490,6 +502,8 @@ void InitMayaqua(bool memcheck, bool debug, int argc, char **argv) return; } + InitProcessCallOnce(); + g_memcheck = memcheck; g_debug = debug; cmdline = NULL; diff --git a/src/Mayaqua/Mayaqua.h b/src/Mayaqua/Mayaqua.h index 36fdc648..400a0dab 100644 --- a/src/Mayaqua/Mayaqua.h +++ b/src/Mayaqua/Mayaqua.h @@ -133,6 +133,8 @@ #endif // VPN_SPEED +void InitProcessCallOnce(); + #ifdef VPN_EXE // To build the executable file #ifdef WIN32 @@ -142,6 +144,7 @@ int main(int argc, char *argv[]); int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow) { char *argv[] = { CmdLine, }; + InitProcessCallOnce(); return main(1, argv); } #endif // WIN32 diff --git a/src/Mayaqua/Microsoft.c b/src/Mayaqua/Microsoft.c index 6d6b9039..227f2e70 100644 --- a/src/Mayaqua/Microsoft.c +++ b/src/Mayaqua/Microsoft.c @@ -273,6 +273,43 @@ typedef struct MS_MSCHAPV2_PARAMS UCHAR ResponseBuffer[MAX_SIZE]; } MS_MSCHAPV2_PARAMS; +// The function which should be called once as soon as possible after the process is started +void MsInitProcessCallOnce() +{ + // Mitigate the DLL injection attack + char system_dir[MAX_PATH]; + char kernel32_path[MAX_PATH]; + UINT len; + HINSTANCE hKernel32; + + // Get the full path of kernel32.dll + memset(system_dir, 0, sizeof(system_dir)); + GetSystemDirectory(system_dir, sizeof(system_dir)); + len = lstrlenA(system_dir); + if (system_dir[len] == '\\') + { + system_dir[len] = 0; + } + wsprintfA(kernel32_path, "%s\\kernel32.dll", system_dir); + + // Load kernel32.dll + hKernel32 = LoadLibraryA(kernel32_path); + if (hKernel32 != NULL) + { + BOOL (WINAPI *_SetDllDirectoryA)(LPCTSTR); + + _SetDllDirectoryA = (BOOL (WINAPI *)(LPCTSTR)) + GetProcAddress(hKernel32, "SetDllDirectoryA"); + + if (_SetDllDirectoryA != NULL) + { + _SetDllDirectoryA(""); + } + + FreeLibrary(hKernel32); + } +} + // Collect the information of the VPN software bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name) { diff --git a/src/Mayaqua/Microsoft.h b/src/Mayaqua/Microsoft.h index 59197b47..0aef64c9 100644 --- a/src/Mayaqua/Microsoft.h +++ b/src/Mayaqua/Microsoft.h @@ -1160,6 +1160,7 @@ void MsTest(); bool MsSaveSystemInfo(wchar_t *dst_filename); bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name); +void MsInitProcessCallOnce(); MS_SUSPEND_HANDLER *MsNewSuspendHandler(); void MsFreeSuspendHandler(MS_SUSPEND_HANDLER *h); diff --git a/src/vpnbridge/vpnbridge.c b/src/vpnbridge/vpnbridge.c index 5228016b..2ac09612 100644 --- a/src/vpnbridge/vpnbridge.c +++ b/src/vpnbridge/vpnbridge.c @@ -155,6 +155,8 @@ void StopProcess() // WinMain function int main(int argc, char *argv[]) { + InitProcessCallOnce(); + VgUseStaticLink(); #ifdef OS_WIN32 diff --git a/src/vpnclient/vpncsvc.c b/src/vpnclient/vpncsvc.c index 179e24a1..fae9ad12 100644 --- a/src/vpnclient/vpncsvc.c +++ b/src/vpnclient/vpncsvc.c @@ -143,6 +143,8 @@ void StopProcess() // WinMain function int main(int argc, char *argv[]) { + InitProcessCallOnce(); + #ifdef OS_WIN32 return MsService(GC_SVC_NAME_VPNCLIENT, StartProcess, StopProcess, ICO_MACHINE, argv[0]); diff --git a/src/vpncmd/vpncmd.c b/src/vpncmd/vpncmd.c index 6499d73a..4a66d1fd 100644 --- a/src/vpncmd/vpncmd.c +++ b/src/vpncmd/vpncmd.c @@ -137,6 +137,8 @@ int main(int argc, char *argv[]) wchar_t *s; UINT ret = 0; + InitProcessCallOnce(); + #ifdef OS_WIN32 SetConsoleTitleA(CEDAR_PRODUCT_STR " VPN Command Line Utility"); #endif // OS_WIN32 diff --git a/src/vpncmgr/vpncmgr.c b/src/vpncmgr/vpncmgr.c index 17c22830..5af387be 100644 --- a/src/vpncmgr/vpncmgr.c +++ b/src/vpncmgr/vpncmgr.c @@ -134,6 +134,8 @@ // WinMain function int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow) { + InitProcessCallOnce(); + InitMayaqua(false, false, 0, NULL); InitCedar(); diff --git a/src/vpndrvinst/vpndrvinst.c b/src/vpndrvinst/vpndrvinst.c index dd8faf2b..423814a3 100644 --- a/src/vpndrvinst/vpndrvinst.c +++ b/src/vpndrvinst/vpndrvinst.c @@ -353,6 +353,8 @@ void MainFunction(char *cmd) // winmain function int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow) { + InitProcessCallOnce(); + InitMayaqua(false, false, 0, NULL); EnableProbe(false); InitCedar(); diff --git a/src/vpninstall/vpninstall.c b/src/vpninstall/vpninstall.c index d343dca1..135f805f 100644 --- a/src/vpninstall/vpninstall.c +++ b/src/vpninstall/vpninstall.c @@ -1634,6 +1634,7 @@ void ViFreeStringTables() int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow) { INSTANCE *instance; + InitProcessCallOnce(); is_debug = false; MayaquaMinimalMode(); InitMayaqua(false, is_debug, 0, NULL); diff --git a/src/vpnserver/vpnserver.c b/src/vpnserver/vpnserver.c index 24a3c0c4..0cb4d5f9 100644 --- a/src/vpnserver/vpnserver.c +++ b/src/vpnserver/vpnserver.c @@ -155,6 +155,8 @@ void StopProcess() // WinMain function int main(int argc, char *argv[]) { + InitProcessCallOnce(); + VgUseStaticLink(); #ifdef OS_WIN32 diff --git a/src/vpnsetup/vpnsetup.c b/src/vpnsetup/vpnsetup.c index 384b0acd..cccb2920 100644 --- a/src/vpnsetup/vpnsetup.c +++ b/src/vpnsetup/vpnsetup.c @@ -134,6 +134,8 @@ int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow) { UINT ret; + InitProcessCallOnce(); + VgUseStaticLink(); ret = SWExec(); diff --git a/src/vpnsmgr/vpnsmgr.c b/src/vpnsmgr/vpnsmgr.c index 2557e6be..94916338 100644 --- a/src/vpnsmgr/vpnsmgr.c +++ b/src/vpnsmgr/vpnsmgr.c @@ -132,6 +132,8 @@ // WinMain function int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow) { + InitProcessCallOnce(); + InitMayaqua(false, false, 0, NULL); InitCedar(); SMExec();