/* 功能:驱动中获取哈希。 注意事项: 1.要链接到cng.lib,而不是应用层的Bcrypt.lib, 否则驱动启动因为找不到以来的文件,而显示错误码:2,及找不到文件。 具体的做法是: SOURCE文件的TARGETLIBS加上$(DDK_LIB_PATH)\cng.lib 或者: sources.props或类似的文件里的TARGETLIBS加上$(DDK_LIB_PATH)\cng.lib。 再说下是DDK_LIB_PATH,而不是SDK_LIB_PATH。 made by correy made at 2017.06.02 http://correy.webs.com */ #include <ntifs.h> #include <windef.h> #include <Bcrypt.h> #include <Ntstrsafe.h> #pragma warning(disable:4201) // nameless struct/union #pragma warning(disable:4214) // bit field types other than int #pragma warning(disable:4100) // 未引用的形参 #pragma warning(disable:4101) // 未引用的局部变量 #pragma warning(disable:4189) // 局部变量已初始化但不引用 #define TAG 'test' //test BOOL HASH(IN PBYTE rgbMsg, IN ULONG cbInput, LPWSTR algorithm, OUT PBYTE * Hash, DWORD * HashLen) /* 注意: 1.多字节和单字节。 2.算法名区分大小写,否者出现异常。 3.pbHash由调用者释放。 参考:https://msdn.microsoft.com/en-us/library/windows/desktop/aa376217(v=vs.85).aspx */ { BOOL B = FALSE; NTSTATUS status = STATUS_UNSUCCESSFUL; BCRYPT_ALG_HANDLE hAlg = NULL; DWORD cbData = 0;//calculate the size of the buffer to hold the hash object DWORD cbHashObject = 0; PBYTE pbHashObject = NULL; DWORD cbHash = 0;//calculate the length of the hash PBYTE pbHash = NULL; BCRYPT_HASH_HANDLE hHash = NULL; if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAlg, algorithm, NULL, 0)))//open an algorithm handle { goto Cleanup; } if(!NT_SUCCESS(status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0))) { goto Cleanup; } pbHashObject = (PBYTE)ExAllocatePoolWithTag(NonPagedPoolNx, cbHashObject, TAG); if(NULL == pbHashObject) { goto Cleanup; } RtlZeroMemory(pbHashObject, cbHashObject); if(!NT_SUCCESS(status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&cbHash, sizeof(DWORD), &cbData, 0))) { goto Cleanup; } pbHash = (PBYTE)ExAllocatePoolWithTag(NonPagedPoolNx, cbHash, TAG); if(NULL == pbHash) { goto Cleanup; } RtlZeroMemory(pbHash, cbHash); if(!NT_SUCCESS(status = BCryptCreateHash(hAlg, &hHash, pbHashObject, cbHashObject, NULL, 0, 0)))//create a hash { goto Cleanup; } if(!NT_SUCCESS(status = BCryptHashData(hHash, rgbMsg, cbInput, 0)))//hash some data { goto Cleanup; } //pbHash是哈希内容,cbHash是哈希的长度。 if(!NT_SUCCESS(status = BCryptFinishHash(hHash, pbHash, cbHash, 0)))//close the hash { goto Cleanup; } //wprintf(L"Success!\n"); * Hash = pbHash; * HashLen = cbHash; B = TRUE; Cleanup: if(hAlg) { BCryptCloseAlgorithmProvider(hAlg,0); } if (hHash) { BCryptDestroyHash(hHash); } if(pbHashObject) { ExFreePoolWithTag(pbHashObject, TAG); } //if(pbHash) //{ // HeapFree(GetProcessHeap(), 0, pbHash); //} return B; } BOOL HASHFILE(LPCTSTR lpFileName, LPWSTR algorithm, LPWSTR lpFileHash) /* 注意:lpFileName支持DOS格式,包括流, 但是不支持: 1.NT式的,\Device\XXX 2.带环境扩展的,%systemroot% 3.网络的也不行,如:\Device\Mup\vmware-host\Shared Folders\XXX 4.还有\SystemRoot\system32\drivers\spsys.sys。 注意:lpFileHash提供的空间要足够大,足够容纳想要的数据。 */ { unsigned int status = STATUS_SUCCESS; BOOL B = FALSE; HANDLE hFile = NULL; PBYTE buffer = NULL; DWORD NumberOfBytesRead = 0; PBYTE Hash; DWORD HashLen; unsigned int i; OBJECT_ATTRIBUTES ob; IO_STATUS_BLOCK IoStatusBlock = {0}; LARGE_INTEGER AllocationSize = {0}; UNICODE_STRING FileName; PFILE_OBJECT FileObject = 0; LARGE_INTEGER file_size = {0}; LARGE_INTEGER ByteOffset = {0}; RtlInitUnicodeString(&FileName, lpFileName); InitializeObjectAttributes(&ob, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0); status = ZwCreateFile( &hFile, FILE_ALL_ACCESS | SYNCHRONIZE, &ob, &IoStatusBlock, &AllocationSize, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_VALID_FLAGS, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if (!NT_SUCCESS (status)) { return FALSE; } status = ObReferenceObjectByHandle(hFile, FILE_LIST_DIRECTORY | SYNCHRONIZE, *IoFileObjectType, KernelMode, (PVOID *)&FileObject, NULL ); ASSERT (NT_SUCCESS( status )); status = FsRtlGetFileSize(FileObject, &file_size); ASSERT (NT_SUCCESS( status )); ASSERT(file_size.QuadPart); ASSERT(0 == file_size.HighPart); buffer = (PBYTE)ExAllocatePoolWithTag(NonPagedPoolNx, file_size.LowPart, TAG);//文件过大,这里会失败。 ASSERT(NULL != buffer); status = ZwReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock, buffer, file_size.LowPart, &ByteOffset, NULL); ASSERT (NT_SUCCESS( status )); B = HASH(buffer, file_size.LowPart, algorithm, &Hash, &HashLen); if (B) { //确保lpFileHash的大小大于HashLen for (i = 0; i < HashLen; i++) { RtlStringCchPrintfW(&lpFileHash[i * 2], 4, L"%02X", Hash[i]); } } ExFreePoolWithTag(Hash, TAG); ExFreePoolWithTag(buffer, TAG); ObDereferenceObject(FileObject); ZwClose( hFile ); return B; } VOID Unload(_In_ PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); PAGED_CODE(); } NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) { NTSTATUS Status = STATUS_SUCCESS; wchar_t buffer[MAX_PATH] = {0}; BOOL B = FALSE; UNREFERENCED_PARAMETER(RegistryPath); PAGED_CODE(); KdBreakPoint(); DriverObject->DriverUnload = Unload; B = HASHFILE(L"\\Device\\HarddiskVolume1\\test.txt", BCRYPT_SHA256_ALGORITHM, buffer); return Status; }
2017年6月2日星期五
驱动中获取哈希
订阅:
博文评论 (Atom)
没有评论:
发表评论