mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-14 03:29:44 +00:00
555 lines
14 KiB
C++
555 lines
14 KiB
C++
/**
|
|
* @file Install.cpp
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief Install functions
|
|
* @details
|
|
* @version 0.1
|
|
* @date 2020-04-11
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
/**
|
|
* @brief Install driver
|
|
*
|
|
* @param SC_HANDLE
|
|
* @param LPCTSTR
|
|
* @param LPCTSTR
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe)
|
|
{
|
|
SC_HANDLE SchService;
|
|
DWORD LastError;
|
|
|
|
//
|
|
// NOTE: This creates an entry for a standalone driver. If this
|
|
// is modified for use with a driver that requires a Tag,
|
|
// Group, and/or Dependencies, it may be necessary to
|
|
// query the registry for existing driver information
|
|
// (in order to determine a unique Tag, etc.)
|
|
//
|
|
|
|
//
|
|
// Create a new a service object
|
|
//
|
|
SchService = CreateService(SchSCManager, // handle of service control manager database
|
|
DriverName, // address of name of service to start
|
|
DriverName, // address of display name
|
|
SERVICE_ALL_ACCESS, // type of access to service
|
|
SERVICE_KERNEL_DRIVER, // type of service
|
|
SERVICE_DEMAND_START, // when to start service
|
|
SERVICE_ERROR_NORMAL, // severity if service fails to start
|
|
ServiceExe, // address of name of binary file
|
|
NULL, // service does not belong to a group
|
|
NULL, // no tag requested
|
|
NULL, // no dependency names
|
|
NULL, // use LocalSystem account
|
|
NULL // no password for service account
|
|
);
|
|
|
|
if (SchService == NULL)
|
|
{
|
|
LastError = GetLastError();
|
|
|
|
if (LastError == ERROR_SERVICE_EXISTS)
|
|
{
|
|
//
|
|
// The service is already been created
|
|
// means that, the driver is previously installed
|
|
//
|
|
ShowMessages("the service (driver) already exists\n");
|
|
|
|
//
|
|
// We need to remove the old instance of the driver first
|
|
// Because the version of the driver might be different from the
|
|
// user-mode application
|
|
//
|
|
ShowMessages("trying to remove the old instance of the driver first\n");
|
|
|
|
//
|
|
// Stop the driver
|
|
//
|
|
ManageDriver(DriverName, NULL, DRIVER_FUNC_STOP);
|
|
|
|
//
|
|
// Remove the driver
|
|
//
|
|
if (ManageDriver(DriverName, NULL, DRIVER_FUNC_REMOVE))
|
|
{
|
|
ShowMessages("the old instance of the driver is removed successfully\n");
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("err, failed to remove the old instance of the driver\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Try to install the driver again
|
|
//
|
|
ShowMessages("installing the driver again\n");
|
|
|
|
if (InstallDriver(SchSCManager, DriverName, ServiceExe))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("err, failed to install the driver after removing the old instance\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (LastError == ERROR_SERVICE_MARKED_FOR_DELETE)
|
|
{
|
|
//
|
|
// Previous instance of the service is not fully deleted so sleep
|
|
// and try again
|
|
//
|
|
ShowMessages("err, previous instance of the service is not fully deleted. Try "
|
|
"again...\n");
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("err, CreateService failed (%x)\n", LastError);
|
|
|
|
//
|
|
// Indicate an error
|
|
//
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close the service object
|
|
//
|
|
if (SchService)
|
|
{
|
|
CloseServiceHandle(SchService);
|
|
}
|
|
|
|
//
|
|
// Indicate success
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Manage Driver
|
|
*
|
|
* @param DriverName
|
|
* @param ServiceName
|
|
* @param Function
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, UINT16 Function)
|
|
{
|
|
SC_HANDLE SchSCManager;
|
|
BOOLEAN Res = TRUE;
|
|
|
|
//
|
|
// Insure (somewhat) that the driver and service names are valid
|
|
//
|
|
if (!DriverName || (Function == DRIVER_FUNC_INSTALL && !ServiceName))
|
|
{
|
|
ShowMessages("invalid Driver or Service provided to ManageDriver() \n");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Connect to the Service Control Manager and open the Services database
|
|
//
|
|
SchSCManager = OpenSCManager(NULL, // local machine
|
|
NULL, // local database
|
|
SC_MANAGER_ALL_ACCESS // access required
|
|
);
|
|
|
|
if (!SchSCManager)
|
|
{
|
|
ShowMessages("err, OpenSCManager failed (%x)\n", GetLastError());
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Do the requested function
|
|
//
|
|
switch (Function)
|
|
{
|
|
case DRIVER_FUNC_INSTALL:
|
|
|
|
//
|
|
// Install the driver service
|
|
//
|
|
|
|
if (InstallDriver(SchSCManager, DriverName, ServiceName))
|
|
{
|
|
//
|
|
// Start the driver service (i.e. start the driver)
|
|
//
|
|
Res = StartDriver(SchSCManager, DriverName);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Indicate an error
|
|
//
|
|
Res = FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case DRIVER_FUNC_STOP:
|
|
|
|
//
|
|
// Stop the driver
|
|
//
|
|
Res = StopDriver(SchSCManager, DriverName);
|
|
|
|
break;
|
|
|
|
case DRIVER_FUNC_REMOVE:
|
|
|
|
//
|
|
// Remove the driver service
|
|
//
|
|
Res = RemoveDriver(SchSCManager, DriverName);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ShowMessages("unknown ManageDriver() function \n");
|
|
|
|
Res = FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Close handle to service control manager
|
|
//
|
|
if (SchSCManager)
|
|
{
|
|
CloseServiceHandle(SchSCManager);
|
|
}
|
|
|
|
return Res;
|
|
}
|
|
|
|
/**
|
|
* @brief Remove Driver
|
|
*
|
|
* @param SC_HANDLE
|
|
* @param LPCTSTR
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
RemoveDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName)
|
|
{
|
|
SC_HANDLE SchService;
|
|
BOOLEAN Res;
|
|
|
|
//
|
|
// Open the handle to the existing service
|
|
//
|
|
SchService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
|
|
|
|
if (SchService == NULL)
|
|
{
|
|
ShowMessages("err, OpenService failed (%x)\n", GetLastError());
|
|
|
|
//
|
|
// Indicate error
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Mark the service for deletion from the service control manager database
|
|
//
|
|
if (DeleteService(SchService))
|
|
{
|
|
//
|
|
// Indicate success
|
|
//
|
|
Res = TRUE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("err, DeleteService failed (%x)\n", GetLastError());
|
|
|
|
//
|
|
// Indicate failure. Fall through to properly close the service handle
|
|
//
|
|
Res = FALSE;
|
|
}
|
|
|
|
//
|
|
// Close the service object
|
|
//
|
|
if (SchService)
|
|
{
|
|
CloseServiceHandle(SchService);
|
|
}
|
|
|
|
return Res;
|
|
}
|
|
|
|
/**
|
|
* @brief Start Driver
|
|
*
|
|
* @param SC_HANDLE
|
|
* @param LPCTSTR
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName)
|
|
{
|
|
SC_HANDLE SchService;
|
|
DWORD LastError;
|
|
BOOLEAN Status = TRUE;
|
|
|
|
//
|
|
// Open the handle to the existing service
|
|
//
|
|
SchService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
|
|
|
|
if (SchService == NULL)
|
|
{
|
|
ShowMessages("err, OpenService failed (%x)\n", GetLastError());
|
|
|
|
//
|
|
// Indicate failure
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Start the execution of the service (i.e. start the driver)
|
|
//
|
|
if (!StartService(SchService, // service identifier
|
|
0, // number of arguments
|
|
NULL // pointer to arguments
|
|
))
|
|
{
|
|
LastError = GetLastError();
|
|
|
|
if (LastError == ERROR_SERVICE_ALREADY_RUNNING)
|
|
{
|
|
//
|
|
// Ignore this error
|
|
//
|
|
}
|
|
else if (LastError == ERROR_PATH_NOT_FOUND)
|
|
{
|
|
//
|
|
// Driver not found, or anti-virus limits the access to it
|
|
//
|
|
ShowMessages("err, path to the driver not found, or the access to the driver file is limited\n");
|
|
|
|
ShowMessages("most of the time, it's because anti-virus software is not finished scanning the drivers, "
|
|
"so, if you try to load the driver again (re-enter the previous command), the problem will be solved\n");
|
|
|
|
//
|
|
// Indicate failure
|
|
//
|
|
Status = FALSE;
|
|
}
|
|
else if (LastError == ERROR_INVALID_IMAGE_HASH)
|
|
{
|
|
ShowMessages(
|
|
"err, failed loading driver\n"
|
|
"it's because either the driver signature enforcement is enabled or HVCI prevents the driver from loading\n"
|
|
"you should disable the driver signature enforcement by attaching WinDbg or from the boot menu\n"
|
|
"if the driver signature enforcement is disabled, HVCI might prevent the driver from loading\n"
|
|
"HyperDbg is not compatible with Virtualization Based Security (VBS)\n"
|
|
"please follow the instructions from: https://docs.hyperdbg.org/getting-started/build-and-install \n");
|
|
|
|
//
|
|
// Indicate failure. Fall through to properly close the service handle
|
|
//
|
|
Status = FALSE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("err, StartService failure (%x)\n", LastError);
|
|
|
|
//
|
|
// Indicate failure. Fall through to properly close the service handle
|
|
//
|
|
Status = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close the service object
|
|
//
|
|
if (SchService)
|
|
{
|
|
CloseServiceHandle(SchService);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
* @brief Stop driver
|
|
*
|
|
* @param SC_HANDLE
|
|
* @param LPCTSTR
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName)
|
|
{
|
|
BOOLEAN Res = TRUE;
|
|
SC_HANDLE SchService;
|
|
SERVICE_STATUS serviceStatus;
|
|
|
|
//
|
|
// Open the handle to the existing service
|
|
//
|
|
SchService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
|
|
|
|
if (SchService == NULL)
|
|
{
|
|
ShowMessages("err, OpenService failed (%x)\n", GetLastError());
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Request that the service stop
|
|
//
|
|
if (ControlService(SchService, SERVICE_CONTROL_STOP, &serviceStatus))
|
|
{
|
|
//
|
|
// Indicate success
|
|
//
|
|
Res = TRUE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("warning, failed to stop the driver. Possible reasons include the driver not currently running or an unsuccessful unload from a previous run. "
|
|
"This is not an error, HyperDbg tries to remove the previous driver and load it again (%x)\n",
|
|
GetLastError());
|
|
|
|
//
|
|
// Indicate failure. Fall through to properly close the service handle
|
|
//
|
|
Res = FALSE;
|
|
}
|
|
|
|
//
|
|
// Close the service object
|
|
//
|
|
if (SchService)
|
|
{
|
|
CloseServiceHandle(SchService);
|
|
}
|
|
|
|
return Res;
|
|
}
|
|
|
|
/**
|
|
* @brief Setup file name
|
|
*
|
|
* @param FileName
|
|
* @param FileLocation
|
|
* @param BufferLength
|
|
* @param CheckFileExists
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
SetupPathForFileName(const CHAR * FileName,
|
|
_Inout_updates_bytes_all_(BufferLength) PCHAR FileLocation,
|
|
ULONG BufferLength,
|
|
BOOLEAN CheckFileExists)
|
|
{
|
|
HANDLE FileHandle;
|
|
DWORD FileLocLen = 0;
|
|
HMODULE ProcHandle = GetModuleHandle(NULL);
|
|
CHAR * Pos;
|
|
|
|
//
|
|
// Get the current directory.
|
|
//
|
|
|
|
/*
|
|
//
|
|
// We use the location of running exe instead of
|
|
// finding driver based on current directory
|
|
//
|
|
FileLocLen = GetCurrentDirectory(BufferLength, DriverLocation);
|
|
|
|
if (FileLocLen == 0) {
|
|
|
|
ShowMessages("err, GetCurrentDirectory failed (%x)\n", GetLastError());
|
|
|
|
return FALSE;
|
|
}
|
|
*/
|
|
|
|
GetModuleFileName(ProcHandle, FileLocation, BufferLength);
|
|
|
|
Pos = strrchr(FileLocation, '\\');
|
|
if (Pos != NULL)
|
|
{
|
|
//
|
|
// this will put the null terminator here. you can also copy to
|
|
// another string if you want, we can also use PathCchRemoveFileSpec
|
|
//
|
|
*Pos = '\0';
|
|
}
|
|
|
|
//
|
|
// Setup path name to driver file
|
|
//
|
|
if (FAILED(
|
|
StringCbCat(FileLocation, BufferLength, "\\")))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (FAILED(
|
|
StringCbCat(FileLocation, BufferLength, FileName)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (CheckFileExists)
|
|
{
|
|
//
|
|
// ensure file is in the specified directory
|
|
//
|
|
if ((FileHandle = CreateFile(FileLocation, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
|
|
{
|
|
ShowMessages("err, target file is not loaded\n");
|
|
|
|
//
|
|
// Indicate failure
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Close open file handle
|
|
//
|
|
if (FileHandle)
|
|
{
|
|
CloseHandle(FileHandle);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Indicate success
|
|
//
|
|
return TRUE;
|
|
}
|