Secure bios dump

Posted on 2015-12-30 (Wed) in misc

I wrote a little helper script to combine bios dumps with random read errors.

When you try to dump your BIOS in a room with lots of electro magnetic noice like the c-lab at c-base, it’s very unlikly that you read everything without any errors. There will always be a read error somewhere in your dump. At a random position.
Cool thing is that the bytes that you read correctly are always at the same spot. So if you ran a diff over your dumps you will only see the read errors.
Everything that is the same is correctly read.

The script takes a minimum of 3 binary dumps (for better output create 5 dumps) and compares them. If the byte that is read the same in at least 2 out of 3 files it is considered correct and written to the output file.
This generates correct dumps out of multiple failed attempts.

Here is the script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env python3
# -*- coding: utf8 -*-

"""
BIOS combine

Usage:
    bios_combine.py [-v | --verbose] [-e ERRORS | --errors ERRORS] <output> <dump> <dump> <dump>...
    bios_combine.py (-h | --help)
    bios_combine.py --version

Options:
    -e ERROR, --errors ERRORS  Number of corrupt dumps allowed (default: 1).
    <output>                   Output filename.
    <dump>..                   BIOS dumps (minimum 3).
    -v, --verbose              Verbose mode.
    -h, --help                 Show this screen.
    --version                  Show version.

Example:
    bios_combine.py -v -e 2 combined_output.bin dump1.bin dump2.bin dump3.bin dump4.bin dump5.bin
"""

import os
import sys

from docopt import docopt


def combine(output, files, verbose, errors):
    with open(output, 'wb') as out:
        dumps = [open(f, 'rb').read() for f in files]
        if not errors:
            errors = 1
        l = len(dumps[0])
        for i in range(l):
            if verbose:
                print('Writing byte {} of {}.'.format(i, l), end='\r')
            c = [dump[i] for dump in dumps]
            m = max(set(c), key=c.count)
            if len(files) - c.count(m) > int(errors):
                sys.exit('Too many errors in dumps at byte {}. Can\'t verify correctness of output file.'.format(i))
            out.write(bytes([m]))

if __name__ == '__main__':
    ARGS = docopt(__doc__, version='1.0.0')
    if len(ARGS['<dump>']) >= 3:
        combine(ARGS['<output>'], ARGS['<dump>'], ARGS['--verbose'], ARGS['--errors'])
    else:
        sys.exit('Provide at least 3 BIOS dumps to combine.')