You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1119 lines
33 KiB
1119 lines
33 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sddump.c
|
|
|
|
Abstract:
|
|
|
|
Debugger Extension Api
|
|
|
|
Author:
|
|
|
|
Baskar Kothandaraman (baskark) 26-Jan-1998
|
|
|
|
Environment:
|
|
|
|
Kernel Mode
|
|
|
|
Revision History:
|
|
|
|
Kshitiz K. Sharma (kksharma)
|
|
|
|
Using debugger type info : SID and ACL have exactly same type definitions on
|
|
all platforms - No change.
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: sid_successfully_read
|
|
|
|
FUNCTION: Tries to read in a SID from the specified address.
|
|
It first reads in the minimal structure, then
|
|
allocates a buffer big enough to hold the whole sid
|
|
& reads in the whole SID....
|
|
|
|
ARGS: Address -- Address from which to read it from
|
|
sid_buffer -- variable to receive the ptr to the
|
|
allocated buffer with the SID.
|
|
|
|
RETURN: TRUE on success, FALSE otherwise.
|
|
|
|
NOTE***: The caller has to call free(*sid_buffer) to free
|
|
up the memory upon a successful call to this
|
|
function.
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
BOOLEAN sid_successfully_read(
|
|
ULONG64 Address,
|
|
PSID *sid_buffer
|
|
)
|
|
{
|
|
ULONG result;
|
|
SID minimum; /* minimum we need to read to get the details */
|
|
|
|
|
|
*sid_buffer = NULL;
|
|
|
|
if ( !ReadMemory( Address,
|
|
&minimum,
|
|
sizeof(minimum),
|
|
&result) )
|
|
{
|
|
dprintf("%08p: Unable to get MIN SID header\n", Address);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Now of read-in any extra sub-authorities necessary */
|
|
|
|
if (minimum.SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
|
|
{
|
|
dprintf("SID has an invalid sub-authority_count, 0x%x\n", minimum.SubAuthorityCount);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
ULONG size_to_read = RtlLengthRequiredSid(minimum.SubAuthorityCount);
|
|
|
|
*sid_buffer = malloc(size_to_read);
|
|
|
|
if (! *sid_buffer)
|
|
{
|
|
dprintf("SID: can't allocate memory to read\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !ReadMemory( Address,
|
|
*sid_buffer,
|
|
size_to_read,
|
|
&result) )
|
|
{
|
|
dprintf("%08p: Unable to get The Whole SID\n", Address);
|
|
free(*sid_buffer);
|
|
*sid_buffer = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
if (! RtlValidSid(*sid_buffer))
|
|
{
|
|
dprintf("%08p: SID pointed to by this address is invalid\n", Address);
|
|
free(*sid_buffer);
|
|
*sid_buffer = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: acl_successfully_read
|
|
|
|
FUNCTION: Tries to read in a ACL from the specified address.
|
|
It first reads in the minimal structure, then
|
|
allocates a buffer big enough to hold the whole acl
|
|
& reads in the whole ACL....
|
|
|
|
ARGS: Address -- Address from which to read it from
|
|
acl_buffer -- variable to receive the ptr to the
|
|
allocated buffer with the ACL.
|
|
|
|
RETURN: TRUE on success, FALSE otherwise.
|
|
|
|
NOTE***: The caller has to call free(*acl_buffer) to free
|
|
up the memory upon a successful call to this
|
|
function.
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
BOOLEAN acl_successfully_read(
|
|
ULONG64 Address,
|
|
PACL *acl_buffer
|
|
)
|
|
{
|
|
ULONG result;
|
|
ACL minimum; /* minimum we need to read to get the details */
|
|
|
|
|
|
*acl_buffer = NULL;
|
|
|
|
if ( !ReadMemory( Address,
|
|
&minimum,
|
|
sizeof(minimum),
|
|
&result) )
|
|
{
|
|
dprintf("%08p: Unable to get MIN ACL header\n", Address);
|
|
return FALSE;
|
|
}
|
|
|
|
*acl_buffer = malloc(minimum.AclSize);
|
|
|
|
if (! *acl_buffer)
|
|
{
|
|
dprintf("ACL: can't allocate memory to read\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !ReadMemory( Address,
|
|
*acl_buffer,
|
|
minimum.AclSize,
|
|
&result) )
|
|
{
|
|
dprintf("%08p: Unable to get The Whole ACL\n", Address);
|
|
free(*acl_buffer);
|
|
*acl_buffer = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
if (! RtlValidAcl(*acl_buffer))
|
|
{
|
|
dprintf("%08p: ACL pointed to by this address is invalid\n", Address);
|
|
free(*acl_buffer);
|
|
*acl_buffer = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: DumpSID
|
|
|
|
FUNCTION: Prints out a SID, with the padding provided.
|
|
|
|
ARGS: pad -- Padding to print before the SID.
|
|
sid_to_dump -- Pointer to the SID to print.
|
|
Flag -- To control options.
|
|
|
|
RETURN: N/A
|
|
|
|
NOTE***: It right now, doesn't lookup the sid.
|
|
In future, you might want ot use the Flag
|
|
parameter to make that optional.
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
|
|
VOID DumpSID(
|
|
CHAR *pad,
|
|
PSID sid_to_dump,
|
|
ULONG Flag
|
|
)
|
|
{
|
|
NTSTATUS ntstatus;
|
|
UNICODE_STRING us;
|
|
|
|
if (sid_to_dump)
|
|
{
|
|
ntstatus = RtlConvertSidToUnicodeString(&us, sid_to_dump, TRUE);
|
|
|
|
if (NT_SUCCESS(ntstatus))
|
|
{
|
|
dprintf("%s%wZ", pad, &us);
|
|
RtlFreeUnicodeString(&us);
|
|
}
|
|
else
|
|
{
|
|
dprintf("0x%08lx: Can't Convert SID to UnicodeString", ntstatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("%s is NULL", pad);
|
|
}
|
|
if (Flag & 1) {
|
|
PCSTR pszStr;
|
|
|
|
dprintf(" ");
|
|
|
|
pszStr = ConvertSidToFriendlyName(sid_to_dump, "(%s: %s\\%s)");
|
|
|
|
if (pszStr && *pszStr) {
|
|
|
|
dprintf(pszStr);
|
|
}
|
|
}
|
|
dprintf("\n");
|
|
|
|
}
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: DumpACL
|
|
|
|
FUNCTION: Prints out a ACL, with the padding provided.
|
|
|
|
ARGS: pad -- Padding to print before the ACL.
|
|
acl_to_dump -- Pointer to the ACL to print.
|
|
Flag -- To control options.
|
|
Start -- Actual start address of the Acl
|
|
|
|
RETURN: N/A
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
BOOL
|
|
DumpACL (
|
|
IN char *pad,
|
|
IN ACL *pacl,
|
|
IN ULONG Flags,
|
|
IN ULONG64 Start
|
|
)
|
|
{
|
|
USHORT x;
|
|
|
|
if (pacl == NULL)
|
|
{
|
|
dprintf("%s is NULL\n", pad);
|
|
return FALSE;
|
|
}
|
|
|
|
dprintf("%s\n", pad);
|
|
dprintf("%s->AclRevision: 0x%x\n", pad, pacl->AclRevision);
|
|
dprintf("%s->Sbz1 : 0x%x\n", pad, pacl->Sbz1);
|
|
dprintf("%s->AclSize : 0x%x\n", pad, pacl->AclSize);
|
|
dprintf("%s->AceCount : 0x%x\n", pad, pacl->AceCount);
|
|
dprintf("%s->Sbz2 : 0x%x\n", pad, pacl->Sbz2);
|
|
|
|
for (x = 0; x < pacl->AceCount; x ++)
|
|
{
|
|
PACE_HEADER ace;
|
|
CHAR temp_pad[MAX_PATH];
|
|
NTSTATUS result;
|
|
|
|
_snprintf(temp_pad, sizeof(temp_pad), "%s->Ace[%u]: ", pad, x);
|
|
|
|
result = RtlGetAce(pacl, x, &ace);
|
|
if (! NT_SUCCESS(result))
|
|
{
|
|
dprintf("%sCan't GetAce, 0x%08lx\n", temp_pad, result);
|
|
return FALSE;
|
|
}
|
|
|
|
dprintf("%s->AceType: ", temp_pad);
|
|
|
|
#define BRANCH_AND_PRINT(x) case x: dprintf(#x "\n"); break
|
|
|
|
switch (ace->AceType)
|
|
{
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_DENIED_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_AUDIT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_ALARM_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_COMPOUND_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_DENIED_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_AUDIT_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_ALARM_OBJECT_ACE_TYPE);
|
|
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_CALLBACK_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_DENIED_CALLBACK_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_AUDIT_CALLBACK_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_ALARM_CALLBACK_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE);
|
|
BRANCH_AND_PRINT(SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE);
|
|
|
|
default:
|
|
dprintf("0x%08lx <-- *** Unknown AceType\n", ace->AceType);
|
|
continue; // With the next ace
|
|
}
|
|
|
|
#undef BRANCH_AND_PRINT
|
|
|
|
dprintf("%s->AceFlags: 0x%x\n", temp_pad, ace->AceFlags);
|
|
|
|
#define BRANCH_AND_PRINT(x) if (ace->AceFlags & x){ dprintf("%s %s\n", temp_pad, #x); }
|
|
|
|
BRANCH_AND_PRINT(OBJECT_INHERIT_ACE)
|
|
BRANCH_AND_PRINT(CONTAINER_INHERIT_ACE)
|
|
BRANCH_AND_PRINT(NO_PROPAGATE_INHERIT_ACE)
|
|
BRANCH_AND_PRINT(INHERIT_ONLY_ACE)
|
|
BRANCH_AND_PRINT(INHERITED_ACE)
|
|
BRANCH_AND_PRINT(SUCCESSFUL_ACCESS_ACE_FLAG)
|
|
BRANCH_AND_PRINT(FAILED_ACCESS_ACE_FLAG)
|
|
|
|
#undef BRANCH_AND_PRINT
|
|
|
|
dprintf("%s->AceSize: 0x%x\n", temp_pad, ace->AceSize);
|
|
|
|
/*
|
|
From now on it is ace specific stuff.
|
|
Fortunately ACEs can be split into 3 groups,
|
|
with the ACE structure being the same within the group
|
|
|
|
Added 8 more ace types for callback support.
|
|
*/
|
|
|
|
switch (ace->AceType)
|
|
{
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
SYSTEM_AUDIT_ACE *tace = (SYSTEM_AUDIT_ACE *) ace;
|
|
|
|
dprintf("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
|
|
_snprintf(more_pad, sizeof(more_pad), "%s->SID: ", temp_pad);
|
|
DumpSID(more_pad, &(tace->SidStart), Flags);
|
|
}
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
|
|
case ACCESS_DENIED_CALLBACK_ACE_TYPE:
|
|
case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
|
|
case SYSTEM_ALARM_CALLBACK_ACE_TYPE:
|
|
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
SYSTEM_AUDIT_ACE *tace = (SYSTEM_AUDIT_ACE *) ace;
|
|
|
|
dprintf("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
|
|
_snprintf(more_pad, sizeof(more_pad), "%s->SID: ", temp_pad);
|
|
DumpSID(more_pad, &(tace->SidStart), Flags);
|
|
dprintf("%s->Address : %08p\n", temp_pad, Start + (ULONG) (((PUCHAR) ace) - ((PUCHAR) pacl)));
|
|
}
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
COMPOUND_ACCESS_ALLOWED_ACE *tace = (COMPOUND_ACCESS_ALLOWED_ACE *) ace;
|
|
PBYTE ptr;
|
|
|
|
dprintf("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
dprintf("%s->CompoundAceType : 0x%08lx\n", temp_pad, tace->CompoundAceType);
|
|
dprintf("%s->Reserved : 0x%08lx\n", temp_pad, tace->Reserved);
|
|
|
|
_snprintf(more_pad, sizeof(more_pad), "%s->SID(1) : ", temp_pad);
|
|
DumpSID(more_pad, &(tace->SidStart), Flags);
|
|
|
|
ptr = (PBYTE)&(tace->SidStart);
|
|
ptr += RtlLengthSid((PSID)ptr); /* Skip this & get to next sid */
|
|
|
|
_snprintf(more_pad, sizeof(more_pad), "%s->SID(2) : ", temp_pad);
|
|
DumpSID(more_pad, ptr, Flags);
|
|
}
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
ACCESS_ALLOWED_OBJECT_ACE *tace = (ACCESS_ALLOWED_OBJECT_ACE *) ace;
|
|
PBYTE ptr;
|
|
GUID *obj_guid = NULL, *inh_obj_guid = NULL;
|
|
|
|
dprintf("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
dprintf("%s->Flags : 0x%08lx\n", temp_pad, tace->Flags);
|
|
|
|
ptr = (PBYTE)&(tace->ObjectType);
|
|
|
|
if (tace->Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
{
|
|
dprintf("%s : ACE_OBJECT_TYPE_PRESENT\n", temp_pad);
|
|
obj_guid = &(tace->ObjectType);
|
|
ptr = (PBYTE)&(tace->InheritedObjectType);
|
|
}
|
|
|
|
if (tace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
{
|
|
dprintf("%s : ACE_INHERITED_OBJECT_TYPE_PRESENT\n", temp_pad);
|
|
inh_obj_guid = &(tace->InheritedObjectType);
|
|
ptr = (PBYTE)&(tace->SidStart);
|
|
}
|
|
|
|
if (obj_guid)
|
|
{
|
|
dprintf("%s->ObjectType : (in HEX)", temp_pad);
|
|
dprintf("(%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n",
|
|
obj_guid->Data1,
|
|
obj_guid->Data2,
|
|
obj_guid->Data3,
|
|
obj_guid->Data4[0],
|
|
obj_guid->Data4[1],
|
|
obj_guid->Data4[2],
|
|
obj_guid->Data4[3],
|
|
obj_guid->Data4[4],
|
|
obj_guid->Data4[5],
|
|
obj_guid->Data4[6],
|
|
obj_guid->Data4[7]
|
|
);
|
|
}
|
|
|
|
if (inh_obj_guid)
|
|
{
|
|
dprintf("%s->InhObjTYpe : (in HEX)", temp_pad);
|
|
dprintf("(%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n",
|
|
inh_obj_guid->Data1,
|
|
inh_obj_guid->Data2,
|
|
inh_obj_guid->Data3,
|
|
inh_obj_guid->Data4[0],
|
|
inh_obj_guid->Data4[1],
|
|
inh_obj_guid->Data4[2],
|
|
inh_obj_guid->Data4[3],
|
|
inh_obj_guid->Data4[4],
|
|
inh_obj_guid->Data4[5],
|
|
inh_obj_guid->Data4[6],
|
|
inh_obj_guid->Data4[7]
|
|
);
|
|
}
|
|
|
|
_snprintf(more_pad, sizeof(more_pad), "%s->SID : ", temp_pad);
|
|
DumpSID(more_pad, ptr, Flags);
|
|
}
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
|
|
case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
|
|
case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE:
|
|
{
|
|
CHAR more_pad[MAX_PATH];
|
|
ACCESS_ALLOWED_OBJECT_ACE *tace = (ACCESS_ALLOWED_OBJECT_ACE *) ace;
|
|
PBYTE ptr;
|
|
GUID *obj_guid = NULL, *inh_obj_guid = NULL;
|
|
|
|
dprintf("%s->Mask : 0x%08lx\n", temp_pad, tace->Mask);
|
|
dprintf("%s->Flags : 0x%08lx\n", temp_pad, tace->Flags);
|
|
|
|
ptr = (PBYTE)&(tace->ObjectType);
|
|
|
|
if (tace->Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
{
|
|
dprintf("%s : ACE_OBJECT_TYPE_PRESENT\n", temp_pad);
|
|
obj_guid = &(tace->ObjectType);
|
|
ptr = (PBYTE)&(tace->InheritedObjectType);
|
|
}
|
|
|
|
if (tace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
{
|
|
dprintf("%s : ACE_INHERITED_OBJECT_TYPE_PRESENT\n", temp_pad);
|
|
inh_obj_guid = &(tace->InheritedObjectType);
|
|
ptr = (PBYTE)&(tace->SidStart);
|
|
}
|
|
|
|
if (obj_guid)
|
|
{
|
|
dprintf("%s->ObjectType : (in HEX)", temp_pad);
|
|
dprintf("(%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n",
|
|
obj_guid->Data1,
|
|
obj_guid->Data2,
|
|
obj_guid->Data3,
|
|
obj_guid->Data4[0],
|
|
obj_guid->Data4[1],
|
|
obj_guid->Data4[2],
|
|
obj_guid->Data4[3],
|
|
obj_guid->Data4[4],
|
|
obj_guid->Data4[5],
|
|
obj_guid->Data4[6],
|
|
obj_guid->Data4[7]
|
|
);
|
|
}
|
|
|
|
if (inh_obj_guid)
|
|
{
|
|
dprintf("%s->InhObjTYpe : (in HEX)", temp_pad);
|
|
dprintf("(%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x)\n",
|
|
inh_obj_guid->Data1,
|
|
inh_obj_guid->Data2,
|
|
inh_obj_guid->Data3,
|
|
inh_obj_guid->Data4[0],
|
|
inh_obj_guid->Data4[1],
|
|
inh_obj_guid->Data4[2],
|
|
inh_obj_guid->Data4[3],
|
|
inh_obj_guid->Data4[4],
|
|
inh_obj_guid->Data4[5],
|
|
inh_obj_guid->Data4[6],
|
|
inh_obj_guid->Data4[7]
|
|
);
|
|
}
|
|
|
|
_snprintf(more_pad, sizeof(more_pad), "%s->SID : ", temp_pad);
|
|
DumpSID(more_pad, ptr, Flags);
|
|
dprintf("%s->Address : %08p\n", temp_pad, Start + (ULONG) (((PUCHAR) ace) - ((PUCHAR) pacl)));
|
|
}
|
|
break;
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: DumpSD
|
|
|
|
FUNCTION: Prints out a Security Descriptor,
|
|
with the padding provided.
|
|
|
|
ARGS: pad -- Padding to print before the ACL.
|
|
sd_to_dump -- Pointer to the ACL to print.
|
|
owner -- Ptr to Owner SID
|
|
group -- Ptr to Group SID
|
|
dacl -- Ptr to DACL
|
|
sacl -- Ptr to SACL
|
|
Flag -- To control options.
|
|
dacl_address -- Actual start address of the dacl
|
|
sacl_address -- Actual start address of the sacl
|
|
|
|
RETURN: N/A
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
BOOL
|
|
DumpSD (
|
|
IN char *pad,
|
|
IN ULONG64 sd_to_dump,
|
|
IN PSID owner,
|
|
IN PSID group,
|
|
IN PACL dacl,
|
|
IN PACL sacl,
|
|
IN ULONG Flags,
|
|
IN ULONG64 dacl_address,
|
|
IN ULONG64 sacl_address
|
|
)
|
|
{
|
|
ULONG Control;
|
|
|
|
InitTypeRead(sd_to_dump, SECURITY_DESCRIPTOR);
|
|
Control = (ULONG) ReadField(Control);
|
|
|
|
#define CHECK_SD_CONTROL_FOR(x)\
|
|
if (Control & x)\
|
|
{\
|
|
dprintf("%s %s\n", pad, #x);\
|
|
}\
|
|
|
|
dprintf("%s->Revision: 0x%x\n", pad, (ULONG) ReadField(Revision));
|
|
dprintf("%s->Sbz1 : 0x%x\n", pad, (ULONG) ReadField(Sbz1));
|
|
dprintf("%s->Control : 0x%x\n", pad, (ULONG) ReadField(Control));
|
|
|
|
CHECK_SD_CONTROL_FOR(SE_OWNER_DEFAULTED)
|
|
CHECK_SD_CONTROL_FOR(SE_GROUP_DEFAULTED)
|
|
CHECK_SD_CONTROL_FOR(SE_DACL_PRESENT)
|
|
CHECK_SD_CONTROL_FOR(SE_DACL_DEFAULTED)
|
|
CHECK_SD_CONTROL_FOR(SE_SACL_PRESENT)
|
|
CHECK_SD_CONTROL_FOR(SE_SACL_DEFAULTED)
|
|
CHECK_SD_CONTROL_FOR(SE_DACL_UNTRUSTED)
|
|
CHECK_SD_CONTROL_FOR(SE_SERVER_SECURITY)
|
|
CHECK_SD_CONTROL_FOR(SE_DACL_AUTO_INHERIT_REQ)
|
|
CHECK_SD_CONTROL_FOR(SE_SACL_AUTO_INHERIT_REQ)
|
|
CHECK_SD_CONTROL_FOR(SE_DACL_AUTO_INHERITED)
|
|
CHECK_SD_CONTROL_FOR(SE_SACL_AUTO_INHERITED)
|
|
CHECK_SD_CONTROL_FOR(SE_DACL_PROTECTED)
|
|
CHECK_SD_CONTROL_FOR(SE_SACL_PROTECTED)
|
|
CHECK_SD_CONTROL_FOR(SE_SELF_RELATIVE)
|
|
|
|
{
|
|
CHAR temp_pad[MAX_PATH];
|
|
|
|
_snprintf(temp_pad, sizeof(temp_pad), "%s->Owner : ", pad);
|
|
|
|
DumpSID(temp_pad, owner, Flags);
|
|
|
|
_snprintf(temp_pad, sizeof(temp_pad), "%s->Group : ", pad);
|
|
|
|
DumpSID(temp_pad, group, Flags);
|
|
|
|
_snprintf(temp_pad, sizeof(temp_pad), "%s->Dacl : ", pad);
|
|
|
|
DumpACL(temp_pad, dacl, Flags, dacl_address);
|
|
|
|
_snprintf(temp_pad, sizeof(temp_pad), "%s->Sacl : ", pad);
|
|
|
|
DumpACL(temp_pad, sacl, Flags, sacl_address);
|
|
}
|
|
|
|
#undef CHECK_SD_CONTROL_FOR
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: sd
|
|
|
|
FUNCTION: Reads in & prints the security descriptor, from
|
|
the address specified. !sd command's workhorse.
|
|
|
|
ARGS: Standard Debugger extensions, refer to DECLARE_API
|
|
macro in the header files.
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
|
|
|
|
DECLARE_API( sd )
|
|
{
|
|
ULONG64 Address;
|
|
ULONG Flags;
|
|
ULONG result;
|
|
PACL dacl = NULL, sacl = NULL;
|
|
ULONG64 dacl_address;
|
|
ULONG64 sacl_address;
|
|
// SECURITY_DESCRIPTOR sd_to_dump;
|
|
PSID owner_sid = NULL, group_sid = NULL;
|
|
ULONG Control;
|
|
|
|
Address = 0;
|
|
Flags = 6;
|
|
GetExpressionEx(args, &Address, &args);
|
|
if (args && *args) Flags = (ULONG) GetExpression(args);
|
|
|
|
if (Address == 0) {
|
|
dprintf("usage: !sd <SecurityDescriptor-address>\n");
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if ( GetFieldValue( Address,
|
|
"SECURITY_DESCRIPTOR",
|
|
"Control",
|
|
Control) ) {
|
|
dprintf("%08p: Unable to get SD contents\n", Address);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if (Control & SE_SELF_RELATIVE)
|
|
{
|
|
ULONG dacl_offset, sacl_offset;
|
|
|
|
InitTypeRead(Address, SECURITY_DESCRIPTOR_RELATIVE);
|
|
|
|
dacl_offset = (ULONG) ReadField(Dacl);
|
|
sacl_offset = (ULONG) ReadField(Sacl);
|
|
|
|
if (!(Control & SE_OWNER_DEFAULTED)) /* read in the owner */
|
|
{
|
|
ULONG owner_offset = (ULONG) ReadField(Owner);
|
|
|
|
if (owner_offset != 0)
|
|
{
|
|
ULONG64 owner_address = Address + owner_offset;
|
|
|
|
if (! sid_successfully_read(owner_address, & owner_sid))
|
|
{
|
|
dprintf("%08p: Unable to read in Owner in SD\n", owner_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(Control & SE_GROUP_DEFAULTED)) /* read in the group */
|
|
{
|
|
ULONG group_offset = (ULONG) ReadField(Group);
|
|
|
|
if (group_offset != 0)
|
|
{
|
|
ULONG64 group_address = Address + group_offset;
|
|
|
|
if (! sid_successfully_read(group_address, & group_sid))
|
|
{
|
|
dprintf("%08p: Unable to read in Group in SD\n", group_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((Control & SE_DACL_PRESENT) &&
|
|
(dacl_offset != 0))
|
|
{
|
|
dacl_address = Address + dacl_offset;
|
|
|
|
if (! acl_successfully_read(dacl_address, & dacl))
|
|
{
|
|
dprintf("%08p: Unable to read in Dacl in SD\n", dacl_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
|
|
if ((Control & SE_SACL_PRESENT) &&
|
|
(sacl_offset != 0))
|
|
{
|
|
sacl_address = Address + sacl_offset;
|
|
|
|
if (! acl_successfully_read(sacl_address, & sacl))
|
|
{
|
|
dprintf("%08p: Unable to read in Sacl in SD\n", sacl_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ULONG64 Dacl, Sacl;
|
|
InitTypeRead(Address, SECURITY_DESCRIPTOR);
|
|
|
|
Dacl = ReadField(Dacl);
|
|
Sacl = ReadField(Sacl);
|
|
|
|
if (!(Control & SE_OWNER_DEFAULTED)) /* read in the owner */
|
|
{
|
|
ULONG64 owner_address = ReadField(Owner);
|
|
|
|
if (owner_address != 0 &&
|
|
! sid_successfully_read(owner_address, & owner_sid))
|
|
{
|
|
dprintf("%08p: Unable to read in Owner in SD\n", owner_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
if (!(Control & SE_GROUP_DEFAULTED)) /* read in the group */
|
|
{
|
|
ULONG64 group_address = ReadField(Group);
|
|
|
|
if (group_address != 0 &&
|
|
! sid_successfully_read(group_address, & group_sid))
|
|
{
|
|
dprintf("%08p: Unable to read in Group in SD\n", group_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
if ((Control & SE_DACL_PRESENT) &&
|
|
(Dacl != 0))
|
|
{
|
|
dacl_address = Dacl;
|
|
|
|
if (! acl_successfully_read(dacl_address, & dacl))
|
|
{
|
|
dprintf("%08p: Unable to read in Dacl in SD\n", dacl_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
if ((Control & SE_SACL_PRESENT) &&
|
|
(Sacl != 0))
|
|
{
|
|
sacl_address = (Sacl);
|
|
|
|
if (! acl_successfully_read(sacl_address, & sacl))
|
|
{
|
|
dprintf("%08p: Unable to read in Sacl in SD\n", sacl_address);
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
}
|
|
|
|
DumpSD("", Address, owner_sid, group_sid, dacl, sacl, Flags, dacl_address, sacl_address);
|
|
|
|
|
|
CLEANUP:
|
|
|
|
if (owner_sid)
|
|
{
|
|
free(owner_sid);
|
|
}
|
|
|
|
if (group_sid)
|
|
{
|
|
free(group_sid);
|
|
}
|
|
|
|
if (dacl)
|
|
{
|
|
free(dacl);
|
|
}
|
|
|
|
if (sacl)
|
|
{
|
|
free(sacl);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
PSTR g_SidAttrType = "nt!_SID_AND_ATTRIBUTES";
|
|
|
|
ULONG64
|
|
GetSidAddr(ULONG64 BaseAddress)
|
|
{
|
|
ULONG64 Addr;
|
|
if (GetFieldValue(BaseAddress, g_SidAttrType, "Sid", Addr))
|
|
{
|
|
dprintf("Cannot read %s.Sid @ %p\n", g_SidAttrType, BaseAddress);
|
|
return 0;
|
|
}
|
|
return Addr;
|
|
}
|
|
|
|
ULONG
|
|
GetSidAttributes(ULONG64 BaseAddress)
|
|
{
|
|
ULONG Attributes;
|
|
|
|
if (GetFieldValue(BaseAddress, g_SidAttrType, "Attributes", Attributes))
|
|
{
|
|
dprintf("Cannot read %s.Attributes @%p\n", g_SidAttrType, BaseAddress);
|
|
return 0;
|
|
}
|
|
return Attributes;
|
|
}
|
|
|
|
typedef
|
|
BOOL
|
|
(* PFuncLookupAccountSidA)(
|
|
IN LPCSTR lpSystemName,
|
|
IN PSID Sid,
|
|
OUT LPSTR Name,
|
|
IN OUT LPDWORD cbName,
|
|
OUT LPSTR ReferencedDomainName,
|
|
IN OUT LPDWORD cbReferencedDomainName,
|
|
OUT PSID_NAME_USE peUse
|
|
);
|
|
|
|
BOOL
|
|
WINAPI
|
|
LsaLookupAccountSidA(
|
|
IN LPCSTR lpSystemName,
|
|
IN PSID Sid,
|
|
OUT LPSTR Name,
|
|
IN OUT LPDWORD cbName,
|
|
OUT LPSTR ReferencedDomainName,
|
|
IN OUT LPDWORD cbReferencedDomainName,
|
|
OUT PSID_NAME_USE peUse
|
|
)
|
|
{
|
|
PFuncLookupAccountSidA pFuncLookupAccountSidA = NULL;
|
|
BOOL bRetval = FALSE;
|
|
|
|
HMODULE hLib = LoadLibrary("advapi32.dll");
|
|
if (hLib)
|
|
{
|
|
pFuncLookupAccountSidA = (PFuncLookupAccountSidA) GetProcAddress(hLib, "LookupAccountSidA");
|
|
|
|
if (pFuncLookupAccountSidA)
|
|
{
|
|
bRetval = pFuncLookupAccountSidA(lpSystemName, Sid, Name, cbName,
|
|
ReferencedDomainName, cbReferencedDomainName, peUse);
|
|
}
|
|
|
|
FreeLibrary(hLib);
|
|
}
|
|
|
|
return bRetval;
|
|
|
|
}
|
|
|
|
PCSTR GetSidTypeStr(IN SID_NAME_USE eUse)
|
|
{
|
|
static PCSTR acszSidTypeStr[] = {
|
|
"Invalid", "User", "Group", "Domain", "Alias", "Well Known Group",
|
|
"Deleted Account", "Invalid", "Unknown", "Computer",
|
|
};
|
|
|
|
if (eUse < SidTypeUser || eUse > SidTypeComputer) {
|
|
dprintf( "Unrecognized SID");
|
|
return NULL;
|
|
}
|
|
|
|
return acszSidTypeStr[eUse];
|
|
}
|
|
|
|
PCSTR ConvertSidToFriendlyName(IN SID* pSid, IN PCSTR pszFmt)
|
|
{
|
|
HRESULT hRetval = E_FAIL;
|
|
|
|
static CHAR szSid[MAX_PATH] = {0};
|
|
|
|
CHAR szName[MAX_PATH] = {0};
|
|
CHAR szDomainName[MAX_PATH] ={0};
|
|
SID_NAME_USE eUse = SidTypeInvalid;
|
|
DWORD cbName = sizeof(szName) - 1;
|
|
DWORD cbDomainName = sizeof(szDomainName) - 1;
|
|
PCSTR pszSidTypeStr;
|
|
|
|
if (CheckControlC())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// null terminates szSid
|
|
//
|
|
szSid[0] = 0;
|
|
|
|
hRetval = LsaLookupAccountSidA(NULL, pSid,
|
|
szName, &cbName,
|
|
szDomainName, &cbDomainName,
|
|
&eUse) ? S_OK : GetLastError() + 0x80000000;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
|
|
pszSidTypeStr = GetSidTypeStr(eUse);
|
|
if (!pszSidTypeStr)
|
|
{
|
|
return NULL;
|
|
}
|
|
hRetval = _snprintf(szSid, sizeof(szSid) -1, pszFmt, pszSidTypeStr, *szDomainName ? szDomainName : "localhost", szName) >= 0 ? S_OK : HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
if (FAILED(hRetval) && (ERROR_NONE_MAPPED != HRESULT_CODE(hRetval))) {
|
|
|
|
dprintf("ConvertSidToFriendlyName on failed with error code %#x\n", hRetval);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Indicate none mapped if so
|
|
//
|
|
if (!*szSid)
|
|
{
|
|
|
|
_snprintf(szSid, sizeof(szSid) - 1, "(no name mapped)");
|
|
}
|
|
|
|
return szSid;
|
|
}
|
|
|
|
void ShowSid(IN PCSTR pszPad, IN ULONG64 addrSid, IN ULONG fOptions)
|
|
{
|
|
PSID sid_to_dump = NULL;
|
|
if (!addrSid) {
|
|
|
|
dprintf("%s(null)\n", pszPad);
|
|
return;
|
|
}
|
|
|
|
if (! sid_successfully_read(addrSid, & sid_to_dump))
|
|
{
|
|
dprintf("%s%08p: Unable to read in SID\n", pszPad,addrSid);
|
|
return ;
|
|
}
|
|
|
|
DumpSID((PCHAR) pszPad, sid_to_dump, fOptions);
|
|
|
|
if (sid_to_dump)
|
|
{
|
|
free (sid_to_dump);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: sid
|
|
|
|
FUNCTION: Reads in & prints the SID, from
|
|
the address specified. !sid command's workhorse.
|
|
|
|
ARGS: Standard Debugger extensions, refer to DECLARE_API
|
|
macro in the header files.
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
DECLARE_API( sid )
|
|
{
|
|
ULONG64 Address;
|
|
ULONG Flags;
|
|
ULONG result;
|
|
PSID sid_to_dump = NULL;
|
|
NTSTATUS ntstatus;
|
|
UNICODE_STRING us;
|
|
|
|
|
|
Address = 0;
|
|
Flags = 6;
|
|
GetExpressionEx(args, &Address, &args);
|
|
if (args && *args) Flags = (ULONG) GetExpression(args);
|
|
|
|
if (Address == 0) {
|
|
dprintf("usage: !sid <SID-address>\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (! sid_successfully_read(Address, & sid_to_dump))
|
|
{
|
|
dprintf("%08p: Unable to read in SID\n", Address);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
DumpSID("SID is: ", sid_to_dump, Flags);
|
|
|
|
if (sid_to_dump)
|
|
{
|
|
free (sid_to_dump);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
+-------------------------------------------------------------------+
|
|
|
|
NAME: acl
|
|
|
|
FUNCTION: Reads in & prints the ACL, from
|
|
the address specified. !acl command's workhorse.
|
|
|
|
ARGS: Standard Debugger extensions, refer to DECLARE_API
|
|
macro in the header files.
|
|
|
|
+-------------------------------------------------------------------+
|
|
*/
|
|
|
|
DECLARE_API( acl )
|
|
{
|
|
ULONG64 Address;
|
|
ULONG Flags;
|
|
ULONG result;
|
|
PACL acl_to_dump;
|
|
NTSTATUS ntstatus;
|
|
UNICODE_STRING us;
|
|
|
|
|
|
Address = 0;
|
|
Flags = 6;
|
|
GetExpressionEx(args, &Address, &args);
|
|
if (args && *args) Flags = (ULONG) GetExpression(args);
|
|
if (Address == 0) {
|
|
dprintf("usage: !acl <ACL-address>\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (! acl_successfully_read(Address, & acl_to_dump))
|
|
{
|
|
dprintf("%08p: Unable to read in ACL\n", Address);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
DumpACL("ACL is: ", acl_to_dump, Flags, Address);
|
|
|
|
return S_OK;
|
|
}
|