Leaked source code of windows server 2003
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

/*++
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;
}