//////////////////////////////////////////////////////////////////// // // skravel - NT SAM enumeration by looking up RIDs // // (c)2000 Olle Segerdahl // // This program is BeerWare, if you like it, buy me a beer! // If you don't like it, don't use it. Give credit where due. // //////////////////////////////////////////////////////////////////// #include #include #include // NetUserGetInfo() // ugly globals int verbose = 0; ////////////////////////////////////////////////////////////////////////////// // GetTextualSid - snarfed MSDN code to convert SID 2 ascii values // I'm too lazy right now to build my own... so sue me... ////////////////////////////////////////////////////////////////////////////// BOOL GetTextualSid(PSID pSid, LPSTR szTextualSid, LPDWORD dwBufferLen) { PSID_IDENTIFIER_AUTHORITY psia; DWORD dwSubAuthorities; DWORD dwSidRev = SID_REVISION; DWORD dwCounter; DWORD dwSidSize; // Test if SID passed in is valid. if(!IsValidSid(pSid)) return FALSE; // Obtain SidIdentifierAuthority. psia = GetSidIdentifierAuthority(pSid); // Obtain sidsubauthority count. dwSubAuthorities = *GetSidSubAuthorityCount(pSid); // Compute buffer length. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); // Check provided buffer length. // If not large enough, indicate proper size and setlasterror if (*dwBufferLen < dwSidSize) { *dwBufferLen = dwSidSize; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } // Prepare S-SID_REVISION-. dwSidSize = wsprintf(szTextualSid, TEXT("S-%lu-"), dwSidRev); // Prepare SidIdentifierAuthority. if ((psia->Value[0] != 0) || (psia->Value[1] != 0)) { dwSidSize += wsprintf(szTextualSid + lstrlen(szTextualSid), TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), (USHORT) psia->Value[0], (USHORT) psia->Value[1], (USHORT) psia->Value[2], (USHORT) psia->Value[3], (USHORT) psia->Value[4], (USHORT) psia->Value[5]); } else { dwSidSize += wsprintf(szTextualSid + lstrlen(szTextualSid), TEXT("%lu"), (ULONG) (psia->Value[5] ) + (ULONG) (psia->Value[4] << 8) + (ULONG) (psia->Value[3] << 16) + (ULONG) (psia->Value[2] << 24)); } // Loop through SidSubAuthorities. for (dwCounter = 0; dwCounter < dwSubAuthorities; dwCounter++) { dwSidSize += wsprintf(szTextualSid + dwSidSize, TEXT("-%lu"), *GetSidSubAuthority(pSid, dwCounter)); } return TRUE; } ////////////////////////////////////////////////////////////////////////////// // sid2user - looks up name of Sid on machine and prints it ////////////////////////////////////////////////////////////////////////////// sid2user(char *sid, char *machine) { SID *psid; int sidl = 127; int domainl = 127; int namel = 127; char domain[128], name[128], *type; SID_NAME_USE use; int err; psid = (SID *)sid; err = LookupAccountSidA( machine, // name of local or remote computer sid, // security identifier name, // account name buffer &namel, // size of account name buffer domain, // domain name &domainl, // size of domain name buffer &use // SID type ); if (err != 1) { err = GetLastError(); if (err != ERROR_NONE_MAPPED) { fprintf(stderr,"\nRID: %d ",psid->SubAuthority[psid->SubAuthorityCount-1]); fprintf(stderr,"LookupAaccountSid Error: %d\n",err); } } else { /* err != 1 */ if (verbose) { fprintf(stdout, "RID %d: \"%s\" is of type ",psid->SubAuthority[psid->SubAuthorityCount-1], name); switch (use) { case SidTypeUser: type = "User"; break; case SidTypeGroup: type = "Group"; break; case SidTypeDomain: type = "Domain"; break; case SidTypeAlias: type = "Alias"; break; case SidTypeWellKnownGroup: type = "WellKnownGroup"; break; case SidTypeDeletedAccount: type = "DeletedAccount"; break; case SidTypeInvalid: type = "InvalidType"; break; case SidTypeComputer: type = "Computer"; break; case SidTypeUnknown: default: type = "UnknownType"; break; } fprintf(stdout, "%s\n", type); } else { /* verbose */ if (use == SidTypeUser) fprintf(stdout,"%s\n",name); } } } void usage(char **argv) { fprintf(stderr,"\n skravel v0.96 (c)2000 olle@nxs.se\n\n"); fprintf(stderr," enumerate NT SAM accounts by RID\n\n"); fprintf(stderr," usage: %s [from-to] [-v]\n\n",argv[0]); fprintf(stderr," host = system to query, requires IPC$ connection\n"); fprintf(stderr," domain = NT domain to enumerate accounts of\n"); fprintf(stderr," from = min RID value to enumerate (default 0)\n"); fprintf(stderr," to = max RID value to enumerate (default 1500)\n"); fprintf(stderr," -v = enumerate RIDs of all types, not just users\n\n"); exit(0); } ////////////////////////////////////////////////////////////////////////////// // main - entrypoint of champions ////////////////////////////////////////////////////////////////////////////// main(int argc, char **argv) { SID *psid; char sid[128]; int sidl = 127; char domain[128]; int domainl = 127; char buf[128]; SID_NAME_USE use; unsigned int minrid = 0; unsigned int maxrid = 1500; char *cp; int err; if (argc < 3) { usage(argv); } // bad argument parsing if (argc == 4) { if (*(argv[3]+1)=='v') { verbose = 1; } else { cp = strchr(argv[3], '-'); if (cp) { *cp = '\0'; minrid = atoi(argv[3]); maxrid = atoi(cp+1); } else { usage(argv); } } } if (argc == 5) { if (*(argv[3]+1)=='v') { verbose = 1; } else { cp = strchr(argv[3], '-'); if (cp) { *cp = '\0'; minrid = atoi(argv[3]); maxrid = atoi(cp+1); } else { usage(argv); } } if (*(argv[4]+1)=='v') { verbose = 1; } else { cp = strchr(argv[4], '-'); if (cp) { *cp = '\0'; minrid = atoi(argv[4]); maxrid = atoi(cp+1); } else { usage(argv); } } } fprintf(stderr,"\nLooking up \"%s\" on system \"%s\"\n",argv[2],argv[1]); err = LookupAccountNameA( argv[1], // system name argv[2], // account name &sid, // security identifier &sidl, // size of security identifier domain, // domain name &domainl, // size of domain name &use // SID-type indicator ); if (err != 1) { err = GetLastError(); if (err == ERROR_NONE_MAPPED) fprintf(stderr,"\n%s: No such name at \"%s\"\n",argv[2], argv[1]); else if (err == RPC_S_SERVER_UNAVAILABLE) fprintf(stderr,"\nCould not contact system \"%s\"\n", argv[1]); else fprintf(stderr,"\nError: %d\n",err); exit(1); } psid = (SID *)sid; if (use == SidTypeDomain) { fprintf(stderr,"\n\"%s\" is a domain, enumerating RID's %i to %i.\n",argv[2],minrid, maxrid); GetTextualSid(&sid,buf,&sidl); fprintf(stderr,"\nDomain: %s\n",domain); fprintf(stderr,"SID: %s\n\n",buf); if (psid->SubAuthority[psid->SubAuthorityCount-1] == 0xFFFFFFFF) // workaround for NT4 ?? --psid->SubAuthorityCount; ++psid->SubAuthorityCount; // loop RIDs for (psid->SubAuthority[psid->SubAuthorityCount-1] = minrid ; psid->SubAuthority[psid->SubAuthorityCount-1] <= maxrid ; ++psid->SubAuthority[psid->SubAuthorityCount-1]) { sid2user(sid,argv[1]); } } else { verbose = 1; GetTextualSid(&sid,buf,&sidl); fprintf(stderr,"\nDomain: %s\n",domain); fprintf(stderr,"SID: %s\n\n",buf); sid2user(sid,argv[1]); } }