關於VAD的兩種內存隱藏方式


Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.html

技術學習來源:火哥(QQ:471194425)

內存在0環的兩種內存隱藏方式(基於VAD樹)

一、通過 _MMVAD.StartingVpn與_MMVAD.EndingVpn等值來隱藏內存。

  這種方法找到需要隱藏的VAD結點,使 _MMVAD.StartingVpn=_MMVAD.EndingVpn,這樣就能達到隱藏的效果

  在 》》VAD樹的屬性及其遍歷 《《 中,在遍歷每個結點下,直接 pVad.StartingVpn = pVad.EndingVpn即可。

  1)隱藏前的效果

    

  2)隱藏后的效果

    

 

二、通過將兩個VAD結點融合達到隱藏效果

  我們需要找到 宿主結點p1 與 被隱藏結點p2,將p2融合進p1中,此時就會顯示p1的段屬性從而忽視p2的段屬性。

  比如掃描內存時,惡意代碼必然可執行 EXECUTE,但是我們隱藏在READ之類段中,往往可以規避掉掃描。

  實現方法 p1.EndingVpn = p2.EndingPvn

1) 實驗代碼 test.exe

 1 // test.cpp : Defines the entry point for the console application.
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <iostream>
 6 #include <Windows.h>
 7 #include <stdlib.h>
 8 int main()
 9 {
10     LPVOID p1 = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE);
11     LPVOID p2 = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
12     printf("p1 = %x / p2 = %x", p1, p2);
13     system("pause");
14 }

2) 驅動代碼

  1 #include <ntddk.h>
  2 
  3 
  4 //---------------------//
  5 // MMVAD結構體簡單定義 //
  6 //---------------------//
  7 typedef struct _MMVAD {
  8     ULONG StartingVpn;
  9     ULONG EndingVpn;
 10     struct _MMVAD * Parent;
 11     struct _MMVAD * LeftChild;
 12     struct _MMVAD * RightChild;
 13 }MMVAD,*PMMVAD;
 14 
 15 
 16 
 17 VOID Unload(IN PDRIVER_OBJECT pDriverObject) {
 18     DbgPrint("Driver UnLoad!");
 19 }
 20 
 21 //-----------//
 22 // 遍歷VAD樹 //
 23 //-----------//
 24 PMMVAD  vad_enum(PMMVAD pVad,ULONG target_StartingVpn) {
 25 
 26     //---------------------------//
 27     // 遍歷目標VAD,並返回其指針 //
 28     //---------------------------//
 29     if (pVad) {
 30         if (target_StartingVpn == pVad->StartingVpn) {
 31             _asm int 3
 32             return pVad;
 33         }
 34         else {
 35             if (pVad->LeftChild) {
 36                 PMMVAD p1 = vad_enum(pVad->LeftChild, target_StartingVpn);
 37                 // 如果結點不為空,則直接返回就好。
 38                 // 否則繼續判斷其右子樹結點。
 39                 if (p1)
 40                     return p1;
 41             }
 42             if (pVad->RightChild) {
 43                 PMMVAD p2 = vad_enum(pVad->RightChild, target_StartingVpn);
 44                 if (p2)
 45                     return p2;
 46             }
 47             return NULL;
 48         }
 49     }
 50     return NULL;
 51 }
 52 
 53 //-------------------------------------------------------------//
 54 //  在內核中進程遍歷的原理就是先獲取系統進程EPROCESS結構       //
 55 //        然后依照其鏈表來獲取其他的進程                         //
 56 //        依次遍歷出來                                           //
 57 //-------------------------------------------------------------//
 58 NTSTATUS process_enum() {
 59 
 60     PEPROCESS pEprocess = NULL; // 得到系統進程地址
 61     PEPROCESS pFirstEprocess = NULL;
 62     ULONG ulProcessName = 0; // 字符串指針,指向進程名稱
 63     ULONG ulProcessID = 0;    // 進程ID
 64     ANSI_STRING target_str; // 帶檢測進程的名稱
 65     ANSI_STRING ansi_string; // 
 66     ULONG VadRoot;
 67 
 68     //----------------------------//
 69     // 得到當前系統進程的EPROCESS //
 70     //----------------------------//
 71     pEprocess = PsGetCurrentProcess();
 72     if (pEprocess == NULL) {
 73         DbgPrint("獲取當前系統進程EPROCESS錯誤..");
 74         return STATUS_SUCCESS;
 75     }
 76     DbgPrint("pEprocess addr is %x0x8\r\n", pEprocess);
 77     pFirstEprocess = pEprocess;
 78 
 79     while (pEprocess) {
 80 
 81         ulProcessName = (ULONG)pEprocess + 0x174;
 82         ulProcessID = *(ULONG*)((ULONG)pEprocess + 0x84);
 83         VadRoot = *(ULONG*)((ULONG)pEprocess + 0x11c);
 84 
 85         //--------------------------------------//
 86         // 將目標進程與當前進程的進程名進行對比 //
 87         //--------------------------------------//
 88         RtlInitAnsiString(&ansi_string, (PCSTR)ulProcessName);    
 89         RtlInitAnsiString(&target_str, "test.exe");
 90         if (RtlEqualString(&ansi_string, &target_str, TRUE)) {
 91             DbgPrint("檢測到進程字符串,%x", ulProcessID);
 92         
 93             PMMVAD p1 = vad_enum((PMMVAD)VadRoot,0x3a0); // 遍歷第一個結點
 94             PMMVAD p2 = vad_enum((PMMVAD)VadRoot, 0x3b0); // 遍歷找到第二個結點
 95             _asm int 3
 96             if(p1 && p2)
 97                 p1->EndingVpn = p2->EndingVpn; // 將第二個結點完全隱藏起來
 98                 
 99 
100             return STATUS_SUCCESS;
101         }
102         pEprocess = (PEPROCESS)(*(ULONG*)((ULONG)pEprocess + 0x88) - 0x88);
103         if (pEprocess == pFirstEprocess || *(ULONG*)((ULONG)pEprocess + 0x84) <= 0) {
104             DbgPrint("遍歷結束!未檢測到進程ID!\r\n");
105             break;
106         }
107     }
108     return STATUS_SUCCESS;
109 }
110 
111 NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING registeryPat) {
112     DbgPrint("Driver Loaded!");
113     pDriverObject->DriverUnload = Unload;
114     process_enum();
115     return STATUS_SUCCESS;
116 }

 3)隱藏效果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM