Created
August 16, 2018 21:33
-
-
Save scottrcarlson/2bc7c954a7a759ffc18b5747e8a3326d to your computer and use it in GitHub Desktop.
DEF CON 26 Badge Emulator (Full Badge Bus Communication Protocol)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import time | |
import serial | |
from crccheck.crc import Crc16AugCcitt | |
#DEF CON 26 Badge Bus Communication Emulator | |
#Requires Python / Python crccheck / TTL USB-to-Serial adapter | |
#Relevant Sources | |
#https://github.com/Wireb/badge_bus/wiki | |
#https://github.com/m0n73/dc26_BadgeEmulator | |
PREAMBLE = "\x55\x55" | |
PACKET_START = "\x42\x42" | |
STATUS_REQ = "\x80" | |
STATUS_RES = "\xC0" | |
COMMAND = "\xAF" | |
PAYLOAD_REQ_LEN = "\x00" | |
PAYLOAD_RES_LEN = "\x05" | |
PAYLOAD_BEGIN = "\x00\x01\x00" | |
TYPE_HUMAN = "\x01" | |
TYPE_CONTEST = "\x02" | |
TYPE_GOON = "\x03" | |
TYPE_ARTIST = "\x04" | |
TYPE_PRESS = "\x05" | |
TYPE_VENDOR = "\x06" | |
TYPE_SPEAKER = "\x07" | |
TYPE_CFP = "\x08" | |
STATUS_RED = "\x00" | |
STATUS_GREEN = "\x01" | |
def buildPacket(isRequest, badgeType, badgeStatus): | |
if isRequest: | |
packet = PACKET_START + STATUS_REQ + COMMAND + PAYLOAD_REQ_LEN | |
crc = str(hex(Crc16AugCcitt.calc(bytearray(packet))))[2:].decode("hex") | |
return PREAMBLE + packet + crc | |
else: | |
packet = PACKET_START + STATUS_RES + COMMAND + PAYLOAD_RES_LEN + PAYLOAD_BEGIN + badgeType + badgeStatus | |
crc = str(hex(Crc16AugCcitt.calc(bytearray(packet))))[2:].decode("hex") | |
return PREAMBLE + packet + crc | |
def nextBadgePacket(index, status): | |
if index == 1: | |
return "Human", buildPacket(False, TYPE_HUMAN, status) | |
elif index == 2: | |
return "Contest", buildPacket(False, TYPE_CONTEST, status) | |
elif index == 3: | |
return "Goon", buildPacket(False, TYPE_GOON, status) | |
elif index == 4: | |
return "Artist", buildPacket(False, TYPE_ARTIST, status) | |
elif index == 5: | |
return "Press", buildPacket(False, TYPE_PRESS, status) | |
elif index == 6: | |
return "Vendor", buildPacket(False, TYPE_VENDOR, status) | |
elif index == 7: | |
return "Speaker", buildPacket(False, TYPE_SPEAKER, status) | |
elif index == 8: | |
return "CFP", buildPacket(False, TYPE_CFP, status) | |
request_packet = buildPacket(True, TYPE_HUMAN, None) | |
with serial.Serial('/dev/ttyUSB0', 9600, timeout=2) as ser: | |
time.sleep(0.1) | |
badgeIndex = 1 | |
while True: | |
ser.write(request_packet) | |
time.sleep(0.1) | |
packet = '' | |
prev_byte = '' | |
isRequest = False | |
isValid = False | |
parse_state = -1 | |
print "--" | |
print "Bytes in Buf: " + str(ser.in_waiting) | |
while ser.in_waiting: | |
byte = ser.read(1) | |
if parse_state == -1 and byte == '\x42': | |
parse_state = 0 | |
elif parse_state == 0 and byte != '\x42' and prev_byte == '\x42': #Packet Start | |
parse_state = 1 | |
if byte == STATUS_REQ: | |
print "Receiving Request Packet" | |
isRequest = True | |
parse_state = 1 | |
elif byte == STATUS_RES: | |
print "Receiving Response Packet" | |
parse_state = 1 | |
elif parse_state == 1: #Command Byte 0xAF | |
if byte == COMMAND: | |
parse_state = 2 | |
elif parse_state == 2: #Payload Length (0 or 5) | |
if byte == PAYLOAD_REQ_LEN: | |
parse_state = 8 | |
print "Payload Length: " + byte.encode("hex") | |
elif byte == PAYLOAD_RES_LEN: | |
parse_state = 3 | |
print "Payload Length: " + byte.encode("hex") | |
elif parse_state == 3 and byte == "\x00": #Payload Byte1 | |
parse_state = 4 | |
elif parse_state == 4 and byte == "\x01": #Payload Byte2 | |
parse_state = 5 | |
elif parse_state == 5 and byte == "\x00": #Payload Byte3 | |
parse_state = 6 | |
elif parse_state == 6: | |
parse_state = 7 | |
print "Badge Type: " + byte.encode("hex") | |
elif parse_state == 7: | |
print "Badge Status: " + byte.encode("hex") | |
parse_state = 8 | |
elif parse_state == 8: | |
parse_state = 9 | |
elif parse_state == 9: | |
parse_state = 10 | |
prev_byte = byte | |
if parse_state >= 0 and parse_state <= 10: | |
packet += byte | |
if parse_state == 10: | |
parse_state = 11 | |
crc = hex(Crc16AugCcitt.calc(bytearray(packet[:-2])))[2:] | |
crc_recv = packet[-2:].encode("hex") | |
print "Packet: " + str(packet[:-2]).encode("hex") | |
print "Calc/Recv CRC: %s/%s " % (crc, crc_recv) | |
if crc == crc_recv: | |
isValid = True | |
print "!! VALID PACKET !!" | |
if isRequest and isValid: | |
type, packet = nextBadgePacket(badgeIndex, STATUS_GREEN) | |
ser.write(packet) | |
print "== " + type + " Badge Response Sent ==" | |
badgeIndex += 1 | |
if badgeIndex > 8: | |
badgeIndex = 1 | |
time.sleep(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment