Skip to content

Commit

Permalink
[Loader] Added an option to create services with boot time start
Browse files Browse the repository at this point in the history
  • Loading branch information
0xcpu committed Oct 24, 2019
1 parent cac67ff commit 6a7e2b1
Showing 1 changed file with 112 additions and 38 deletions.
150 changes: 112 additions & 38 deletions Loader/Loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,30 @@
#include <string.h>


#define ALTSYSCALL_SERVICE_NAMEW L"ExCallbackObjectsSvc"
#define ALTSYSCALL_SERVICE_INSTALL 0
#define ALTSYSCALL_SERVICE_UNINSTALL 1
#define CALLBACKOBJ_SERVICE_NAMEW L"ExCallbackObjectsSvc"
#define CALLBACKOBJ_SERVICE_INSTALL 0
#define CALLBACKOBJ_SERVICE_UNINSTALL 1


PCWSTR g_ExCallbackObjectDrivers[] = {
L"WdProcessNotificationCallback.sys",
L"Phase1InitComplete.sys",
L"EnlightenmentState.sys"
typedef struct _EX_CALLBACK_OBJ_TUPLE {
PCWSTR DriverName;
DWORD StartType;
} EX_CALLBACK_OBJ_TUPLE;

EX_CALLBACK_OBJ_TUPLE g_ExCallbackObjectDrivers[] = {
{ L"WdProcessNotificationCallback.sys", SERVICE_DEMAND_START },
{ L"Phase1InitComplete.sys", SERVICE_BOOT_START },
{ L"EnlightenmentState.sys", SERVICE_BOOT_START }
};
DWORD g_NumCallbackObjectDrivers = sizeof(g_ExCallbackObjectDrivers) / sizeof(g_ExCallbackObjectDrivers[0]);

_Success_(return == TRUE)
BOOLEAN
InstallDriver(
_In_ SC_HANDLE hSCManager,
_In_ LPCTSTR ServiceName,
_In_ LPCTSTR DriverPath
_In_ SC_HANDLE hSCManager,
_In_ LPCTSTR ServiceName,
_In_ LPCTSTR DriverPath,
_In_ DWORD StartType
)
{
SC_HANDLE schService;
Expand All @@ -33,7 +39,7 @@ InstallDriver(
ServiceName,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
StartType,
SERVICE_ERROR_NORMAL,
DriverPath,
NULL,
Expand Down Expand Up @@ -175,9 +181,10 @@ StopDriver(
_Success_(return == TRUE)
BOOLEAN
ManageDriver(
_In_ LPCTSTR DriverPath,
_In_ LPCTSTR ServiceName,
_In_ SIZE_T Action
_In_ LPCTSTR DriverPath,
_In_ LPCTSTR ServiceName,
_In_ SIZE_T Action,
_In_ DWORD StartType
)
{
SC_HANDLE schSCManager;
Expand All @@ -197,15 +204,21 @@ ManageDriver(
}

switch (Action) {
case ALTSYSCALL_SERVICE_INSTALL:
if (InstallDriver(schSCManager, ServiceName, DriverPath)) {
bRetVal = StartDriver(schSCManager, ServiceName);
case CALLBACKOBJ_SERVICE_INSTALL:
if (InstallDriver(schSCManager, ServiceName, DriverPath, StartType)) {
if (StartType == SERVICE_DEMAND_START) {
bRetVal = StartDriver(schSCManager, ServiceName);
} else {
fprintf(stderr, __FUNCTION__ " StartType isn't DEMAND_START, the service isn't started\n");

bRetVal = TRUE;
}
} else {
bRetVal = FALSE;
}

break;
case ALTSYSCALL_SERVICE_UNINSTALL:
case CALLBACKOBJ_SERVICE_UNINSTALL:
if (StopDriver(schSCManager, ServiceName)) {
bRetVal = UninstallDriver(schSCManager, ServiceName);
} else {
Expand Down Expand Up @@ -267,52 +280,113 @@ int __cdecl main(int argc, char* argv[])
goto usage;
}

fprintf(stdout, "Selected callback object: %ls\n", g_ExCallbackObjectDrivers[dwCallbackId]);
fprintf(stdout, "Selected callback object: %ls\n", g_ExCallbackObjectDrivers[dwCallbackId].DriverName);

if (_strnicmp(argv[1], "load", strlen("load")) == 0) {
lpDriverName = g_ExCallbackObjectDrivers[dwCallbackId];

dwBufferLength = GetCurrentDirectory(dwBufferLength, lpBuffer);
if (!dwBufferLength) {
retCode = GetLastError();
fwprintf(stderr, L"Failed to query current directory length: %08X\n", retCode);
lpDriverName = g_ExCallbackObjectDrivers[dwCallbackId].DriverName;

return retCode;
} else {
lpBuffer = calloc(dwBufferLength + wcslen(lpDriverName) + 2, sizeof(WCHAR)); // + 2: 1 for \ and 1 for NULL
if (g_ExCallbackObjectDrivers[dwCallbackId].StartType == SERVICE_BOOT_START) {
// FIXME: User env variable expansion or read system drive letter instead of hardcoding.
LPCWSTR lpSystem32W = L"C:\\Windows\\System32\\";
lpBuffer = calloc(wcslen(lpSystem32W) + wcslen(lpDriverName) + 1, sizeof(WCHAR));
if (NULL == lpBuffer) {
retCode = GetLastError();
fwprintf(stderr, L"Failed allocating a buffer for current directory: %08X\n", retCode);
fwprintf(stderr, L"Failed allocating a buffer for System32: %08X\n", retCode);

return retCode;
goto free_buff;
}
if (wcsncpy_s(lpBuffer,
wcslen(lpSystem32W) + wcslen(lpDriverName) + 1,
lpSystem32W,
wcslen(lpSystem32W)) != 0) {
retCode = GetLastError();
fwprintf(stderr, L"wcsncpy_s failed: %08X\n", retCode);

free(lpBuffer);
lpBuffer = NULL;

if (!GetCurrentDirectory(dwBufferLength, lpBuffer)) {
goto free_buff;
}
if (wcsncat_s(lpBuffer,
wcslen(lpSystem32W) + wcslen(lpDriverName) + 1,
lpDriverName,
wcslen(lpDriverName)) != 0) {
retCode = GetLastError();
fwprintf(stderr, L"Failed to query current directory length: %08X\n", retCode);
fwprintf(stderr, L"wcsncat_s failed: %08X\n", retCode);

free(lpBuffer);
lpBuffer = NULL;

goto free_buff;
}

if (!CopyFile(lpDriverName, lpBuffer, TRUE)) {
retCode = GetLastError();
fwprintf(stderr, L"CopyFile failed: %08X\n", retCode);
} else {
fwprintf(stdout, L"%lS was successfully copied\n", lpBuffer);
}
} else if (g_ExCallbackObjectDrivers[dwCallbackId].StartType == SERVICE_DEMAND_START) {
dwBufferLength = GetCurrentDirectory(dwBufferLength, lpBuffer);
if (!dwBufferLength) {
retCode = GetLastError();
fwprintf(stderr, L"Failed to query current directory length: %08X\n", retCode);

return retCode;
} else {
lpBuffer = calloc(dwBufferLength + wcslen(lpDriverName) + 2, sizeof(WCHAR)); // + 2: 1 for \ and 1 for NULL
if (NULL == lpBuffer) {
retCode = GetLastError();
fwprintf(stderr, L"Failed allocating a buffer for current directory: %08X\n", retCode);

return retCode;
}

if (!GetCurrentDirectory(dwBufferLength, lpBuffer)) {
retCode = GetLastError();
fwprintf(stderr, L"Failed to query current directory length: %08X\n", retCode);

goto free_buff;
}
}

wcsncat_s(lpBuffer, dwBufferLength + wcslen(lpDriverName) + 1, L"\\", wcslen(L"\\"));
wcsncat_s(lpBuffer, dwBufferLength + wcslen(lpDriverName) + 1, lpDriverName, wcslen(lpDriverName));
if (wcsncat_s(lpBuffer,
dwBufferLength + wcslen(lpDriverName) + 1,
L"\\",
wcslen(L"\\")) != 0) {
retCode = GetLastError();
fwprintf(stderr, L"wcsncat_s failed: %08X\n", retCode);

goto free_buff;
}
if (wcsncat_s(lpBuffer,
dwBufferLength + wcslen(lpDriverName) + 1,
lpDriverName,
wcslen(lpDriverName)) != 0) {
retCode = GetLastError();
fwprintf(stderr, L"wcsncat_s failed: %08X\n", retCode);

fwprintf(stdout, L"Absolute path of the driver to load: %lS\n", lpBuffer);
goto free_buff;
}
} else {
fwprintf(stderr, L"Unknown service start option: %08X\n", g_ExCallbackObjectDrivers[dwCallbackId].StartType);

return EXIT_FAILURE;
}

ManageDriver(lpBuffer, ALTSYSCALL_SERVICE_NAMEW, ALTSYSCALL_SERVICE_INSTALL);
fwprintf(stdout, L"Absolute path of the driver to load: %lS\n", lpBuffer);

ManageDriver(lpBuffer, CALLBACKOBJ_SERVICE_NAMEW, CALLBACKOBJ_SERVICE_INSTALL, g_ExCallbackObjectDrivers[dwCallbackId].StartType);

free_buff:
free(lpBuffer);
lpBuffer = NULL;
} else {
goto usage;
}
} else if (argc > 1) {
if (_strnicmp(argv[1], "unload", strlen("unload")) == 0) {
ManageDriver(L"", ALTSYSCALL_SERVICE_NAMEW, ALTSYSCALL_SERVICE_UNINSTALL);
ManageDriver(L"", CALLBACKOBJ_SERVICE_NAMEW, CALLBACKOBJ_SERVICE_UNINSTALL, ULONG_MAX);
} else {
goto usage;
}
Expand All @@ -321,7 +395,7 @@ int __cdecl main(int argc, char* argv[])
fwprintf(stdout, L"[*] Usage: %hs [ load <callback_id> | unload ]\n", argv[0]);
fwprintf(stdout, L"[*] Available callback object drivers:\n");
for (size_t i = 0; i < g_NumCallbackObjectDrivers; i++) {
fwprintf(stdout, L"[+] %zu: %ls\n", i, g_ExCallbackObjectDrivers[i]);
fwprintf(stdout, L"[+] %zu: %ls\n", i, g_ExCallbackObjectDrivers[i].DriverName);
}
}

Expand Down

0 comments on commit 6a7e2b1

Please sign in to comment.