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