[CVE-2016-4802] Windows DLL hijacking
[platform/upstream/curl.git] / lib / system_win32.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2016, Steve Holme, <steve_holme@hotmail.com>.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #if defined(WIN32)
26
27 #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \
28                                   defined(USE_WINSOCK))
29
30 #include <curl/curl.h>
31 #include "system_win32.h"
32
33 /* The last #include files should be: */
34 #include "curl_memory.h"
35 #include "memdebug.h"
36
37 #if !defined(LOAD_WITH_ALTERED_SEARCH_PATH)
38 #define LOAD_WITH_ALTERED_SEARCH_PATH  0x00000008
39 #endif
40
41 #if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
42 #define LOAD_LIBRARY_SEARCH_SYSTEM32   0x00000800
43 #endif
44
45 /* We use our own typedef here since some headers might lack these */
46 typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
47
48 /* See function definitions in winbase.h */
49 #ifdef UNICODE
50 #  ifdef _WIN32_WCE
51 #    define LOADLIBARYEX  L"LoadLibraryExW"
52 #  else
53 #    define LOADLIBARYEX  "LoadLibraryExW"
54 #  endif
55 #else
56 #  define LOADLIBARYEX    "LoadLibraryExA"
57 #endif
58
59 /*
60  * Curl_load_library()
61  *
62  * This is used to dynamically load DLLs using the most secure method available
63  * for the version of Windows that we are running on.
64  *
65  * Parameters:
66  *
67  * filename  [in] - The filename or full path of the DLL to load. If only the
68  *                  filename is passed then the DLL will be loaded from the
69  *                  Windows system directory.
70  *
71  * Returns the handle of the module on success; otherwise NULL.
72  */
73 HMODULE Curl_load_library(LPCTSTR filename)
74 {
75   HMODULE hModule = NULL;
76   LOADLIBRARYEX_FN pLoadLibraryEx = NULL;
77
78   /* Get a handle to kernel32 so we can access it's functions at runtime */
79   HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32"));
80   if(!hKernel32)
81     return NULL;
82
83   /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
84      and above */
85   pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX);
86
87   /* Detect if there's already a path in the filename and load the library if
88      there is. Note: Both back slashes and forward slashes have been supported
89      since the earlier days of DOS at an API level although they are not
90      supported by command prompt */
91   if(_tcspbrk(filename, TEXT("\\/")))
92     hModule = pLoadLibraryEx ?
93       pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
94       LoadLibrary(filename);
95   /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
96      supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
97      Server 2008 R2 with this patch or natively on Windows 8 and above */
98   else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
99     /* Load the DLL from the Windows system directory */
100     hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
101   }
102   else {
103     /* Attempt to get the Windows system path */
104     UINT systemdirlen = GetSystemDirectory(NULL, 0);
105     if(systemdirlen) {
106       /* Allocate space for the full DLL path (Room for the null terminator
107          is included in systemdirlen) */
108       size_t filenamelen = _tcslen(filename);
109       TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
110       if(path && GetSystemDirectory(path, systemdirlen)) {
111         /* Calculate the full DLL path */
112         _tcscpy(path + _tcslen(path), TEXT("\\"));
113         _tcscpy(path + _tcslen(path), filename);
114
115         /* Load the DLL from the Windows system directory */
116         hModule = pLoadLibraryEx ?
117           pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
118           LoadLibrary(path);
119
120         free(path);
121       }
122     }
123   }
124
125   return hModule;
126 }
127
128 #endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */
129
130 #endif /* WIN32 */
131