自己调用NTDLL函数

本文介绍了一种在DLL初始化时避免调用其他系统DLL函数的问题,即直接调用NTDLL接口。作者提供了如何声明并使用NTDLL导出函数的方法,并封装了一个NTRegistry类来代替系统注册表API,详细说明了项目设置和测试程序的实现。
摘要由CSDN通过智能技术生成

一、概述

在DLL初始化的时候有时不能调用其它系统DLL的函数,以免导致问题,但有时候又必须要调用怎么办?一种办法就是自己直接调用NTDLL接口,这样肯定没有问题。

下面我写个自己调用Registry的封装类,用来代替原本系统注册表API。

 

二、申明NTDLL导出函数

在自己工程中需要调用NTDLL导出函数,可以通GetProcessAddr来获取函数地址再调用,也可以通过导入库的方式(这种需要ntdll.lib文件,在DDK中有),我这里采用第二种方式。

函数和类型声明:

NTDllDecl.h

#pragma once
#include <windows.h>
#include <winternl.h>

namespace NT {
    extern "C" {

// macro definition
#ifndef NTSTATUS
#define NTSTATUS    LONG                                
#endif

#ifndef NTAPI
#define NTAPI        __stdcall                                
#endif

#ifndef NTSYSAPI 
#define NTSYSAPI    __declspec(dllimport)
#endif

#ifndef STATUS_BUFFER_OVERFLOW
#define STATUS_BUFFER_OVERFLOW           ((NTSTATUS)0x80000005L)
#endif

typedef enum _KEY_INFORMATION_CLASS {
    KeyBasicInformation,
    KeyNodeInformation,
    KeyFullInformation,
    KeyNameInformation,
    KeyCachedInformation,
    KeyFlagsInformation,
    KeyVirtualizationInformation,
    KeyHandleTagsInformation,
    MaxKeyInfoClass  // MaxKeyInfoClass should always be the last enum
} KEY_INFORMATION_CLASS;

typedef enum _KEY_VALUE_INFORMATION_CLASS {
    KeyValueBasicInformation,
    KeyValueFullInformation,
    KeyValuePartialInformation,
    KeyValueFullInformationAlign64,
    KeyValuePartialInformationAlign64,
    MaxKeyValueInfoClass  // MaxKeyValueInfoClass should always be the last enum
} KEY_VALUE_INFORMATION_CLASS;

typedef struct _KEY_BASIC_INFORMATION {
    LARGE_INTEGER LastWriteTime;
    ULONG   TitleIndex;
    ULONG   NameLength;
    WCHAR   Name[1];            // Variable length string
} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;

typedef struct _KEY_NODE_INFORMATION {
    LARGE_INTEGER LastWriteTime;
    ULONG   TitleIndex;
    ULONG   ClassOffset;
    ULONG   ClassLength;
    ULONG   NameLength;
    WCHAR   Name[1];            // Variable length string
//          Class[1];           // Variable length string not declared
} KEY_NODE_INFORMATION, *PKEY_NODE_INFORMATION;

typedef struct _KEY_FULL_INFORMATION {
    LARGE_INTEGER LastWriteTime;
    ULONG   TitleIndex;
    ULONG   ClassOffset;
    ULONG   ClassLength;
    ULONG   SubKeys;
    ULONG   MaxNameLen;
    ULONG   MaxClassLen;
    ULONG   Values;
    ULONG   MaxValueNameLen;
    ULONG   MaxValueDataLen;
    WCHAR   Class[1];           // Variable length
} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;

typedef struct _KEY_VALUE_BASIC_INFORMATION {
    ULONG   TitleIndex;
    ULONG   Type;
    ULONG   NameLength;
    WCHAR   Name[1];            // Variable size
} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;

typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
    ULONG   TitleIndex;
    ULONG   Type;
    ULONG   DataLength;
    UCHAR   Data[1];            // Variable size
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;

// Registry
NTSYSAPI
NTSTATUS
NTAPI
ZwCreateKey(
    OUT PHANDLE KeyHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN ULONG TitleIndex,
    IN PUNICODE_STRING Class,
    IN ULONG CreateOptions,
    OUT PULONG Disposition
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwOpenKey(
    OUT PHANDLE KeyHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwQueryKey(
    IN HANDLE KeyHandle,
    IN KEY_INFORMATION_CLASS KeyInformationClass,
    OUT PVOID KeyInformation,
    IN ULONG KeyInformationLength,
    OUT PULONG ResultLength
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwSetValueKey(
    IN HANDLE KeyHandle,
    IN PUNICODE_STRING ValueName,
    IN ULONG TitleIndex,
    IN ULONG Type,
    IN PVOID Data,
    IN ULONG DataSize
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwQueryValueKey(
    IN HANDLE KeyHandle,
    IN PUNICODE_STRING ValueName,
    IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
    OUT PVOID KeyValueInformation,
    IN ULONG KeyValueInformationLength,
    OUT PULONG ResultLength
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwEnumerateKey(
    IN HANDLE KeyHandle,
    IN ULONG Index,
    IN KEY_INFORMATION_CLASS KeyInformationClass,
    OUT PVOID KeyInformation,
    IN ULONG KeyInformationLength,
    OUT PULONG ResultLength
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwClose(
    IN HANDLE Handle
    );

NTSYSAPI
NTSTATUS 
NTAPI
RtlFormatCurrentUserKeyPath( 
    OUT PUNICODE_STRING RegistryPath 
    );


    }
};

 

三、封装自己注册表函数

自己定义一个类用来封装注册表函数,我这里只封装了几个需要用的注册表函数(参考ReatOS和Windows代码),其余的可以后续再添加。

注册封装类声明:

NTRegistry.h

//********************************************************************  
//    文件名:        NTRegistry.h
//    文件描述:      Ntdll导出注册表函数定义头文件
//    作者:           
//    版本:          1.0
// 
//    修改历史:      
//    备注:          
//*********************************************************************
#pragma once

#ifndef STATIC
#define STATIC        static
#endif

#ifndef NTSTATUS
#define NTSTATUS    LONG
#endif


class NTRegistry
{
public:
    
    STATIC LONG RegCreateKey(
                HKEY hKey,
                LPCWSTR lpSubKey,
                DWORD Reserved,
                LPWSTR lpClass,
                DWORD dwOptions,
                REGSAM samDesired,
                LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                PHKEY phkResult,
                LPDWORD lpdwDisposition);

    STATIC LONG RegOpenKey(
                HKEY hKey,
                LPCWSTR lpSubKey,
                DWORD ulOptions,
                REGSAM samDesired,
                PHKEY phkResult);

    STATIC LONG RegQueryInfoKey(
                HKEY hKey,
                LPWSTR lpClass,
                LPDWORD lpcbClass,
                LPDWORD lpReserved,
                LPDWORD lpcSubKeys,
                LPDWORD lpcbMaxSubKeyLen,
                LPDWORD lpcbMaxClassLen,
                LPDWORD lpcValues,
                LPDWORD lpcbMaxValueNameLen,
                LPDWORD lpcbMaxValueLen,
                LPDWORD lpcbSecurityDescriptor,
                PFILETIME lpftLastWriteTime
                );

    STATIC LONG RegSetValue( 
                HKEY hKey,
                LPCWSTR lpValueName,
                DWORD Reserved,
                DWORD dwType,
                CONST BYTE* lpData,
                DWORD cbData);

    STATIC LONG RegQueryValue(
                HKEY hKey,
                LPCWSTR lpValueName,
                LPDWORD lpReserved,
                LPDWORD lpType,
                LPBYTE lpData,
                LPDWORD lpcbData
                );

    STATIC LONG RegEnumKey(
                HKEY hKey,
                DWORD dwIndex,
                LPWSTR lpName,
                LPDWORD lpcbName,
                LPDWORD lpReserved,
                LPWSTR lpClass,
                LPDWORD lpcbClass,
                PFILETIME lpftLastWriteTime);

    STATIC LONG RegCloseKey(HKEY hKey);

private:

    STATIC NTSTATUS OpenCurrentUser(
                IN ACCESS_MASK DesiredAccess,
                OUT PHANDLE KeyHandle);

    STATIC NTSTATUS OpenLocalMachineKey(
                OUT PHANDLE KeyHandle);

    STATIC NTSTATUS OpenCurrentConfigKey (PHANDLE KeyHandle);

    STATIC NTSTATUS OpenUsersKey(PHANDLE KeyHandle);

    STATIC NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);

    STATIC NTSTATUS MapDefaultKey(
                OUT PHANDLE RealKey, 
                IN HKEY Key);
};

 

注册封装类定义:

NTRegistry.cpp

#include "StdAfx.h"
#include "NTRegistry.h"
#include "NTDllDecl.h"

#define ARGUMENT_PRESENT( arg )                                            \
    ((( PVOID ) arg ) != (( PVOID ) NULL ))

#define DEFAULT_KEY_NAME_SIZE                    128
#define DEFAULT_CLASS_SIZE                        128
#define DEFAULT_VALUE_SIZE                        128

#define REG_MAX_NAME_SIZE                        256
#define REG_MAX_DATA_SIZE                        2048

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS                          ((NTSTATUS)0x00000000L) 
#endif

#define RTL_CONSTANT_STRING(__SOURCE_STRING__)                            \
{                                                                        \
    sizeof(__SOURCE_STRING__) - sizeof((__SOURCE_STRING__)[0]),            \
    sizeof(__SOURCE_STRING__),                                            \
    (__SOURCE_STRING__)                                                    \
}

#define IsPredefKey(HKey)                                               \
    (((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000)

#define ClosePredefKey(Handle)         
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值