Skip to content

Commit

Permalink
Add Credential listing
Browse files Browse the repository at this point in the history
  • Loading branch information
helviojunior committed Jul 30, 2024
1 parent e72a65b commit 042f8fb
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 1 deletion.
2 changes: 1 addition & 1 deletion knowsmore/__meta__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.1.38'
__version__ = '0.1.39'
__title__ = "knowsmore"
__description__ = "KnowsMore is a swiss army knife tool for pentesting Microsoft Active Directory (NTLM Hashes, BloodHound, NTDS and DCSync)."
__url__ = "https://github.com/helviojunior/knowsmore"
Expand Down
153 changes: 153 additions & 0 deletions knowsmore/cmd/credentials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import json
import os
import sqlite3
import time
from argparse import _ArgumentGroup, Namespace
from pathlib import Path

from ansi2image.ansi2image import Ansi2Image
from binascii import hexlify
from enum import Enum

from knowsmore.util.tools import Tools

from knowsmore.cmdbase import CmdBase
from knowsmore.password import Password
from knowsmore.util.color import Color
from knowsmore.util.database import Database
from knowsmore.util.knowsmoredb import KnowsMoreDB
from knowsmore.util.logger import Logger


class Credentials(CmdBase):
db = None
out_file = None
out_path = None

def __init__(self):
super().__init__('credentials', 'Show cracked credentials')

def add_flags(self, flags: _ArgumentGroup):
flags.add_argument('--save-to',
action='store',
default='',
dest=f'out_file',
help=Color.s(
'Output file to save JSON data'))

flags.add_argument('--save-to-img',
action='store',
default='',
dest=f'out_path',
help=Color.s(
'Output path to save PNG files'))

def add_commands(self, cmds: _ArgumentGroup):
pass

def load_from_arguments(self, args: Namespace) -> bool:

if args.out_file is not None and args.out_file.strip() != '':
self.out_file = Path(args.out_file).absolute()

if self.out_file is not None:
if os.path.exists(self.out_file):
Logger.pl('{!} {R}error: out file ({O}%s{R}) already exists {W}\r\n' % (
self.out_file))
exit(1)

if args.out_path is not None and args.out_path.strip() != '':
self.out_path = Path(args.out_path).absolute()

if self.out_path is not None:
if not os.path.isdir(self.out_path):
Logger.pl('{!} {R}error: output path ({O}%s{R}) does not exists {W}\r\n' % (
self.out_path))
exit(1)

self.db = self.open_db(args)

return True

def run(self):

data = []

domains = self.db.select('domains')
for r in domains:

# Domain
rows = self.db.select_raw(
sql='select row_number() OVER (ORDER BY c.name) AS __line, c.name, p.password '
'from credentials as c '
'inner join passwords as p '
'on c.password_id = p.password_id '
'where p.password <> "" and c.domain_id = ? '
'order by c.name ',
args=[r['domain_id']]
)

if len(rows) > 0:
data.append({
'type': 'credentials',
'domain': r['name'],
'description': 'Cracked credentials for %s' % r['name'],
'rows': rows
})

if self.out_file is not None:
Color.pl('{?} {W}{D}Credentials saved at {W}{C}%s{W}{D}{W}' % self.out_file)

with open(self.out_file, "a", encoding="UTF-8") as text_file:
text_file.write(json.dumps(
{
'data': data,
'meta': {
'type': 'stats',
'count': len(data),
'version': 1
}
}
))

elif self.out_path is not None:

for i, d in enumerate(data):
name = f"{i:03}_{Tools.sanitize_filename(d['description'])}"
file_data = ' \033[38;5;52m=\033[38;5;88m=\033[38;5;124m=\033[38;5;160m=\033[38;5;196m> ' + Color.s(
'{W}{G}%s{W}\n' % d['description'])

file_data += ''.join([
'%s─' % c for k, c in sorted(Color.gray_scale.items(), key=lambda x: x[0], reverse=True)
]) + Color.s('{W}\n')

Color.pl('{?} {W}{D}Saving %s...{W}' % d['description'])

if len(data) == 0:
file_data += Color.s(
'\n {R}ATTENTION!!!{O} \n %s{W}\n' % 'Table is empty')
else:
file_data += Tools.get_ansi_tabulated(d['rows'])

o = Ansi2Image(0, 0, font_name=Ansi2Image.get_default_font_name(), font_size=13)
o.loads(file_data)
o.min_margin = 10
o.max_margin = 30
o.calc_size(margin=0.01)
o.save_image(os.path.join(self.out_path, f'{name}.png'), format='PNG')

#with open(os.path.join(self.out_path, f'{name}.ansi.txt'), 'wb') as f:
# f.write(file_data.encode('utf-8', 'ignore'))

else:

for d in data:
Color.pl('{?} {W}{D}%s{W}' % d['description'])
print(Tools.get_tabulated(d['rows']))
print(' ')






0 comments on commit 042f8fb

Please sign in to comment.