Esempio n. 1
0
BOOL GetNtosInformation(WCHAR** pKernelFullPath,ULONG* ulKernelBase, ULONG* ulKernelSize)
{
	ULONG ulBase = 0;
	ULONG ulSize = 0;
	ULONG ulBufferLength = 0;
	ULONG ulUnicodeKernelFullPath = 0;
	WCHAR wszNtosFullPath[260];
	KeSetSystemAffinityThread(1); //使当前线程运行在第一个处理器上  
	__asm
	{  
		push eax
		push ebx
		mov  eax, fs:[0x34]     //+0x34得到KdVersionBlock的地址  
		add  eax,0x18			//得到指向PsLoadedModuleList的地址   
		mov  eax,[eax]			//得到PsLoadedModuleList的地址   
		mov  ebx,[eax]			//取出PsLoadedModuleList里面的内容, 即KLDR_DATA_TABLE_ENTRY结构  
		mov  eax,[ebx+0x18]		//取出DllBase, 即ntoskrnl.exe的基地址 
		mov ulBase, eax
		mov eax,[ebx+0x20]		//+20h SizeOfImage
		mov ulSize,eax
		mov eax,ebx
		add eax,0x24			//+24h 是ntos在3环下的UNICODE_STRING全路径	
		mov ulUnicodeKernelFullPath,eax
		pop ebx
		pop eax  
	}  
	KeRevertToUserAffinityThread();//恢复线程运行的处理器 
	//PsLoadedModuleList的第一个就是ntos
	//nt!_LDR_DATA_TABLE_ENTRY
	//+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x82195338 - 0x8055e720 ]
	//+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
	//+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
	//+0x018 DllBase          : 0x804d8000 Void
	//+0x01c EntryPoint       : 0x806a3c08 Void
	//+0x020 SizeOfImage      : 0x20e000
	//+0x024 FullDllName      : _UNICODE_STRING "\WINDOWS\system32\ntkrnlpa.exe"
	//+0x02c BaseDllName      : _UNICODE_STRING "ntoskrnl.exe"
	//+0x034 Flags            : 0xc004000
	//+0x038 LoadCount        : 1
	//+0x03a TlsIndex         : 0
	//+0x03c HashLinks        : _LIST_ENTRY [ 0x0 - 0x1f107a ]
	//+0x03c SectionPointer   : (null) 
	//+0x040 CheckSum         : 0x1f107a
	//+0x044 TimeDateStamp    : 0
	//+0x044 LoadedImports    : (null) 
	//+0x048 EntryPointActivationContext : (null) 
	//+0x04c PatchInformation : 0x0074006e Void
	RtlZeroMemory(wszNtosFullPath,260*2);
	//UNICODE_STRING->Length 不包括NULL字符
	if (!MmIsAddressValidEx((PUNICODE_STRING)ulUnicodeKernelFullPath))
	{
		return FALSE;
	}
	ulBufferLength = (((PUNICODE_STRING)ulUnicodeKernelFullPath)->Length + 1) * 2;
	if (SafeCopyMemory((PVOID)((PUNICODE_STRING)ulUnicodeKernelFullPath)->Buffer,
		wszNtosFullPath,
		ulBufferLength) != STATUS_SUCCESS)
	{
		*ulKernelBase = 0;
		*ulKernelSize = 0;
		return FALSE;
	}
	//拷贝成功的话,就进行对比
	*pKernelFullPath = (WCHAR*)ExAllocatePool(NonPagedPool,260*2);
	if (!*pKernelFullPath)
	{
		*ulKernelBase = 0;
		*ulKernelSize = 0;
		return FALSE;
	}
	wcscat(*pKernelFullPath,L"\\SystemRoot\\system32\\");
	if (wcsstr((const wchar_t*)wszNtosFullPath,L"ntoskrnl.exe") != NULL)
	{
		wcscat(*pKernelFullPath,L"ntoskrnl.exe");
	}
	else if (wcsstr((const wchar_t*)wszNtosFullPath,L"ntkrnlpa.exe") != NULL)
	{
		wcscat(*pKernelFullPath,L"ntkrnlpa.exe");
	}
	else if (wcsstr((const wchar_t*)wszNtosFullPath,L"ntkrnlmp.exe") != NULL)
	{
		wcscat(*pKernelFullPath,L"ntkrnlmp.exe");
	}
	else if (wcsstr((const wchar_t*)wszNtosFullPath,L"ntkrpamp.exe") != NULL)
	{
		wcscat(*pKernelFullPath,L"ntkrpamp.exe");
	}
	//else if (wcsstr((const wchar_t*)wszNtosFullPath,L"ntkrnlup.exe") != NULL)
	//{
	//	wcscat(*pKernelFullPath,L"ntkrnlup.exe");
	//}
	else//失败了
	{
		*ulKernelBase = 0;
		*ulKernelSize = 0;
		ExFreePool(*pKernelFullPath);
		return FALSE;
	}
	*ulKernelBase = ulBase;
	*ulKernelSize = ulSize;
	return TRUE;
}
Esempio n. 2
0
/*
NTSTATUS SafeMmUnmapViewOfSection(PEPROCESS Process,ULONG lpBase)  //NtUnmapViewOfSection
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;

	RMmUnmapViewOfSection = ReLoadNtosCALL(L"MmUnmapViewOfSection",SystemKernelModuleBase,ImageModuleBase);
	if (RMmUnmapViewOfSection)
	{
		ObReferenceObject(Process);
		status = RMmUnmapViewOfSection(Process,lpBase);
		ObDereferenceObject(Process);
	}
	return status;
}
*/
BOOL MyParseVadTreeRoutine(BYTE* VadNode,PDLLINFO PDll)
{
	DWORD ControlAreaOffset;
	PCONTROL_AREA ControlArea=NULL;
	PFILE_OBJECT FileObject=NULL;
	DWORD StartingVpnOffset=0;
	DWORD StartingVpn;
	DWORD Subsection;
	DWORD SubsectionOffset;
	PEX_FAST_REF FilePointer;
	POBJECT_NAME_INFORMATION UnicodeDosFullPath = NULL;
	WIN_VER_DETAIL WinVer;
	BOOL bRetOK = FALSE;

	if (KeGetCurrentIrql() > PASSIVE_LEVEL)
	{
		return bRetOK;
	}
	__try
	{
		WinVer=GetWindowsVersion();
		switch (WinVer)
		{
		case WINDOWS_VERSION_XP:
			StartingVpnOffset=0x00;
			ControlAreaOffset=0x18;
			break;
		case WINDOWS_VERSION_2K3:
			StartingVpnOffset=0x0c;
			ControlAreaOffset=0x18;
			break;
		case WINDOWS_VERSION_2K3_SP1_SP2:
			StartingVpnOffset=0x0c;
			ControlAreaOffset=0x18;
			break;
		case WINDOWS_VERSION_VISTA_2008:                             //Vista+2008开始
			StartingVpnOffset=0x0c;
			SubsectionOffset=0x24;
			break;
			/*case 6002:                             //2008
			StartingVpnOffset=0x0c;
			SubsectionOffset=0x24;
			break;
			*/
		case WINDOWS_VERSION_7_7000:
		case WINDOWS_VERSION_7_7600_UP:
			StartingVpnOffset=0x0c;
			SubsectionOffset=0x24;
			break;
		}
		if ( WinVer == WINDOWS_VERSION_XP || WinVer == WINDOWS_VERSION_2K3 || WinVer == WINDOWS_VERSION_2K3_SP1_SP2 )   //xp || 2003
		{
			if (!MmIsAddressValidEx((VadNode+StartingVpnOffset)))
			{
				bRetOK = FALSE;
				__leave;
			}
			StartingVpn=*(DWORD*)(VadNode+StartingVpnOffset);
			if (!StartingVpn)
			{
				bRetOK = FALSE;
				__leave;
			}
			// StartingVpn<<12 is base (xp下exe模块的地址一般都是 0x01000000)
			if (NULL != StartingVpn<<12)
			{
				if (!MmIsAddressValidEx((VadNode+ControlAreaOffset)))
				{
					bRetOK = FALSE;
					__leave;
				}
				ControlArea=(PCONTROL_AREA)(*(DWORD*)(VadNode+ControlAreaOffset));

				//好像这里用RMmIsAddressValidEx判断VCS_TRANSITION内存不准确蓝屏,无语~~
				//(蓝屏其实就是没有判断VCS_TRANSITION类型,这个类型也是无法访问)
				if (MmIsAddressValidEx(ControlArea))
				{
					FileObject=ControlArea->FilePointer;
					if (MmIsAddressValidEx(FileObject) &&
						ValidateUnicodeString(&FileObject->FileName) &&
						FileObject->FileName.Buffer != NULL &&
						FileObject->FileName.Length > 0)
					{
						if (ModuleCount < 518)  //会有518个dll么?
						{
							if (sizeof(PDll->DllInfo[ModuleCount].lpwzDllModule) > FileObject->FileName.Length)
							{
								memset(PDll->DllInfo[ModuleCount].lpwzDllModule,0,sizeof(PDll->DllInfo[ModuleCount].lpwzDllModule));

								//KdPrint(("%d:%ws\n",FileObject->FileName.Buffer,FileObject->FileName.Length));

								SafeCopyMemory(
									FileObject->FileName.Buffer,
									PDll->DllInfo[ModuleCount].lpwzDllModule,
									FileObject->FileName.Length
									);
								PDll->DllInfo[ModuleCount].ulBase = (ULONG)StartingVpn<<12;
								ModuleCount++;
								PDll->ulCount = ModuleCount;
								bRetOK = TRUE;
							}
						}
					}
				}
			}

		}
		else if ( WinVer == WINDOWS_VERSION_VISTA_2008 || WinVer == WINDOWS_VERSION_7_7000 || WinVer == WINDOWS_VERSION_7_7600_UP) //win7||vista||2008
		{
			if (!MmIsAddressValidEx((VadNode+StartingVpnOffset)))
			{
				bRetOK = FALSE;
				__leave;
			}
			StartingVpn=*(DWORD*)(VadNode+StartingVpnOffset);
			if (!StartingVpn)
			{
				bRetOK = FALSE;
				__leave;
			}
			// StartingVpn<<12 is base (xp下exe模块的地址一般都是 0x01000000)
			if (NULL != StartingVpn<<12)
			{
				if (DebugOn)
					KdPrint(("[%08x]VadNode:%X\n",StartingVpn<<12,VadNode));

				if (!MmIsAddressValidEx((VadNode+SubsectionOffset)))
				{
					bRetOK = FALSE;
					__leave;
				}
				Subsection=*(DWORD*)(VadNode+SubsectionOffset); //win7下新加的结构
				if (MmIsAddressValidEx(Subsection))
				{
					ControlArea=(PCONTROL_AREA)(*(DWORD*)Subsection);

					//好像这里用RMmIsAddressValidEx判断VCS_TRANSITION内存不准确蓝屏,无语~~
					//(蓝屏其实就是没有判断VCS_TRANSITION类型,这个类型也是无法访问)
					if (MmIsAddressValidEx(ControlArea))
					{
						FilePointer=(PEX_FAST_REF)&ControlArea->FilePointer;
						if (MmIsAddressValidEx(FilePointer))
						{
							FileObject=(PFILE_OBJECT)(((DWORD)FilePointer->Object)&(~FilePointer->RefCnt));
							if (MmIsAddressValidEx(FileObject) &&
								ValidateUnicodeString(&FileObject->FileName) &&
								FileObject->FileName.Buffer != NULL &&
								FileObject->FileName.Length > 0)
							{
								if (ModuleCount < 518)  //会有518个dll么?
								{
									if (sizeof(PDll->DllInfo[ModuleCount].lpwzDllModule) > FileObject->FileName.Length)
									{
										memset(PDll->DllInfo[ModuleCount].lpwzDllModule,0,sizeof(PDll->DllInfo[ModuleCount].lpwzDllModule));

										SafeCopyMemory(
											FileObject->FileName.Buffer,
											PDll->DllInfo[ModuleCount].lpwzDllModule,
											FileObject->FileName.Length
											);
										PDll->DllInfo[ModuleCount].ulBase = (ULONG)StartingVpn<<12;
										ModuleCount++;
										PDll->ulCount = ModuleCount;
										bRetOK = TRUE;
									}
								}
							}
						}
					}
				}
			}

		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		if (DebugOn)
			DbgPrint("VadTree Error \r\n");
	}
	return bRetOK;
}
Esempio n. 3
0
/*
DWORD GetDllModuleFromPeb(PEPROCESS Process,PDLLINFO PDll)
{

	DWORD PebOffset=0;
	DWORD PebLdrOffset = 0;
	DWORD Peb;
	PPEB_LDR_DATA PebLdr;
	PLDR_DATA_TABLE_ENTRY LdrTableEntry;
	PLIST_ENTRY pListHead,pListNext;
	int i = 0;
	WIN_VER_DETAIL WinVer;
	BOOL bRetOK = FALSE;

	if (!MmIsAddressValidEx(Process))
	{
		return bRetOK;
	}
	__try
	{
		WinVer=GetWindowsVersion();
		switch (WinVer)
		{
		case WINDOWS_VERSION_XP:     //xp
			PebOffset=0x1b0;
			PebLdrOffset = 0x0c;
			break;
		case WINDOWS_VERSION_2K3_SP1_SP2:     //2003
			PebOffset=0x1a0;
			PebLdrOffset = 0x0c;
			break;
		case WINDOWS_VERSION_7_7000:    //win7 7000
			PebOffset=0x1a0;
			PebLdrOffset = 0x0c;
			break;
	    case WINDOWS_VERSION_7_7600_UP:     //win7 7600
			PebOffset=0x1a8;
			PebLdrOffset = 0x0c;
			break;
		}
		if (PebOffset==0 ||
			PebLdrOffset==0)
		{
			bRetOK = FALSE;
			__leave;
		}
		Peb = *(DWORD*)((DWORD)Process+PebOffset);

		ProbeForRead((PVOID)Peb,4,1);//PEB是用户空间的,可能会不能访问

		if (Peb == 0 ||
			!MmIsAddressValidEx(Peb))
		{
			if (DebugOn)
				DbgPrint("Peb is null\n");
			bRetOK = FALSE;
			__leave;
		}

		PebLdr=(PPEB_LDR_DATA)*(DWORD*)(Peb+PebLdrOffset);

		ProbeForRead((PVOID)PebLdr,4,1);

		if (!MmIsAddressValidEx(PebLdr))
		{
			if (DebugOn)
				DbgPrint("PebLdr offset is null\n");
			bRetOK = FALSE;
			__leave;
		}
		pListHead=&PebLdr->InLoadOrderModuleList;
		pListNext=pListHead->Flink;
		while (pListHead!=pListNext)
		{
			LdrTableEntry=(PLDR_DATA_TABLE_ENTRY)pListNext;
			if (!MmIsAddressValidEx(LdrTableEntry))
			{
				break;
			}
			if (ValidateUnicodeString(&LdrTableEntry->FullDllName) &&
				LdrTableEntry->FullDllName.Buffer != NULL &&
				LdrTableEntry->FullDllName.Length > 0 )
			{
				if (i < 518)  //会有518个dll么?
				{
					if (sizeof(PDll->DllInfo[i].lpwzDllModule) > LdrTableEntry->FullDllName.Length)
					{
						if (DebugOn)
							DbgPrint("DllBase:%x  dll path %ws:%d\n",LdrTableEntry->DllBase,LdrTableEntry->FullDllName.Buffer,LdrTableEntry->FullDllName.Length);

						PDll->DllInfo[i].ulBase = LdrTableEntry->DllBase;

						memset(PDll->DllInfo[i].lpwzDllModule,0,sizeof(PDll->DllInfo[i].lpwzDllModule));
						SafeCopyMemory(
							LdrTableEntry->FullDllName.Buffer,
							PDll->DllInfo[i].lpwzDllModule,
							LdrTableEntry->FullDllName.Length
							);
						i++;
						PDll->ulCount = i;
					}
				}
			}
			pListNext=pListNext->Flink;

		}
		bRetOK = TRUE;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		if (DebugOn)
			DbgPrint("GetDllNameFromPeb Error \r\n");
	}
	return bRetOK;
}
*/
VOID EunmProcessModuleByVirtualMemory(ULONG EProcess,PDLLINFO PDll)
{
	ULONG dwStartAddr = 0x00000000;
	HANDLE hProcess;
	MEMORY_BASIC_INFORMATION mbi;
	PUNICODE_STRING SectionName = NULL;
	OBJECT_ATTRIBUTES ObjectAttributes;
	CLIENT_ID ClientId={0};
	NTSTATUS status;
	int i=0;
	int count = 0;
	ULONG ulDllSize;
	BOOL bInit = FALSE;


	WinVer = GetWindowsVersion();
	switch(WinVer)
	{
	case WINDOWS_VERSION_XP:
		if (!MmIsAddressValidEx(RZwQueryVirtualMemory)){
			RZwQueryVirtualMemory = GetZwQueryVirtualMemoryAddress();
		}
		break;
	case WINDOWS_VERSION_7_7600_UP:
	case WINDOWS_VERSION_7_7000:
		ReLoadNtosCALL(&RZwQueryVirtualMemory,L"ZwQueryVirtualMemory",SystemKernelModuleBase,ImageModuleBase); //win7导出了,可以直接用
		break;
	case WINDOWS_VERSION_2K3_SP1_SP2:
		if (!MmIsAddressValidEx(RZwQueryVirtualMemory)){
			RZwQueryVirtualMemory = GetZwQueryVirtualMemoryAddress();
		}
		break;
	}
	ReLoadNtosCALL(&RObOpenObjectByPointer,L"ObOpenObjectByPointer",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RExAllocatePool,L"ExAllocatePool",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RExFreePool,L"ExFreePool",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RZwClose,L"ZwClose",SystemKernelModuleBase,ImageModuleBase);
	if (RZwQueryVirtualMemory &&
		RObOpenObjectByPointer &&
		RExAllocatePool &&
		RExFreePool &&
		RZwClose)
	{
		bInit = TRUE;
	}
	if (!bInit)
		return FALSE;

	//进程已经退出鸟
	if (!IsExitProcess(EProcess)){
		return FALSE;
	}
	status = RObOpenObjectByPointer(
		EProcess,          // Object    
		OBJ_KERNEL_HANDLE,  // HandleAttributes    
		NULL,               // PassedAccessState OPTIONAL    
		NULL,       // DesiredAccess    
		*PsProcessType,     // ObjectType    
		KernelMode,         // AccessMode    
		&hProcess);    
	if (!NT_SUCCESS(status))
	{
		if (DebugOn)
			KdPrint(("ObOpenObjectByPointer failed:%d",RtlNtStatusToDosError(status)));
		return NULL;
	}
	SectionName = (PUNICODE_STRING)RExAllocatePool(NonPagedPool,260*sizeof(WCHAR));
	if (!SectionName)
	{
		RZwClose(hProcess);
		return;
	}
	memset(SectionName,0,260*sizeof(WCHAR));

	__try
	{
		for (dwStartAddr=0; dwStartAddr<0x80000000; dwStartAddr=dwStartAddr+0x10000)
		{
			status = RZwQueryVirtualMemory(
				hProcess,
				(PVOID)dwStartAddr,
				MemoryBasicInformation,
				&mbi,
				sizeof(MEMORY_BASIC_INFORMATION),
				0
				);
			if (NT_SUCCESS(status))
			{
				if(mbi.Type == MEM_IMAGE)
				{
					status = RZwQueryVirtualMemory(
						hProcess,
						(PVOID)dwStartAddr,
						MemorySectionName,
						SectionName,
						260*sizeof(WCHAR),
						0
						);
					if (NT_SUCCESS(status))
					{
						if (i)
							count = i - 1;

						//如果当前的DLL模块路径 不等于前一个,则说明是开始了下一个DLL的枚举了。比如:
						//c:\windows\system32\ntdll.dll
						//c:\windows\system32\ntdll.dll
						//c:\windows\system32\ntdll.dll
						//c:\windows\system32\ntdll.dll
						//c:\windows\system32\ntdll.dll
						//c:\windows\system32\kernel32.dll
						if (_wcsnicmp(PDll->DllInfo[count].lpwzDllModule,SectionName->Buffer,SectionName->Length/2) != 0 &&
							sizeof(PDll->DllInfo[i].lpwzDllModule) > SectionName->Length)
						{
							if (DebugOn)
								KdPrint(("DLL-->%08x:%08x:%ws\r\n",mbi.BaseAddress,dwStartAddr,SectionName->Buffer));

							PDll->DllInfo[i].ulBase = dwStartAddr;
							SafeCopyMemory(
								SectionName->Buffer,
								PDll->DllInfo[i].lpwzDllModule,
								SectionName->Length
								);
							i++;
							PDll->ulCount = i;

							if (i > 518)
							{
								break;
							}
							/*
							//获取dll大小
							//备注一下这个方法
							for (ulDllSize = dwStartAddr+mbi.RegionSize;ulDllSize < 0x80000000;ulDllSize += mbi.RegionSize)
							{
								status = ZwQueryVirtualMemory(
									hProcess,
									(PVOID)ulDllSize,
									MemoryBasicInformation,
									&mbi,
									sizeof(MEMORY_BASIC_INFORMATION),
									0
									);
								if (NT_SUCCESS(status))
								{
									if(mbi.Type != MEM_IMAGE)
									{
										KdPrint(("DLL-->%08x:%08x:%ws\r\n",dwStartAddr,ulDllSize-dwStartAddr,SectionName->Buffer));
										break;
									}
								}
							}
							*/
						}
					}
				}
			}
		}

	}__except(EXCEPTION_EXECUTE_HANDLER){
		goto _FunctionRet;
	}
_FunctionRet:

	RExFreePool(SectionName);

	if (DebugOn)
		KdPrint(("ZwQueryVirtualMemory DLL count:%d-%d\r\n",i,PDll->ulCount));

	RZwClose(hProcess);
}
Esempio n. 4
0
//L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
NTSTATUS ReadRegistry(PSTARTUP_INFO Startup,WCHAR *DriverServiceNamePath,WCHAR *ReadKey)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;

	OBJECT_ATTRIBUTES NetworkClassKeyObject;
	OBJECT_ATTRIBUTES SubKeyObject;
	HANDLE NetworkClassKeyHandle;
	HANDLE SubKeyHandle;
	ULONG i, SubkeyIndex, ResultLength, InterfacesKeyStringLength;
	PWCHAR InterfacesKeyString;
	UNICODE_STRING NetworkClassKey, InterfacesKey, UnicodeReadKey, DriverServiceName;
	PKEY_BASIC_INFORMATION KeyInformation;
	PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
	WCHAR *KeyName = NULL;
	BOOL bInit = FALSE;

	ReLoadNtosCALL(&RRtlInitUnicodeString,L"RtlInitUnicodeString",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RZwOpenKey,L"ZwOpenKey",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RExAllocatePool,L"ExAllocatePool",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RExFreePool,L"ExFreePool",SystemKernelModuleBase,ImageModuleBase);

	ReLoadNtosCALL(&RZwEnumerateKey,L"ZwEnumerateKey",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RZwQueryValueKey,L"ZwQueryValueKey",SystemKernelModuleBase,ImageModuleBase);
	ReLoadNtosCALL(&RZwClose,L"ZwClose",SystemKernelModuleBase,ImageModuleBase);
	if (RRtlInitUnicodeString &&
		RZwOpenKey &&
		RExAllocatePool &&
		RExFreePool &&
		RZwEnumerateKey &&
		RZwQueryValueKey &&
		RZwClose)
	{
		bInit = TRUE;
	}
	if (!bInit)
	{
		return Status;
	}
	if (DebugOn)
		KdPrint(("Starting"));

	RRtlInitUnicodeString(&UnicodeReadKey,ReadKey);
	RRtlInitUnicodeString(&NetworkClassKey,DriverServiceNamePath);

	InitializeObjectAttributes(
		&NetworkClassKeyObject, 
		&NetworkClassKey, 
		OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 
		NULL, 
		NULL
		);
	Status = RZwOpenKey(
		&NetworkClassKeyHandle, 
		KEY_ALL_ACCESS, 
		&NetworkClassKeyObject
		);
	if (!NT_SUCCESS(Status))
	{
		if (DebugOn)
			DbgPrint("Failed to open Network Class key\n");

		return Status;
	}
	if (DebugOn)
		KdPrint(("ZwOpenKey success"));

	SubkeyIndex = 0;
	i = Startup->ulCount;

	while ((Status = RZwEnumerateKey(NetworkClassKeyHandle, SubkeyIndex, KeyBasicInformation, NULL, 0, &ResultLength)) != STATUS_NO_MORE_ENTRIES) 
	{
		if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_OVERFLOW) && (Status != STATUS_BUFFER_TOO_SMALL))
		{
			if (DebugOn)
				DbgPrint("ZwEnumerateKey 1 failed in SetupRegistry (%lx)\n", Status);
			Status = STATUS_UNSUCCESSFUL;
			break;
		}
		if ((KeyInformation = (PKEY_BASIC_INFORMATION)RExAllocatePool(NonPagedPool, ResultLength)) == NULL)
		{
			if (DebugOn)
				DbgPrint("ExAllocatePool KeyData failed in SetupRegistry\n");
			Status = STATUS_UNSUCCESSFUL;
			break;
		}
		memset(KeyInformation,0,ResultLength);
		Status = RZwEnumerateKey(
			NetworkClassKeyHandle,
			SubkeyIndex, 
			KeyBasicInformation, 
			KeyInformation, 
			ResultLength, 
			&ResultLength
			);
		if (!NT_SUCCESS(Status))
		{
			if (DebugOn)
				DbgPrint("ZwEnumerateKey 2 failed in SetupRegistry\n");

			Status = STATUS_UNSUCCESSFUL;
			RExFreePool(KeyInformation);
			break;
		}
		if ((KeyName = (WCHAR *)RExAllocatePool(NonPagedPool, 260*sizeof(WCHAR))) == NULL){
			continue;
		}
		memset(KeyName,0,260*sizeof(WCHAR));
		SafeCopyMemory(KeyInformation->Name,KeyName,KeyInformation->NameLength);

		//KdPrint(("Key:%ws\n",KeyName));

		//读取UnicodeReadKey
		RRtlInitUnicodeString(&DriverServiceName,KeyName);
		InitializeObjectAttributes(
			&SubKeyObject, 
			&DriverServiceName, 
			OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 
			NetworkClassKeyHandle, 
			NULL
			);
		Status = RZwOpenKey(
			&SubKeyHandle, 
			KEY_ALL_ACCESS, 
			&SubKeyObject
			);
		if (NT_SUCCESS(Status)) 
		{
			if ((Status = RZwQueryValueKey(SubKeyHandle, &UnicodeReadKey, KeyValuePartialInformation, NULL, 0, &ResultLength)) != STATUS_OBJECT_NAME_NOT_FOUND)
			{
				if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_OVERFLOW) && (Status != STATUS_BUFFER_TOO_SMALL))
				{
					RZwClose(SubKeyHandle);
					RExFreePool(KeyInformation);
					break;
				}
				KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RExAllocatePool(NonPagedPool, ResultLength);
				if (KeyValueInformation)
				{
					memset(KeyValueInformation,0,ResultLength);
					Status = RZwQueryValueKey(
						SubKeyHandle, 
						&UnicodeReadKey, 
						KeyValuePartialInformation,
						KeyValueInformation,
						ResultLength, 
						&ResultLength
						);
					if (NT_SUCCESS(Status))
					{
						//KdPrint(("%ws -> %ws\n",KeyName,KeyValueInformation->Data));
						if (MmIsAddressValidEx(KeyValueInformation->Data) &&
							KeyValueInformation->DataLength > 0)
						{
							SafeCopyMemory(DriverServiceName.Buffer,Startup->Startup[i].lpwzName,DriverServiceName.Length);
							SafeCopyMemory(DriverServiceNamePath,Startup->Startup[i].lpwzKeyPath,wcslen(DriverServiceNamePath)*2);
							SafeCopyMemory(KeyValueInformation->Data,Startup->Startup[i].lpwzKeyValue,KeyValueInformation->DataLength);
							i++;
		                    Startup->ulCount = i;

							if (DebugOn)
								KdPrint(("%ws -> %ws\n",KeyName,KeyValueInformation->Data));
						}
					}
					RExFreePool(KeyValueInformation);
				}

			}
			RZwClose(SubKeyHandle);
		}
		RExFreePool(KeyName);
 		RExFreePool(KeyInformation);

		KeyName = NULL;
		KeyInformation = NULL;

		SubkeyIndex++;
	}

	if (NetworkClassKeyHandle)
		RZwClose(NetworkClassKeyHandle);

	return Status;        
}