看了看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打开相应的注册表文件。
如果要保护注册表,在创建线程前处理一下就好了。还只是猜想,哪天闲出毛病了再试试。