调用CE驱动实现内存读写、映射、远程APC等功能易语言源码重要!Windows 22H2下加载CE驱动会报签名吊销。
如何调用CE驱动?
调用CE驱动是一个比较困难的事情,主要体现在两个方面:
首先是加载驱动:正常加载CE驱动时程序会读取RegistryPath下的A/B/C/D项作为“DriverString”“DeviceString”“ProcessEventString”和“ThreadEventString”
不过这部分绕过很简单,模拟CE写好注册项就好。
其次的部分是最难的,不要以为驱动加载起来之后就完事大吉。
当你加载好驱动,用CreateFileA创建驱动通信句柄时,却发现会创建失败。
看CE代码:
首先创建端口时使用了SeSinglePrivilegeCheck检测进程是否有SE_DEBUG_PRIVILEGE(调试权限),没有就返回STATUS_UNSUCCESSFUL,其次程序会使用SecurityCheck校验程序是否为CE。
SecurityCheck首先调用了ZwQueryInformationProcess获取进程IMAGE路径,然后使用CheckSignatureOfFile校验程序。
CheckSignatureOfFile部分代码:
这个检测很严格,首先用CheckSignature命令检测程序数字签名是否正常,然后又使用TestProcess检测进程的.text段是否正常,总之,这两步校验在驱动层完成,用户层想要直接绕过两次校验的可能性基本为0。
那么应该怎么绕过去呢?
其实方法有很多,例如CE在启动的时候会加载lua53-32.dll,只要知道这点问题就很简单了。
首先用易语言创建一个Dll(源码:lua注入.e),劫持掉lua53-32.dll,然后主程序启动正常CE,被劫持中的lua53-32.dll使用CreateFileA创建驱动通信句柄即可,创建好句柄后再利用DuplicateHandle函数将驱动句柄拷贝给主程序即可:
测试非常成功:
注意,开启x64的CE后,有可能会导致x86的CE加载失败(概率比较低,但是原因不明),所以使用CE驱动时最好不要先启动着x64的CE。
CE驱动的功能:
CE驱动的功能非常的多(DBVM技术,VT技术,读写什么的都有)
看了一下驱动中DispatchIoctl部分的代码,大致写了一点接口出来:
1.IOCTL_CE_READMEMORY:
读进程数据(一次性读最多32767Byte),没什么说多的。
原理:KeAttachProcess附加到进程,检测地址是否可读,检测是否读取内核数据,RtlCopyMemory读取数据,KeDetachProcess取消附加,非常简单:
测试结果(读取ntoskrnl.exe的内核数据):
2.IOCTL_CE_WRITEMEMORY:
写进程数据(一次性读最多32767Byte),没什么说多的。
原理:KeAttachProcess附加到进程,检测地址是否可写,检测是否是写入内核数据,RtlCopyMemory读取数据,KeDetachProcess取消附加
3.IOCTL_CE_OPENPROCESS
打开任意进程。
原理:PsLookupProcessByProcessId将PID转换为EPROCESS,然后使用ObOpenObjectByPointer实现将EPROCESS打开一个引用对象,最后ObDereferenceObject函数减少一次EPROCESS的引用,将打开的对象返回给程序即可。
测试结果(尝试打开进程System,成功拿到其Full Control的进程句柄):
4.IOCTL_CE_OPENTHREAD
打开任意线程。
原理:使用内核ZwOpenThread函数
5.IOCTL_CE_QUERY_VIRTUAL_MEMORY
查询内存属性
原理:KeAttachProcess附加到进程,将虚拟地址转换为PageIndex,直接查询Page保护属性,最后KeDetachProcess取消附加,大致的过程:
6.IOCTL_CE_GETPETHREAD
获取PETHREAD
原理:PsLookupThreadByThreadId函数直接获取
7.IOCTL_CE_GETPEPROCESS
获取PEPROCESS
原理:PsLookupProcessByProcessId函数直接获取
8.IOCTL_CE_GETPHYSICALADDRESS
将虚拟内存地址转物理内存地址
原理:PsLookupProcessByProcessId函数获取进程EPROCESS地址,KeStackAttachProcess附加到进程,MmGetPhysicalAddress将虚拟内存地址转换为物理地址,最后KeUnstackDetachProcess取消进程附加,
基本效果:
9.IOCTL_CE_READPHYSICALMEMORY
读取物理内存
原理:利用ZwOpenSection函数打开devicephysicalmemory,然后使用ZwMapViewOfSection将物理内存映射到虚拟内存进行读。
10.IOCTL_CE_WRITEPHYSICALMEMORY
写物理内存
原理:利用ZwOpenSection函数打开devicephysicalmemory,然后使用ZwMapViewOfSection将物理内存映射到虚拟内存进行写。
11.IOCTL_CE_CREATEAPC
创建线程APC
原理:利用KeInitializeApc和KeInsertQueueApc函数直接实现向线程中插入APC。
12.IOCTL_CE_SUSPENDTHREAD
暂停线程
原理:内核暂停线程非常简单,直接给线程插一条APC,然后使用KeWaitForSingleObject去无限等待。
13.IOCTL_CE_RESUMETHREAD
恢复线程
原理:解除KeWaitForSingleObject的无限等待。
14.IOCTL_CE_SUSPENDPROCESS
暂停进程
原理:PsSuspendProcess直接暂停进程。
15.IOCTL_CE_RESUMEPROCESS
恢复进程
原理:PsResumeProcess恢复进程运行。
16.IOCTL_CE_ALLOCATEMEM
分配内存
原理:ZwAllocateVirtualMemory直接分配内存。
17.IOCTL_CE_EXECUTE_CODE
运行代码
原理:直接运行(注意,不能用这个操作执行任何的R3代码)。
18.IOCTL_CE_READMSR
读MSR寄存器
19.IOCTL_CE_WRITEMSR
写MSR寄存器
20.IOCTL_CE_MAP_MEMORY
映射任意内存到本地内存。
原理:用IoAllocateMdl给欲映射的虚拟内存分配一张MDL,用MmProbeAndLockPages使其内存驻留,最后使用MmMapLockedPagesSpecifyCache将MDL映射到指定虚拟内存地址。
测试效果(将ntoskrnl.exe的内核数据映射到用户层,还可以直接任意读写,因为物理地址相同):
IOCTL_CE_UNMAP_MEMORY
解除IOCTL_CE_MAP_MEMORY的映射
原理:用MmUnmapLockedPages解除映射,然后用MmUnlockPages解除页面锁定。
评论(3)
太强了,学习
太强了
太强了,学习