/*
功能:驱动中获取哈希。
注意事项:
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)
没有评论:
发表评论