MDL (Memory Descriptor List) refers to the Memory Descriptor table, which contains the starting address, owner process, number of bytes, and flag of the Memory region. The MDL structure is defined in ntddk. h. The specific structure is as follows:
Typedef struct _ MDL {
Struct _ MDL * Next;
CSHORT Size;
CSHORT MdlFlags;
Struct _ EPROCESS * Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, * PMDL;
To modify the memory flag, you need to declare a structure that is used to forcibly convert the type of the KeServiceDescriptorTable variable exported by the Windows Kernel. The structure is as follows:
Typedef struct ServiceDescriptorEntry { Unsigned int * ServiceTableBase; Unsigned int * ServiceCounterTableBase; // Used only in checked build Unsigned int NumberOfServices; Unsigned char * paramtablebase; } Servicedescriptortableentry_t, * pservicedescriptortableentry_t; |
The source code in Rootkits is as follows. Although it can be compiled and executed in windows XP, some of the functions are outdated and new functions are replaced. The descriptions are as follows:
G_pmdlsystemcall = mmcreatemdl (null, keservicedescriptortable. servicetablebase, keservicedescriptortable. numberofservices * 4 ); If (! G_pmdlsystemcall) Return status_unsuccessful; Mmbuildmdlfornonpagedpool (g_pmdlsystemcall ); // Change the flags of the MDL G_pmdlsystemcall-> mdlflags = g_pmdlsystemcall-> mdlflags | mdl_mapped_to_system_va; Mappedsystemcalltable = mmmaplockedpages (g_pmdlsystemcall, kernelmode ); |
The MmCreateMdl function is defined as follows:
PMDL MmCreateMdl ( IN PMDL MemoryDescriptorListOPTIONAL, IN PVOID Base, IN SIZE_TLength ); |
The new function is
PMDL IoAllocateMdl ( _ In_opt PVOIDVirtualAddress, _ In ULONGLength, _ In BOOLEANSecondaryBuffer, _ In BOOLEANChargeQuota, _ Inout_opt PIRPIrpOPTIONAL ); |
IoAllocateMdl is used to allocate an MDL structure, that is, to map a piece of memory space of the system to another place, modify the protection attribute of this part of memory, and modify its content, to modify the protected memory. The first parameter is the start address of the MDL memory, and the second parameter is the MDL length.
Because the MDL created by IoAllocateMdl is directed to the buffer of the non-Paging virtual memory, the MmBuildMdlForNonPagedPool function is required to update the MDL in the physical memory.
The MmMapLocakedPages function is defined as follows:
PVOID MmMapLockedPages ( IN PMDL MemoryDescriptorList, IN KPROCESSOR_MODEAccessMode ); |
The new function is MmMapLockedPagesSpecifyCache, which is defined
PVOID MmMapLockedPagesSpecifyCache ( _ In PMDLXMemoryDescriptorList, _ In KPROCESSOR_MODEAccessMode, _ In MEMORY_CACHING_TYPECacheType, _ In_opt PVOIDBaseAddress, _ In ULONGBugCheckOnFailure, _ In MM_PAGE_PRIORITYPriority ); |
It is used to lock the MDL page in the memory and allow users to modify its attributes.
The Code modified after using the new function is as follows:
// G_pmdlsystemcall = mmcreatemdl (null, keservicedescriptortable. servicetablebase, // keservicedescriptortable. numberofservices * 4 ); G_pmdlsystemcall = ioallocatemdl (keservicedescriptortable. servicetablebase, keservicedescriptortable. numberofservices * 4, false, false, null ); If (! G_pmdlsystemcall) Return status_unsuccessful; Mmbuildmdlfornonpagedpool (g_pmdlsystemcall ); // Change the flags of the MDL // Mappedsystemcalltable = mmmaplockedpages (g_pmdlsystemcall, kernelmode ); Mappedsystemcalltable = mmmaplockedpagesspecifycache (g_pmdlsystemcall, kernelmode, mmwritecombined, null, false, 0 ); MappedSystemCallTable = MmMapLockedPages (g_pmdlSystemCall, KernelMode ); |