看了看wrk的代码,发现一个函数会调用ZwCreateFile打开注册表的文件,这个函数就是CmpOpenHiveFiles
这个函数会打开两个注册表文件,master为不带后辍的,secondary为带后辍的。
system32\config\system和software就是这样被加载的。
查找过程,先找SAM,这个词不常见,grep一下找到一个配置表:
HIVE_LIST_ENTRY CmpMachineHiveList[] = {
{ L"HARDWARE", L"MACHINE\\", NULL, HIVE_VOLATILE , 0 , NULL, FALSE, FALSE, FALSE},
{ L"SECURITY", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
{ L"SOFTWARE", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
{ L"SYSTEM", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
{ L"DEFAULT", L"USER\\.DEFAULT", NULL, 0 , CM_CMHIVE_FLAG_UNTRUSTED , NULL, FALSE, FALSE, FALSE},
{ L"SAM", L"MACHINE\\", NULL, HIVE_NOLAZYFLUSH , 0 , NULL, FALSE, FALSE, FALSE},
{ NULL, NULL, 0, 0 , 0 , NULL, FALSE, FALSE, FALSE}
};
注册表应该就是从这里初始化的了。
再找引用:
for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++) {
ASSERT( CmpMachineHiveList[i].Name != NULL );
//
// just spawn the Threads to load the hives in parallel
//
Status = PsCreateSystemThread(
&Thread,
THREAD_ALL_ACCESS,
NULL,
0,
NULL,
CmpLoadHiveThread,
(PVOID)(ULONG_PTR)(ULONG)i
);
if (NT_SUCCESS(Status)) {
ZwClose(Thread);
} else {
//
// cannot spawn thread; Fatal error
//
CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_HIVE_LIST,3,i,Status);
}
}
这里为每个hive创建一个线程,进入CmpLoadHiveThread函数:
// <sysroot>\config\hive
if (CmpMachineHiveList[i].CmHive == NULL) {
//
// Hive has not been initialized in any way.
//
CmpMachineHiveList[i].Allocate = TRUE;
Status = CmpInitHiveFromFile(&FileName,
CmpMachineHiveList[i].HHiveFlags,
&CmHive,
&(CmpMachineHiveList[i].Allocate),
CM_CHECK_REGISTRY_CHECK_CLEAN
);
if ( (!NT_SUCCESS(Status)) ||
(!CmpShareSystemHives && (CmHive->FileHandles[HFILE_TYPE_LOG] == NULL)) )
{
ErrorParameters = &FileName;
ExRaiseHardError(
STATUS_CANNOT_LOAD_REGISTRY_FILE,
1,
1,
(PULONG_PTR)&ErrorParameters,
OptionOk,
&ErrorResponse
);
}
CmpInitHiveFromFile会调用CmpOpenHiveFiles,后者会调用zwcreatefile打开相应的注册表文件。
如果要保护注册表,在创建线程前处理一下就好了。还只是猜想,哪天闲出毛病了再试试。