Skip to content
Branch: master
Find file Copy path
Find file Copy path
4 contributors

Users who have contributed to this file

@gypsophlia @doegox @geo-rg @dev-zzo
executable file 109 lines (82 sloc) 3.67 KB
#!/usr/bin/env python3
# Command line tool to analyze binary dump files from the Chameleon
# Authors: Simon K. (
from __future__ import print_function
import argparse
import sys
import json
import Chameleon
import io
import datetime
from Chameleon.ISO14443 import CardTypesMap
def verboseLog(text):
formatString = "[{}] {}"
timeString = datetime.datetime.utcnow()
print(formatString.format(timeString, text), file=sys.stderr)
def formatText(log):
formatString = '{timestamp:0>5d} ms <{deltaTimestamp:>+6d} ms>:'
formatString += '{eventName:<28} ({dataLength:<3} bytes) [{data:<20}] ' \
'\033[94m {note} \x1b[0m \n'
text = ''
for logEntry in log:
text += formatString.format(**logEntry)
return text
def formatJSON(log):
text = json.dumps(log, sort_keys=True, indent=4)
return text
def main():
outputTypes = {
'text': formatText,
'json': formatJSON
argParser = argparse.ArgumentParser(description="Analyzes binary Chameleon logfiles")
group = argParser.add_mutually_exclusive_group(required=True)
group.add_argument("-f", "--file", dest="logfile", metavar="LOGFILE")
group.add_argument("-p", "--port", dest="port", metavar="COMPORT")
argParser.add_argument("-t", "--type", choices=outputTypes.keys(), default='text',
help="specifies output type")
argParser.add_argument("-d", "--decode", dest="decode", choices=CardTypesMap.keys(), default=None, help="Decode the sniffed traffic and application data with a decoder")
argParser.add_argument("-l", "--live", dest="live", action='store_true', help="Use live logging capabilities of Chameleon")
argParser.add_argument("-c", "--clear", dest="clear", action='store_true', help="Clear Chameleon's log memory when using -p")
argParser.add_argument("-m", "--mode", dest="mode", metavar="LOGMODE", help="Additionally set Chameleon's log mode after reading it's memory")
argParser.add_argument("-v", "--verbose", dest="verbose", action='store_true', default=0)
args = argParser.parse_args()
if (args.verbose):
verboseFunc = verboseLog
verboseFunc = None
print("\nNote: If parityBit check failed, '!' is appended to the decoded data and raw data with parity bit is displayed.\n")
if (
# Live logging mode
if (args.port is not None):
chameleon = Chameleon.Device(verboseFunc)
if (chameleon.connect(args.port)):
while True:
stream = io.BytesIO(
log = Chameleon.Log.parseBinary(stream, args.decode)
if (len(log) > 0):
if (args.logfile is not None):
handle = open(args.logfile, "rb")
elif (args.port is not None):
chameleon = Chameleon.Device(verboseFunc)
if (chameleon.connect(args.port)):
handle = io.BytesIO()
if (args.clear):
if (args.mode is not None):
# Parse actual logfile
log = Chameleon.Log.parseBinary(handle, args.decode)
# Print to console using chosen output type
if __name__ == "__main__":
You can’t perform that action at this time.