当前位置: 首页 > 科技观察

网络安全编程:内核驱动进程遍历

时间:2023-03-20 11:09:16 科技观察

内核驱动在安全中扮演着重要的角色。本文实现了一个枚举进程的功能。枚举过程不能在用户态进行,需要在内核态进行,所以必须使用驱动来完成。先用WinDbg完成一个手工枚举过程,再通过代码完成。1、配置VMware和WinDbg进行驱动调试使用WinDbg调试驱动或内核,需要两台电脑进行调试。所谓双机就是两台电脑。通常,大多数人往往只有一台计算机。那么,解决方法就是安装虚拟机,然后在虚拟机上进行一些设置,也可以通过WinDbg进行调试。虚拟机选择使用VMware,下面介绍如何配置虚拟机。安装VMware,并在VMware中安装操作系统,然后对安装好的虚拟机进行一些设置。通过这个设置,可以实现调试器和虚拟机的连接。点击菜单“VM”→“设置”命令弹出“虚拟机设置”对话框,如图1所示。图1“虚拟机设置”对话框点击“添加”按钮打开“添加硬件”向导”(AddHardwareWizard)对话框,如图2所示。图2“添加硬件向导”对话框1在该对话框中选择“SerialPort”选项,也就是串口,然后点击“Next””按钮弹出“添加硬件向导”对话框第二个界面,如图3所示。图3“添加硬件向导”对话框2在该界面中选中“输出到命名管道”单选按钮,即是,命名管道。命名管道是Windows下进程通信的一种方式。选择此项后,继续点击“下一步”按钮,进入下一个界面,也是上次设置的界面,如图4所示。图4“添加硬件向导”对话框3在此界面设置命名管道,然后单击“完成”按钮。至此,设置完成一半。接下来,启动虚拟机配置WindowsBoot.ini文件。Boot.ini文件原内容如下:[bootloader]timeout=30default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS[operatingsystems]multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="MicrosoftWindowsXPProfessional"/fastdetect/NoExecute=AlwaysOff复制最后一行,放在最后,修改。修改内容如下:[bootloader]timeout=30default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS[operatingsystems]multi(0)disk(0)rdisk(0)partition(1))\WINDOWS="MicrosoftWindowsXPProfessional"/fastdetect/NoExecute=AlwaysOffmulti(0)disk(0)rdisk(0)partition(1)\WINDOWS="MicrosoftWindowsXPProfessional"/fastdetect/NoExecute=optin/debug/debugport=com1/baudrate=115200去除Boot.ini文件的只读属性,然后保存Boot.ini文件。下次需要调试驱动程序或内核时,选择以调试模式启动Windows。这里只介绍WindowsXP系统的配置方法。其他版本系统的配置方法请参考相关内容。至此,所有的配置工作都已经完成,但是在使用WinDbg连接时,仍然存在连接参数问题。首先在桌面创建WinDbg快捷方式,然后在WinDbg快捷方式上右击,在弹出的快捷菜单中选择“属性”命令,弹出“属性”对话框,更改“目标”位置to:F:\WinDDK\7600.16385.0\Debuggers\windbg.exe-b-kcom:port=\\.\pipe\com_1,baud=115200,pipe这样就可以在WindowsXP中使用WinDbg连接了虚拟机中的调试状态。2.EPROCESS与手动遍历进程Windows有一个非常庞大的进程相关结构——EPROCESS。每个进程对应一个EPROCESS结构,但EPROCESS是系统未公开的结构。在WDK中只能找到描述,找不到其结构的具体定义,需要通过WinDbg查看。这次使用WinDbg和VMware进行调试。按照前面的方法,让WinDbg和VMware可以连接。当出现WinDbg调试界面时,在其命令处输入dt_eprocess命令查看结构,如图5所示图5WinDbg显示的部分EPROCESS结构从图中可以看出EPROCESS结构显示了很多的内容,从WinDbg调试界面只能看到部分成员变量,偏移量已经到了0x258,非常大。看一下WinDbg的全部内容。kd>dt_eprocessnt!_EPROCESS+0x000Pcb:_KPROCESS//进程控制块+0x06cProcessLock:_EX_PUSH_LOCK+0x070CreateTime:_LARGE_INTEGER+0x078ExitTime:_LARGE_INTEGER+0x080RundownProtect:_EX_RUNDOWN_REF+0x084UniqueProcessId:Ptr32Void//进程ID+0x088ActiveProcessLinks:_LIST_ENTRY//活动进程链表+0x090QuotaUsage:[3]Uint4B+0x09cQuotaPeak:[3]Uint4B+0x0a8CommitCharge:Uint4B+0x0acPeakVirtualSize:Uint4B+0x0b0VirtualSize:Uint4B+0x0b4SessionProcessLinks:_LIST_ENTRY+0x0bcDebugPort:Ptr32Void+0x0c0ExceptionPort:Ptr32Void+0x0c4ObjectTable:Ptr32_HANDLE_TABLE+0x0c8Token:_EX_FAST_REF+0x0ccWorkingSetLock:_FAST_MUTEX+0x0ecWorkingSetPage:Uint4B+0x0f0AddressCreationLock:_FAST_MUTEX+0x110HyperSpaceLock:Uint4B+0x114ForkInProgress:Ptr32_ETHREAD+0x118HardwareTrigger:Uint4B+0x11cVadRoot:Ptr32Void+0x120VadHint:Ptr32Void+0x124CloneRoot:Ptr32Void+0x128NumberOfPrivatePages:Uint4B+0x12cNumberOfLockedPages:Uint4B+0x130Win32Process:Ptr32Void+0x134Job:Ptr32_EJOB+0x138SectionObject:Ptr32Void+0x13cSectionBaseAddress:Ptr32Void+0x140QuotaBlock:Ptr32_EPROCESS_QUOTA_BLOCK+0x144WorkingSetWatch:Ptr32_PAGEFAULT_HISTORY+0x148Win32WindowStation:Ptr32Void+0x14cInheritedFromUniqueProcessId:Ptr32Void+0x150LdtInformation:Ptr32Void+0x154VadFreeHint:Ptr32Void+0x158VdmObjects:Ptr32Void+0x15cDeviceMap:Ptr32Void+0x160PhysicalVadList:_LIST_ENTRY+0x168PageDirectoryPte:_HARDWARE_PTE+0x168Filler:Uint8B+0x170Session:Ptr32Void+0x174ImageFileName:[16]UChar//进程名+0x184JobLinks:_LIST_ENTRY+0x18cLockedPagesList:Ptr32Void+0x190ThreadListHead:_LIST_ENTRY+0x198SecurityPort:Ptr32Void+0x19cPaeTop:Ptr32Void+0x1a0ActiveThreads:Uint4B+0x1a4GrantedAccess:Uint4B+0x1a8DefaultHardErrorProcessing:Uint4B+0x1acLastThreadExitStatus:Int4B+0x1b0Peb:Ptr32_PEB//进程环境块+0x1b4PrefetchTrace:_EX_FAST_REF+0x1b8ReadOperationCount:_LARGE_INTEGER+0x1c0WriteOperationCount:_LARGE_INTEGER+0x1c8OtherOperationCount:_LARGE_INTEGER+0x1d0ReadTransferCount:_LARGE_INTEGER+0x1d8WriteTransferCount:_LARGE_INTEGER+0x1e0OtherTransferCount:_LARGE_INTEGER+0x1e8CommitChargeLimit:Uint4B+0x1ecCommitChargePeak:Uint4B+0x1f0AweInfo:Ptr32Void+0x1f4SeAuditProcessCreationInfo:_SE_AUDIT_PROCESS_CREATION_INFO+0x1f8Vm:_MMSUPPORT+0x238LastFaultCount:Uint4B+0x23cModifiedPageCount:Uint4B+0x240NumberOfVads:Uint4B+0x244JobStatus:Uint4B+0x248Flags:Uint4B+0x248CreateReported:Pos0,1Bit+0x248NoDebugInherit:Pos1,1Bit+0x248ProcessExiting:Pos2,1Bit+0x248ProcessDelete:Pos3,1Bit+0x248Wow64SplitPages:Pos4,1Bit+0x248VmDeleted:Pos5,1Bit+0x248OutswapEnabled:Pos6,1Bit+0x248Outswapped:Pos7,1Bit+0x248ForkFailed:Pos8,1Bit+0x248HasPhysicalVad:Pos9,1Bit+0x248AddressSpaceInitialized:Pos10,2Bits+0x248SetTimerResolution:Pos12,1Bit+0x248BreakOnTermination:Pos13,1Bit+0x248SessionCreationUnderway:Pos14,1Bit+0x248WriteWatch:Pos15,1Bit+0x248ProcessInSession:Pos16,1Bit+0x248OverrideAddressSpace:Pos17,1Bit+0x248HasAddressSpace:Pos18,1Bit+0x248LaunchPrefetched:Pos19,1Bit+0x248InjectInpageErrors:Pos20,1Bit+0x248VmTopDown:Pos21,1Bit+0x248Unused3:Pos22,1Bit+0x248Unused4:Pos23,1Bit+0x248VdmAllowed:Pos24,1Bit+0x248Unused:Pos25,5Bits+0x248Unused1:Pos30,1Bit+0x248Unused2:Pos31,1Bit+0x24cExitStatus:Int4B+0x250Nex??tPageColor:Uint2B+0x252SubSystemMinorVersion:UChar+0x253SubSystemMajorVersion:UChar+0x252SubSystemVersion:Uint2B+0x254PriorityClass:UChar+0x255WorkingSetAcquiredUnsafe:UChar+0x258Cookie:Uint4B以上就是EPROCESS结构的全部内容。遍历进程列表,有用的内容只有几个,第一个是偏移量0x84处的进程ID,然后是偏移量0x88处的进程列表,最后一个是偏移量0x174处的进程名。下面是手动遍历。输入!在WinDbg的命令输入提示符下执行Process00命令获取进程列表,如图6所示。图6进程信息PROCESS后给定的值为当前进程中EPROCESS的地址,选择由给定的地址0xff364708explorer.exe进程来分析EPROCESS。输入命令dt_eprocessff364708,输出如下:kd>dt_eprocessff364708nt!_EPROCESS+0x000Pcb:_KPROCESS+0x06cProcessLock:_EX_PUSH_LOCK+0x070CreateTime:_LARGE_INTEGER0x1cb6af5`91d56cea+0x078ExitTime:_LARGE_INTEGER0x0+0x080RundownProtect:_EX_RUNDOWN_REF+0x084UniqueProcessId:0x00000600+0x088ActiveProcessLinks:_LIST_ENTRY[0xff2b44b0-0xff3640a8]<部分遗漏>+0x174ImageFileName:[16]"explorer.exe"<部分遗漏>+0x1b0Peb:0x7ffde000_PEB<后续遗漏>可以看到根据EPROCESS结构解析了ff364708地址,输出了需要的内容。Next,gettheinformationofthenextprocessthroughActiveProcessLinks.输入命令ddff364708+0x88,输出如下:kd>ddff364708+0x88ff364790ff2b44b0ff3640a80000294000021944ff3647a000000a920000394000024cb400000bf8ff3647b000000a9205e040000563a000ff2b44dcff3647c0ff3640d400000000e15b6eb8e1ce2640ff3647d0e166f38900000001f39a544000000000ff3647e00004000100000000ff3647e8ff3647e8ff3647f00000003d000059ca00000001f39a5440ff364800000000000004000100000000ff36480cff364790地址处保存了下一个EPROCESS结构体ActiveProcessLinks的地址。TogettheaddressofthenextEPROCESS,you必须减去0x88。输入命令dt_eprocess(ff2b44b0–0x88),输出如下:kd>dt_eprocess(ff2b44b0-0x88)nt!_EPROCESS+0x000Pcb:_KPROCESS+0x06cProcessLock:_EX_PUSH_LOCK+0x070CreateTime:_LARGE_INTEGER0x1cb6af5`95026ecc+0x078ExitTime:_LARGE_INTEGER0x0+0x080RundownProtect:_EX_RUNDOWN_REF+0x084UniqueProcessId:0x000006b8+0x088ActiveProcessLinks:_LIST_ENTRY[0xff2b7580-0xff364790]<下略>+0x174ImageFileName:[16]"VMwareTray.exe"<下略>将输出结果与图6的结果进行比较,explorer.exe的下一个进程是VMwareTray。EXE文件。可见遍历方法是正确的。3.编程实现过程遍历上面介绍的手动遍历过程是为了指导用户如何编写代码。只要能掌握上面的手动遍历过程,那么写代码就不是问题了。下面直接查看代码:NTSTATUSDriverEntry(PDRIVER_OBJECTpDriverObject,PUNICODE_STRINGpRegistryPath){PEPROCESSpEprocess=NULL;PEPROCESSpFirstEprocess=NULL;ULONGulProcessName=0;ULONGulProcessId=0;pDriverObject->DriverUnloadDriverUnload=DriverUnload==;pEprocess=Pcessd()(("PsGetcurrentProcessError!\r\n"));returnSTATUS_SUCCESS;}pFirstEprocess=pEprocess;while(pEprocess!=NULL){ulProcessName=(ULONG)pEprocess+0x174;ulProcessId=*(ULONG*)((ULONG)pEprocess+0x84);KdPrint(("ProcessName=%s,ProcessId=%d\r\n",ulProcessName,ulProcessId));pEprocess=(ULONG)(*(ULONG*)((ULONG)pEprocess+0x88)-0x88);if(pEprocess==pFirstEprocess||(*(LONG*)((LONG)pEprocess+0x84))<0){break;}}returnSTATUS_SUCCESS;}代码中用到了一个函数,就是PsGetCurrentProcess()。该函数用于获取当前进程的EPROCESS指针,定义如下:PEPROCESSPsGetCurrentProcess(VOID);系统进程的EPROCESS是通过PsGetCurrentProcess()函数获取的,大部分内核态系统线程都在系统进程中。除了这个函数没有动过,剩下的就是对EPROCESS结构体的操作,这里就不过多介绍了。隐藏进程内DLL文件的方法是将DLL链表中的指定DLL“脱链”。为了隐藏进程,还可以将指定进程的EPROCESS结构在进程链表中“脱链”,达到隐藏的目的。

猜你喜欢