Python3
script stub
#!/usr/bin/env python3
import argparse
import logging
import sys
def main(args):
# start of program
logging.info("hello world!")
if __name__ == "__main__":
# arguments parsing
argParser = argparse.ArgumentParser(description="Default description to replace.")
argParser.add_argument("files", nargs="+", help="Input files to parse.")
argParser.add_argument("-o", "--output", required=True, help="Output file")
argParser.add_argument("-v", "--verbose", help="Turn on verbose messages", action="store_true")
argParser.add_argument("-d", "--debug", help="Turn on debugging", action="store_true")
args = argParser.parse_args()
# logging configuration
logger = logging.getLogger()
handler = logging.StreamHandler(sys.stdout)
if args.debug:
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
fmt="%(asctime)-19s %(levelname)-8s %(name)s %(message)s",
datefmt="%Y-%m-%d_%H:%M:%S",
)
else:
if args.verbose:
logger.setLevel(logging.INFO)
else:
logger.setLevel(logging.WARNING)
formatter = logging.Formatter(fmt="%(message)s", datefmt="%Y-%m-%d_%H:%M:%S")
handler.setFormatter(formatter)
logger.addHandler(handler)
main(args)
Standard Types
dict
tab = {'key' : 'value', 'name' : 'jack', 'city' : 'laval'}
if 'key' in tab:
print(tab['key'])
for value in tab.values():
print(value)
for key, value in tab.items():
print('key = {}, value = {}'.format(key, value))
bytes
>>> a = b'abc'
>>> a[0]
97
>>> a[0:1]
b'a'
>>> a.hex()
'616263'
>>> bytes(23) # probably not what you want
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> bytes([23]) # probably exactly what you want
b'\x17'
debug_var
debug any (short) variable, human readable
def debug_var(var: Any, tabs: int = 0) -> str:
retour = ""
if var is None:
retour = "<None>"
elif isinstance(var, str) or isinstance(var, int) or isinstance(var, float):
retour = str(var)
elif isinstance(var, tuple):
retour += "(\n"
for i in var:
retour += " " * tabs + f" + {debug_var(i, tabs+2)}\n"
retour += " " * tabs + ")"
elif isinstance(var, list):
retour += "[\n"
for i in var:
retour += " " * tabs + f" - {debug_var(i, tabs+2)}\n"
retour += " " * tabs + "]"
elif isinstance(var, dict):
retour += "{\n"
for k, v in var.items():
retour += (
" " * tabs + f" * {debug_var(k, tabs+2)}: {debug_var(v, tabs+2)}\n"
)
retour += " " * tabs + "}"
else:
retour += " " * tabs + f"### Type non supporté ({var.__class__})\n"
return retour
# Usage:
print(debug_var(my_tab))
format
argparse
Simple example with optionnal argument and multiple value argument:
argParser = argparse.ArgumentParser(description='Port scan using censys database')
argParser.add_argument('filter', nargs='+', help='Censys filter to search for. Can be a list of IPs.')
argParser.add_argument('-c', '--csv', dest='csv', help='Turn on CSV output', action='store_true')
args = argParser.parse_args()
More complex example with mandatory arguments depending on the request type:
# Parse arguments
argParser = argparse.ArgumentParser(description="Active Directory LDAP Enumerator")
argParser.add_argument('-l', '--server', required=True, dest='ldap_server', help='IP address of the LDAP server.')
argParser.add_argument('-t', '--type', required=True, dest='request_type', help='Request type: info, whoami, search, trusts, TODO')
argParser.add_argument('-d', '--domain', dest='domain', help='Authentication account\'s FQDN. Example: "contoso.local".')
argParser.add_argument('-u', '--username', dest='username', help='Authentication account\'s username.')
argParser.add_argument('-p', '--password', dest='password', help='Authentication account\'s password.')
argParser.add_argument('-s', '--search-filter', dest='search_filter', help='Search filter (use LDAP format).')
argParser.add_argument('search_attributes', default='*', nargs='*', help='LDAP attributes to look for.')
argParser.add_argument('-z', '--size_limit', dest='size_limit', default=10, help='Size limit (default is server\'s limit).')
argParser.add_argument('-o', '--output', dest='output_file', help='Write results in specified file too.')
argParser.add_argument('-v', '--verbose', dest='verbosity', help='Turn on debug mode', action='store_true')
args = argParser.parse_args()
# Set mandatory arguments for each request_type
mandatory_arguments = {}
mandatory_arguments['info'] = []
mandatory_arguments['whoami'] = ['domain', 'username', 'password']
mandatory_arguments['search'] = ['domain', 'username', 'password', 'search_filter']
mandatory_arguments['trusts'] = ['domain', 'username', 'password']
mandatory_arguments['show'] = ['domain', 'username', 'password', 'search_filter']
if args.request_type not in mandatory_arguments.keys():
argParser.error('request type must be one of: {}.'.format(', '.join(mandatory_arguments.keys())))
for mandatory_argument in mandatory_arguments[args.request_type]:
if vars(args)[mandatory_argument] is None:
argParser.error('{} argument is mandatory with request type = {}'.format(mandatory_argument, args.request_type))
csv
Example that I use often to output result in a CSV file:
fichier_resultat = args.output
logging.debug(f"Writing results in {fichier_resultat}")
with open(fichier_resultat, "w", newline="") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=headers)
writer.writeheader()
writer.writerows(vulns)
logging.info(f"End of script. Results are in {fichier_resultat}")
logging
Example to log on stdout instead of the default stderr and to enable DEBUG messages if args.debug
is enabled:
logger = logging.getLogger()
handler = logging.StreamHandler(sys.stdout)
if args.debug:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
formatter = logging.Formatter(fmt='%(asctime)-19s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d_%H:%M:%S')
handler.setFormatter(formatter)
logger.addHandler(handler)
json
Pretty print
echo '{"json":"obj"}' | python -m json.tool
import json
print(json.dumps(json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]'), indent=2, sort_keys=True))
re
How to use the Regular Expression module of python3.
import re
regex = re.compile(r'([A-Za-z]*):\s*(.*)')
data = 'Username: \n user3837'
matches = regex.findall(data)
print(matches)
[('Username', 'user3837')]
colors
termcolor
, colorama
or without any dependance with: https://stackoverflow.com/questions/287871/print-in-terminal-with-colors/21786287#21786287
for style in range(8):
for fg in range(30,38):
s1 = ''
for bg in range(40,48):
format = ';'.join([str(style), str(fg), str(bg)])
s1 += '\x1b[%sm %s \x1b[0m' % (format, format)
print(s1)
print('\n')
scapy
Run on a pcap file to extract all TCP data in raw format.
It is then possible to run a binwalk -e
to extract known file types.
#!/usr/bin/env python3
from scapy.all import *
import sys
def main():
pkt_cap = rdpcap(sys.argv[1])
for pkt in pkt_cap:
sys.stdout.buffer.write(bytes(pkt[TCP]))
sys.exit(0)
if __name__ == '__main__':
main()
Run on a pcap file to extract all DNS queries and responses (might be enhanced)
#!/usr/bin/env python3
from scapy.all import *
import sys
def main():
pkt_cap = rdpcap(sys.argv[1])
for pkt in pkt_cap:
if pkt.haslayer(DNSQR):
query = pkt[DNSQR].qname.decode('utf-8')
print('> {}'.format(query))
if pkt.haslayer(DNSRR):
response = pkt[DNSRR].rdata
print('< {}'.format(response))
sys.exit(0)
if __name__ == '__main__':
main()