/********************************************************/ /* ntapi: Native API core library */ /* Copyright (C) 2013--2017 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ /********************************************************/ #include #include #include #include #include #include "ntapi_impl.h" typedef ntapi_zw_open_directory_object objdir_open_fn; static void __tt_guid_to_hex_utf16( __in const nt_guid * guid, __out wchar16_t * hex_str) { uint16_t key; __ntapi_tt_uint32_to_hex_utf16( guid->data1,&hex_str[0]); __ntapi_tt_uint16_to_hex_utf16( guid->data2,&hex_str[9]); __ntapi_tt_uint16_to_hex_utf16( guid->data3,&hex_str[14]); key = guid->data4[0] * 0x100 + guid->data4[1]; __ntapi_tt_uint16_to_hex_utf16( key,&hex_str[19]); key = guid->data4[2] * 0x100 + guid->data4[3]; __ntapi_tt_uint16_to_hex_utf16( key,&hex_str[24]); key = guid->data4[4] * 0x100 + guid->data4[5]; __ntapi_tt_uint16_to_hex_utf16( key,&hex_str[28]); key = guid->data4[6] * 0x100 + guid->data4[7]; __ntapi_tt_uint16_to_hex_utf16( key,&hex_str[32]); hex_str[8] = '-'; hex_str[13] = '-'; hex_str[18] = '-'; hex_str[23] = '-'; } static nt_access_allowed_ace * __ipc_ace_init( nt_access_allowed_ace * ace, uint32_t mask, const nt_sid * sid) { ace->mask = mask; ace->header.ace_type = NT_ACE_TYPE_ACCESS_ALLOWED; ace->header.ace_flags = 0; ace->header.ace_size = sizeof(uint32_t) * sid->sub_authority_count + __offsetof(nt_access_allowed_ace,sid_start) + __offsetof(nt_sid,sub_authority); __ntapi->tt_sid_copy( (nt_sid *)&ace->sid_start, sid); return (nt_access_allowed_ace *)((size_t)ace + ace->header.ace_size); } static void __ipc_sd_init(nt_sd_common_buffer * sd, int fdir) { nt_access_allowed_ace * ace; uint32_t mask_system; uint32_t mask_owner; uint32_t mask_other; /* access mask */ if (fdir) { mask_system = NT_SEC_READ_CONTROL | NT_DIRECTORY_QUERY | NT_DIRECTORY_TRAVERSE | NT_DIRECTORY_CREATE_OBJECT | NT_DIRECTORY_CREATE_SUBDIRECTORY; mask_owner = NT_DIRECTORY_ALL_ACCESS; mask_other = mask_system; } else { mask_system = NT_SYMBOLIC_LINK_ALL_ACCESS; mask_owner = NT_SYMBOLIC_LINK_ALL_ACCESS; mask_other = NT_SYMBOLIC_LINK_QUERY; } /* sd header */ sd->sd.revision = 1; sd->sd.sbz_1st = 0; sd->sd.control = NT_SE_SELF_RELATIVE | NT_SE_DACL_PRESENT; sd->sd.offset_owner = __offsetof(nt_sd_common_buffer,owner); sd->sd.offset_group = 0; sd->sd.offset_dacl = __offsetof(nt_sd_common_buffer,dacl); sd->sd.offset_sacl = 0; /* owner sid */ __ntapi->tt_sid_copy( (nt_sid *)&sd->owner, __ntapi_internals()->user); /* ace's for LOCAL_SYSTEM, AUTHENTICATED_USERS, and process token user */ ace = (nt_access_allowed_ace *)&sd->buffer; ace = __ipc_ace_init(ace,mask_system,&(nt_sid){1,1,{{0,0,0,0,0,5}},{18}}); ace = __ipc_ace_init(ace,mask_other,&(nt_sid){1,1,{{0,0,0,0,0,5}},{11}}); ace = __ipc_ace_init(ace,mask_owner,(nt_sid *)&sd->owner); sd->dacl.acl_revision = 0x02; sd->dacl.sbz_1st = 0; sd->dacl.acl_size = (uint16_t)((char *)ace - (char *)&sd->dacl); sd->dacl.ace_count = 3; sd->dacl.sbz_2nd = 0; } static int32_t __stdcall __tt_create_ipc_object_directory( __out void ** hdir, __in uint32_t desired_access, __in const wchar16_t prefix[6], __in const nt_guid * guid) { int32_t status; nt_ipc_objdir_name objdir_name; nt_unicode_string name; nt_sd_common_buffer sd; nt_oa oa; nt_sqos sqos = { sizeof(sqos), NT_SECURITY_IMPERSONATION, NT_SECURITY_TRACKING_DYNAMIC, 1}; __ipc_sd_init(&sd,1); __ntapi->tt_generic_memcpy( objdir_name.base_named_objects, (wchar16_t[])__NT_BASED_NAMED_OBJECTS, sizeof(objdir_name.base_named_objects)); __ntapi->tt_memcpy_utf16( objdir_name.prefix, prefix, sizeof(objdir_name.prefix)); __tt_guid_to_hex_utf16( guid,objdir_name.guid); objdir_name.backslash = '\\'; objdir_name.uscore = '_'; name.strlen = sizeof(objdir_name); name.maxlen = 0; name.buffer = objdir_name.base_named_objects; oa.len = sizeof(oa); oa.root_dir = 0; oa.obj_name = &name; oa.obj_attr = NT_OBJ_INHERIT | NT_OBJ_OPENIF | NT_OBJ_CASE_INSENSITIVE; oa.sec_desc = &sd.sd; oa.sec_qos = &sqos; status = __ntapi->zw_create_directory_object( hdir,desired_access,&oa); return (status == NT_STATUS_OBJECT_NAME_EXISTS) ? NT_STATUS_SUCCESS : status; } static int32_t __stdcall __tt_create_keyed_object_directory( __out void ** hdir, __in uint32_t desired_access, __in void * hparent, __in uint32_t key, __in objdir_open_fn * openfn) { wchar16_t keystr[8]; nt_unicode_string name; nt_sd_common_buffer sd; nt_oa oa; nt_sqos sqos = { sizeof(sqos), NT_SECURITY_IMPERSONATION, NT_SECURITY_TRACKING_DYNAMIC, 1}; __ipc_sd_init(&sd,1); __ntapi->tt_uint32_to_hex_utf16( key,keystr); name.strlen = sizeof(keystr); name.maxlen = 0; name.buffer = keystr; oa.len = sizeof(oa); oa.root_dir = hparent; oa.obj_name = &name; oa.obj_attr = NT_OBJ_INHERIT; oa.sec_desc = &sd.sd; oa.sec_qos = &sqos; return openfn(hdir,desired_access,&oa); } static int32_t __stdcall __tt_create_object_directory_entry( __out void ** hentry, __in uint32_t desired_access, __in void * hdir, __in void * htarget, __in nt_unicode_string * target_name, __in uint32_t key) { int32_t status; nt_oa oa; nt_unicode_string name; nt_sd_common_buffer sd; wchar16_t keystr[8]; uintptr_t buffer[2048/sizeof(uintptr_t)]; nt_sqos sqos = { sizeof(sqos), NT_SECURITY_IMPERSONATION, NT_SECURITY_TRACKING_DYNAMIC, 1}; if (!target_name) { if ((status = __ntapi->zw_query_object( htarget, NT_OBJECT_NAME_INFORMATION, buffer,sizeof(buffer),0))) return status; target_name = (nt_unicode_string *)buffer; } __ipc_sd_init(&sd,0); __ntapi->tt_uint32_to_hex_utf16(key,keystr); name.strlen = sizeof(keystr); name.maxlen = 0; name.buffer = keystr; oa.len = sizeof(oa); oa.root_dir = hdir; oa.obj_name = &name; oa.obj_attr = 0; oa.sec_desc = &sd.sd; oa.sec_qos = &sqos; return __ntapi->zw_create_symbolic_link_object( hentry, desired_access, &oa,target_name); } int32_t __stdcall __ntapi_tt_open_ipc_object_directory( __out void ** hdir, __in uint32_t desired_access, __in const wchar16_t prefix[6], __in const nt_guid * guid) { return __tt_create_ipc_object_directory( hdir,desired_access, prefix,guid); } int32_t __stdcall __ntapi_tt_create_ipc_object_directory_entry( __out void ** hentry, __in uint32_t desired_access, __in void * hdir, __in void * htarget, __in nt_unicode_string * target_name, __in uint32_t key) { return __tt_create_object_directory_entry( hentry,desired_access, hdir,htarget,target_name,key); } int32_t __stdcall __ntapi_tt_open_dev_object_directory( __out void ** hdir, __in uint32_t desired_access, __in const wchar16_t prefix[6], __in const nt_guid * ipc_guid) { return __tt_create_ipc_object_directory( hdir,desired_access, prefix,ipc_guid); } int32_t __stdcall __ntapi_tt_create_dev_object_directory_entry( __out void ** hentry, __in uint32_t desired_access, __in void * hdir, __in void * htarget, __in nt_unicode_string * target_name, __in const nt_guid * dev_guid) { int32_t status; nt_oa oa; nt_unicode_string name; nt_sd_common_buffer sd; nt_guid_str_utf16 guidstr; uintptr_t buffer[2048/sizeof(uintptr_t)]; nt_sqos sqos = { sizeof(sqos), NT_SECURITY_IMPERSONATION, NT_SECURITY_TRACKING_DYNAMIC, 1}; if (!target_name) { if ((status = __ntapi->zw_query_object( htarget, NT_OBJECT_NAME_INFORMATION, buffer,sizeof(buffer),0))) return status; target_name = (nt_unicode_string *)buffer; } __ipc_sd_init(&sd,0); __ntapi->tt_guid_to_string_utf16(dev_guid,&guidstr); name.strlen = sizeof(guidstr); name.maxlen = 0; name.buffer = &guidstr.lbrace; oa.len = sizeof(oa); oa.root_dir = hdir; oa.obj_name = &name; oa.obj_attr = 0; oa.sec_desc = &sd.sd; oa.sec_qos = &sqos; return __ntapi->zw_create_symbolic_link_object( hentry, desired_access, &oa,target_name); } int32_t __stdcall __ntapi_tt_create_keyed_object_directory( __out void ** hdir, __in uint32_t desired_access, __in void * hparent, __in uint32_t key) { return __tt_create_keyed_object_directory( hdir,desired_access, hparent,key, __ntapi->zw_create_directory_object); } int32_t __stdcall __ntapi_tt_open_keyed_object_directory( __out void ** hdir, __in uint32_t desired_access, __in void * hparent, __in uint32_t key) { return __tt_create_keyed_object_directory( hdir,desired_access, hparent,key, __ntapi->zw_open_directory_object); } int32_t __stdcall __ntapi_tt_create_keyed_object_directory_entry( __out void ** hentry, __in uint32_t desired_access, __in void * hdir, __in void * htarget, __in nt_unicode_string * target_name, __in uint32_t key) { return __tt_create_object_directory_entry( hentry,desired_access, hdir,htarget,target_name,key); }