aboutsummaryrefslogtreecommitdiffstats
path: root/api/rundll32.c
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2020-10-19 22:23:09 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2020-10-30 16:51:01 +0100
commitfaf7d3771c9bd7b8b9a3ee20ceed2a432542c318 (patch)
treebad93f3e3406a5b57b51d9a2b61133e9f9dd49bd /api/rundll32.c
parentapi: installer: switch from MSM to ZIP distribution (diff)
downloadwintun-faf7d3771c9bd7b8b9a3ee20ceed2a432542c318.tar.xz
wintun-faf7d3771c9bd7b8b9a3ee20ceed2a432542c318.zip
api: connect rundll32 child with parent using stdout and stderr
The WintunCreateAdapter()+CreateAdapter() and WintunDeleteAdapter()+ DeleteAdapter() communicate using Unicode anonymous pipes now. This allows the WintunCreateAdapter() to exactly determine the adapter CreateAdapter() just created by its GUID rather than its name - avoiding the possible ambiguity caused by same-adapter-name ordinal suffixes. This also allows exact retrieval of the result code and pending reboot flag from the rundll32 child process. Furthermore, CreateAdapter() and DeleteAdapter() are now available in _DEBUG for all platforms to allow testing. It took a #pragma comment( linker, "/EXPORT") trick to stop compiler from decorating function names and exporting as _CreateAdapter@16() and _DeleteAdapter@16() in x86. Signed-off-by: Simon Rozman <simon@rozman.si>
Diffstat (limited to 'api/rundll32.c')
-rw-r--r--api/rundll32.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/api/rundll32.c b/api/rundll32.c
index 77e4842..dcd6628 100644
--- a/api/rundll32.c
+++ b/api/rundll32.c
@@ -5,7 +5,34 @@
#include "pch.h"
-#if defined(_M_AMD64) || defined(_M_ARM64)
+#define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
+
+#if defined(_M_AMD64) || defined(_M_ARM64) || defined(_DEBUG)
+
+static DWORD
+WriteFormatted(_In_ DWORD StdHandle, _In_z_ const WCHAR *Template, ...)
+{
+ WCHAR *FormattedMessage = NULL;
+ DWORD SizeWritten;
+ va_list Arguments;
+ va_start(Arguments, Template);
+ WriteFile(
+ GetStdHandle(StdHandle),
+ FormattedMessage,
+ sizeof(WCHAR) * FormatMessageW(
+ FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ Template,
+ 0,
+ 0,
+ (void *)&FormattedMessage,
+ 0,
+ &Arguments),
+ &SizeWritten,
+ NULL);
+ LocalFree(FormattedMessage);
+ va_end(Arguments);
+ return SizeWritten / sizeof(WCHAR);
+}
static BOOL CALLBACK
ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_ const WCHAR *LogLine)
@@ -14,22 +41,23 @@ ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_ const WCHAR *LogLine)
switch (Level)
{
case WINTUN_LOG_INFO:
- Template = L"[+] %s\n";
+ Template = L"[+] %1\n";
break;
case WINTUN_LOG_WARN:
- Template = L"[-] %s\n";
+ Template = L"[-] %1\n";
break;
case WINTUN_LOG_ERR:
- Template = L"[!] %s\n";
+ Template = L"[!] %1\n";
break;
default:
return FALSE;
}
- fwprintf(stderr, Template, LogLine);
+ WriteFormatted(STD_ERROR_HANDLE, Template, LogLine);
return TRUE;
}
-static BOOL ElevateToSystem(void)
+static BOOL
+ElevateToSystem(void)
{
HANDLE CurrentProcessToken, ThreadToken, ProcessSnapshot, WinlogonProcess, WinlogonToken, DuplicatedToken;
PROCESSENTRY32W ProcessEntry = { .dwSize = sizeof(PROCESSENTRY32W) };
@@ -126,21 +154,24 @@ cleanup:
static int Argc;
static WCHAR **Argv;
-static void Init(void)
+static void
+Init(void)
{
WintunSetLogger(ConsoleLogger);
Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
ElevateToSystem();
}
-static void Done(void)
+static void
+Done(void)
{
RevertToSelf();
LocalFree(Argv);
}
-__declspec(dllexport) VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
+VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
+# pragma EXPORT
UNREFERENCED_PARAMETER(hwnd);
UNREFERENCED_PARAMETER(hinst);
UNREFERENCED_PARAMETER(lpszCmdLine);
@@ -160,16 +191,23 @@ __declspec(dllexport) VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, L
WINTUN_ADAPTER *Adapter;
BOOL RebootRequired = FALSE;
DWORD Result = WintunCreateAdapter(Argv[2], Argv[3], Argc > 4 ? &RequestedGUID : NULL, &Adapter, &RebootRequired);
- if (Result != ERROR_SUCCESS)
- goto cleanup;
+ WCHAR GuidStr[MAX_GUID_STRING_LEN];
+ WriteFormatted(
+ STD_OUTPUT_HANDLE,
+ L"%1!X! %2!.*s! %3!X!",
+ Result,
+ StringFromGUID2(Result == ERROR_SUCCESS ? &Adapter->CfgInstanceID : &GUID_NULL, GuidStr, _countof(GuidStr)),
+ GuidStr,
+ RebootRequired);
WintunFreeAdapter(Adapter);
cleanup:
Done();
}
-__declspec(dllexport) VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
+VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
+# pragma EXPORT
UNREFERENCED_PARAMETER(hwnd);
UNREFERENCED_PARAMETER(hinst);
UNREFERENCED_PARAMETER(lpszCmdLine);
@@ -183,7 +221,7 @@ __declspec(dllexport) VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, L
if (FAILED(CLSIDFromString(Argv[2], &Adapter.CfgInstanceID)))
goto cleanup;
BOOL RebootRequired = FALSE;
- WintunDeleteAdapter(&Adapter, &RebootRequired);
+ WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", WintunDeleteAdapter(&Adapter, &RebootRequired), RebootRequired);
cleanup:
Done();