//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1998. // // File: Main.cxx // // Contents: Main file for CI security dump utility // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- #include #include #include typedef ULONG SDID; // // Copied from SecCache.hxx (NtCiUtil directory) // const USHORT SECSTORE_REC_SIZE = 64; const ULONG SECSTORE_HASH_SIZE = 199; struct SSdHeaderRecord { ULONG cbSD; // size in bytes of the security descriptor ULONG ulHash; // the hash of the security descriptor SDID iHashChain; // index to previous entry for hash bucket }; // // Used for mapping bitmasks to text. // struct SPermDisplay { DWORD Perm; char * Display; }; // // Local constants and function prototypes // unsigned const SixtyFourK = 1024 * 64; void DisplayTrustee( TRUSTEE const & Trustee ); void DisplayACE( char const * pszPreface, unsigned cACE, EXPLICIT_ACCESS * pACE ); void DisplayMode( DWORD mode ); void DisplayInheritance( DWORD Inherit ); void DisplayPerms( DWORD grfAccess ); void Display( DWORD grfAccess, SPermDisplay aPerm[], unsigned cPerm, unsigned cDisplay = 0 ); void Usage(); //+--------------------------------------------------------------------------- // // Function: wmain, public // // Synopsis: Program entry point. Iterates and displays SDID mapping. // // Arguments: [argc] -- Argument count // [argv] -- Program arguments // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- extern "C" int __cdecl wmain( int argc, WCHAR * argv[] ) { if ( argc != 2 ) { Usage(); return 1; } // // Open handle // if ( wcslen( argv[1] ) > ( MAX_PATH - 20 ) ) { Usage(); return 1; } WCHAR wszSecFile[MAX_PATH]; wcscpy( wszSecFile, argv[1] ); wcscat( wszSecFile, L"\\CiST0000.001" ); HANDLE h = CreateFile( wszSecFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0 ); if ( INVALID_HANDLE_VALUE == h ) { printf( "Can't open file %ws. Error %u\n", wszSecFile, GetLastError() ); return GetLastError(); } // // Read until done. // BYTE abTemp[SixtyFourK]; DWORD cbRead; int i = 0; SSdHeaderRecord Header; while ( ReadFile( h, &Header, sizeof(Header), &cbRead, 0 ) ) { if ( 0 == Header.cbSD ) break; i++; printf( "SDID %u / 0x%x (cbSD = %u bytes)\n", i, i, Header.cbSD ); // // Read rest of first record. // if ( !ReadFile( h, abTemp, SECSTORE_REC_SIZE - sizeof(Header) + 4, &cbRead, 0 ) ) { printf( "Error %u reading file\n", GetLastError() ); return 1; } // // Read additional records, which together create one security descriptor // if ( Header.cbSD > (SECSTORE_REC_SIZE - sizeof(Header)) ) { unsigned iCurrent = SECSTORE_REC_SIZE - sizeof(Header); for ( unsigned cLeft = (Header.cbSD - SECSTORE_REC_SIZE + sizeof(Header) - 1) / SECSTORE_REC_SIZE + 1; cLeft > 0; cLeft-- ) { if ( !ReadFile( h, abTemp + iCurrent, SECSTORE_REC_SIZE + 4, &cbRead, 0 ) ) { printf( "Error %u reading file\n", GetLastError() ); return 1; } i++; iCurrent += SECSTORE_REC_SIZE; } } SECURITY_DESCRIPTOR * pSD = (SECURITY_DESCRIPTOR *)abTemp; // // Create a human-readable descriptor // TRUSTEE * pOwner = 0; TRUSTEE * pGroup = 0; DWORD cACE; EXPLICIT_ACCESS * pACE; DWORD cAudit = 0; EXPLICIT_ACCESS * pAudit = 0; DWORD dwError = LookupSecurityDescriptorParts( &pOwner, &pGroup, &cACE, &pACE, &cAudit, &pAudit, pSD ); // // And display it. // if ( ERROR_SUCCESS == dwError ) { if ( 0 != pOwner ) { printf( "Owner: " ); DisplayTrustee( *pOwner ); printf( "\n" ); LocalFree( pOwner ); } if ( 0 != pGroup ) { printf( "Group: " ); DisplayTrustee( *pGroup ); printf( "\n" ); LocalFree( pGroup ); } if ( cACE > 0 ) { printf( "Access: " ); DisplayACE( " ", cACE, pACE ); printf( "\n" ); LocalFree( pACE ); } #if 0 // comes out the same as the access if ( cAudit > 0 ) { printf( "Audit: " ); DisplayACE( " ", cAudit, pAudit ); printf( "\n" ); LocalFree( pAudit ); } #endif } else printf( "LookupSecurityDescriptorParts returned %u\n", dwError ); printf( "\n\n" ); } CloseHandle( h ); return 0; } //+--------------------------------------------------------------------------- // // Function: DisplayTrustee // // Synopsis: Prints out trustee (user, group, etc.) // // Arguments: [Trustee] -- Trustee description // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- char * aszTrusteeType[] = { "Unknown", // TRUSTEE_IS_UNKNOWN "User", // TRUSTEE_IS_USER, "Group", // TRUSTEE_IS_GROUP, "Domain", // TRUSTEE_IS_DOMAIN, "Alias", // TRUSTEE_IS_ALIAS, "Group", // TRUSTEE_IS_WELL_KNOWN_GROUP, "Deleted", // TRUSTEE_IS_DELETED, "Invalid", // TRUSTEE_IS_INVALID "Unknown", "Computer" }; void DisplayTrustee( TRUSTEE const & Trustee ) { if ( TRUSTEE_IS_NAME == Trustee.TrusteeForm ) { printf( "%ws (%s)", Trustee.ptstrName, aszTrusteeType[Trustee.TrusteeType] ); } else if ( TRUSTEE_IS_SID == Trustee.TrusteeForm ) { WCHAR wszName[100]; DWORD ccName = sizeof(wszName)/sizeof(wszName[0]); WCHAR wszDomain[100]; DWORD ccDomain = sizeof(wszDomain)/sizeof(wszDomain[0]); SID_NAME_USE snu; BOOL fOk = LookupAccountSid( 0, // local system (PSID)Trustee.ptstrName, // address of security identifier wszName, // address of string for account name &ccName, // address of size account string wszDomain, // address of string for referenced domain &ccDomain, // address of size domain string &snu ); // address of structure for SID type if ( fOk ) { if ( 0 == wszDomain[0] ) printf( "%ws (%s)", wszName, aszTrusteeType[snu] ); else printf( "%ws\\%ws (%s)", wszDomain, wszName, aszTrusteeType[snu] ); } else printf( "" ); } else printf( "Invalid Trustee form: %d\n", Trustee.TrusteeForm ); } //+--------------------------------------------------------------------------- // // Function: DisplayACE // // Synopsis: Prints out Access Control Entry(ies) // // Arguments: [pszPreface] -- String to append at beginning of each line. // [cACE] -- Count of entries // [pACE] -- Array of entries // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- void DisplayACE( char const * pszPreface, unsigned cACE, EXPLICIT_ACCESS * pACE ) { for ( unsigned i = 0; i < cACE; i++ ) { if ( 0 != i ) printf( "%s", pszPreface ); DisplayTrustee( pACE[i].Trustee ); printf( " : " ); DisplayMode( pACE[i].grfAccessMode ); printf( " /" ); DisplayInheritance( pACE[i].grfInheritance ); printf( " /" ); DisplayPerms( pACE[i].grfAccessPermissions ); printf( "\n" ); } //ACCESS_MODE grfAccessMode; DWORD grfInheritance; } //+--------------------------------------------------------------------------- // // Function: DisplayMode, private // // Synopsis: Prints out access mode (Set or Deny access) // // Arguments: [mode] -- Access mode // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- char * aszAccessDisplay[] = { "NOT_USED", "GRANT_ACCESS", "SET_ACCESS", "DENY_ACCESS", "REVOKE_ACCESS", "SET_AUDIT_SUCCESS", "SET_AUDIT_FAILURE" }; void DisplayMode( DWORD mode ) { printf( "%s", aszAccessDisplay[mode] ); } //+--------------------------------------------------------------------------- // // Function: DisplayInheritance, private // // Synopsis: Prints out inheritance, both up (to parent) and down (to children) // // Arguments: [Inherit] -- Inheritance bitmask // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- SPermDisplay aInheritDisplay[] = { //{ INHERITED_ACCESS_ENTRY, "(inherited)" }, { INHERITED_PARENT, "(inherited from parent)" }, { INHERITED_GRANDPARENT, "(inherited from grandparent)" }, { SUB_OBJECTS_ONLY_INHERIT, "SUB_OBJECTS_ONLY" }, { SUB_CONTAINERS_ONLY_INHERIT, "SUB_CONTAINERS_ONLY" }, { SUB_CONTAINERS_AND_OBJECTS_INHERIT, "SUB_CONTAINERS_AND_OBJECTS" }, { INHERIT_NO_PROPAGATE, "INHERIT_NO_PROPAGATE" }, { INHERIT_ONLY, "INHERIT_ONLY" } }; void DisplayInheritance( DWORD Inherit ) { if ( NO_INHERITANCE == Inherit ) printf( "\n\t\t(not inherited)" ); else Display( Inherit, aInheritDisplay, sizeof(aInheritDisplay)/sizeof(aInheritDisplay[0]) ); } //+--------------------------------------------------------------------------- // // Function: DisplayPerms // // Synopsis: Displays file permissions // // Arguments: [grfAccess] -- Access permission bitmask // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- SPermDisplay aPermDisplay[] = { { FILE_READ_DATA, "READ_DATA" }, { FILE_WRITE_DATA, "WRITE_DATA" }, { FILE_ADD_FILE, "ADD_FILE" }, { FILE_APPEND_DATA, "APPEND_DATA" }, { FILE_ADD_SUBDIRECTORY, "ADD_SUBDIRECTORY" }, { FILE_CREATE_PIPE_INSTANCE, "CREATE_PIPE_INSTANCE" }, { FILE_READ_EA, "READ_EA" }, { FILE_WRITE_EA, "WRITE_EA" }, { FILE_EXECUTE, "EXECUTE" }, { FILE_TRAVERSE, "TRAVERSE" }, { FILE_DELETE_CHILD, "DELETE_CHILD" }, { FILE_READ_ATTRIBUTES, "READ_ATTRIBUTES" }, { FILE_WRITE_ATTRIBUTES, "WRITE_ATTRIBUTES" }, { DELETE, "DELETE" }, { READ_CONTROL, "READ_CONTROL" }, { WRITE_DAC, "WRITE_DAC" }, { WRITE_OWNER, "WRITE_OWNER" }, { SYNCHRONIZE, "SYNCHRONIZE" }, { GENERIC_READ, "GENERIC_READ" }, { GENERIC_WRITE, "GENERIC_WRITE" }, { GENERIC_EXECUTE, "GENERIC_EXECUTE" } }; void DisplayPerms( DWORD grfAccess ) { BOOL cDisplay = 0; DWORD grfRemove = 0; printf( "\n\t\t" ); // // First, get rid of the basics... // if ( (grfAccess & FILE_GENERIC_READ) == FILE_GENERIC_READ ) { printf( "GENERIC_READ" ); grfRemove = FILE_GENERIC_READ; cDisplay++; } if ( (grfAccess & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE ) { if ( 0 != cDisplay ) printf( " | " ); printf( "GENERIC_WRITE" ); grfRemove = grfRemove | FILE_GENERIC_WRITE; cDisplay++; } if ( (grfAccess & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE ) { if ( 0 != cDisplay ) printf( " | " ); if ( 0 == (cDisplay % 2) ) printf( " \n\t\t" ); printf( "GENERIC_EXECUTE" ); grfRemove = grfRemove | FILE_GENERIC_EXECUTE; cDisplay++; } // // Now, individual permissions. // DWORD grfRemainder = grfAccess & ~grfRemove; Display( grfRemainder, aPermDisplay, sizeof(aPermDisplay)/sizeof(aPermDisplay[0]), cDisplay ); printf( " (0x%x)", grfAccess ); } //+--------------------------------------------------------------------------- // // Function: Display, private // // Synopsis: Print bit masks // // Arguments: [grfAccess] -- Bit mask // [aPerm] -- Description of bits // [cPerm] -- Count of entries in [aPerm] // [cDisplay] -- Number of entries already displayed on // current line by caller. // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- void Display( DWORD grfAccess, SPermDisplay aPerm[], unsigned cPerm, unsigned cDisplay ) { for ( unsigned i = 0; i < cPerm ; i++ ) { if ( grfAccess & aPerm[i].Perm ) { if ( 0 != cDisplay ) printf( " | " ); if ( 0 == (cDisplay % 2) ) printf( " \n\t\t" ); printf( "%s", aPerm[i].Display ); cDisplay++; } } } //+--------------------------------------------------------------------------- // // Function: Usage // // Synopsis: Displays program usage // // History: 29-Jul-1998 KyleP Created // //---------------------------------------------------------------------------- void Usage() { printf( "Usage: DumpSec \n" ); }