Chinaunix首页 | 论坛 | 博客
  • 博客访问: 921004
  • 博文数量: 194
  • 博客积分: 7991
  • 博客等级: 少将
  • 技术积分: 2067
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-09 22:03
文章分类

全部博文(194)

文章存档

2010年(8)

2009年(71)

2008年(109)

2007年(6)

我的朋友

分类: WINDOWS

2009-06-03 09:29:38

加载windows内核模块的又一个方法
加载驱动比较常规的方法是先后调用openSCmanager()/CreateService()/StartService()等API,这里介绍的是rootkit migbot中展现的一种方法,使用了MS未公开的API。该方法不需要创建注册表键就可以将driver加载入系统中,有利于rootkit的隐藏。下边展示一下这种技术:
 
编写一个内核模块sxg.sys:

#include <ntddk.h>
NTSTATUS DriverEntry(PDRIVER_OBJECT obj, PUNICODE_STRING reg){
    DbgPrint("DriverEntry...");
    return STATUS_SUCCESS;
}

 
编写loader:

#include <stdio.h>
#include <windows.h>

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef long NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)

typedef NTSTATUS (__stdcall *ZWSETSYSTEMINFORMATION)(
            DWORD SystemInformationClass,
            PVOID SystemInformation,
            ULONG SystemInformationLength
);

typedef VOID (__stdcall *RTLINITUNICODESTRING)(
    PUNICODE_STRING DestinationString,
    PCWSTR SourceString
);

ZWSETSYSTEMINFORMATION ZwSetSystemInformation;
RTLINITUNICODESTRING RtlInitUnicodeString;

typedef struct _SYSTEM_LOAD_AND_CALL_IMAGE
{
    UNICODE_STRING ModuleName;
} SYSTEM_LOAD_AND_CALL_IMAGE, *PSYSTEM_LOAD_AND_CALL_IMAGE;

#define SystemLoadAndCallImage 38

int main()
{
    SYSTEM_LOAD_AND_CALL_IMAGE GregsImage;
    WCHAR daPath[] = L"\\??\\D:\\sxg.sys";
    NTSTATUS status;
    
    RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress(
                GetModuleHandle("ntdll.dll"), "RtlInitUnicodeString");
    if (NULL == RtlInitUnicodeString)
    {
        printf("Failed to get RtlInitUnicodeString\r\n"); return -1;
    }
    ZwSetSystemInformation = (ZWSETSYSTEMINFORMATION)GetProcAddress(
                GetModuleHandle("ntdll.dll"), "ZwSetSystemInformation");
    if (NULL == ZwSetSystemInformation)
    {
        printf("Failed to get ZwSetSystemInformation\r\n"); return -1;
    }

    RtlInitUnicodeString(&(GregsImage.ModuleName), daPath);
    
    status = ZwSetSystemInformation(SystemLoadAndCallImage,
                        &GregsImage, sizeof(SYSTEM_LOAD_AND_CALL_IMAGE));
    if(!NT_SUCCESS(status)){
        printf("Failed to load sys\r\n");return -1;}
    else
        printf("driver loaded!\n");
    
    return 0;
}

通过debugger可看到,“DriverEntry...”字样被打印出来,说明驱动已被加载。这种方法将驱动映像加载到了可分页的内存区域,对于内核模块来说,这是非常危险的,需要在驱动中将代码拷贝到不可分页内存区域之后再执行其他功能,不然蓝屏重启的概率很大很大。另外一点就是,通过这种方法加载的内核模块无法动态卸载,只能等到重启之后了。本测试在windows xp sp3上测试的。

song.xian-guang#hotmail.com
http://sxg.cublog.cn
http://blog.chinaunix.net/u/8754/showart_1953096.html

阅读(3222) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~