diff --git a/monkey_island/cc/resources/pthmap.py b/monkey_island/cc/resources/pthmap.py index f1f1825c3..63967d91f 100644 --- a/monkey_island/cc/resources/pthmap.py +++ b/monkey_island/cc/resources/pthmap.py @@ -167,6 +167,16 @@ class Machine(object): def GetLocalAdmins(self): return set(self.GetUsersByGroupSid(self.GetGroupSidByGroupName("Administrators")).keys()) + + def GetLocalSids(self): + doc = self.latest_system_info + + SIDs = set() + + for user in doc["data"]["Win32_UserAccount"]: + SIDs.add(eval(user["SID"])) + + return SIDs def GetLocalAdminNames(self): return set(self.GetUsersByGroupSid(self.GetGroupSidByGroupName("Administrators")).values()) @@ -392,19 +402,22 @@ class PassTheHashMap(object): return None - def GetAllSids(self): - SIDs = {} + def GetAttackableMachineCountBySid(self, sid): + count = 0 for m in self.vertices: - for sid in m.GetLocalAdmins(): - if sid not in SIDs.keys(): - SIDs[sid] = {} - SIDs[sid]["admin_count"] = 0 - SIDs[sid]["cache_count"] = self.GetSecretCacheCount(self.GetSecretBySid(sid)) - - SIDs[sid]["admin_count"] += 1 + if sid in m.GetLocalAdmins(): + count += 1 + + return count + + def GetAttackableMachineCountByMachine(self, attacker): + count = 0 - return SIDs + for secret in attack.GetCachedSecrets(): + count += len(m.GetVictimsBySecret(secret)) + + return count def GetSecretCacheCount(self, secret): count = 0 @@ -415,14 +428,22 @@ class PassTheHashMap(object): return count + def GetAllSids(self): + SIDs = set() + + for m in self.vertices: + SIDs |= m.GetLocalSids() + + return SIDs + def GetAllSecrets(self): - secrets = {} + secrets = set() for m in self.vertices: for secret in m.GetLocalAdminSecrets(): - if secret not in secrets.keys(): - secrets[secret] = {} - secrets[secret]["cache_count"] = GetSecretCacheCount(secret) + secret.add(secret) + #secrets[secret]["cache_count"] = self.GetSecretCacheCount(secret) + #secrets[secret]["sid_count"] = len(self.GetSidsBySecret(secret)) return secrets @@ -492,4 +513,52 @@ class PassTheHashMap(object): return machines def GetAttackersByVictim(self, victim): - assert False, "TODO, get information from the graph" \ No newline at end of file + assert False, "TODO, get information from the graph" + +def main(): + pth = PassTheHashMap() + + print "

Pass The Hash Report

" + + print "

Duplicated Passwords

" + print "

How many users share each secret?

" + dups = dict(map(lambda x: (x, len(self.GetSidsBySecret(x))), pth.GetAllSecrets())) + + print """""" + print """SecretUser Count""" + for secret, count in sorted(dups.iteritems(), key=lambda (k,v): (v,k), reverse=True): + print """{secret}{count}""".format(secret=secret, count=count) + print """""" + + print "

Cached Passwords

" + print "

On how many machines each secret is cached?

" + cache_counts = dict(map(lambda x: (x, self.GetSecretCacheCount(x)), pth.GetAllSecrets())) + + print """""" + print """SecretMachine Count""" + for secret, count in sorted(cache_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True): + print """{secret}{count}""".format(secret=secret, count=count) + print """""" + + print "

User's Creds

" + print "

To how many machines each user is able to connect with admin rights?

" + attackable_counts = dict(map(lambda x: (x, self.GetAttackableMachineCountBySid(x)), pth.GetAllSids())) + + print """""" + print """SIDUsernameMachine Count""" + for sid, count in sorted(attackable_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True): + print """{sid}{username}{count}""".format(sid=sid, username=pth.GetUsernameBySid(sid), count=count) + print """""" + + print "

Machine's Creds

" + print "

To how many machines each machine is able to directly connect with admin rights?

" + attackable_counts = dict(map(lambda m: (m, pth.GetAttackableMachineCountByMachine(m)), pth.vertices)) + + print """""" + print """Attacker IpAttacker HostnameDomain NameVictim Machine Count""" + for m, count in sorted(attackable_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True): + print """{ip}{hostname}{domain}{count}""".format(ip=m.GetIp(), hostname=n.GetHostName(), domain=m.GetDomainName(), count=count) + print """""" + +if __name__ == "__main__": + main() \ No newline at end of file