windows系统在某些版本下对某些内存区域启用了写保护的功能,因为这些区域一般合法程序是不可能修改其内容的,那么我们如何来写这些内存呢? PS:1) 这些系统包括:windows xp与windows 2003 2) CPU提供写保护的功能是从486开始的 3) 一般合法程序不包括杀毒软件,因为他们在Hook SSDT中是直接改ServiceTableBase,而没有用inline的方法 我们就用SSDT做例子吧,在Hook SSDT时不用innline hook方法,我们就要修改SSDT这个系统服务描述表;而这个表是被写保护了,在ring0下也是没有写的权限。 方法一: 首先我们来看一下CR0寄存器的格式 |31|30| |18|17|16| 5|4|3|2|0|1| |P |C | |A | |W | N|E|T|E|M|P| |G |D | |M | |P | E|T|S|M|P|E| 我们主要注意这个WP这位,其他的请参考IA-32 Volume 3A; WP——Write Protect,当设置为1时只提供读页权限 PE——Paging,当设置为1时提供分页 MP——Protection Enable,当设置为1时进入保护模式 所以我们只要把WP这一位设置为0时,就可以修改SSDT了 //1 关闭写保护 __asm { push eax mov eax, CR0 and eax, 0FFFEFFFFh mov CR0, eax pop eax } //2 打开写保护 __asm { push eax mov eax, CR0 or eax, NOT 0FFFEFFFFh mov CR0, eax pop eax } 通过上面的第一组指令我们就可以正常修改SSDT,记得修改后要还原。 方法二: 此方法是盖茨提供的,在内存描述表(MDL)中描述一块内存区域,MDL包含此内存区域的起始地址,拥有者进程,字节数量以及标志。 //在ddk中的描述 typedef struct _MDL { struct _MDL *Next; CSHORT Size; CSHORT MdlFlags; struct _EPROCESS *Process; PVOID MappedSystemVa; PVOID StartVa; ULONG ByteCount; ULONG ByteOffset; } MDL, *PMDL;
#define MDL_MAPPED_TO_SYSTEM_VA 0x0001 #define MDL_PAGES_LOCKED 0x0002 #define MDL_SOURCE_IS_NONPAGED_POOL 0x0004 #define MDL_ALLOCATED_FIXED_SIZE 0x0008 #define MDL_PARTIAL 0x0010 #define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020 #define MDL_IO_PAGE_READ 0x0040 #define MDL_WRITE_OPERATION 0x0080 #define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100 #define MDL_LOCK_HELD 0x0200 #define MDL_PHYSICAL_VIEW 0x0400 #define MDL_IO_SPACE 0x0800 #define MDL_NETWORK_HEADER 0x1000 #define MDL_MAPPING_CAN_FAIL 0x2000 #define MDL_ALLOCATED_MUST_SUCCEED 0x4000 // Declarations #pragma pack(1) typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char *ParamTableBase; } SSDT; #pragma pack() __declspec(dllimport) SSDTKeServiceDescriptorTable; PMDL g_pmdlSystemCall; PVOID *MappedSystemCallTable; // save old system call locations // Map the memory into our domain to change the permissions on // the MDL 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); MappedSystemCallTable就是SSDT的地址,现在可以放心的操作它吧!用完了最好MmFreePagesFromMdl。
如何写windows系统已保护的内存区域
最新推荐文章于 2021-08-06 02:37:22 发布