mirror of
				https://github.com/mgeeky/Penetration-Testing-Tools.git
				synced 2025-11-04 04:55:26 +01:00 
			
		
		
		
	findSymbols: added option to colorize output.
This commit is contained in:
		@@ -31,6 +31,7 @@ optional arguments:
 | 
			
		||||
                        Extensions of files to scan. By default will scan all files. Can be repeated: -E exe -E dll
 | 
			
		||||
  -o PATH, --output PATH
 | 
			
		||||
                        Write output to file.
 | 
			
		||||
  -C, --color           Add colors to text output. May uglify table text output
 | 
			
		||||
 | 
			
		||||
Output sorting:
 | 
			
		||||
  -u, --unique          Return unique symbols only. The first symbol with a name that occurs in results, will be returned.
 | 
			
		||||
@@ -42,7 +43,7 @@ Output sorting:
 | 
			
		||||
Output filtering:
 | 
			
		||||
  -i, --imports         Filter only Imports.
 | 
			
		||||
  -e, --exports         Filter only Exports.
 | 
			
		||||
  -s NAME, --name NAME  Search for symbols with name matching this regular expression. Can be repeated, case insensitive, constructs: ".+VALUE.+"
 | 
			
		||||
  -s NAME, --name NAME  Search for symbols with name matching this regular expression. Can be repeated, case insensitive
 | 
			
		||||
  -S NOT_NAME, --not-name NOT_NAME
 | 
			
		||||
                        Search for symbols with name NOT matching this regular expression.
 | 
			
		||||
  -m MODULE, --module MODULE
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,41 @@ headers = [
 | 
			
		||||
 | 
			
		||||
symbol_idx = headers.index('symbol')
 | 
			
		||||
 | 
			
		||||
class Logger:
 | 
			
		||||
    colors_map = {
 | 
			
		||||
        'red':      31, 
 | 
			
		||||
        'green':    32, 
 | 
			
		||||
        'yellow':   33,
 | 
			
		||||
        'blue':     34, 
 | 
			
		||||
        'magenta':  35, 
 | 
			
		||||
        'cyan':     36,
 | 
			
		||||
        'white':    37, 
 | 
			
		||||
        'grey':     38,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    colors_dict = {
 | 
			
		||||
        'error': colors_map['red'],
 | 
			
		||||
        'trace': colors_map['magenta'],
 | 
			
		||||
        'info ': colors_map['green'],
 | 
			
		||||
        'debug': colors_map['grey'],
 | 
			
		||||
        'other': colors_map['grey'],
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def with_color(c, s):
 | 
			
		||||
        return "\x1b[%dm%s\x1b[0m" % (c, s)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def end_color(s):
 | 
			
		||||
        return "%s\x1b[0m" % (s)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def colored(args, txt, col):
 | 
			
		||||
        if not args.color:
 | 
			
		||||
            return txt
 | 
			
		||||
 | 
			
		||||
        return Logger.with_color(Logger.colors_map[col], txt)
 | 
			
		||||
 | 
			
		||||
def out(x):
 | 
			
		||||
    sys.stderr.write(x + '\n')
 | 
			
		||||
 | 
			
		||||
@@ -107,18 +142,35 @@ def verifyCriterias(args, regexes, infos, uniqueSymbols):
 | 
			
		||||
 | 
			
		||||
    regexesVerified = sum([len(v) for k, v in regexes.items()])
 | 
			
		||||
 | 
			
		||||
    regexes_name = len(regexes['name'])
 | 
			
		||||
    regexes_not_name = len(regexes['not-name'])
 | 
			
		||||
    regexes_module = len(regexes['module'])
 | 
			
		||||
    regexes_not_module = len(regexes['not-module'])
 | 
			
		||||
 | 
			
		||||
    for name, rex in regexes['not-name']:
 | 
			
		||||
        match = rex.search(infos['symbol'])
 | 
			
		||||
        if match:
 | 
			
		||||
            matched = match.group(1)
 | 
			
		||||
            infos['symbol'] = infos['symbol'].replace(matched, Logger.colored(args, matched, 'red'))
 | 
			
		||||
            verbose(args, f'(-) Skipping symbol {infos["module"]}.{infos["symbol"]} as it DID satisfy not-name ({name}) regex.')
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
    if regexes_not_module+regexes_module+regexes_name == 0:
 | 
			
		||||
        verbose(args, f'(+) Symbol {infos["module"]}.{infos["symbol"]} satisfied all criterias.')
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    for name, rex in regexes['not-module']:
 | 
			
		||||
        match = rex.search(infos['module'])
 | 
			
		||||
        if match:
 | 
			
		||||
            matched = match.group(1)
 | 
			
		||||
            infos['module'] = infos['module'].replace(matched, Logger.colored(args, matched, 'red'))
 | 
			
		||||
            verbose(args, f'(-) Skipping symbol\'s module {infos["module"]}.{infos["symbol"]} as it DID satisfy not-module ({name}) regex.')
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
    if regexes_module+regexes_name == 0:
 | 
			
		||||
        verbose(args, f'(+) Symbol {infos["module"]}.{infos["symbol"]} satisfied all criterias.')
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    satisifed = False
 | 
			
		||||
    carryOn = False
 | 
			
		||||
 | 
			
		||||
@@ -126,16 +178,24 @@ def verifyCriterias(args, regexes, infos, uniqueSymbols):
 | 
			
		||||
        for name, rex in regexes['module']:
 | 
			
		||||
            match = rex.search(infos['module'])
 | 
			
		||||
            if match:
 | 
			
		||||
                matched = match.group(1)
 | 
			
		||||
                infos['module'] = infos['module'].replace(matched, Logger.colored(args, matched, 'green'))
 | 
			
		||||
                verbose(args, f'(+) Symbol\'s module {infos["module"]}.{infos["symbol"]} satisfied module ({name}) regex.')
 | 
			
		||||
                carryOn = True
 | 
			
		||||
                break
 | 
			
		||||
    else:
 | 
			
		||||
        carryOn = True
 | 
			
		||||
 | 
			
		||||
    if regexes_name == 0:
 | 
			
		||||
        verbose(args, f'(+) Symbol {infos["module"]}.{infos["symbol"]} satisfied all criterias.')
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    if carryOn:
 | 
			
		||||
        for name, rex in regexes['name']:
 | 
			
		||||
            match = rex.search(infos['symbol'])
 | 
			
		||||
            if match:
 | 
			
		||||
                matched = match.group(1)
 | 
			
		||||
                infos['symbol'] = infos['symbol'].replace(matched, Logger.colored(args, matched, 'green'))
 | 
			
		||||
                verbose(args, f'(+) Symbol {infos["module"]}.{infos["symbol"]} satisfied name ({name}) regex.')
 | 
			
		||||
                satisifed = True
 | 
			
		||||
                break
 | 
			
		||||
@@ -194,10 +254,16 @@ def processFile(args, regexes, path, results, uniqueSymbols, filesProcessed, sym
 | 
			
		||||
 | 
			
		||||
        if args.format == 'text':
 | 
			
		||||
            appendRow = verifyCriterias(args, regexes, infos, uniqueSymbols)
 | 
			
		||||
 | 
			
		||||
            if args.color:
 | 
			
		||||
                if infos['symbol type'] == 'import': 
 | 
			
		||||
                    infos['symbol type'] = Logger.colored(args, infos['symbol type'], 'cyan')
 | 
			
		||||
                else:
 | 
			
		||||
                    infos['symbol type'] = Logger.colored(args, infos['symbol type'], 'yellow')
 | 
			
		||||
        
 | 
			
		||||
            if appendRow:
 | 
			
		||||
                row = []
 | 
			
		||||
                MaxWidth = 80
 | 
			
		||||
                MaxWidth = 40
 | 
			
		||||
 | 
			
		||||
                for h in headers:
 | 
			
		||||
                    obj = None
 | 
			
		||||
@@ -208,7 +274,10 @@ def processFile(args, regexes, path, results, uniqueSymbols, filesProcessed, sym
 | 
			
		||||
                        obj = infos[h]
 | 
			
		||||
 | 
			
		||||
                    if type(obj) == str and len(obj) > MaxWidth:
 | 
			
		||||
                        obj = '\n'.join(textwrap.wrap(obj, width = MaxWidth))
 | 
			
		||||
                        if h == 'path':
 | 
			
		||||
                            obj = '\n'.join(textwrap.wrap(obj, width = 2 * MaxWidth))
 | 
			
		||||
                        else:
 | 
			
		||||
                            obj = '\n'.join(textwrap.wrap(obj, width = MaxWidth))
 | 
			
		||||
 | 
			
		||||
                    row.append(obj)
 | 
			
		||||
 | 
			
		||||
@@ -222,6 +291,12 @@ def processFile(args, regexes, path, results, uniqueSymbols, filesProcessed, sym
 | 
			
		||||
 | 
			
		||||
        elif args.format == 'json':
 | 
			
		||||
            appendRow = verifyCriterias(args, regexes, infos, uniqueSymbols)
 | 
			
		||||
 | 
			
		||||
            if args.color:
 | 
			
		||||
                if infos['symbol type'] == 'import': 
 | 
			
		||||
                    infos['symbol type'] = Logger.colored(args, infos['symbol type'], 'cyan')
 | 
			
		||||
                else:
 | 
			
		||||
                    infos['symbol type'] = Logger.colored(args, infos['symbol type'], 'yellow')
 | 
			
		||||
        
 | 
			
		||||
            if appendRow:
 | 
			
		||||
                results.append(infos)
 | 
			
		||||
@@ -236,7 +311,7 @@ def processFile(args, regexes, path, results, uniqueSymbols, filesProcessed, sym
 | 
			
		||||
    symbolsProcessed.value += len(symbols)
 | 
			
		||||
 | 
			
		||||
def trap_handler(signum, frame):
 | 
			
		||||
    out('[-] CTRL-C pressed. Wait a minute until all processes wrap up.')
 | 
			
		||||
    out('[-] CTRL-C pressed. Wait a minute until all processes wrap up or manually terminate python\'s child processes tree.')
 | 
			
		||||
 | 
			
		||||
def init_worker():
 | 
			
		||||
    signal.signal(signal.SIGINT, trap_handler)
 | 
			
		||||
@@ -300,6 +375,7 @@ def opts(argv):
 | 
			
		||||
    params.add_argument('-f', '--format', choices=['text', 'json'], default='text', help='Output format. Text or JSON.')
 | 
			
		||||
    params.add_argument('-E', '--extension', default=[], action='append', help='Extensions of files to scan. By default will scan all files. Can be repeated: -E exe -E dll')
 | 
			
		||||
    params.add_argument('-o', '--output', metavar='PATH', help='Write output to file.')
 | 
			
		||||
    params.add_argument('-C', '--color', default=False, action='store_true', help='Add colors to text output. May uglify table text output')
 | 
			
		||||
 | 
			
		||||
    sorting = params.add_argument_group('Output sorting')
 | 
			
		||||
    sorting.add_argument('-u', '--unique', action='store_true', help = 'Return unique symbols only. The first symbol with a name that occurs in results, will be returned.')
 | 
			
		||||
@@ -310,7 +386,7 @@ def opts(argv):
 | 
			
		||||
    filters = params.add_argument_group('Output filtering')
 | 
			
		||||
    filters.add_argument('-i', '--imports', action='store_true', help = 'Filter only Imports.')
 | 
			
		||||
    filters.add_argument('-e', '--exports', action='store_true', help = 'Filter only Exports.')
 | 
			
		||||
    filters.add_argument('-s', '--name', action='append', default=[], help = 'Search for symbols with name matching this regular expression. Can be repeated, case insensitive, constructs: ".+VALUE.+"')
 | 
			
		||||
    filters.add_argument('-s', '--name', action='append', default=[], help = 'Search for symbols with name matching this regular expression. Can be repeated, case insensitive')
 | 
			
		||||
    filters.add_argument('-S', '--not-name', action='append', default=[], help = 'Search for symbols with name NOT matching this regular expression.')
 | 
			
		||||
    filters.add_argument('-m', '--module', action='append', default=[], help = 'Search for symbols exported in/imported from this module matching regular expression.')
 | 
			
		||||
    filters.add_argument('-M', '--not-module', action='append', default=[], help = 'Search for symbols NOT exported in/NOT imported from this module matching regular expression.')
 | 
			
		||||
@@ -321,7 +397,7 @@ def opts(argv):
 | 
			
		||||
        out('[!] --imports and --exports are mutually exclusive. Pick only one of them!')
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    accomodate_rex = lambda x: x
 | 
			
		||||
    accomodate_rex = lambda x: f'({x})'
 | 
			
		||||
 | 
			
		||||
    regexes = {
 | 
			
		||||
        'name': [],
 | 
			
		||||
@@ -418,15 +494,15 @@ def main():
 | 
			
		||||
                print(table)
 | 
			
		||||
 | 
			
		||||
            if args.first > 0:
 | 
			
		||||
                out(f'\n[+] Found {len(resultsList)} symbols meeting all the criterias (but shown only first {args.first} ones).\n')
 | 
			
		||||
                out(f'\n[+] Found {Logger.colored(args, len(resultsList), "green")} symbols meeting all the criterias (but shown only first {Logger.colored(args, args.first, "magenta")} ones).\n')
 | 
			
		||||
            else:
 | 
			
		||||
                out(f'\n[+] Found {len(resultsList)} symbols meeting all the criterias.\n')
 | 
			
		||||
                out(f'\n[+] Found {Logger.colored(args, len(resultsList), "green")} symbols meeting all the criterias.\n')
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            out(f'[-] Did not find symbols meeting specified criterias.')
 | 
			
		||||
 | 
			
		||||
        out(f'[.] Processed {filesProcessed.value} files and {symbolsProcessed.value} symbols.')
 | 
			
		||||
        out('[.] Time elapsed: {}'.format(time_elapsed))
 | 
			
		||||
        out(f'[.] Processed {Logger.colored(args, filesProcessed.value, "green")} files and {Logger.colored(args, symbolsProcessed.value, "green")} symbols.')
 | 
			
		||||
        out('[.] Time elapsed: {}'.format(Logger.colored(args, time_elapsed, "magenta")))
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    freeze_support()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user