/* 功能:驱动中获取哈希。 注意事项: 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日星期五
驱动中获取哈希
驱动中获取域名的IP地址
/* 功能:获取域名的IP地址。 made by correy made at 2017.06.01 http://correy.webs.com */ #include <ntddk.h> #include <wsk.h> #include <ws2def.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) // 局部变量已初始化但不引用 const WSK_CLIENT_DISPATCH WskAppDispatch = { MAKE_WSK_VERSION(1,0), // Use WSK version 1.0 0, // Reserved NULL // WskClientEvent callback not required for WSK version 1.0 }; WSK_REGISTRATION WskRegistration; NTSTATUS SyncIrpCompletionRoutine( __in PDEVICE_OBJECT Reserved, __in PIRP Irp, __in PVOID Context ) { PKEVENT compEvent = (PKEVENT)Context; UNREFERENCED_PARAMETER(Reserved); UNREFERENCED_PARAMETER(Irp); KeSetEvent(compEvent, 2, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS KernelNameResolutionSample( __in PCWSTR NodeName, __in_opt PCWSTR ServiceName, __in_opt PADDRINFOEXW Hints, __in PWSK_PROVIDER_NPI WskProviderNpi ) //https://docs.microsoft.com/en-us/windows-hardware/drivers/network/resolving-host-names-and-ip-addresses { NTSTATUS status; PIRP irp; KEVENT completionEvent; UNICODE_STRING uniNodeName, uniServiceName, *uniServiceNamePtr; PADDRINFOEXW results; SOCKADDR_IN * psi = NULL; wchar_t buffer[64] = {0}; PWSTR p = NULL; UNICODE_STRING ip = {0}; const struct in_addr * temp = NULL; PAGED_CODE(); RtlInitUnicodeString(&uniNodeName, NodeName);// Initialize UNICODE_STRING structures for NodeName and ServiceName if(ServiceName == NULL) { uniServiceNamePtr = NULL; } else { RtlInitUnicodeString(&uniServiceName, ServiceName); uniServiceNamePtr = &uniServiceName; } KeInitializeEvent(&completionEvent, SynchronizationEvent, FALSE);// Use an event object to synchronously wait for the WskGetAddressInfo request to be completed. // Allocate an IRP for the WskGetAddressInfo request, and set the IRP completion routine, which will signal the completionEvent when the request is completed. irp = IoAllocateIrp(1, FALSE); if(irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } IoSetCompletionRoutine(irp, SyncIrpCompletionRoutine, &completionEvent, TRUE, TRUE, TRUE); // Make the WskGetAddressInfo request. WskProviderNpi->Dispatch->WskGetAddressInfo ( WskProviderNpi->Client, &uniNodeName, uniServiceNamePtr, NS_ALL, NULL, // Provider Hints, &results, NULL, // OwningProcess NULL, // OwningThread irp); // Wait for completion. // Note that processing of name resolution results can also be handled directly within the IRP completion routine, // but for simplicity, this example shows how to wait synchronously for completion. KeWaitForSingleObject(&completionEvent, Executive, KernelMode, FALSE, NULL); status = irp->IoStatus.Status; IoFreeIrp(irp); if(!NT_SUCCESS(status)) { return status; } // Process the name resolution results by iterating through the addresses within the returned ADDRINFOEXW structure. //results; // your code here psi = (SOCKADDR_IN *)results->ai_addr;//注意:这一行很重要。有时要该为IPV6版本的。 temp = (const struct in_addr *)&psi->sin_addr; p = RtlIpv4AddressToString(temp, buffer); ASSERT(p); RtlInitUnicodeString(&ip, buffer); KdPrint(("ipv4:%wZ.\r\n", &ip)); WskProviderNpi->Dispatch->WskFreeAddressInfo(WskProviderNpi->Client, results);// Release the returned ADDRINFOEXW structure when no longer needed. return status; } VOID Unload(_In_ PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); PAGED_CODE(); WskDeregister(&WskRegistration); } NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) { NTSTATUS Status = STATUS_SUCCESS; WSK_CLIENT_NPI wskClientNpi; WSK_PROVIDER_NPI wskProviderNpi; //UNICODE_STRING test = RTL_CONSTANT_STRING(L"DESKTOP-SQRJ1QU"); UNREFERENCED_PARAMETER(RegistryPath); PAGED_CODE(); KdBreakPoint(); DriverObject->DriverUnload = Unload; wskClientNpi.ClientContext = NULL; wskClientNpi.Dispatch = &WskAppDispatch; Status = WskRegister(&wskClientNpi, &WskRegistration); ASSERT(NT_SUCCESS(Status)); Status = WskCaptureProviderNPI(&WskRegistration, WSK_INFINITE_WAIT, &wskProviderNpi); ASSERT(NT_SUCCESS(Status)); /* 做一些事情。 */ Status = KernelNameResolutionSample(L"www.baidu.com", NULL, NULL, &wskProviderNpi); ASSERT(NT_SUCCESS(Status)); WskReleaseProviderNPI(&WskRegistration); return Status; }
snwscanf
/* 文件名snwscanf.C 缘故: 系统中格式化字符串的函数不少,如: 2: kd> x nt!*Printf* fffff800`04dd1fa4 nt!vsnwprintf (<no parameter info>) fffff800`04dbe0e8 nt!RtlStringCbPrintfA (<no parameter info>) fffff800`04c96890 nt!RtlStringCbVPrintfA (<no parameter info>) fffff800`04dd746c nt!snwprintf_s (<no parameter info>) fffff800`04dd20b0 nt!vsnprintf_l (<no parameter info>) fffff800`04ec3e04 nt!StringCchPrintfExW (<no parameter info>) fffff800`04dd36f4 nt!sprintf (<no parameter info>) fffff800`04dd4164 nt!vsprintf_l (<no parameter info>) fffff800`04dd7ddc nt!sprintf_s (<no parameter info>) fffff800`04dd2098 nt!vsnprintf (<no parameter info>) fffff800`04dd7380 nt!snprintf_s (<no parameter info>) fffff800`04dd6c70 nt!vswprintf_s (<no parameter info>) fffff800`04dd1fbc nt!vsnwprintf_l (<no parameter info>) fffff800`04dd748c nt!vsnwprintf_s (<no parameter info>) fffff800`04c9cf54 nt!RtlStringCbPrintfW (<no parameter info>) fffff800`04d83d80 nt!StringCchPrintfW (<no parameter info>) fffff800`04f867e8 nt!g_AslLogPfnVPrintf = <no type information> fffff800`04d7e268 nt!RtlStringCbPrintfExW (<no parameter info>) fffff800`04dd29e0 nt!swprintf (<no parameter info>) fffff800`04dd29e0 nt!swprintf (<no parameter info>) fffff800`04dd6750 nt!get_printf_count_output (<no parameter info>) fffff800`04dd24d0 nt!snprintf (<no parameter info>) fffff800`05352008 nt!AslLogCallPrintf (<no parameter info>) fffff800`04dd2578 nt!snwprintf (<no parameter info>) fffff800`04dd6c50 nt!swprintf_s (<no parameter info>) fffff800`04dd2aa0 nt!vswprintf_l (<no parameter info>) fffff800`04dd2a94 nt!vswprintf (<no parameter info>) fffff800`04dbfdcc nt!RtlUnicodeStringPrintf (<no parameter info>) fffff800`04dd41dc nt!vsprintf (<no parameter info>) fffff800`04dd73a0 nt!vsnprintf_s (<no parameter info>) fffff800`04e5eba0 nt!RtlUnicodeStringPrintfEx (<no parameter info>) fffff800`04dd7dfc nt!vsprintf_s (<no parameter info>) fffff800`04d331b0 nt!RtlStringCchPrintfExW (<no parameter info>) fffff800`04e41a80 nt!RtlStringCbPrintfExA (<no parameter info>) fffff800`04dbfc5c nt!RtlStringCchPrintfA (<no parameter info>) fffff800`04d8ca18 nt!RtlStringCchPrintfW (<no parameter info>) WRK中也有不少,不信,你看代码。 凡是反过来,就没有,如:WRK中没有,XP和2003中没有。 还好vista开始有了,不信,你看: 2: kd> x nt!*scanf* fffff800`04dd7434 nt!snscanf_s (<no parameter info>) fffff800`04dd7e44 nt!sscanf_s (<no parameter info>) fffff800`04dd8298 nt!swscanf_s (<no parameter info>) fffff800`04dd752c nt!snwscanf_s (<no parameter info>) 有此足矣! stdio.h中尽管有_snwscanf_s的定义/声明,但是没有实现,不信,你编译下: error LNK2019: 无法解析的外部符号 _snwscanf_s,该符号在函数 XXX 中被引用。 但是,这不是难事,不信,你看本文的实现办法。 参考: https://msdn.microsoft.com/zh-cn/library/dktz45bk.aspx made by correy made at 2017.03.31 homepage:http://correy.webs.com */ #include <ntifs.h> //#include <ntddk.h> //这两个次序不能乱(乱会出错的),有上面的,这个可以注释掉。 #include <windef.h> #include <stdio.h> #define tag 'tset' //test #pragma warning(disable:4100) //未引用的形参 #pragma warning(disable:4214) //整形以外的位域类型 #pragma warning(disable:4121) //封装要区分成员对齐方式 #pragma warning(disable:4189) //局部变量已初始化但不引用 #pragma warning(disable:4101) //未引用的局部变量 #pragma warning(disable:4201) //使用了非标准扩展 : 无名称的结构/联合 #pragma warning(disable:4055) // //typedef OBJECT_TYPE * (*ObGetObjectType)(IN PVOID pObject); typedef int (__cdecl * SNWSCANF_S)(//snwscanf_s const wchar_t * input, size_t length, const wchar_t * format, ... ); SNWSCANF_S g_snwscanf_s; DRIVER_UNLOAD Unload; VOID Unload(__in PDRIVER_OBJECT DriverObject) { NTSTATUS status = STATUS_UNSUCCESSFUL; } DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_UNSUCCESSFUL; UNICODE_STRING test; KdBreakPoint(); DriverObject->DriverUnload = Unload; RtlInitUnicodeString( &test, L"_snwscanf_s" ); g_snwscanf_s = (SNWSCANF_S)MmGetSystemRoutineAddress(&test);//注意:赋值的类型转换。 if (g_snwscanf_s) { wchar_t input[] = L"999999999"; int number = 0; int i = g_snwscanf_s(input, wcslen(input) * sizeof(wchar_t), L"%d", &number); ASSERT(i); } return status; }
订阅:
博文 (Atom)