2015年5月8日星期五

编码遍历进程的VAD

#include <ntifs.h>
#include <windef.h>


/*
功能:遍历进程的VAD。仅仅是演示的目录,不支持X64,X64需要自己改造。

参考资料:
http://bbs.pediy.com/showthread.php?t=66886
http://lilxam.tuxfamily.org/blog/?p=326&lang=en
http://forum.sysinternals.com/vad-tree-walking_topic12362.html
http://bbs.pediy.com/showthread.php?t=117634
http://forum.eviloctal.com/viewthread.php?action=printable&tid=17929

结构的定义来自:
\WRK-v1.2\base\ntos\mm\mi.h
\WRK-v1.2\base\ntos\mm\i386\mi386.h
\WRK-v1.2\base\ntos\mm\amd64\miamd.h
\WRK-v1.2\base\ntos\inc\mm.h
\WRK-v1.2\public\sdk\inc\ntmmapi.h
\WRK-v1.2\base\ntos\inc\i386.h
注意:一些X64的结构没有摘抄。

made by correy
made at 2015.05.08
*/


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/*
0: kd> !process 0 1 smss.exe
PROCESS 81e15da0  SessionId: none  Cid: 020c    Peb: 7ffdf000  ParentCid: 0004
    DirBase: 02940040  ObjectTable: e149f4c8  HandleCount:  17.
    Image: smss.exe
    VadRoot 81c25be8 Vads 16 Clone 0 Private 30. Modified 8. Locked 0.
    DeviceMap e10002a0
    Token                             e17ea020
    ElapsedTime                       00:00:26.468
    UserTime                          00:00:00.031
    KernelTime                        00:00:00.906
    QuotaPoolUsage[PagedPool]         6068
    QuotaPoolUsage[NonPagedPool]      640
    Working Set Sizes (now,min,max)  (112, 50, 345) (448KB, 200KB, 1380KB)
    PeakWorkingSetSize                117
    VirtualSize                       3 Mb
    PeakVirtualSize                   14 Mb
    PageFaultCount                    206
    MemoryPriority                    BACKGROUND
    BasePriority                      11
    CommitCharge                      43

0: kd> dt nt!_eprocess VadRoot 81e15da0
   +0x11c VadRoot : 0x81c25be8 Void
0: kd> dt nt!_MMVAD 81c25be8
   +0x000 StartingVpn      : 0x48580
   +0x004 EndingVpn        : 0x4858e
   +0x008 Parent           : (null)
   +0x00c LeftChild        : 0x82110778 _MMVAD
   +0x010 RightChild       : 0x81c27c28 _MMVAD
   +0x014 u                : __unnamed
   +0x018 ControlArea      : 0x81e1b6e0 _CONTROL_AREA
   +0x01c FirstPrototypePte : 0xe176c4b0 _MMPTE
   +0x020 LastContiguousPte : 0xfffffffc _MMPTE
   +0x024 u2               : __unnamed
0: kd> dt 0x81e1b6e0 _CONTROL_AREA
nt!_CONTROL_AREA
   +0x000 Segment          : 0xe176c470 _SEGMENT
   +0x004 DereferenceList  : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x00c NumberOfSectionReferences : 1
   +0x010 NumberOfPfnReferences : 0xd
   +0x014 NumberOfMappedViews : 1
   +0x018 NumberOfSubsections : 5
   +0x01a FlushInProgressCount : 0
   +0x01c NumberOfUserReferences : 2
   +0x020 u                : __unnamed
   +0x024 FilePointer      : 0x81c42f28 _FILE_OBJECT
   +0x028 WaitingForDeletion : (null)
   +0x02c ModifiedWriteCount : 0
   +0x02e NumberOfSystemCacheViews : 0
0: kd> dt 0x81c42f28 _FILE_OBJECT
nt!_FILE_OBJECT
   +0x000 Type             : 0n5
   +0x002 Size             : 0n112
   +0x004 DeviceObject     : 0x820be900 _DEVICE_OBJECT
   +0x008 Vpb              : 0x821611e8 _VPB
   +0x00c FsContext        : 0xe1610d90 Void
   +0x010 FsContext2       : 0xe1697630 Void
   +0x014 SectionObjectPointer : 0x81fd82f4 _SECTION_OBJECT_POINTERS
   +0x018 PrivateCacheMap  : (null)
   +0x01c FinalStatus      : 0n0
   +0x020 RelatedFileObject : (null)
   +0x024 LockOperation    : 0 ''
   +0x025 DeletePending    : 0 ''
   +0x026 ReadAccess       : 0x1 ''
   +0x027 WriteAccess      : 0 ''
   +0x028 DeleteAccess     : 0 ''
   +0x029 SharedRead       : 0x1 ''
   +0x02a SharedWrite      : 0x1 ''
   +0x02b SharedDelete     : 0x1 ''
   +0x02c Flags            : 0x44040
   +0x030 FileName         : _UNICODE_STRING "\WINDOWS\system32\smss.exe"
   +0x038 CurrentByteOffset : _LARGE_INTEGER 0x0
   +0x040 Waiters          : 0
   +0x044 Busy             : 0
   +0x048 LastLock         : (null)
   +0x04c Lock             : _KEVENT
   +0x05c Event            : _KEVENT
   +0x06c CompletionContext : (null)
0: kd> !vad 0x81c25be8
VAD     level      start      end    commit
82110778 ( 1)          0       ff         0 Private      READWRITE        
820cf5c0 ( 2)        100      100         1 Private      READWRITE        
820cf930 ( 3)        110      110         1 Private      READWRITE        
820fc4a8 ( 4)        120      15f         4 Private      READWRITE        
81c24a80 ( 5)        160      25f         6 Private      READWRITE        
82114570 ( 6)        260      26f         6 Private      READWRITE        
821143b8 ( 7)        270      2af         4 Private      READWRITE        
82113ca0 ( 8)        2b0      2ef         4 Private      READWRITE        
820beae0 ( 9)        2f0      2f0         1 Private      READWRITE        
81c25be8 ( 0)      48580    4858e         2 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\smss.exe
81c27c28 ( 1)      7c920    7c9b5         5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\ntdll.dll
81c25c78 ( 2)      7ffa0    7ffd2         0 Mapped       READONLY           Pagefile-backed section
81f77068 ( 6)      7ffdc    7ffdc         1 Private      READWRITE        
81c27c90 ( 5)      7ffdd    7ffdd         1 Private      READWRITE        
82136278 ( 4)      7ffde    7ffde         1 Private      READWRITE        
81fe6a90 ( 3)      7ffdf    7ffdf         1 Private      READWRITE        

Total VADs: 16, average level: 5, maximum depth: 9
*/

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#define tag  'tset' //test

#if defined (_WIN64)

#define COMMIT_SIZE 51

#if ((COMMIT_SIZE + PAGE_SHIFT) < 63)
#error COMMIT_SIZE too small
#endif

#else
#define COMMIT_SIZE 19

#if ((COMMIT_SIZE + PAGE_SHIFT) < 31)
#error COMMIT_SIZE too small
#endif
#endif

#define MM_MAX_COMMIT (((ULONG_PTR) 1 << COMMIT_SIZE) - 1)

#define MM_VIEW_UNMAP 0
#define MM_VIEW_SHARE 1

typedef struct _MMVAD_FLAGS {
    ULONG_PTR CommitCharge : COMMIT_SIZE; // limits system to 4k pages or bigger!
    ULONG_PTR NoChange : 1;
    ULONG_PTR VadType : 3;
    ULONG_PTR MemCommit: 1;
    ULONG_PTR Protection : 5;
    ULONG_PTR Spare : 2;
    ULONG_PTR PrivateMemory : 1;    // used to tell VAD from VAD_SHORT
} MMVAD_FLAGS;

typedef struct _EVENT_COUNTER {
    SLIST_ENTRY ListEntry;
    ULONG RefCount;
    KEVENT Event;
} EVENT_COUNTER, *PEVENT_COUNTER;

typedef struct _MMSECTION_FLAGS {
    unsigned BeingDeleted : 1;
    unsigned BeingCreated : 1;
    unsigned BeingPurged : 1;
    unsigned NoModifiedWriting : 1;

    unsigned FailAllIo : 1;
    unsigned Image : 1;
    unsigned Based : 1;
    unsigned File : 1;

    unsigned Networked : 1;
    unsigned NoCache : 1;
    unsigned PhysicalMemory : 1;
    unsigned CopyOnWrite : 1;

    unsigned Reserve : 1;  // not a spare bit!
    unsigned Commit : 1;
    unsigned FloppyMedia : 1;
    unsigned WasPurged : 1;

    unsigned UserReference : 1;
    unsigned GlobalMemory : 1;
    unsigned DeleteOnClose : 1;
    unsigned FilePointerNull : 1;

    unsigned DebugSymbolsLoaded : 1;
    unsigned SetMappedFileIoComplete : 1;
    unsigned CollidedFlush : 1;
    unsigned NoChange : 1;

    unsigned filler0 : 1;
    unsigned ImageMappedInSystemSpace : 1;
    unsigned UserWritable : 1;
    unsigned Accessed : 1;

    unsigned GlobalOnlyPerSession : 1;
    unsigned Rom : 1;
    unsigned WriteCombined : 1;
    unsigned filler : 1;
} MMSECTION_FLAGS;

typedef struct _MMVAD_FLAGS2 {
    unsigned FileOffset : 24;       // number of 64k units into file
    unsigned SecNoChange : 1;       // set if SEC_NOCHANGE specified
    unsigned OneSecured : 1;        // set if u3 field is a range
    unsigned MultipleSecured : 1;   // set if u3 field is a list head
    unsigned ReadOnly : 1;          // protected as ReadOnly
    unsigned LongVad : 1;           // set if VAD is a long VAD
    unsigned ExtendableFile : 1;
    unsigned Inherit : 1;           //1 = ViewShare, 0 = ViewUnmap
    unsigned CopyOnWrite : 1;
} MMVAD_FLAGS2;

typedef struct _MMADDRESS_LIST {
    ULONG_PTR StartVpn;
    ULONG_PTR EndVpn;
} MMADDRESS_LIST, *PMMADDRESS_LIST;

typedef struct _MMEXTEND_INFO {
    UINT64 CommittedSize;
    ULONG ReferenceCount;
} MMEXTEND_INFO, *PMMEXTEND_INFO;

typedef struct _SEGMENT_FLAGS {
    ULONG_PTR TotalNumberOfPtes4132 : 10;
    ULONG_PTR ExtraSharedWowSubsections : 1;
    ULONG_PTR LargePages : 1;
#if defined (_WIN64)
    ULONG_PTR Spare : 52;
#else
    ULONG_PTR Spare : 20;
#endif
} SEGMENT_FLAGS, *PSEGMENT_FLAGS;

#if !defined (_X86PAE_)
typedef struct _HARDWARE_PTE {
    ULONG Valid : 1;
    ULONG Write : 1;
    ULONG Owner : 1;
    ULONG WriteThrough : 1;
    ULONG CacheDisable : 1;
    ULONG Accessed : 1;
    ULONG Dirty : 1;
    ULONG LargePage : 1;
    ULONG Global : 1;
    ULONG CopyOnWrite : 1; // software field
    ULONG Prototype : 1;   // software field
    ULONG reserved : 1;  // software field
    ULONG PageFrameNumber : 20;
} HARDWARE_PTE, *PHARDWARE_PTE;

#else
typedef struct _HARDWARE_PTE {
    union {
        struct {
            ULONGLONG Valid : 1;
            ULONGLONG Write : 1;
            ULONGLONG Owner : 1;
            ULONGLONG WriteThrough : 1;
            ULONGLONG CacheDisable : 1;
            ULONGLONG Accessed : 1;
            ULONGLONG Dirty : 1;
            ULONGLONG LargePage : 1;
            ULONGLONG Global : 1;
            ULONGLONG CopyOnWrite : 1; // software field
            ULONGLONG Prototype : 1;   // software field
            ULONGLONG reserved0 : 1;  // software field
            ULONGLONG PageFrameNumber : 26;
            ULONGLONG reserved1 : 26;  // software field
        };
        struct {
            ULONG LowPart;
            ULONG HighPart;
        };
    };
} HARDWARE_PTE, *PHARDWARE_PTE;
#endif

// A Page Table Entry on the x86 has the following definition.
// Note the MP version is to avoid stalls when flushing TBs across processors.
typedef struct _MMPTE_HARDWARE {
    ULONG Valid : 1;
#if defined(NT_UP)
    ULONG Write : 1;       // UP version
#else
    ULONG Writable : 1;    // changed for MP version
#endif
    ULONG Owner : 1;
    ULONG WriteThrough : 1;
    ULONG CacheDisable : 1;
    ULONG Accessed : 1;
    ULONG Dirty : 1;
    ULONG LargePage : 1;
    ULONG Global : 1;
    ULONG CopyOnWrite : 1; // software field
    ULONG Prototype : 1;   // software field
#if defined(NT_UP)
    ULONG reserved : 1;    // software field
#else
    ULONG Write : 1;       // software field - MP change
#endif
    ULONG PageFrameNumber : 20;
} MMPTE_HARDWARE, *PMMPTE_HARDWARE;

typedef struct _MMPTE_PROTOTYPE {
    ULONG Valid : 1;
    ULONG ProtoAddressLow : 7;
    ULONG ReadOnly : 1;  // if set allow read only access.
    ULONG WhichPool : 1;
    ULONG Prototype : 1;
    ULONG ProtoAddressHigh : 21;
} MMPTE_PROTOTYPE;

typedef struct _MMPTE_SOFTWARE {
    ULONG Valid : 1;
    ULONG PageFileLow : 4;
    ULONG Protection : 5;
    ULONG Prototype : 1;
    ULONG Transition : 1;
    ULONG PageFileHigh : 20;
} MMPTE_SOFTWARE;

typedef struct _MMPTE_TRANSITION {
    ULONG Valid : 1;
    ULONG Write : 1;
    ULONG Owner : 1;
    ULONG WriteThrough : 1;
    ULONG CacheDisable : 1;
    ULONG Protection : 5;
    ULONG Prototype : 1;
    ULONG Transition : 1;
    ULONG PageFrameNumber : 20;
} MMPTE_TRANSITION;

typedef struct _MMPTE_SUBSECTION {
    ULONG Valid : 1;
    ULONG SubsectionAddressLow : 4;
    ULONG Protection : 5;
    ULONG Prototype : 1;
    ULONG SubsectionAddressHigh : 20;
    ULONG WhichPool : 1;
} MMPTE_SUBSECTION;

typedef struct _MMPTE_LIST {
    ULONG Valid : 1;
    ULONG OneEntry : 1;
    ULONG filler0 : 8;

    //
    // Note the Prototype bit must not be used for lists like freed nonpaged
    // pool because lookaside pops can legitimately reference bogus addresses
    // (since the pop is unsynchronized) and the fault handler must be able to
    // distinguish lists from protos so a retry status can be returned (vs a
    // fatal bugcheck).
    //

    ULONG Prototype : 1;            // MUST BE ZERO as per above comment.
    ULONG filler1 : 1;
    ULONG NextEntry : 20;
} MMPTE_LIST;

typedef struct _MMPTE {
    union  {
        ULONG Long;
        HARDWARE_PTE Flush;
        MMPTE_HARDWARE Hard;
        MMPTE_PROTOTYPE Proto;
        MMPTE_SOFTWARE Soft;
        MMPTE_TRANSITION Trans;
        MMPTE_SUBSECTION Subsect;
        MMPTE_LIST List;
        } u;
} MMPTE;

typedef MMPTE *PMMPTE;

typedef
VOID
(*PBANKED_SECTION_ROUTINE) (
    IN ULONG ReadBank,
    IN ULONG WriteBank,
    IN PVOID Context
    );

typedef struct _MMBANKED_SECTION {
    PFN_NUMBER BasePhysicalPage;
    PMMPTE BasedPte;
    ULONG BankSize;
    ULONG BankShift; // shift for PTEs to calculate bank number
    PBANKED_SECTION_ROUTINE BankedRoutine;
    PVOID Context;
    PMMPTE CurrentMappedPte;
    MMPTE BankTemplate[1];
} MMBANKED_SECTION, *PMMBANKED_SECTION;

typedef struct _SECTION_IMAGE_INFORMATION {
    PVOID TransferAddress;
    ULONG ZeroBits;
    SIZE_T MaximumStackSize;
    SIZE_T CommittedStackSize;
    ULONG SubSystemType;
    union {
        struct {
            USHORT SubSystemMinorVersion;
            USHORT SubSystemMajorVersion;
        };
        ULONG SubSystemVersion;
    };
    ULONG GpValue;
    USHORT ImageCharacteristics;
    USHORT DllCharacteristics;
    USHORT Machine;
    BOOLEAN ImageContainsCode;
    BOOLEAN Spare1;
    ULONG LoaderFlags;
    ULONG ImageFileSize;
    ULONG Reserved[ 1 ];
} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;

//
// This structure is used only by Wow64 processes. The offsets
// of structure elements should the same as viewed by a native Win64 application.
//
typedef struct _SECTION_IMAGE_INFORMATION64 {
    ULONGLONG TransferAddress;
    ULONG ZeroBits;
    ULONGLONG MaximumStackSize;
    ULONGLONG CommittedStackSize;
    ULONG SubSystemType;
    union {
        struct {
            USHORT SubSystemMinorVersion;
            USHORT SubSystemMajorVersion;
        };
        ULONG SubSystemVersion;
    };
    ULONG GpValue;
    USHORT ImageCharacteristics;
    USHORT DllCharacteristics;
    USHORT Machine;
    BOOLEAN ImageContainsCode;
    BOOLEAN Spare1;
    ULONG LoaderFlags;
    ULONG ImageFileSize;
    ULONG Reserved[ 1 ];
} SECTION_IMAGE_INFORMATION64, *PSECTION_IMAGE_INFORMATION64;

#define MM_PROTO_PTE_ALIGNMENT ((ULONG)PAGE_SIZE)

//\WRK-v1.2\base\ntos\mm\amd64\miamd.h
//#define MM_PROTO_PTE_ALIGNMENT ((ULONG)MM_MAXIMUM_NUMBER_OF_COLORS * (ULONG)PAGE_SIZE)

typedef struct _SEGMENT {
    struct _CONTROL_AREA *ControlArea;
    ULONG TotalNumberOfPtes;
    ULONG NonExtendedPtes;
    ULONG Spare0;

    UINT64 SizeOfSegment;
    MMPTE SegmentPteTemplate;

    SIZE_T NumberOfCommittedPages;
    PMMEXTEND_INFO ExtendInfo;

    SEGMENT_FLAGS SegmentFlags;
    PVOID BasedAddress;

    //
    // The fields below are for image & pagefile-backed sections only.
    // Common fields are above and new common entries must be added to
    // both the SEGMENT and MAPPED_FILE_SEGMENT declarations.
    //

    union {
        SIZE_T ImageCommitment;     // for image-backed sections only
        PEPROCESS CreatingProcess;  // for pagefile-backed sections only
    } u1;

    union {
        PSECTION_IMAGE_INFORMATION ImageInformation;    // for images only
        PVOID FirstMappedVa;        // for pagefile-backed sections only
    } u2;

    PMMPTE PrototypePte;
    MMPTE ThePtes[MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE];

} SEGMENT, *PSEGMENT;

//这个WRK定义的与WINDBG显示的不一样。
//typedef struct _CONTROL_AREA {
//    PSEGMENT Segment;                   //1
//    LIST_ENTRY DereferenceList;         //2
//    ULONG NumberOfSectionReferences;    //3 All section refs & image flushes
//    ULONG NumberOfPfnReferences;        //4 valid + transition prototype PTEs
//    ULONG NumberOfMappedViews;          //5 total # mapped views, including system cache & system space views
//    ULONG NumberOfSystemCacheViews;     //6 system cache views only
//    ULONG NumberOfUserReferences;       //7 user section & view references
//    union {
//        ULONG LongFlags;
//        MMSECTION_FLAGS Flags;
//    } u;                                //8
//    PFILE_OBJECT FilePointer;           //9
//    PEVENT_COUNTER WaitingForDeletion;  //10
//    USHORT ModifiedWriteCount;          //11
//    USHORT FlushInProgressCount;        //12
//    ULONG WritableUserReferences;       //13
//#if !defined (_WIN64)
//    ULONG QuadwordPad;                  //14
//#endif
//} CONTROL_AREA, *PCONTROL_AREA;

//其实这个和上面的是一样的,只不过更详细点。
typedef struct _CONTROL_AREA {
    PSEGMENT Segment;                   //1
    LIST_ENTRY DereferenceList;         //2
    ULONG NumberOfSectionReferences;    //3 All section refs & image flushes
    ULONG NumberOfPfnReferences;        //4 valid + transition prototype PTEs
    ULONG NumberOfMappedViews;          //5 total # mapped views, including system cache & system space views  
    USHORT NumberOfSubsections;         //6
    USHORT FlushInProgressCount;        //7
    ULONG NumberOfUserReferences;       //8 user section & view references
    union {
        ULONG LongFlags;
        MMSECTION_FLAGS Flags;
    } u;                                //9
    PFILE_OBJECT FilePointer;           //10
    PEVENT_COUNTER WaitingForDeletion;  //11
    USHORT ModifiedWriteCount;          //12
    USHORT NumberOfSystemCacheViews;    //13ULONG NumberOfSystemCacheViews;     // system cache views only
    //
    //ULONG WritableUserReferences;
#if !defined (_WIN64)
    ULONG QuadwordPad;                  //14
#endif
} CONTROL_AREA, *PCONTROL_AREA;
//因为:XP-32下sizeof(_CONTROL_AREA) == 0x30,所以NumberOfSystemCacheViews是Uint2B,而不是不是ULONG。

typedef struct _MMVAD_LONG {
    union {
        LONG_PTR Balance : 2;
        struct _MMVAD *Parent;
    } u1;
    struct _MMVAD *LeftChild;
    struct _MMVAD *RightChild;
    ULONG_PTR StartingVpn;
    ULONG_PTR EndingVpn;

    union {
        ULONG_PTR LongFlags;
        MMVAD_FLAGS VadFlags;
    } u;
    PCONTROL_AREA ControlArea;
    PMMPTE FirstPrototypePte;
    PMMPTE LastContiguousPte;
    union {
        ULONG LongFlags2;
        MMVAD_FLAGS2 VadFlags2;
    } u2;
    union {
        LIST_ENTRY List;
        MMADDRESS_LIST Secured;
    } u3;
    union {
        PMMBANKED_SECTION Banked;
        PMMEXTEND_INFO ExtendedInfo;
    } u4;
} MMVAD_LONG, *PMMVAD_LONG;

//这个WRK定义的和WINDBG命令显示的不一样。
//typedef struct _MMVAD {
//    union {
//        LONG_PTR Balance : 2;
//        struct _MMVAD *Parent;
//    } u1;
//    struct _MMVAD *LeftChild;
//    struct _MMVAD *RightChild;
//    ULONG_PTR StartingVpn;
//    ULONG_PTR EndingVpn;
//
//    union {
//        ULONG_PTR LongFlags;
//        MMVAD_FLAGS VadFlags;
//    } u;
//    PCONTROL_AREA ControlArea;
//    PMMPTE FirstPrototypePte;
//    PMMPTE LastContiguousPte;
//    union {
//        ULONG LongFlags2;
//        MMVAD_FLAGS2 VadFlags2;
//    } u2;
//} MMVAD, *PMMVAD;

typedef struct _MMVAD {
    LONG_PTR StartingVpn;//用指针兼容64
    LONG_PTR EndingVpn;//用指针兼容64
    struct _MMVAD *Parent;
    struct _MMVAD *LeftChild;
    struct _MMVAD *RightChild;
    union {
        ULONG_PTR LongFlags;
        MMVAD_FLAGS VadFlags;
    } u;
    PCONTROL_AREA ControlArea;
    PMMPTE FirstPrototypePte;
    PMMPTE LastContiguousPte;
    union {
        ULONG LongFlags2;
        MMVAD_FLAGS2 VadFlags2;
    } u2;
} MMVAD, *PMMVAD;


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{

}


VOID print(IN PMMVAD t)
    /*
    看看还需要附加进程不?
    */
{
    PCONTROL_AREA ControlArea = 0;
    PFILE_OBJECT FilePointer = 0;
    UNICODE_STRING FileName = {0};
    NTSTATUS status = STATUS_UNSUCCESSFUL;    

    __try {
        //ProbeForRead(t, sizeof (MMVAD), sizeof(UCHAR));
        ControlArea = t->ControlArea;
        if (ControlArea != NULL && (PVOID)ControlArea >= MmSystemRangeStart && MmIsAddressValid((PVOID)ControlArea))
        {
            //ProbeForRead(ControlArea, sizeof (CONTROL_AREA), sizeof(UCHAR));
            FilePointer = ControlArea->FilePointer;
            if (FilePointer != NULL && (PVOID)FilePointer>= MmSystemRangeStart && MmIsAddressValid((PVOID)FilePointer))
            {
                //ProbeForRead(FilePointer, sizeof (FILE_OBJECT), sizeof(UCHAR));
                FileName = FilePointer->FileName;//这里简单获取下,有可能获取的不是全路径。
                //if (FileName != NULL)
                {
                    //KdPrint(("FileName:%wZ\n", &FileName));
                }
            }
        }
    }__except (EXCEPTION_EXECUTE_HANDLER) {
        status = GetExceptionCode();
        //KdPrint(("access user memory exception:0x%X, in line: %d at file:%s。\n", status, __LINE__, __FILE__));
    }  

    //可以仿照!VAD命令打印信息。
    KdPrint(("VAD:%p, start:%p, end:%p, FileName:%wZ\n", t, t->StartingVpn, t->EndingVpn, &FileName));
}


VOID traversal(IN PMMVAD t)
{
    if ( t != 0)
    {
        print(t);

        traversal(t->LeftChild);
        traversal(t->RightChild);
    }
}


VOID test(wchar_t * process_name)
    /*
    这个名字改如何填写才不导致ZwOpenProcess失败呢?
    smss.exe
    \\smss.exe
    \\Process\\smss.exe
    都失败。
    网上只有传递ID成功的代码。
    */
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;    
    HANDLE  ProcessHandle;
    OBJECT_ATTRIBUTES ob;
    UNICODE_STRING  ObjectName;

    RtlInitUnicodeString(&ObjectName, process_name);
    InitializeObjectAttributes(&ob, &ObjectName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
    status = ZwOpenProcess(&ProcessHandle, GENERIC_ALL, &ob, 0);
    if (!NT_SUCCESS(status)) {
        KdPrint(("ZwOpenProcess fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
        return;
    }


}


DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    unsigned int x = (unsigned int)((unsigned char *)PsInitialSystemProcess + 0x11c);
    PMMVAD p = 0;

    x = *(unsigned int *)x;
    p = (PMMVAD)x;

    KdBreakPoint();//此时可以用!process 0 1 pname获取一个进程的VAD,然后改写p的值,可以试试看测试效果。

    DriverObject->DriverUnload = Unload;  
   
    traversal(p);

    return status;//STATUS_SUCCESS
}  

没有评论:

发表评论