内核挂钩调试记录

2019-07-24 15:36:46 浏览数 (1)

NTSTATUS Ioctl_DeviceControl(__in PDEVICE_OBJECT pDeviceObject, __in PIRP pIrp)

项目地址:https://github.com/angelkillah/zer0m0n

传入要监控的pid,具体代码例子:

代码语言:javascript复制
NTSTATUS Ioctl_DeviceControl(__in PDEVICE_OBJECT pDeviceObject,
   							 __in PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION pIoStackIrp = NULL;
	PCHAR buffer;
	ULONG ioControlCode;
	ULONG inputLength;
	ULONG malware_pid = 0;

	if(pIrp == NULL || pDeviceObject == NULL)
		return STATUS_INVALID_PARAMETER;

	pIoStackIrp = IoGetCurrentIrpStackLocation(pIrp);

	ioControlCode = pIoStackIrp->Parameters.DeviceIoControl.IoControlCode;
	inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength;
	buffer = pIrp->AssociatedIrp.SystemBuffer;

	switch(ioControlCode)
	{
		case IOCTL_PROC_MALWARE:
			Dbg("IOCTL_PROC_MALWARE receivedn");
			status = RtlCharToInteger(buffer, 10, &malware_pid);
			Dbg("malware_pid : %dn", malware_pid);
			if(NT_SUCCESS(status) && malware_pid > 0)
				StartMonitoringProcess(malware_pid);				
			break;	

		case IOCTL_PROC_TO_HIDE:
			Dbg("pids to hide : %sn", buffer);
			status = ParsePids(buffer);
			RtlZeroMemory(buffer, inputLength);
			break;


		case IOCTL_CUCKOO_PATH:
			cuckooPath = PoolAlloc(MAX_SIZE);
			if(inputLength && inputLength < MAX_SIZE)
				RtlStringCchPrintfW(cuckooPath, MAX_SIZE, L"\??\%ws", buffer);
			else
			{
				Dbg("IOCTL_CUCKOO_PATH : Buffer too largen");
				return STATUS_BUFFER_TOO_SMALL;
			}
			Dbg("cuckoo path : %wsn", cuckooPath);
			break;

		default:
			break;
	}

	pIrp->IoStatus.Status = status;	
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
}


注册接口:
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ioctl_DeviceControl;

ring3调用方式,代码如下:

代码语言:javascript复制
    if(kernel_analysis)
    {
        Sleep(5000);   
        // get handle to device driver and send IOCTLs   
        hDevice = CreateFile(PATH_KERNEL_DRIVER, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if(hDevice != INVALID_HANDLE_VALUE)
        {

            // send processes pid to hide
            processes_to_hide = malloc(MAX_PATH);
            sprintf(processes_to_hide, "%d,%d,%d", GetCurrentProcessId(), pid_from_process_name(L"VBoxService.exe"), pid_from_process_name(L"VBoxTray.exe"));
            if(DeviceIoControl(hDevice, IOCTL_PROC_TO_HIDE, processes_to_hide, strlen(processes_to_hide), NULL, 0, &dwBytesReturned, NULL))
                fprintf(stderr, "[ ] processes to hide [%s] sent to zer0m0nn", processes_to_hide);
            free(processes_to_hide);

            // send malware's pid
            s_pid = malloc(MAX_PATH);
            sprintf(s_pid, "%d", pid);
            if(DeviceIoControl(hDevice, IOCTL_PROC_MALWARE, s_pid, strlen(s_pid), NULL, 0, &dwBytesReturned, NULL))
                fprintf(stderr, "[ ] malware pid : %s sent to zer0m0nn", pid);
            free(s_pid);
        

            fprintf(stderr, "[ ] cuckoo path : %lsn", cuckoo_path);
            // send current directory
            if(DeviceIoControl(hDevice, IOCTL_CUCKOO_PATH, cuckoo_path, 200, NULL, 0, &dwBytesReturned, NULL))
                fprintf(stderr, "[ ] cuckoo path %ws sent to zer0m0nn", cuckoo_path);
        }
        else
            fprintf(stderr, "[-] failed to access kernel drivern");
        CloseHandle(hDevice);
    }

下面也是一种方法:

NtDebugActiveProcess( __in HANDLE ProcessHandle, __in HANDLE DebugHandle);

通过调用这个传入挂钩的handle,由于内核中hook了这个,因此宿主只要调用这个,就把自己传入进来了。

0 人点赞