From f77ee39e8cae2eaaea3a8fdd1eaffaf484cada08 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 13 Mar 2017 21:42:44 +0000 Subject: [PATCH] Load comctl32.dll (for drag lists) at run time. This too is not in the list of known DLLs on Windows 10. I don't know of any actual viable hijacking attack based on it, which according to my reading of MSDN (specifically, a rather vague hint in https://msdn.microsoft.com/library/ff919712) _may_ be because we mention the common controls assembly in our application manifest; but better safe than sorry. Now the entire list of remaining DLLs that PuTTY links against at load time is a subset of the Win10 known DLLs list, so that _should_ mean that everything we load before we've deployed our own defence (SetDefaultDllDirectories) is defended against for us by Windows itself. --- Recipe | 2 +- windows/winctrls.c | 33 ++++++++++++++++++++++++--------- windows/window.c | 2 +- windows/winpgen.c | 2 +- windows/winstuff.h | 1 + 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Recipe b/Recipe index 0fb7bbb7..f5458122 100644 --- a/Recipe +++ b/Recipe @@ -273,7 +273,7 @@ IMPORT = import sshbcrypt sshblowf CHARSET = sbcsdat slookup sbcs utf8 toucs fromucs xenc mimeenc macenc localenc # Standard libraries. -LIBS = advapi32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib +LIBS = advapi32.lib user32.lib gdi32.lib comdlg32.lib + shell32.lib imm32.lib ole32.lib # Network backend sets. This also brings in the relevant attachment diff --git a/windows/winctrls.c b/windows/winctrls.c index a03967e6..737018e4 100644 --- a/windows/winctrls.c +++ b/windows/winctrls.c @@ -38,6 +38,21 @@ #define PUSHBTNHEIGHT 14 #define PROGBARHEIGHT 14 +DECL_WINDOWS_FUNCTION(static, void, InitCommonControls, (void)); +DECL_WINDOWS_FUNCTION(static, BOOL, MakeDragList, (HWND)); +DECL_WINDOWS_FUNCTION(static, int, LBItemFromPt, (HWND, POINT, BOOL)); +DECL_WINDOWS_FUNCTION(static, int, DrawInsert, (HWND, HWND, int)); + +void init_common_controls(void) +{ + HMODULE comctl32_module = load_system32_dll("comctl32.dll"); + GET_WINDOWS_FUNCTION(comctl32_module, InitCommonControls); + GET_WINDOWS_FUNCTION(comctl32_module, MakeDragList); + GET_WINDOWS_FUNCTION(comctl32_module, LBItemFromPt); + GET_WINDOWS_FUNCTION(comctl32_module, DrawInsert); + p_InitCommonControls(); +} + void ctlposinit(struct ctlpos *cp, HWND hwnd, int leftborder, int rightborder, int topborder) { @@ -921,7 +936,7 @@ void prefslist(struct prefslist *hdl, struct ctlpos *cp, int lines, WS_VSCROLL | LBS_HASSTRINGS | LBS_USETABSTOPS, WS_EX_CLIENTEDGE, "", listid); - MakeDragList(ctl); + p_MakeDragList(ctl); } break; @@ -996,17 +1011,17 @@ int pl_itemfrompt(HWND hwnd, POINT cursor, BOOL scroll) * current item if the upper edge is closer than * the lower edge, or _below_ it if vice versa. */ - ret = LBItemFromPt(hwnd, cursor, scroll); + ret = p_LBItemFromPt(hwnd, cursor, scroll); if (ret == -1) return ret; - ret = LBItemFromPt(hwnd, cursor, FALSE); + ret = p_LBItemFromPt(hwnd, cursor, FALSE); updist = downdist = 0; for (i = 1; i < 4096 && (!updist || !downdist); i++) { uppoint = downpoint = cursor; uppoint.y -= i; downpoint.y += i; - upitem = LBItemFromPt(hwnd, uppoint, FALSE); - downitem = LBItemFromPt(hwnd, downpoint, FALSE); + upitem = p_LBItemFromPt(hwnd, uppoint, FALSE); + downitem = p_LBItemFromPt(hwnd, downpoint, FALSE); if (!updist && upitem != ret) updist = i; if (!downdist && downitem != ret) @@ -1047,13 +1062,13 @@ int handle_prefslist(struct prefslist *hdl, SendDlgItemMessage(hwnd, hdl->listid, LB_ADDSTRING, 0, (LPARAM) ""); - hdl->srcitem = LBItemFromPt(dlm->hWnd, dlm->ptCursor, TRUE); + hdl->srcitem = p_LBItemFromPt(dlm->hWnd, dlm->ptCursor, TRUE); hdl->dragging = 0; /* XXX hack Q183115 */ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE); ret |= 1; break; case DL_CANCELDRAG: - DrawInsert(hwnd, dlm->hWnd, -1); /* Clear arrow */ + p_DrawInsert(hwnd, dlm->hWnd, -1); /* Clear arrow */ SendDlgItemMessage(hwnd, hdl->listid, LB_DELETESTRING, hdl->dummyitem, 0); hdl->dragging = 0; @@ -1062,7 +1077,7 @@ int handle_prefslist(struct prefslist *hdl, hdl->dragging = 1; dest = pl_itemfrompt(dlm->hWnd, dlm->ptCursor, TRUE); if (dest > hdl->dummyitem) dest = hdl->dummyitem; - DrawInsert (hwnd, dlm->hWnd, dest); + p_DrawInsert (hwnd, dlm->hWnd, dest); if (dest >= 0) SetWindowLongPtr(hwnd, DWLP_MSGRESULT, DL_MOVECURSOR); else @@ -1072,7 +1087,7 @@ int handle_prefslist(struct prefslist *hdl, if (hdl->dragging) { dest = pl_itemfrompt(dlm->hWnd, dlm->ptCursor, TRUE); if (dest > hdl->dummyitem) dest = hdl->dummyitem; - DrawInsert (hwnd, dlm->hWnd, -1); + p_DrawInsert (hwnd, dlm->hWnd, -1); } SendDlgItemMessage(hwnd, hdl->listid, LB_DELETESTRING, hdl->dummyitem, 0); diff --git a/windows/window.c b/windows/window.c index cb42addf..e01a3c32 100644 --- a/windows/window.c +++ b/windows/window.c @@ -359,7 +359,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) sk_init(); - InitCommonControls(); + init_common_controls(); /* Set Explicit App User Model Id so that jump lists don't cause PuTTY to hang on to removable media. */ diff --git a/windows/winpgen.c b/windows/winpgen.c index c4f4de45..2507d37e 100644 --- a/windows/winpgen.c +++ b/windows/winpgen.c @@ -1529,7 +1529,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) dll_hijacking_protection(); - InitCommonControls(); + init_common_controls(); hinst = inst; hwnd = NULL; diff --git a/windows/winstuff.h b/windows/winstuff.h index 007889e4..f8c4243f 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -329,6 +329,7 @@ struct ctlpos { int boxystart, boxid; char *boxtext; }; +void init_common_controls(void); /* also does some DLL-loading */ /* * Exports from winutils.c.