aboutsummaryrefslogtreecommitdiffstats
path: root/api/rundll32.c
diff options
context:
space:
mode:
Diffstat (limited to 'api/rundll32.c')
-rw-r--r--api/rundll32.c321
1 files changed, 63 insertions, 258 deletions
diff --git a/api/rundll32.c b/api/rundll32.c
index 37d4387..6bdc7c9 100644
--- a/api/rundll32.c
+++ b/api/rundll32.c
@@ -15,134 +15,6 @@
#include <objbase.h>
#include <assert.h>
-#ifdef ACCEPT_WOW64
-
-# define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
-
-static DWORD
-WriteFormatted(_In_ DWORD StdHandle, _In_z_ LPCWSTR Template, ...)
-{
- LPWSTR FormattedMessage = NULL;
- DWORD Size;
- va_list Arguments;
- va_start(Arguments, Template);
- DWORD Len = FormatMessageW(
- FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- Template,
- 0,
- 0,
- (VOID *)&FormattedMessage,
- 0,
- &Arguments);
- if (SUCCEEDED(DWordMult(Len, sizeof(*FormattedMessage), &Size)))
- WriteFile(GetStdHandle(StdHandle), FormattedMessage, Size, &Size, NULL);
- else
- Size = 0;
- LocalFree(FormattedMessage);
- va_end(Arguments);
- return Size / sizeof(*FormattedMessage);
-}
-
-static VOID CALLBACK
-ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR LogLine)
-{
- LPCWSTR Template;
- switch (Level)
- {
- case WINTUN_LOG_INFO:
- Template = L"[+] %1\n";
- break;
- case WINTUN_LOG_WARN:
- Template = L"[-] %1\n";
- break;
- case WINTUN_LOG_ERR:
- Template = L"[!] %1\n";
- break;
- default:
- return;
- }
- WriteFormatted(STD_ERROR_HANDLE, Template, LogLine);
-}
-
-VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
-{
-# pragma EXPORT
-
- int Argc;
- LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
- WintunSetLogger(ConsoleLogger);
-
- if (Argc < 4)
- goto cleanup;
- if (wcslen(Argv[2]) >= WINTUN_MAX_POOL)
- goto cleanup;
- if (wcslen(Argv[3]) >= MAX_ADAPTER_NAME)
- goto cleanup;
- GUID RequestedGUID;
- if (Argc > 4 && FAILED(CLSIDFromString(Argv[4], &RequestedGUID)))
- goto cleanup;
-
- BOOL RebootRequired;
- WINTUN_ADAPTER *Adapter = WintunCreateAdapter(Argv[2], Argv[3], Argc > 4 ? &RequestedGUID : NULL, &RebootRequired);
- DWORD LastError = Adapter ? ERROR_SUCCESS : GetLastError();
- WriteFormatted(
- STD_OUTPUT_HANDLE, L"%1!X! %2!s! %3!X!", LastError, Adapter ? Adapter->DevInstanceID : L"\"\"", RebootRequired);
- if (Adapter)
- WintunFreeAdapter(Adapter);
-
-cleanup:
- LocalFree(Argv);
-}
-
-VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
-{
-# pragma EXPORT
-
- int Argc;
- LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
- WintunSetLogger(ConsoleLogger);
-
- if (Argc < 4)
- goto cleanup;
-
- DWORD LastError;
- BOOL RebootRequired = FALSE;
- WINTUN_ADAPTER *Adapter = AdapterOpenFromDevInstanceId(Argv[2], Argv[3]);
- if (!Adapter)
- {
- LastError = GetLastError();
- goto write;
- }
- BOOL ForceCloseSessions = wcstoul(Argv[4], NULL, 10);
- LastError = WintunDeleteAdapter(Adapter, ForceCloseSessions, &RebootRequired) ? ERROR_SUCCESS : GetLastError();
- WintunFreeAdapter(Adapter);
-write:
- WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
-
-cleanup:
- LocalFree(Argv);
-}
-
-VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
-{
-# pragma EXPORT
-
- int Argc;
- LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
- WintunSetLogger(ConsoleLogger);
-
- if (Argc < 2)
- goto cleanup;
-
- BOOL RebootRequired;
- DWORD LastError = WintunDeletePoolDriver(Argv[2], &RebootRequired) ? ERROR_SUCCESS : GetLastError();
- WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
-
-cleanup:
- LocalFree(Argv);
-}
-#endif
-
#ifdef MAYBE_WOW64
_Return_type_success_(return != FALSE)
@@ -265,52 +137,23 @@ ProcessStdout(_Inout_ PROCESS_STDOUT_STATE *State)
static DWORD WINAPI
ProcessStderr(_In_ HANDLE Stderr)
{
- enum
- {
- OnNone,
- OnLevelStart,
- OnLevel,
- OnLevelEnd,
- OnSpace,
- OnMsg
- } State = OnNone;
- WCHAR Msg[0x200];
- DWORD Count = 0;
- WINTUN_LOGGER_LEVEL Level = WINTUN_LOG_INFO;
+ WCHAR Msg[0x200], Buf[0x220], LevelRune;
+ DWORD64 Timestamp;
+ DWORD SizeRead;
+ WINTUN_LOGGER_LEVEL Level;
for (;;)
{
- WCHAR Buf[0x200];
- DWORD SizeRead;
- if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL))
+ if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL) || !SizeRead)
return ERROR_SUCCESS;
if (SizeRead % sizeof(*Buf))
return ERROR_INVALID_DATA;
- SizeRead /= sizeof(*Buf);
- for (DWORD i = 0; i < SizeRead; ++i)
- {
- WCHAR c = Buf[i];
- if (State == OnNone && c == L'[')
- State = OnLevelStart;
- else if (
- State == OnLevelStart && ((Level = WINTUN_LOG_INFO, c == L'+') ||
- (Level = WINTUN_LOG_WARN, c == L'-') || (Level = WINTUN_LOG_ERR, c == L'!')))
- State = OnLevelEnd;
- else if (State == OnLevelEnd && c == L']')
- State = OnSpace;
- else if (State == OnSpace && !iswspace(c) || State == OnMsg && c != L'\r' && c != L'\n')
- {
- if (Count < _countof(Msg) - 1)
- Msg[Count++] = c;
- State = OnMsg;
- }
- else if (State == OnMsg && c == L'\n')
- {
- Msg[Count] = 0;
- LoggerLog(Level, NULL, Msg);
- State = OnNone;
- Count = 0;
- }
- }
+ Msg[0] = Buf[SizeRead / sizeof(*Buf) - 1] = L'\0';
+ if (swscanf_s(Buf, L"[%c %I64u] %[^\n]", &LevelRune, 1, &Timestamp, Msg, (DWORD)_countof(Msg)) != 3 || !Msg[0])
+ return ERROR_INVALID_DATA;
+ if (!((Level = WINTUN_LOG_INFO, LevelRune == L'+') || (Level = WINTUN_LOG_WARN, LevelRune == L'-') ||
+ (Level = WINTUN_LOG_ERR, LevelRune == L'!')))
+ return ERROR_INVALID_DATA;
+ Logger(Level, Timestamp, Msg);
}
}
@@ -343,7 +186,7 @@ ExecuteRunDll32(
return FALSE;
}
WCHAR DllPath[MAX_PATH] = { 0 };
- if (!PathCombineW(DllPath, RandomTempSubDirectory, L"wintun.dll"))
+ if (!PathCombineW(DllPath, RandomTempSubDirectory, L"setupapihost.dll"))
{
LastError = ERROR_BUFFER_OVERFLOW;
goto cleanupDirectory;
@@ -352,10 +195,10 @@ ExecuteRunDll32(
switch (NativeMachine)
{
case IMAGE_FILE_MACHINE_AMD64:
- WintunDllResourceName = L"wintun-amd64.dll";
+ WintunDllResourceName = L"setupapihost-amd64.dll";
break;
case IMAGE_FILE_MACHINE_ARM64:
- WintunDllResourceName = L"wintun-arm64.dll";
+ WintunDllResourceName = L"setupapihost-arm64.dll";
break;
default:
LOG(WINTUN_LOG_ERR, L"Unsupported platform 0x%x", NativeMachine);
@@ -444,9 +287,9 @@ cleanupThreads:
WaitForSingleObject(ThreadStdout, INFINITE);
DWORD ThreadResult;
if (!GetExitCodeThread(ThreadStdout, &ThreadResult))
- LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
+ LastError = LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
else if (ThreadResult != ERROR_SUCCESS)
- LOG_ERROR(LastError, L"Failed to read process output");
+ LastError = LOG_ERROR(ThreadResult, L"Failed to read process output");
CloseHandle(ThreadStdout);
}
cleanupPipes:
@@ -462,132 +305,94 @@ cleanupDirectory:
return RET_ERROR(TRUE, LastError);
}
-_Use_decl_annotations_
-WINTUN_ADAPTER *
-CreateAdapterViaRundll32(LPCWSTR Pool, LPCWSTR Name, const GUID *RequestedGUID, BOOL *RebootRequired)
+static _Return_type_success_(return != FALSE)
+BOOL
+InvokeClassInstaller(_In_ LPCWSTR Action, _In_ LPCWSTR Function, _In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
- LOG(WINTUN_LOG_INFO, L"Spawning native process");
- LPWSTR Arguments = NULL;
- if (RequestedGUID)
+ LOG(WINTUN_LOG_INFO, L"Spawning native process to %s instance", Action);
+
+ WCHAR InstanceId[MAX_INSTANCE_ID];
+ DWORD RequiredChars = _countof(InstanceId);
+ if (!SetupDiGetDeviceInstanceIdW(DevInfo, DevInfoData, InstanceId, RequiredChars, &RequiredChars))
{
- WCHAR RequestedGUIDStr[MAX_GUID_STRING_LEN];
- if (StringFromGUID2(RequestedGUID, RequestedGUIDStr, _countof(RequestedGUIDStr)))
- Arguments = ArgvToCommandLineW(3, Pool, Name, RequestedGUIDStr);
+ LOG_LAST_ERROR(L"Failed to get adapter instance ID");
+ return FALSE;
}
- else
- Arguments = ArgvToCommandLineW(2, Pool, Name);
+ LPWSTR Arguments = ArgvToCommandLineW(1, InstanceId);
if (!Arguments)
{
- LOG(WINTUN_LOG_ERR, L"Command line too long");
- SetLastError(ERROR_INVALID_PARAMETER);
- return NULL;
+ SetLastError(LOG_ERROR(ERROR_INVALID_PARAMETER, L"Command line too long"));
+ return FALSE;
}
- WINTUN_ADAPTER *Adapter = NULL;
DWORD LastError;
- WCHAR Response[8 + 1 + MAX_GUID_STRING_LEN + 1 + 8 + 1];
- if (!ExecuteRunDll32(L"CreateAdapter", Arguments, Response, _countof(Response)))
+ WCHAR Response[8 + 1];
+ if (!ExecuteRunDll32(Function, Arguments, Response, _countof(Response)))
{
- LastError = GetLastError();
- LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
+ LastError = LOG_LAST_ERROR(L"Error executing worker process: %s", Arguments);
goto cleanupArguments;
}
int Argc;
LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
- if (Argc < 3)
+ if (Argc < 1)
{
- LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
- LastError = ERROR_INVALID_PARAMETER;
+ LastError = LOG_ERROR(ERROR_INVALID_PARAMETER, L"Incomplete response: %s", Response);
goto cleanupArgv;
}
LastError = wcstoul(Argv[0], NULL, 16);
- if (LastError == ERROR_SUCCESS && (Adapter = AdapterOpenFromDevInstanceId(Pool, Argv[1])) == NULL)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get adapter %s", Argv[1]);
- LastError = ERROR_FILE_NOT_FOUND;
- }
- if (wcstoul(Argv[2], NULL, 16))
- *RebootRequired = TRUE;
cleanupArgv:
LocalFree(Argv);
cleanupArguments:
Free(Arguments);
- SetLastError(LastError);
- return Adapter;
+ return RET_ERROR(TRUE, LastError);
}
_Use_decl_annotations_
BOOL
-DeleteAdapterViaRundll32(const WINTUN_ADAPTER *Adapter, BOOL ForceCloseSessions, BOOL *RebootRequired)
+RemoveInstanceViaRundll32(HDEVINFO DevInfo, SP_DEVINFO_DATA *DevInfoData)
{
- LOG(WINTUN_LOG_INFO, L"Spawning native process");
- LPWSTR Arguments = ArgvToCommandLineW(3, Adapter->Pool, Adapter->DevInstanceID, ForceCloseSessions ? L"1" : L"0");
- if (!Arguments)
- {
- LOG(WINTUN_LOG_ERR, L"Command line too long");
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- WCHAR Response[8 + 1 + 8 + 1];
- DWORD LastError;
- if (!ExecuteRunDll32(L"DeleteAdapter", Arguments, Response, _countof(Response)))
- {
- LastError = GetLastError();
- LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
- goto cleanupArguments;
- }
- int Argc;
- LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
- if (Argc < 2)
- {
- LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
- LastError = ERROR_INVALID_PARAMETER;
- goto cleanupArgv;
- }
- LastError = wcstoul(Argv[0], NULL, 16);
- if (wcstoul(Argv[1], NULL, 16))
- *RebootRequired = TRUE;
-cleanupArgv:
- LocalFree(Argv);
-cleanupArguments:
- Free(Arguments);
- return RET_ERROR(TRUE, LastError);
+ return InvokeClassInstaller(L"remove", L"RemoveInstance", DevInfo, DevInfoData);
}
_Use_decl_annotations_
BOOL
-DeletePoolDriverViaRundll32(LPCWSTR Pool, BOOL *RebootRequired)
+EnableInstanceViaRundll32(HDEVINFO DevInfo, SP_DEVINFO_DATA *DevInfoData)
{
- LOG(WINTUN_LOG_INFO, L"Spawning native process");
- LPWSTR Arguments = ArgvToCommandLineW(1, Pool);
- if (!Arguments)
- {
- LOG(WINTUN_LOG_ERR, L"Command line too long");
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- WCHAR Response[8 + 1 + 8 + 1];
+ return InvokeClassInstaller(L"enable", L"EnableInstance", DevInfo, DevInfoData);
+}
+
+_Use_decl_annotations_
+BOOL
+DisableInstanceViaRundll32(HDEVINFO DevInfo, SP_DEVINFO_DATA *DevInfoData)
+{
+ return InvokeClassInstaller(L"disable", L"DisableInstance", DevInfo, DevInfoData);
+}
+
+_Use_decl_annotations_
+BOOL
+CreateInstanceWin7ViaRundll32(LPWSTR InstanceId)
+{
+ LOG(WINTUN_LOG_INFO, L"Spawning native process to create instance");
+
DWORD LastError;
- if (!ExecuteRunDll32(L"DeletePoolDriver", Arguments, Response, _countof(Response)))
+ WCHAR Response[MAX_INSTANCE_ID + 1];
+ if (!ExecuteRunDll32(L"CreateInstanceWin7", L"", Response, _countof(Response)))
{
- LastError = GetLastError();
- LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
- goto cleanupArguments;
+ LastError = LOG_LAST_ERROR(L"Error executing worker process");
+ goto cleanup;
}
int Argc;
LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
if (Argc < 2)
{
- LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
- LastError = ERROR_INVALID_PARAMETER;
+ LastError = LOG_ERROR(ERROR_INVALID_PARAMETER, L"Incomplete response: %s", Response);
goto cleanupArgv;
}
LastError = wcstoul(Argv[0], NULL, 16);
- if (wcstoul(Argv[1], NULL, 16))
- *RebootRequired = TRUE;
+ if (LastError == ERROR_SUCCESS)
+ wcsncpy_s(InstanceId, MAX_INSTANCE_ID, Argv[1], _TRUNCATE);
cleanupArgv:
LocalFree(Argv);
-cleanupArguments:
- Free(Arguments);
+cleanup:
return RET_ERROR(TRUE, LastError);
}
#endif