首页
社区
课程
招聘
[原创]创建注册表的根键
2014-4-24 14:08 8175

[原创]创建注册表的根键

2014-4-24 14:08
8175
/*
功能:创建注册表的根键.

尽管:《深入解析windows操作系统》的第四章有如下说明:
There are six root keys (and you can't add new root keys or delete existing ones) that store information

RegLoadKey函数有如下说明:
Creates a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE and loads the data from the specified registry hive into that subkey.

而且:http://msdn.microsoft.com/en-us/library/windows/hardware/ff546907(v=vs.85).aspx
的补充说明里面说不建议使用如下函数.
NtRestoreKey
NtSaveKey
NtSaveKeyEx
NtLoadKeyEx
NtUnloadKey2
NtUnloadKeyEx
NtReplaceKey
NtRenameKey
NtSetInformationKey

这些函数没有公开的调用接口,但是导出了,而且很早的版本就导出了,所以可以安心的使用.

注册表根键创建的成功与失败可以通过代码的返回值查看.
                          也可以通过注册表路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\hivelist查看.

不足之处,敬请指出.
made by correy
made at 2013.11.13
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com                          
*/

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
用户层创建注册表根键的代码.

#include <windows.h>

typedef _Return_type_success_(return >= 0) LONG NTSTATUS;
typedef NTSTATUS *PNTSTATUS;

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
#ifdef MIDL_PASS
    [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
#else // MIDL_PASS
    _Field_size_bytes_part_(MaximumLength, Length) PWCH   Buffer;
#endif // MIDL_PASS
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
    PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;

#ifdef __cplusplus
extern "C++"
{
char _RTL_CONSTANT_STRING_type_check(const char *s);
char _RTL_CONSTANT_STRING_type_check(const WCHAR *s);
// __typeof would be desirable here instead of sizeof.
template <size_t N> class _RTL_CONSTANT_STRING_remove_const_template_class;
template <> class _RTL_CONSTANT_STRING_remove_const_template_class<sizeof(char)>  {public: typedef  char T; };
template <> class _RTL_CONSTANT_STRING_remove_const_template_class<sizeof(WCHAR)> {public: typedef WCHAR T; };
#define _RTL_CONSTANT_STRING_remove_const_macro(s) \
    (const_cast<_RTL_CONSTANT_STRING_remove_const_template_class<sizeof((s)[0])>::T*>(s))
}
#else
char _RTL_CONSTANT_STRING_type_check(const void *s);
#define _RTL_CONSTANT_STRING_remove_const_macro(s) (s)
#endif
#define RTL_CONSTANT_STRING(s) \
{ \
    sizeof( s ) - sizeof( (s)[0] ), \
    sizeof( s ) / sizeof(_RTL_CONSTANT_STRING_type_check(s)), \
    _RTL_CONSTANT_STRING_remove_const_macro(s) \
}

#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;               \
    }

#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)

#define OBJ_INHERIT             0x00000002L
#define OBJ_PERMANENT           0x00000010L
#define OBJ_EXCLUSIVE           0x00000020L
#define OBJ_CASE_INSENSITIVE    0x00000040L
#define OBJ_OPENIF              0x00000080L
#define OBJ_OPENLINK            0x00000100L
#define OBJ_KERNEL_HANDLE       0x00000200L
#define OBJ_FORCE_ACCESS_CHECK  0x00000400L
#define OBJ_VALID_ATTRIBUTES    0x000007F2L

//NTSTATUS ZwUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes);
//NTSTATUS ZwLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, IN POBJECT_ATTRIBUTES FileObjectAttributes);

//函数指针.
typedef NTSTATUS (WINAPI  * ZWLOADKEY) (IN POBJECT_ATTRIBUTES KeyObjectAttributes, IN POBJECT_ATTRIBUTES FileObjectAttributes);//__stdcall
typedef NTSTATUS (WINAPI * ZWUNLOADKEY) (IN POBJECT_ATTRIBUTES KeyObjectAttributes);//__stdcall

//全局变量
UNICODE_STRING uRegistryPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\correy");
UNICODE_STRING uRegDatPath = RTL_CONSTANT_STRING(L"\\DosDevices\\c:\\correy.DAT");
OBJECT_ATTRIBUTES obj;
OBJECT_ATTRIBUTES HiveFile;
ZWUNLOADKEY ZwUnloadKey;
ZWLOADKEY ZwLoadKey;

BOOL SetPrivilege(
    //HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    )
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    HANDLE hToken; // Get a token for this process.
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        return( FALSE );
    }

    if ( !LookupPrivilegeValue(
        NULL,            // lookup privilege on local system
        lpszPrivilege,   // privilege to lookup
        &luid ) )        // receives LUID of privilege
    {
        printf("LookupPrivilegeValue error: %u\n", GetLastError() );
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.
    if ( !AdjustTokenPrivileges(
        hToken,
        FALSE,
        &tp,
        sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES) NULL,
        (PDWORD) NULL) )
    {
        printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
        return FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    }

    return TRUE;
}

void main( )
{
    BOOL B;

    B = SetPrivilege(SE_BACKUP_NAME, TRUE);
    B = SetPrivilege(SE_RESTORE_NAME, TRUE);//必须加上这个RegSaveKey才成功.

    int r;

    LONG l = RegSaveKey(HKEY_CURRENT_USER, L"c:\\correy.dat", NULL);//如果已经存在,即使不在使用中,这个会失败.
    if (l != ERROR_SUCCESS)
    {
        r = GetLastError();
    }

    InitializeObjectAttributes(&obj,&uRegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL );//|OBJ_KERNEL_HANDLE
    InitializeObjectAttributes(&HiveFile,&uRegDatPath,OBJ_CASE_INSENSITIVE, NULL, NULL );//|OBJ_KERNEL_HANDLE

    HINSTANCE hinstLib = LoadLibrary(TEXT("ntdll.dll")); // Get a handle to the DLL module.     
    if (hinstLib != NULL) // If the handle is valid, try to get the function address.
    {
        ZwLoadKey = (ZWLOADKEY) GetProcAddress(hinstLib, "NtLoadKey");  
        if (NULL != ZwLoadKey) // If the function address is valid, call the function.
        {
            NTSTATUS status = ZwLoadKey(&obj,&HiveFile);//只一行运行会出错.
            if(!NT_SUCCESS(status))
            {
                MessageBox(0,0,0,0);
                //return;
            }
        }   

        MessageBox(0,L"下面开始卸载",0,0);

        ZwUnloadKey = (ZWUNLOADKEY) GetProcAddress(hinstLib, "NtUnloadKey");  
        if (NULL != ZwUnloadKey) // If the function address is valid, call the function.
        {
            NTSTATUS status = ZwUnloadKey(&obj);//只一行运行会出错.
            if(!NT_SUCCESS(status))
            {
                MessageBox(0,0,0,0);
                //return;
            }
        }

        FreeLibrary(hinstLib); // Free the DLL module.
    }

    //BOOL b = CopyFile(L"C:\\Users\\Administrator\\NTUSER.DAT", L"c:\\hkcu_copy.dat",false);
    //if (!b)
    //{
    //    r = GetLastError();//0x00000020,另一个程序(system)正在使用此文件,进程无法访问。
    //}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
驱动层创建注册表根键的代码如下:

#include <ntifs.h>

NTSTATUS ZwUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes);
NTSTATUS ZwLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, IN POBJECT_ATTRIBUTES FileObjectAttributes);

UNICODE_STRING uRegistryPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\correy");
UNICODE_STRING uRegDatPath = RTL_CONSTANT_STRING(L"\\DosDevices\\c:\\correy.DAT");//此文件必须是本计算机的,系统的或者自己生成的.
OBJECT_ATTRIBUTES obj;
OBJECT_ATTRIBUTES HiveFile;

VOID RegisterLoad()
{
    NTSTATUS status;
    HANDLE hRegister;
    ULONG i=0,ulSize=0;
    UNICODE_STRING us;

    status = ZwLoadKey(&obj,&HiveFile);
    if(!NT_SUCCESS(status))
    {
        DbgPrint("LoadKey failed Error: [%x] \n", status);
        return;
    }

    //一下是列举其子键的,也就是验证下.
    status = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &obj);
    if (NT_SUCCESS(status))
    {         
        PKEY_FULL_INFORMATION pfi;

        ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize);
        pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize);// 第一次调用是为了获取需要的长度

        ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize);// 第二次调用是为了获取数据
        for (i = 0; i < pfi->SubKeys; i++)
        {     
            PKEY_BASIC_INFORMATION pbi;

            ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize);// 获取第i个子项的长度
            pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize);         

            ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize);// 获取第i个子项的数据

            us.Buffer = pbi->Name;
            us.Length = (USHORT)pbi->NameLength;
            us.MaximumLength = pbi->NameLength + sizeof(wchar_t);

            DbgPrint("The %d SubItem Name : %wZ\n", i, &us);

            ExFreePool(pbi);// 释放内存
        }

        ExFreePool(pfi);
        ZwClose(hRegister);
    } else {
        DbgPrint("ZwOpenKey failed unknown cause. Error: [%x] \n", status);
    }  
}

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{   
    NTSTATUS status;   

    status = ZwUnloadKey(&obj);
    if(!NT_SUCCESS(status))
    {
        DbgPrint("ZwUnloadKey fail!\n");
    }
}

#pragma INITCODE
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
    NTSTATUS Status = 0;

    KdBreakPoint();// == DbgBreakPoint()  

    DriverObject->DriverUnload = Unload;   

    InitializeObjectAttributes(&obj,&uRegistryPath, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL );
    InitializeObjectAttributes(&HiveFile,&uRegDatPath,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL );

    RegisterLoad();   

    return Status;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞1
打赏
分享
最新回复 (3)
雪    币: 339
活跃值: (133)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
地狱怪客 2 2014-4-24 14:19
2
0
前来看看。。
雪    币: 94
活跃值: (400)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dico 2014-4-25 08:12
3
0
感谢你的分享
雪    币: 17
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小灬灰灰 2022-9-23 14:42
4
0
zwloadkey这个接口会返回STATUS_ACCESS_DENIED,有什么方法提权解决吗,补充下,我已经是在驱动中调用了,并且做了token    DefaultDacl 替换为driver acl。
游客
登录 | 注册 方可回帖
返回