Windows内核态开发笔记

embedded/2024/10/19 9:34:52/

文章目录

    • r3/r0通信
    • x64 HOOK
    • 回调监控
    • 进程强杀
    • minifilter
    • ObRegisterCallbacks
    • WFP
    • 后记

r3/r0通信

用户态

#include <Windows.h>
#include <stdio.h>#define SENDSTR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
void main() {HANDLE device = CreateFileW(L"\\\\.\\cc", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);if (device == INVALID_HANDLE_VALUE) {printf("获取驱动句柄失败! 错误:%d\n", GetLastError());getchar();return;}const char* msg = "hello cccccccccc";char response[256] = { 0 };DWORD size = 0;DWORD bytesReturned = 0;if (!DeviceIoControl(device, SENDSTR, (LPVOID)msg, strlen(msg) + 1, response, sizeof(response), &bytesReturned, 0)) {printf("发送消息失败! 错误:%d\n", GetLastError());}else {printf("发送消息成功! 输出缓冲区大小:%d\n", bytesReturned);printf("从内核收到的回复: %s\n", response);}getchar();CloseHandle(device);
}

内核态

#include "ntddk.h"
#define SYMBOLLINK L"\\??\\cc"
//生成一个自己设备控制请求功能号 0-7ff 被微软保留,只能用比这大的
#define SENDSTR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
PDEVICE_OBJECT dev = NULL; //控制设备
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{if (DriverObject != NULL){UNICODE_STRING SymbolName;//符号链接RtlInitUnicodeString(&SymbolName, SYMBOLLINK);IoDeleteSymbolicLink(&SymbolName);//删除符号链接if (dev != NULL){IoDeleteDevice(dev);}DbgPrint("删除设备和符号链接成功");}
}
NTSTATUS CreateDevice(PDRIVER_OBJECT DriverObject) {NTSTATUS Status;  //返回状态UNICODE_STRING DeviceName; //设备名称UNICODE_STRING SymbolName;//符号链接RtlInitUnicodeString(&DeviceName, L"\\Device\\cc");Status = IoCreateDevice(DriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,0,TRUE, //是否是独占设备,安全软件一般都是独占,由某个进程打开着永不关闭&dev);do{if (!NT_SUCCESS(Status)) {if (Status == STATUS_OBJECT_NAME_COLLISION){DbgPrint("设备名称冲突");}DbgPrint("创建失败");break;}//初始化符号链接  设备名称应用程序是不可见的,因此驱动要暴露一个符号链接给应用层RtlInitUnicodeString(&SymbolName, SYMBOLLINK);Status = IoCreateSymbolicLink(&SymbolName, &DeviceName);if (!NT_SUCCESS(Status)) { //不等于0IoDeleteDevice(dev); //删除设备DbgPrint("删除设备成功");break;}else {DbgPrint("创建符号链接成功");}} while (FALSE);//仅执行一次的经典写法,为内核态的跳出格式return Status;
}
NTSTATUS fDispatch(PDEVICE_OBJECT pdev, PIRP irp) {UNREFERENCED_PARAMETER(pdev);NTSTATUS Status = STATUS_SUCCESS;  //返回状态ULONG len = 0;PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp);ULONG inBufferLength = stack->Parameters.DeviceIoControl.InputBufferLength;ULONG outBufferLength = stack->Parameters.DeviceIoControl.OutputBufferLength;PVOID inBuffer = (PCHAR)irp->AssociatedIrp.SystemBuffer;if (stack->MajorFunction == IRP_MJ_DEVICE_CONTROL){//处理DeviceIoControlswitch (stack->Parameters.DeviceIoControl.IoControlCode){case SENDSTR:if (inBufferLength > 0 && inBuffer != NULL) {DbgPrint("Received message from user: %s\n",(char*) inBuffer);char response[10] = "coleak";ULONG responseLength = (ULONG)strlen(response) + 1;if (outBufferLength >= responseLength) {RtlZeroMemory(inBuffer, outBufferLength);RtlCopyMemory(inBuffer, response, responseLength);len = responseLength;}else {Status = STATUS_BUFFER_TOO_SMALL;irp->IoStatus.Information = 0;}break;}default://到这里的请求都是不接受的请求,返回参数错误Status = STATUS_INVALID_PARAMETER;break;}}irp->IoStatus.Information = len;irp->IoStatus.Status = Status;IoCompleteRequest(irp, IO_NO_INCREMENT);return  Status;
}NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING  RegistryPath)
{//KdBreakPoint(); if (RegistryPath != NULL){DbgPrint("[%ws]所在注册表位置:%wZ\n", __FUNCTIONW__, RegistryPath);}if (DriverObject != NULL){DbgPrint("[%ws]驱动对象地址:%p\n", __FUNCTIONW__, DriverObject);//创建控制设备CreateDevice(DriverObject);//设置分发函数for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++){DriverObject->MajorFunction[i] = fDispatch;}DriverObject->DriverUnload = DriverUnload;DbgPrint("驱动加载成功");}return STATUS_SUCCESS;
}

浅记

  • CreateFileW的dwFlagsAndAttributes为FILE_ATTRIBUTE_SYSTEM,该文件是操作系统的一部分或由操作系统独占使用

  • DeviceIoControl设置功能号和r0进行通信,r0应该设置对应的的功能号以便判断IoControlCode后处理该请求

  • 用户态的链接符号格式为\\\\.\\链接名,内核态链接符号格式为\\??\\链接名

  • UNREFERENCED_PARAMETER可以忽略参数未使用的报错

  • METHOD_BUFFERED通信中内核的输入和输出缓冲区均为irp->AssociatedIrp.SystemBuffer

x64 HOOK

windbg调试下结构

cmd下:bcdedit -debug on
.sympath srv*C:\symbols\microsoft*https://msdl.microsoft.com/download/symbols
.reload
rdmsr C0000082
u fffff807`6502b800	(nt!KiSystemCall64)
u...
找到如下
nt!KiSystemServiceRepeat:
fffff807`6502bb64 4c8d15555d9d00  lea     r10,[nt!KeServiceDescriptorTable (fffff807`65a018c0)]
fffff807`6502bb6b 4c8d1d8e258f00  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff807`6591e100)]
特征码:4c8d15
这里的fffff807`65a018c0=fffff807`6502bb6b+9d5d55接下来找sysnumber
u zwopenprocess
nt!ZwOpenProcess+0x14:
fffff800`72c13414 b826000000      mov     eax,26h
fffff800`72c13419 e962830100      jmp     nt!KiServiceInternal (fffff800`72c2b780)
这里的26h也就是表中的38
dd KeServiceDescriptorTable
fffff800`736018c0  728cfb80 fffff800 00000000 00000000
fffff800`736018d0  000001e6 00000000 728d031c fffff800
这里主要找四个字节的偏移量ServiceTableBase

内核态

#include "ntddk.h"
#include<intrin.h>
#include "c.h"
PVOID oldfun = NULL;
ULONG funoffset = 0;
typedef NTSTATUS(*pNtOpenProcess)(_Out_ PHANDLE ProcessHandle,_In_ ACCESS_MASK DesiredAccess,_In_ POBJECT_ATTRIBUTES ObjectAttributes,_In_opt_ PCLIENT_ID ClientId);
KIRQL WPOFFx64()
{KIRQL irql = KeRaiseIrqlToDpcLevel();UINT64 cr0 = __readcr0();cr0 &= 0xfffffffffffeffff;__writecr0(cr0);_disable();return irql;
}
void WPONx64(KIRQL irql)
{UINT64 cr0 = __readcr0();cr0 |= 0x10000;_enable();__writecr0(cr0);KeLowerIrql(irql);
}
typedef struct _SERVICE_DESCRIPTOR_TABLE
{PVOID ServiceTableBase;PVOID ServiceCounterTableBase;ULONGLONG  NumberOfService;//SSDT表中服务函数的总数PVOID ParamTableBase;
} SSDTEntry, * PSSDTEntry;
NTSTATUS myNtOpenProcess(_Out_ PHANDLE ProcessHandle,_In_ ACCESS_MASK DesiredAccess,_In_ POBJECT_ATTRIBUTES ObjectAttributes,_In_opt_ PCLIENT_ID ClientId
) {DbgPrint("打开了一个进程:ClientId---%ld", ClientId->UniqueProcess);return ((pNtOpenProcess)oldfun)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
ULONGLONG Get_SSDT_Base()
{PUCHAR Base = (PUCHAR)__readmsr(0xC0000082);      // 读取C0000082寄存器PUCHAR Address = Base + 0x500;                    // 相加偏移PUCHAR i = NULL;UCHAR b1 = 0, b2 = 0, b3 = 0;                     // 保存特征码ULONG templong = 0;ULONGLONG addr = 0;                               // 最后获取到的地址for (i = Base; i < Address; i++){if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2)){b1 = *i; b2 = *(i + 1); b3 = *(i + 2);if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15)   // 判断是否=4c8d15{memcpy(&templong, i + 3, 4);              // 在i+3位置拷贝,拷贝4字节addr = (ULONGLONG)templong + (ULONGLONG)i + 7;return addr;}}}return addr;
}
VOID unhook() {PSSDTEntry ssdt = (PSSDTEntry)Get_SSDT_Base();PULONG stb = (PULONG)(ssdt->ServiceTableBase);KIRQL irql = WPOFFx64();//关保护stb[38] = funoffset;WPONx64(irql);DbgPrint("unhook");
}
ULONGLONG GetSSDTFunction(ULONG Index)
{PSSDTEntry ssdt = (PSSDTEntry)Get_SSDT_Base();PULONG stb = (PULONG)(ssdt->ServiceTableBase);LONG qwTemp = stb[Index];qwTemp = qwTemp >> 4;return (ULONGLONG)stb + (ULONGLONG)qwTemp;
}
ULONG getOffset(ULONGLONG addrFunction)
{PSSDTEntry ssdt = (PSSDTEntry)Get_SSDT_Base();PULONG stb = (PULONG)(ssdt->ServiceTableBase);LONG tmp = (LONG)(addrFunction - (ULONGLONG)stb);tmp = tmp << 4;return tmp;
}
VOID initKeBugCheckEx()
{/*48 B8 xxxx    mov rax,XXXh;FF E0      jmp rax*/UCHAR jmpCode[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0";ULONGLONG proxyFunction = (ULONGLONG)myNtOpenProcess;  //自己的NtOpenProessmemcpy(jmpCode + 2, &proxyFunction, 8);KIRQL irql = WPOFFx64();//关保护memcpy((void*)KeBugCheckEx, jmpCode, 12);WPONx64(irql);
}
VOID hookSSDT()
{oldfun = (PVOID)GetSSDTFunction(38);initKeBugCheckEx();PSSDTEntry ssdt = (PSSDTEntry)Get_SSDT_Base();PULONG stb = (PULONG)(ssdt->ServiceTableBase);funoffset = stb[38];KIRQL irql = WPOFFx64();//关保护stb[38] = getOffset((ULONGLONG)KeBugCheckEx);WPONx64(irql);DbgPrint("SSDT hooked");
}VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{UNREFERENCED_PARAMETER(DriverObject);unhook();DbgPrint("DriverUnload");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING  RegistryPath)
{DbgPrint("DriverEntry");UNREFERENCED_PARAMETER(RegistryPath);DriverObject->DriverUnload = DriverUnload;hookSSDT();return STATUS_SUCCESS;
}

浅记

  • 通过修改cr0寄存器的WP位来关闭写保护,并提高IRQL到DPC级别
  • 通过读取MSR寄存器0xC0000082,并向下查找特征码4c 8d 15以定位SSDT的基地址
  • ServiceTableBase+偏移量(stb[Index])可以和获取函数的地址
  • 构造jmpCode修改KeBugCheckEx前12位进行jmp到我们的函数
  • 函数地址-ServiceTableBase然后左移四位即可获取偏移量

回调监控

进程通知

#include "ntddk.h"
NTKERNELAPI UCHAR* PsGetProcessImageFileName( PEPROCESS Process);
VOID PcreateProcessNotifyRoutineEx(PEPROCESS Process,HANDLE ProcessId,PPS_CREATE_NOTIFY_INFO CreateInfo //进程创建相关的信息
) {//为Null表示是进程结束的通知if (CreateInfo == NULL){DbgPrint("进程结束id:%d 通知例程的当前线程ID:%d \n----------",(LONG) ProcessId, (LONG)PsGetCurrentThreadId());return;}/*进程创建通知*///获取进程的信息PCUNICODE_STRING ImageFileName = CreateInfo->ImageFileName;//进程名称HANDLE parentprocessid = CreateInfo->CreatingThreadId.UniqueProcess;//父进程idHANDLE parentthreadid = CreateInfo->CreatingThreadId.UniqueThread;//父进程线程idDbgPrint("通知例程的当前线程ID:%d 创建进程id:%d  父进程id:%d  父进程线程id:%d  进程名称:%wZ\n----------",(LONG)PsGetCurrentThreadId(),(LONG)ProcessId,(LONG)parentprocessid,(LONG)parentthreadid,ImageFileName);//在这里可以对进程进行监控,例如对指定进程禁止创建PUCHAR imageName = PsGetProcessImageFileName(Process);if (strcmp((const char*)imageName, "aaa.exe") == 0){CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;//拒绝操作DbgPrint("拦截了你创建进程:%wZ", imageName);}
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{UNREFERENCED_PARAMETER(DriverObject);PsSetCreateProcessNotifyRoutineEx(PcreateProcessNotifyRoutineEx, TRUE);DbgPrint("驱动卸载完成----------");}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING  RegistryPath)
{UNREFERENCED_PARAMETER(RegistryPath);PsSetCreateProcessNotifyRoutineEx(PcreateProcessNotifyRoutineEx, FALSE);DbgPrint("驱动加载完成----------");DriverObject->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}

浅记

  • PsSetCreateProcessNotifyRoutineEx对进程创建前进行回调,获得新进程handle、pid和CreateInfo
  • PsGetProcessImageFileName可以通过进程句柄获取进程的主模块路径,已导出需要声明

模块加载通知拦截

#include <ntifs.h>//PsLookupProcessByProcessId
#include "ntddk.h"
#include <ntimage.h>//pe格式解析需要
#include "c.h"
NTSTATUS MmUnmapViewOfSection(PEPROCESS Process, PVOID BaseAddr);typedef struct DATA {HANDLE processid;PVOID image;
} data, * pdata;void loadImageNotifyRoutine(PUNICODE_STRING FullImageName,HANDLE ProcessId,PIMAGE_INFO ImageInfo //模块在内存中的加载基址
) {DbgPrint("PID:[%d]	FullImageName:[%wZ]	size:[%d]	Base:[%p]----------", (LONG)ProcessId, FullImageName, ImageInfo->ImageSize, ImageInfo->ImageBase);//把模块路径转成普通的字符串便于操作CHAR name[1024] = { 0 };ANSI_STRING temp;RtlUnicodeStringToAnsiString(&temp, FullImageName, TRUE);RtlCopyMemory(name, temp.Buffer, temp.Length);RtlFreeAnsiString(&temp);HANDLE thread = NULL;//ProcessId = 0表示是驱动模块if (ProcessId != 0)//dll或exe{//要卸载DLL必须要等到进程里的所有模块加载完毕之后,采用办法多线程延时等待if (strstr(name, "aaa.dll") != NULL){pdata mydata = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(data),'a');//pdata mydata = ExAllocatePool(NonPagedPool, sizeof(data)); //堆里面分配内存mydata->image = ImageInfo->ImageBase;mydata->processid = ProcessId;//避免死锁,创建多线程延迟1秒然后卸载PsCreateSystemThread(&thread, 0, NULL, NtCurrentProcess(), NULL, threadProc, mydata);DbgPrint("拦截了你的DLL:%s", name);}}else//驱动{if (strstr(name, "aaa.sys") != NULL){disableDriver(ImageInfo->ImageBase);DbgPrint("拦截了你的驱动:%s", name);}}
}//拒绝加载驱动
VOID disableDriver(PVOID pImageBase) {UCHAR code[6] = { 0xB8, 0x22, 0x00, 0x00, 0xC0, 0xC3 };//STATUS_ACCESS_DENIED mov eax,0xc0000022 ret//根据基址找到入口地址DriverEntryPIMAGE_DOS_HEADER dosheader = pImageBase;PIMAGE_NT_HEADERS ntheads = (PIMAGE_NT_HEADERS)((PUCHAR)dosheader + dosheader->e_lfanew);PVOID pDriverEntry = (PVOID)((PUCHAR)dosheader + ntheads->OptionalHeader.AddressOfEntryPoint);//基地址加上偏移找到入口/*修改前6个字节*/PMDL pmdl = MmCreateMdl(NULL, pDriverEntry, 6);MmBuildMdlForNonPagedPool(pmdl);PVOID addr = MmMapLockedPages(pmdl, KernelMode);RtlCopyMemory(addr, code, 6);MmUnmapLockedPages(addr, pmdl);IoFreeMdl(pmdl);
}VOID threadProc(PVOID data) {pdata mydata = (pdata)data;LARGE_INTEGER time = { 0 };time.QuadPart = -10 * 1000 * 1000;//1秒KeDelayExecutionThread(KernelMode, FALSE, &time);//睡眠unDLL(mydata->processid, mydata->image);ExFreePool(mydata);
}//调用 MmUnmapViewOfSection卸载 
VOID unDLL(HANDLE processid, PVOID image) {PEPROCESS pEprocess = NULL;PsLookupProcessByProcessId(processid, &pEprocess);MmUnmapViewOfSection(pEprocess, image); //强力卸载
}VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{PsRemoveLoadImageNotifyRoutine(loadImageNotifyRoutine);DbgPrint("驱动卸载完成----------");}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING  RegistryPath)
{PsSetLoadImageNotifyRoutine(loadImageNotifyRoutine);DbgPrint("驱动加载完成----------");DriverObject->DriverUnload = DriverUnload;return STATUS_SUCCESS;	
}

浅记

  • RtlAnsiStringToUnicodeString的AllocateDestinationString选项分配了内存,需要用rtlFreeAnsiString释放
  • PsLookupProcessByProcessId接受pid返回PEPROCESS ,MmUnmapViewOfSection(需要声明)接受PEPROCESS 和dllbase强行取消加载的dll,测试中发现容易不稳定导致进程直接结束
  • KeDelayExecutionThread完成sleep操作,负数为相对时间,单位为100纳秒
  • ExAllocatePool2分配的内存必须ExFreePool去释放
  • 拒绝驱动加载即在对方驱动DriverEntry返回STATUS_ACCESS_DENIED,即mov eax,0xc0000022; ret
  • MmCreateMdl本质是申请一个非分页内存。然后初始化为MDL, MmBuildMdlForNonPagedPool更新 MDL 对物理内存的描述,MmMapLockedPages映射到一个内核地址,MmUnmapLockedPages先解除锁定,IoFreeMdl然后再释放
  • MDL 是用来建立一块虚拟地址空间与物理页面之间的映射,当我们要对一块内核内存进行修改的时候,我们先为这块内存创建 MDL,那么就会建立一块新的虚拟内存空间,与将要修改内存对应的物理空间相映射。也就是说,同一块物理空间,映射了两块不同的虚拟内存地址。我们可以通过这两个虚拟内存地址,来操作这块物理内存,这便是 MDL 修改内存的实现思路

进程强杀

查找特征码

.sympath srv*C:\symbols\microsoft*https://msdl.microsoft.com/download/symbols
.reload
u PsTerminateSystemThreadnt!PsTerminateSystemThread:
fffff803`525a5290 4883ec28        sub     rsp,28h
fffff803`525a5294 8bd1            mov     edx,ecx
fffff803`525a5296 65488b0c2588010000 mov   rcx,qword ptr gs:[188h]
fffff803`525a529f f7417400040000  test    dword ptr [rcx+74h],400h
fffff803`525a52a6 0f84d6df1400    je      nt!PsTerminateSystemThread+0x14dff2 (fffff803`526f3282)
fffff803`525a52ac 41b001          mov     r8b,1
fffff803`525a52af e8ecb1fcff      call    nt!PspTerminateThreadByPointer (fffff803`525704a0)
fffff803`525a52b4 4883c428        add     rsp,28hfffff803525704a0-fffff803525a52b4=FFFF FFFF FFFC B1EC,这里即fffcb1ec
#include <ntifs.h>
#include "ntddk.h"
#include "c.h"typedef NTSTATUS(_fastcall* PSPTERMINATETHREADBYPOINTER)(PETHREAD Thread, NTSTATUS Exitstatus, BOOLEAN DirectTerminate);VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{DriverObject = DriverObject;//消除未引用警告DbgPrint("驱动卸载完成----------");}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING  RegistryPath)
{RegistryPath = RegistryPath;DbgPrint("驱动加载完成----------");KillProcess((HANDLE)3408);DriverObject->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}//从PsTerminateSystemThread里面找到PsTerminateThreadByPointerPVOID getPsTerminateThreadByPointer() {UCHAR code = 0xe8;UNICODE_STRING FUNname;PVOID offset = NULL;RtlInitUnicodeString(&FUNname, L"PsTerminateSystemThread");//找到PsTerminateSystemThread地址PVOID pPsTerminateSystemThread = MmGetSystemRoutineAddress(&FUNname);if (pPsTerminateSystemThread == NULL){DbgPrint("pPsTerminateSystemThread找不到----------");return 0;}//扫描内存找到PsTerminateThreadByPointer地址for (PUCHAR i = (PUCHAR)pPsTerminateSystemThread; i < ((PUCHAR)pPsTerminateSystemThread + 0xFF); i++){//判断符合特征码地址if (*i == code){offset = (PVOID)(i + 1);break;}}if (offset == NULL){DbgPrint("OFFSET找不到----------");return 0;}//获取偏移计算地址LONG loffset = *(PLONG)offset;//取出偏移PVOID PsTerminateThreadByPointerAddress = (PVOID)((PUCHAR)offset + 4 + loffset);return PsTerminateThreadByPointerAddress;
}//强杀进程
NTSTATUS KillProcess(HANDLE pid) {NTSTATUS status = STATUS_SUCCESS;PEPROCESS pEprocess = NULL;PEPROCESS ThreadProcess = NULL;PETHREAD pEthread = NULL;//获取PsTerminateThreadByPointer地址PVOID PsTerminateThreadByPointerAddress = getPsTerminateThreadByPointer();//获取结束进程的EPROCESSstatus = PsLookupProcessByProcessId(pid, &pEprocess);if (!NT_SUCCESS(status)){DbgPrint("PsLookupProcessByProcessId GG----------");return status;}//遍历所有线程,并结束指定进程的所有线程ULONG i = 0;for (i = 4; i < 0x80000; i += 4){status = PsLookupThreadByThreadId((HANDLE)i, &pEthread);if (NT_SUCCESS(status)){//获取线程所属的进程的EPROCESSThreadProcess = PsGetThreadProcess(pEthread);if (pEprocess == ThreadProcess){((PSPTERMINATETHREADBYPOINTER)PsTerminateThreadByPointerAddress)(pEthread, 0, 1);DbgPrint(" thread:【%d】----------", i);}//lookup打开的必须释放掉ObDereferenceObject(pEthread);}}ObDereferenceObject(pEprocess);return status;
}
  • 根据特征码扫描内存,获取 PspTerminateThreadByPointer 函数地址
  • 调用 PsLookupProcessByProcessId 函数,根据将要结束进程 ID 获取对应的进程结构对象 EPROCESS
  • 遍历所有的线程 ID,并调用 PsLookupThreadByThreadId 函数根据线程 ID 获取对应的线程结构 ETHREAD
  • 调用函数 PsGetThreadProcess 获取线程结构 ETHREAD 对应的进程结构 EPROCESS
  • 通过判断该进程是不是我们指定要结束的进程,若是则调用PspTerminateThreadByPointer 函数结束线程;否则,继续遍历下一个线程 ID
  • 查杀指定进程的所有线程,所有线程被结束之后,进程也随之结束
  • 这里地址用PUCHAR计算进行位数对齐

minifilter

在vs2022中minifilter框架被移除,需要自己构建项目框架

https://github.com/microsoft/Windows-driver-samples/tree/main/filesys/miniFilter
https://blog.csdn.net/lyshark_csdn/article/details/134738527

需要手动在链接器-输入-依赖项中添加fltMgr.lib

代码框架:

#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
PFLT_FILTER gFilterHandle;DRIVER_INITIALIZE DriverEntry;
NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath
);NTSTATUS
PtInstanceSetup(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_SETUP_FLAGS Flags,_In_ DEVICE_TYPE VolumeDeviceType,_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
);VOID
PtInstanceTeardownStart(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);VOID
PtInstanceTeardownComplete(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);NTSTATUS
PtUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags
);NTSTATUS
PtInstanceQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);FLT_PREOP_CALLBACK_STATUS
PtPreOperationPassThrough(_Inout_ PFLT_CALLBACK_DATA Data,_In_ PCFLT_RELATED_OBJECTS FltObjects,_Flt_CompletionContext_Outptr_ PVOID* CompletionContext
);FLT_POSTOP_CALLBACK_STATUS
PtPostOperationPassThrough(_Inout_ PFLT_CALLBACK_DATA Data,_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_opt_ PVOID CompletionContext,_In_ FLT_POST_OPERATION_FLAGS Flags
);// 回调函数集
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{// 创建时触发 PreOperation(之前回调函数) / PostOperation(之后回调函数){ IRP_MJ_CREATE, 0, PtPreOperationPassThrough, PtPostOperationPassThrough },// 读取时触发{ IRP_MJ_READ, 0, PtPreOperationPassThrough, PtPostOperationPassThrough },// 写入触发{ IRP_MJ_WRITE, 0, PtPreOperationPassThrough, PtPostOperationPassThrough },// 设置时触发{ IRP_MJ_SET_INFORMATION, 0, PtPreOperationPassThrough, PtPostOperationPassThrough },// 结束标志{ IRP_MJ_OPERATION_END }
};//
//  This defines what we want to filter with FltMgr
//
CONST FLT_REGISTRATION FilterRegistration = {sizeof(FLT_REGISTRATION),         //  SizeFLT_REGISTRATION_VERSION,           //  Version0,                                  //  FlagsNULL,                               //  ContextCallbacks,                          //  Operation callbacksPtUnload,                           //  MiniFilterUnloadPtInstanceSetup,                    //  InstanceSetupPtInstanceQueryTeardown,            //  InstanceQueryTeardownPtInstanceTeardownStart,            //  InstanceTeardownStartPtInstanceTeardownComplete,         //  InstanceTeardownCompleteNULL,                               //  GenerateFileNameNULL,                            //  GenerateDestinationFileNameNULL                                //  NormalizeNameComponent
};// 当实例被安装时触发
NTSTATUS
PtInstanceSetup(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_SETUP_FLAGS Flags,_In_ DEVICE_TYPE VolumeDeviceType,_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
{DbgPrint("PassThrough!PtInstanceSetup: Entered\n");return STATUS_SUCCESS;
}// 当实例被销毁时触发
NTSTATUS
PtInstanceQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
{DbgPrint("PassThrough!PtInstanceQueryTeardown: Entered\n");return STATUS_SUCCESS;
}// 实例解除绑定时触发
VOID
PtInstanceTeardownStart(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{DbgPrint("PassThrough!PtInstanceTeardownStart: Entered\n");
}// 实例解绑完成时触发
VOID
PtInstanceTeardownComplete(_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{DbgPrint("PassThrough!PtInstanceTeardownComplete: Entered\n");
}/*************************************************************************MiniFilter initialization and unload routines.
*************************************************************************/NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath
)
{NTSTATUS status;DbgPrint("PassThrough!DriverEntry: Entered\n");status = FltRegisterFilter(DriverObject,&FilterRegistration,&gFilterHandle);if (NT_SUCCESS(status)) {status = FltStartFiltering(gFilterHandle);if (!NT_SUCCESS(status)) {FltUnregisterFilter(gFilterHandle);DbgPrint("[过滤器] 取消注册.. \n");}DbgPrint("[过滤器] 开启监控.. \n");}return status;
}NTSTATUS
PtUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags
)
{DbgPrint("PassThrough!PtUnload: Entered\n");FltUnregisterFilter(gFilterHandle);return STATUS_SUCCESS;
}/*************************************************************************MiniFilter callback routines.
*************************************************************************/
FLT_PREOP_CALLBACK_STATUS
PtPreOperationPassThrough(_Inout_ PFLT_CALLBACK_DATA Data,_In_ PCFLT_RELATED_OBJECTS FltObjects,_Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{NTSTATUS status;// 获取文件路径UCHAR MajorFunction = Data->Iopb->MajorFunction;PFLT_FILE_NAME_INFORMATION lpNameInfo = NULL;// 得到文件名相关信息status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &lpNameInfo);if (NT_SUCCESS(status)){status = FltParseFileNameInformation(lpNameInfo);if (NT_SUCCESS(status)){// 创建if (IRP_MJ_CREATE == MajorFunction){DbgPrint("[创建文件时] %wZ", &lpNameInfo->Name);// 拒绝创建// STATUS_INSUFFICIENT_RESOURCES                 提示不是有效的资源// STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY  静默拒绝// STATUS_ACCESS_DENIED                          提示访问拒绝// return STATUS_ACCESS_DENIED;// return FLT_PREOP_COMPLETE;}// 读取else if (IRP_MJ_READ == MajorFunction){DbgPrint("[读取文件] %wZ", &lpNameInfo->Name);// return FLT_PREOP_COMPLETE;}// 文件写入else if (IRP_MJ_WRITE == MajorFunction){DbgPrint("[写入文件] %wZ", &lpNameInfo->Name);// return FLT_PREOP_COMPLETE;}// 修改文件信息else if (IRP_MJ_SET_INFORMATION == MajorFunction){DbgPrint("[修改文件] %wZ", &lpNameInfo->Name);// return FLT_PREOP_COMPLETE;}}FltReleaseFileNameInformation(lpNameInfo);}return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}FLT_POSTOP_CALLBACK_STATUS
PtPostOperationPassThrough(_Inout_ PFLT_CALLBACK_DATA Data,_In_ PCFLT_RELATED_OBJECTS FltObjects,_In_opt_ PVOID CompletionContext,_In_ FLT_POST_OPERATION_FLAGS Flags
)
{return FLT_POSTOP_FINISHED_PROCESSING;
}

FltReleaseFileNameInformation需要放到FltGetFileNameInformation返回成功的逻辑里,否则会计数减失败从而造成蓝屏

注意:

Post-operation callback routines are called in an arbitrary thread context, at IRQL <= DISPATCH_LEVEL. Because this callback routine can be called at IRQL DISPATCH_LEVEL, it is subject to the following constraints:

  • It cannot safely call any kernel-mode routine that must run at a lower IRQL.
  • Any data structures used in this routine must be allocated from nonpaged pool.
  • It cannot be made pageable.
  • It cannot acquire resources, mutexes, or fast mutexes. However, it can acquire spin locks.
  • It cannot get, set, or delete contexts, but it can release contexts.

由于inf第三方没有签名,所以用c++进行手动加载添加注册表和服务

#include<windows.h>
#include <winsvc.h>
#include <winioctl.h>
#include <iostream>
BOOL InstallDriver(const char* lpszDriverName, const char* lpszDriverPath, const char* lpszAltitude);
BOOL StartDriver(const char* lpszDriverName);
BOOL StopDriver(const char* lpszDriverName);
BOOL DeleteDriver(const char* lpszDriverName);
BOOL InstallDriver(const char* lpszDriverName, const char* lpszDriverPath, const char* lpszAltitude)
{char    szTempStr[MAX_PATH];HKEY    hKey;DWORD    dwData;char    szDriverImagePath[MAX_PATH];if (NULL == lpszDriverName || NULL == lpszDriverPath){return FALSE;}//得到完整的驱动路径GetFullPathNameA(lpszDriverPath, MAX_PATH, szDriverImagePath, NULL);SC_HANDLE hServiceMgr = NULL;// SCM管理器的句柄SC_HANDLE hService = NULL;// NT驱动程序的服务句柄//打开服务控制管理器hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (hServiceMgr == NULL){// OpenSCManager失败CloseServiceHandle(hServiceMgr);return FALSE;}// OpenSCManager成功  //创建驱动所对应的服务hService = CreateServiceA(hServiceMgr,lpszDriverName,             // 驱动程序的在注册表中的名字lpszDriverName,             // 注册表驱动程序的DisplayName 值SERVICE_ALL_ACCESS,         // 加载驱动程序的访问权限SERVICE_FILE_SYSTEM_DRIVER, // 表示加载的服务是文件系统驱动程序SERVICE_DEMAND_START,       // 注册表驱动程序的Start 值SERVICE_ERROR_IGNORE,       // 注册表驱动程序的ErrorControl 值szDriverImagePath,          // 注册表驱动程序的ImagePath 值"FSFilter Activity Monitor",// 注册表驱动程序的Group 值NULL,"FltMgr",                   // 注册表驱动程序的DependOnService 值NULL,NULL);if (hService == NULL){if (GetLastError() == ERROR_SERVICE_EXISTS){//服务创建失败,是由于服务已经创立过CloseServiceHandle(hService);       // 服务句柄CloseServiceHandle(hServiceMgr);    // SCM句柄printf("already create");return TRUE;}else{CloseServiceHandle(hService);       // 服务句柄CloseServiceHandle(hServiceMgr);    // SCM句柄return FALSE;}}CloseServiceHandle(hService);       // 服务句柄CloseServiceHandle(hServiceMgr);    // SCM句柄//-------------------------------------------------------------------------------------------------------// SYSTEM\\CurrentControlSet\\Services\\DriverName\\Instances子健下的键值项 //-------------------------------------------------------------------------------------------------------strcpy_s(szTempStr, "SYSTEM\\CurrentControlSet\\Services\\");strcat_s(szTempStr, lpszDriverName);strcat_s(szTempStr, "\\Instances");if (RegCreateKeyExA(HKEY_LOCAL_MACHINE, szTempStr, 0, NULL, TRUE, KEY_ALL_ACCESS, NULL, &hKey, (LPDWORD)&dwData) != ERROR_SUCCESS){return FALSE;}// 注册表驱动程序的DefaultInstance 值 strcpy_s(szTempStr, lpszDriverName);strcat_s(szTempStr, " Instance");if (RegSetValueExA(hKey, "DefaultInstance", 0, REG_SZ, (CONST BYTE*)szTempStr, (DWORD)strlen(szTempStr)) != ERROR_SUCCESS){return FALSE;}RegFlushKey(hKey);//刷新注册表RegCloseKey(hKey);//-------------------------------------------------------------------------------------------------------//-------------------------------------------------------------------------------------------------------// SYSTEM\\CurrentControlSet\\Services\\DriverName\\Instances\\DriverName Instance子健下的键值项 //-------------------------------------------------------------------------------------------------------strcpy_s(szTempStr, "SYSTEM\\CurrentControlSet\\Services\\");strcat_s(szTempStr, lpszDriverName);strcat_s(szTempStr, "\\Instances\\");strcat_s(szTempStr, lpszDriverName);strcat_s(szTempStr, " Instance");if (RegCreateKeyExA(HKEY_LOCAL_MACHINE, szTempStr, 0, NULL,TRUE, KEY_ALL_ACCESS, NULL, &hKey, (LPDWORD)&dwData) != ERROR_SUCCESS){return FALSE;}// 注册表驱动程序的Altitude 值strcpy_s(szTempStr, lpszAltitude);if (RegSetValueExA(hKey, "Altitude", 0, REG_SZ, (CONST BYTE*)szTempStr, (DWORD)strlen(szTempStr)) != ERROR_SUCCESS){return FALSE;}// 注册表驱动程序的Flags 值dwData = 0x0;if (RegSetValueExA(hKey, "Flags", 0, REG_DWORD, (CONST BYTE*) & dwData, sizeof(DWORD)) != ERROR_SUCCESS){return FALSE;}RegFlushKey(hKey);//刷新注册表RegCloseKey(hKey);//-------------------------------------------------------------------------------------------------------printf("succ");return TRUE;
}BOOL StartDriver(const char* lpszDriverName)
{SC_HANDLE        schManager;SC_HANDLE        schService;SERVICE_STATUS    svcStatus;if (NULL == lpszDriverName){return FALSE;}schManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (NULL == schManager){printf("11");CloseServiceHandle(schManager);return FALSE;}schService = OpenServiceA(schManager, lpszDriverName, SERVICE_ALL_ACCESS);if (NULL == schService){CloseServiceHandle(schService);CloseServiceHandle(schManager);printf("22");return FALSE;}if (!StartServiceA(schService, 0, NULL)){CloseServiceHandle(schService);CloseServiceHandle(schManager);if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING){printf("33");// 服务已经开启return TRUE;}printf("44");return FALSE;}CloseServiceHandle(schService);CloseServiceHandle(schManager);printf("55");return TRUE;
}BOOL StopDriver(const char* lpszDriverName)
{SC_HANDLE        schManager;SC_HANDLE        schService;SERVICE_STATUS    svcStatus;bool            bStopped = false;schManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (NULL == schManager){return FALSE;}schService = OpenServiceA(schManager, lpszDriverName, SERVICE_ALL_ACCESS);if (NULL == schService){CloseServiceHandle(schManager);return FALSE;}if (!ControlService(schService, SERVICE_CONTROL_STOP, &svcStatus) && (svcStatus.dwCurrentState != SERVICE_STOPPED)){CloseServiceHandle(schService);CloseServiceHandle(schManager);return FALSE;}CloseServiceHandle(schService);CloseServiceHandle(schManager);return TRUE;
}BOOL DeleteDriver(const char* lpszDriverName)
{SC_HANDLE        schManager;SC_HANDLE        schService;SERVICE_STATUS    svcStatus;schManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (NULL == schManager){return FALSE;}schService = OpenServiceA(schManager, lpszDriverName, SERVICE_ALL_ACCESS);if (NULL == schService){CloseServiceHandle(schManager);return FALSE;}ControlService(schService, SERVICE_CONTROL_STOP, &svcStatus);if (!DeleteService(schService)){CloseServiceHandle(schService);CloseServiceHandle(schManager);return FALSE;}CloseServiceHandle(schService);CloseServiceHandle(schManager);return TRUE;
}
int main(int argc, char* argv[])
{while (1){char str[20] = "\0";printf("请输入命令: ");gets_s(str);if (strcmp(str, "1") == 0){if(StartDriver("minifilter"))printf("[*] 启动驱动 \n");}if (strcmp(str, "2") == 0){printf("[-] 关闭驱动 \n");StopDriver("minifilter");}if (strcmp(str, "3") == 0){printf("[-] 卸载驱动 \n");DeleteDriver("minifilter");}if (strcmp(str, "0") == 0){if (!InstallDriver("minifilter", ".\\mini.sys", "225000")){printf("InstallDriver failed");return 0;}}}return 0;
}

minifilter框架使用端口通信

FltCreateCommunicationPort
FltCloseCommunicationPort
通过回调函数的InputBuffer接受用户态的消息并通过OutputBuffer回复用户态通过FilterConnectCommunicationPort和FilterSendMessage通信

ObRegisterCallbacks

主要对下面三种方式进行过滤

  • 句柄的打开
  • 句柄的复制
  • 句柄的继承

微软提供了一个ObRegisterCallbacks函数可实现对对象回调的注册,这个函数可以监控获取进程句柄对象、线程句柄对象、桌面句柄对象

#include <ntifs.h>
#include "ntddk.h"HANDLE g_obProcessHandle;
PUCHAR PsGetProcessImageFileName(PEPROCESS pEProcess);
OB_PREOP_CALLBACK_STATUS ProcessPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo);
NTSTATUS SetProcessCallbacks();
BOOLEAN IsProtectProcess(PEPROCESS pEProcess);
VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{pRegPath = pRegPath;DbgPrint("驱动加载\n");NTSTATUS status;pDriverObject->DriverUnload = DriverUnload;// 设置进程回调函数status=SetProcessCallbacks();return status;
}VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{pDriverObject = pDriverObject;// 删除进程回调函数if (NULL != g_obProcessHandle){ObUnRegisterCallbacks(g_obProcessHandle);}DbgPrint("驱动卸载\n");
}// 设置进程回调函数
NTSTATUS SetProcessCallbacks()
{NTSTATUS status = STATUS_SUCCESS;OB_CALLBACK_REGISTRATION obCallbackReg = { 0 };OB_OPERATION_REGISTRATION obOperationReg = { 0 };// 设置 OB_CALLBACK_REGISTRATIONobCallbackReg.Version = OB_FLT_REGISTRATION_VERSION;//设置回调版本obCallbackReg.OperationRegistrationCount = 1;//回调函数数量obCallbackReg.RegistrationContext = NULL;RtlInitUnicodeString(&obCallbackReg.Altitude, L"321000");obCallbackReg.OperationRegistration = &obOperationReg;obOperationReg.ObjectType = PsProcessType;//设置过滤操作obOperationReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;obOperationReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)(&ProcessPreCall);obOperationReg.PostOperation = NULL;// 注册回调函数status = ObRegisterCallbacks(&obCallbackReg, &g_obProcessHandle);if (!NT_SUCCESS(status)){DbgPrint("ObRegisterCallbacks注册失败\n", status);return status;}return status;
}// 进程回调函数
OB_PREOP_CALLBACK_STATUS ProcessPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo)
{RegistrationContext = RegistrationContext;PEPROCESS pEProcess = NULL;pEProcess = (PEPROCESS)pObPreOperationInfo->Object;if (IsProtectProcess(pEProcess)){if (OB_OPERATION_HANDLE_CREATE == pObPreOperationInfo->Operation){pObPreOperationInfo->Parameters->CreateHandleInformation.DesiredAccess = 0;}else if (OB_OPERATION_HANDLE_DUPLICATE == pObPreOperationInfo->Operation){pObPreOperationInfo->Parameters->DuplicateHandleInformation.DesiredAccess = 0;}}return OB_PREOP_SUCCESS;
}
BOOLEAN IsProtectProcess(PEPROCESS pEProcess)
{PUCHAR pProcessName = PsGetProcessImageFileName(pEProcess);if (NULL != pProcessName){if (0 == _stricmp((const char*)pProcessName,"cc.exe")){DbgPrint("cc被保护了");return TRUE;}DbgPrint("ProcessName=%s\n", pProcessName);}return FALSE;
}

WFP

在这里插入图片描述

reference

https://v3ded.github.io/redteam/red-team-tactics-writing-windows-kernel-drivers-for-advanced-persistence-part-2
https://www.cnblogs.com/LyShark/p/17134954.html

逻辑梳理

WfpInit:
IoCreateDevice->FwpmEngineOpen->FwpsCalloutRegister->FwpmCalloutAdd->FwpmSubLayerAdd->FwpmFilterAdd
在FwpsCalloutRegister中指定CalloutFilter和CalloutNotify
CalloutFilter:
layerData->NET_BUFFER_LIST->NET_BUFFER_LIST_FIRST_NB->NdisGetDataBuffer
WfpCleanup:
FwpmSubLayerDeleteByKey,FwpmFilterDeleteById,FwpmCalloutDeleteById

icmp header

Type	Code	Checksum  Rest of header
8		8		16		  32
一共64位,即8字节ULONG  icmpLength = firstFragment->DataLength;
UINT32 dataLength = icmpLength - 8;
UINT32 payloadLength = dataLength - 4 - 1; //passwd:4,flag:1

发现std:c++20新语法hhh

    ExampleStruct example = {.id = 1,.name = "Example",.value = 10.5f};

icmp协议传输也是很方便,为了隐蔽还可以加密处理

在这里插入图片描述

补充一下显式事务

FwpmTransactionBegin、FwpmTransactionCommit、FwpmTransactionAbort
FwpmTransactionBegin 用于开始一个事务。在事务开始之后,对 WFP 对象的所有更改将被暂存,直到事务被提交或中止。
FwpmTransactionCommit 用于提交当前事务,应用所有暂存的更改。
FwpmTransactionAbort 用于中止当前事务,丢弃所有暂存的更改

再补充一下权限操作

actionType:一个FWP_ACTION_TYPE值,该值指定要根据标注驱动程序的分类Fn 标注函数确定的建议操作。 标注驱动程序将此变量设置为以下值之一:
FWP_ACTION_BLOCK
阻止传输或接收数据。
FWP_ACTION_CONTINUE
将阻止或允许数据传输或接收的决定传递给筛选器引擎中的下一个筛选器。
FWP_ACTION_NONE
不对数据执行任何操作。
FWP_ACTION_NONE_NO_MATCH
不对数据执行任何操作,因为它与枚举的筛选器数据类型不匹配。
FWP_ACTION_PERMIT
允许传输或接收数据。否定三连:classifyOut->actionType = FWP_ACTION_BLOCK;classifyOut->rights = classifyOut->rights & (~FWPS_RIGHT_ACTION_WRITE);classifyOut->flags = classifyOut->flags | FWPS_CLASSIFY_OUT_FLAG_ABSORB;

后记

输出格式控制

符号格式说明符类型
%c, %lcANSI字符char
%C, %wc宽字符wchar_t
%d, %i十进制有符号整数int
%D十进制__int64__int64
%L十六进制的LARGE_INTEGERLARGE_INTEGER
%s, %lsNULL终止的ANSI字符串char*
%S, %wsNULL终止的宽字符串wchar_t*
%ZANSI_STRING字符串ANSI_STRING
%wZUNICODE_STRING字符串UNICODE_STRING
%u十进制的ULONGULONG
%x小写字符十六进制的ULONGULONG
%X大写字符十六进制的ULONGULONG
%p指针Pointer 32/64位

api开头含义

Nt:NewTechnology WindowsNT系统

Ke:Kernel core / Ki:Kernel interfacce 内核接口

Cm:Configuration Manager 系统配置管理

Ex:Executive 执行相关

Hal:Hardware Abstraction Layer 硬件抽象层

Io:I/O Manager 输入/输出管理

Mm:Memory Manager 内存管理

Ob:Object Manager 对象管理

Po:Power Manager 电源管理

Tm:Transaction Manager 事务管理

Ps:Process Manager 进程管理

Se:Security 安全管理

Fs:File System 文件系统

PnP:Plug-and-Play 即插即用

Rtl:Runtime Library 运行时程序库

WDM:Windows Driver Model 驱动模式

DMA:Direct Memory Access 直接存储器访问

DPCs:Deferred Procedure Calls 延迟过程调用

ISRs:Interrupt Service Routines 中断服务例程

常识浅记

内存

我们程序所使用的内存地址叫做虚拟内存地址(Virtual Memory Address)
实际存在硬件里面的空间地址叫物理内存地址(Physical Memory Address)
操作系统引入了虚拟内存,进程持有的虚拟地址会通过 CPU 芯片中的内存管理单元(MMU)的映射关系,来转换变成物理地址,然后再通过物理地址访问内存内存分段:
内存碎片的问题共有两处地方:
外部内存碎片,也就是产生了多个不连续的小物理内存,导致新的程序无法被装载;
内部内存碎片,程序所有的内存都被装载到了物理内存,但是这个程序有部分的内存可能并不是很常使用,这也会导致内存的浪费;
为了解决内存分段的内存碎片和内存交换效率低的问题,就出现了内存分页。内存分页:
页表实际上存储在 CPU 的内存管理单元 (MMU) 中,于是 CPU 就可以直接通过 MMU,找出要实际要访问的物理内存地址。
而当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。

IRQL级别控制

Windows NT把内核模式地址空间分成分页内存池和非分页内存池。(用户模式地址空间总是分页的) 必须驻留的代码和数据放在非分页池;不必常驻的代码和数据放在分页池中。非分页内容的空间是很小的,所以一般的东西都会放入分页内存中。执行在高于或等于DISPATCH_LEVEL级上的代码必须存在于非分页内存中在写驱动的时候,经常要调用ExAllocatePoolWithTag函数分配内存,其中第一个参数可以是如下:
NonPagedPool:从非分页内存池中分配内存
PagedPool:从分页内存池中分配内存
即:分页内存是低中断级别的例程可以访问的,而非分页内存则是各个中断级别的例程都可以使用的(区别在于:分页内为存虚拟内存在,物理上未必总是能得到)在windows驱动开发中,常见的有以下几类中断优先级:
PASSIVE_LEVEL(0):
IRQL优先级最低的中断等级,用户模式执行在这个中断级,可以访问分页内存。这个等级的中断只能被其他高优先级的中断所中断,而不能中断其他中断APC_LEVEL(1):
IRQL为APC级别的中断会被屏蔽,可以访问分页内存。当有APC发生时,处理器提升到APC级别,这样,就屏蔽掉其它APC,为了和APC执行一些同步,驱动程序可以手动提升到这个级别,如果提升到这个级别,APC就不能调用。在这个级别,APC被禁止了,导致禁止一些I/O完成APC, 所以有一些API不能调用。DISPATCH_LEVEL(2):
这个级别,DISPATCH_LEVEL 和APC_LEVEL 中断被屏蔽,剩余拦不住的中断还有这些:设备、时钟、电源错误。StartIO、AdapterControl、IoTimer、Cancel等例程会要求屏蔽DISPATCH_LEVEL级中断。从这里开始只能使用非分页的内存DIRQL (Device IRQL 3-26)
IRQL<=26的中断都被屏蔽。大于该等级的拦不住,例如:clock、电源错误。InterruptService、SynchCritSection例程需要屏蔽这个等级的中断。APC_LEVEL 和 PASSIVE_LEVEL 之间的唯一区别是,在 APC_LEVEL 执行的进程无法获得 APC 中断。但两个 IRQL暗含线程上下文,两者都意味着代码可以使用分页内存。在内核模式下,可以通过内核函数 KeGetCurrentIrql(),来获得当前的中断等级。可以通过调用KeLowerIrql与KeRaiseIrql来降低和升级等级。可以先提升IRQL,然后恢复(下降)到原有IRQL;不能单独调用KeLowerIrql来降低IRQL;调用了KeRaiseIrql后必须调用KeLowerIrql恢复原有IRQL。

PAGED_CODE

PAGED_CODE 宏确保调用方线程在足够低的允许分页的 IRQL 上运行。
如果 IRQL >APC_LEVEL,PAGED_CODE 宏会导致系统出现 ASSERT。PAGED_CODE 宏仅检查位于驱动程序代码执行宏的位置的 IRQL。
和内存交换效率低的问题,就出现了内存分页。内存分页:
页表实际上存储在 CPU 的内存管理单元 (MMU) 中,于是 CPU 就可以直接通过 MMU,找出要实际要访问的物理内存地址。
而当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。

http://www.ppmy.cn/embedded/88842.html

相关文章

零基础入门转录组数据分析——机器学习算法之SVM-RFE(筛选特征基因)

零基础入门转录组数据分析——机器学习算法之SVM-RFE&#xff08;筛选特征基因&#xff09; 目录 零基础入门转录组数据分析——机器学习算法之SVM-RFE&#xff08;筛选特征基因&#xff09;1. SVM-RFE基础知识2. SVM-RFE&#xff08;Rstudio&#xff09;——代码实操2. 1 数据…

基于YOLOv8的船舶检测系统

基于YOLOv8的船舶检测系统 (价格85) 包含 【散货船&#xff0c;集装箱船&#xff0c;渔船&#xff0c;杂货船&#xff0c;矿砂船&#xff0c;客船】 6个类 通过PYQT构建UI界面&#xff0c;包含图片检测&#xff0c;视频检测&#xff0c;摄像头实时检测。 &#xff08;该…

【虚拟仿真】Unity3D中实现2DUI显示在3D物体旁边

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 这篇文章来实现2DUI显示在3D物体旁边,当我们需要在3D模型旁边显示2DUI的时候,比如人物的对…

VBA字典与数组第十七讲:工作表数组大小的扩展及意义

《VBA数组与字典方案》教程&#xff08;10144533&#xff09;是我推出的第三套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;字典是VBA的精华&#xff0c;我要求学员必学。7.1.3.9教程和手册掌握后&#xff0c;可以解决大多数工作中遇到的实际问题。…

代码改进跑通 创新点 文章复现 人工智能

代码改进跑通➕创新点➕文章复现➕人工智能 高质量接创新点代码改进跑通复现代码&#xff0c;模型优化 python代跑时间序列预测分析代码编写python编 程 深度学习算法自然语言处理神经网络跑通指导爬虫调试 项目指导定制代做改进提升创新优化Python Matlab COpencvNlp Pytorch …

计算机网络-PIM协议基础概念

一、PIM基础概念 组播网络回顾&#xff1a; 组播网络从网络结构上大体可以分为三个部分&#xff1a; 源端网络&#xff1a;将组播源产生的组播数据发送至组播网络。 组播转发网络&#xff1a;形成无环的组播转发路径&#xff0c;该转发路径也被称为组播分发树&#xff08;Multi…

网安零基础入门神书,全面介绍Web渗透核心攻击与防御方式!

Web安全是指Web服务程序的漏洞&#xff0c;通常涵盖Web漏洞、操作系统洞、数据库漏洞、中间件漏洞等。 “渗透测试”作为主动防御的一种关键手段&#xff0c;对评估网络系统安全防护及措施至关重要&#xff0c;因为只有发现问题才能及时终止并预防潜在的安全风险。 根据网络安…

如何确保PLC系统安全的可靠性,这几个注意事项你需要牢记

PLC&#xff08;可编程逻辑控制器&#xff09;是现代工业自动化系统中的关键组成部分。在设计 PLC 系统时&#xff0c;安全性是至关重要的考虑因素。本文将介绍 PLC 系统设计中的一些安全注意事项&#xff0c;包括电源设计、接地设计、关键数字量输入输出设计和报警设计。 一.…