垃圾堆——windowssky
人生就象一场旅行 不必在乎目的地 在乎的是沿途的风景以及看风景的心情
<2007年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

留言簿(8)

随笔分类

随笔档案

文章档案

相册

NDIS IFS

内核研究

基础知识

安全技术

操作系统

病毒技术

网络技术

逆向工程

驱动开发

搜索

最新评论

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-21 文章-0 评论-26 Trackbacks-1
2007年5月23日

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。







发表于 2007-05-23 16:29 垃圾一堆 阅读(2248) | 评论 (0)编辑 收藏