Skip to the content.

Python snippets

Some snippets of Python code that I use too infrequently to remember, but frequently enough to be annoyed every time I have to track down an example again.

iPython3 execfile helper

Python3 removes execfile, so its nice to have a helper.

Simple:

coder = lambda x : compile(open(x).read(), x, 'exec')

Use it like so:

exec(coder(filename))

More complex including setting the global __file__ variable to the executed filename (which can sometimes be useful):

coder = lambda x : [compile(open(x).read(), x, 'exec'), globals().update({'__file__' : x})]

Use:

exec(coder(filename))

Put these in ~/.ipython/profile_default/startup/startup.py to make them always available in iPython.

Generate sortable timestamp

Do the necessary import

import datetime

Timestamp with only the date:

def timestamp():
    return datetime.datetime.now().strftime('%Y%m%d')

Timestamp with date and time:

def timestamp():
    return datetime.datetime.now().strftime('%Y%m%d%H%M%S')

Timestamp to datetime and reverse

Do the import

from datetime import datetime

Timestamp to datetime

datetime.fromtimestamp(1545730073)

Datetime to timestamp

datetime.timestamp(datetime.now())

An example HTML parser

An example of a HTMLPaser, you will need to edit this to make it useful, this is just a template thats a bit better than the obvious one in the Python docs.

from html.parser import HTMLParser
class HParser(HTMLParser):
    '''Example HTML parser'''

    def __init__(self):
        HTMLParser.__init__(self)
        self.outData = ''
        self.divData = ''
        self.inHtag = False
        self.inDtag = False


    def handle_starttag(self, tag, attrs):
        if tag == 'h1':
            self.inHtag = True
        elif tag == 'div':
            if (self.get_starttag_text().find('content') > -1):
                self.inDtag = True
    
    def handle_endtag(self, tag):
        if tag == "h1":
            self.inHtag = False
        elif tag == "div":
            self.inDtag = False


    def handle_data(self, data):
        if self.inHtag:
            self.outData = self.outData + data
        elif self.inDtag:
            self.divData = self.divData + data
            

    def close(self):
        return [ self.outData, self.divData ]

HTML parsing using BeautifulSoup

This simple example shows how to get a list of all “td” elements in HTML in the variable html_text.

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_text, 'html.parser')
soup.find_all('td')

wsgi example to load a Flask app

Most of the times my Python helper servers are single use code and run temporarily listening on their own socket, but sometimes you want to offer multiple functions and take advantage of existing infrastructure, such as an existing https server with legitimate certificate. In this case, the following with the wsgi module will allow a web server like Apache to serve the Python code.

# if the app isn't already installed as a module or in the Python path, import sys and add the folder it sits in to Python path
import sys
sys.path.insert(0, '/usr/local/www/wsgi-scripts/')

# where flask_app is the name of the script file/module
from flask_app import app as application

A good reference for the Apache configuration is here, which can be followed once the wsgi module is installed and enabled using a2enmod. The WSGIScriptAlias and Allow/Require instructions (depending on version) are minimums, for SSL you may also want to add SSLOptions +StdEnvVars.

An example Flask app that could be loaded is here.

A simple Python3 https server

From Github gists here.

Python http command

python -m http.server 8000

Python smtp stdout email receiver command

sudo python -m smtpd -n -c DebuggingServer 0.0.0.0:25

Python __import__

An example of calling the path.isdir method from the os module without an explicit import. Full docco here.

__import__('os').path.isdir('/Users')

Xor

Xor with a single character:

def xorSingle(input: bytes, xorVal: bytes) -> bytes:
    return bytes([a^xorVal[0] for a in input])

Xor two values, truncate to the length of the shortest:

def xorValues(input1: bytes, input2: bytes) -> bytes:
    return bytes([input1[a] ^ input2[a] for a in range(0,min(len(input1),len(input2)))])

Xor one longer value with a repeating shorter second value:

def xorRepeat(input1: bytes, xorVal: bytes) -> bytes:
    return bytes([input1[a] ^ xorVal[a%len(xorVal)] for a in range(0,len(input1))])

Crypto

PCKS7 padding

def pad(value: bytes, bs: int=16) -> bytes:
    pv = bs - (len(value) % bs)
    return value + (chr(pv) * pv).encode()

PKCS7 unpadding

def unpad(value: bytes, bs: int=16) -> bytes:
    pv = value[-1]
    if pv > bs:
        raise Exception('Bad padding')
    padding = value[-pv:]
    if len(padding) != pv or len(set([a for a in padding])) != 1:
        raise Exception('Bad padding')
    return value[:-pv]

AES CBC encrypt and decrypt with leading IV and PKCS7 padding

from Crypto.Cipher import AES
from Crypto import Random
BLOCKSIZE=16

def encrypt(value: bytes, key:bytes) -> bytes:
    iv = Random.new().read(BLOCKSIZE)
    cipher = AES.new(key, AES.MODE_CBC, iv) 
    return iv + cipher.encrypt(pad(value))

def decrypt(value: bytes, key: bytes) -> bytes:
    cipher = AES.new(key, AES.MODE_CBC, value[:BLOCKSIZE]) # iv is value[:BLOCKSIZE]
    decrypted = cipher.decrypt(value[BLOCKSIZE:]) # encrypted data is value[BLOCKSIZE:]
    return unpad(decrypted)

Run executable and get output

A very simple approach

import subprocess
subprocess.check_output(['ls', '-lart']).decode()

Or a slightly more involved example:

def run_process(command: list) -> str:
    proc = subprocess.Popen(command, stdout=subprocess.PIPE)
    out =  proc.stdout.read().decode()
    proc.terminate()
    return out

Resolve a name using DNS

import dns.resolver

def resolve(name, rdtype='A'):
    return [a.to_text() for a in dns.resolver.resolve(name, rdtype=rdtype)]

Adding error handling to prevent exceptions in case of lookup failures:

def try_resolve(name, rdtype='A'):
    try:
        return resolve(name, rdtype)
    except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.NoNameservers):
        return []

Test if you can connect to a host on a given TCP port

import socket


def test_connect(host: str, port: int) -> bool:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(1)
    result = sock.connect_ex((host, int(port)))
    return True if result == 0 else False

Get the certificate from a remote SSL service

import socket
from OpenSSL import SSL

def get_cert(hostname: str, port: int):
    sock = socket.socket()
    sock.connect((hostname, int(port)))
    ctx = SSL.Context(SSL.SSLv23_METHOD) # most compatible
    ctx.check_hostname = False
    ctx.verify_mode = SSL.VERIFY_NONE

    sock_ssl = SSL.Connection(ctx, sock)
    sock_ssl.set_connect_state()
    sock_ssl.set_tlsext_host_name(hostname.encode())
    sock_ssl.do_handshake()
    cert = sock_ssl.get_peer_certificate()
    sock_ssl.close()
    sock.close()

    return cert

Create an NTLM hash

import hashlib
ntlm = lambda pwd : hashlib.new('md4', pwd.encode('utf-16le')).hexdigest()
ntlm('password_to_hash')

On newer Pythons that dont include md4 in hashlib, install pycryptodome and try this

from Crypto.Hash import MD4
ntlm = lambda pwd : MD4.new(pwd.encode('utf-16le')).hexdigest()

Get all permutations of a given input list

The following will get all combinations of the given list, including combinations of items of list length n-1 to 2.

from itertools import permutations
getListPerms = lambda x: [ a for b in range(1, len(x)) for a in permutations(x, b+1)]
getListPerms(['one', 'two', 'three', 'four'])

Make the requests module shut up about insecure requests

If you choose to make unverified https requests and the certificate of the site is not considered valid, the requests module makes sure to tell you about it with a InsecureRequestWarning error, saying Unverified HTTPS request is being made to host. This seems to work to make those errors go away:

requests.packages.urllib3.disable_warnings()

Custom argument parser

The custom argument parser I use for Python code that I intend for other people to be able to use to provide a more friendly interface.

Setup:

import sys
import argparse

class MyParser(argparse.ArgumentParser):
    def error(self, message):
        sys.stderr.write('error: %s\n' % message)
        self.print_help()
        sys.exit(2)

Example use:

if __name__ == "__main__":
    parser = MyParser()
    parser.epilog = 'Text to include after help output'
    parser.description = 'Text to include after usage and before options help'
    parser.add_argument('-c', '--cookies', type=str, required=True, help='Cookie value. REQUIRED.')
    parser.add_argument('-r', '--role', type=str,  default='role1', help='Help string. Default: role1')
    parser.add_argument('-o', '--other', action='store_true', help='Not implemented')
    args = parser.parse_args()
    cookie = args.cookies

Custom logger

The custom logger I use for more significant Python programs.

Setup:

import logging
from logging import Logger 

def create_logger(loglevel: str, name: str) -> Logger:
    logger = logging.getLogger(name)
    logger.setLevel(loglevel)
    handler = logging.StreamHandler(sys.stderr)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    return logger


logger = create_logger(args.loglevel, 'Log Name')

Usage:

logger.info('Info message')

Check if code is running in iPython

Useful to add to scripts to enable you to determine whether it is running in iPython or not to enable different code flows

def check_ipython():
    """Returns True if script is running in interactive iPython shell"""
    try:
        get_ipython()
        return True
    except NameError:
        return False