def AesGetAllRoundKeys(targetbin, targetdata, goldendata, iblock=0x74657374746573747465737474657374, processinput=deadpool_dfa.processinput, processoutput=deadpool_dfa.processoutput, verbose=1, maxleaf=256 * 256, minleaf=64, minleafnail=8, addresses=None, start_from_left=True, depth_first_traversal=False, faults=4, minfaultspercol=4, timeoutfactor=2, savetraces_format='default', logfile=None, tolerate_error=False, lastroundkeys=[], encrypt=None, outputbeforelastrounds=False, shell=False, debug=False): engine = deadpool_dfa.Acquisition( targetbin, targetdata, goldendata, phoenixAES, iblock, processinput, processoutput, verbose, maxleaf, minleaf, minleafnail, addresses, start_from_left, depth_first_traversal, faults, minfaultspercol, timeoutfactor, savetraces_format, logfile, tolerate_error, encrypt, outputbeforelastrounds, shell, debug) foundkey = True while foundkey: foundkey = False tracefiles_sets = engine.run(lastroundkeys, encrypt) if encrypt is not None: tracefiles = tracefiles_sets[not encrypt] else: assert len(tracefiles_sets[0]) > 0 or len(tracefiles_sets[1]) > 0 if len(tracefiles_sets[0]) > 0: encrypt = True tracefiles = tracefiles_sets[0] elif len(tracefiles_sets[1]) > 0: encrypt = False tracefiles = tracefiles_sets[1] else: tracefiles = [] for tracefile in tracefiles: k = phoenixAES.crack( tracefile, lastroundkeys, encrypt, outputbeforelastrounds and len(lastroundkeys) > 0, verbose) if k: foundkey = True lastroundkeys.append(k) open('lastroundkeys.log', 'w').write('\n'.join(lastroundkeys)) break # Fuzzing directly the input: # This was only tested on encryption! foundkey = False tracefiles_sets = engine.runoninput(lastroundkeys) if encrypt is not None: tracefiles = tracefiles_sets[not encrypt] else: assert len(tracefiles_sets[0]) > 0 or len(tracefiles_sets[1]) > 0 if len(tracefiles_sets[0]) > 0: encrypt = True tracefiles = tracefiles_sets[0] elif len(tracefiles_sets[1]) > 0: encrypt = False tracefiles = tracefiles_sets[1] else: tracefiles = [] for tracefile in tracefiles: k = phoenixAES.crack(tracefile, lastroundkeys, encrypt, outputbeforelastrounds and len(lastroundkeys) > 0, verbose) if k: foundkey = True lastroundkeys.append(k) open('lastroundkeys.log', 'w').write('\n'.join(lastroundkeys)) break if foundkey: p = 0 # null plaintext cint, _, _ = engine.doit(engine.goldendata, processinput(p, 16), lastroundkeys=[]) c = [(cint >> (i << 3) & 0xff) for i in range(16)][::-1] kr0 = phoenixAES.rewind(cint, lastroundkeys, encrypt=encrypt, mimiclastround=False) # Be cautious, round key could be wrong if there is some external encoding... print("First round key found?:\n%032X" % kr0) lastroundkeys.append('%032X' % kr0) return lastroundkeys
def processinput(iblock, blocksize): p = '%0*x' % (2 * blocksize, iblock) return (None, [p[j * 2:(j + 1) * 2] for j in range(len(p) // 2)]) def processoutput(output, blocksize): i = int( b''.join([x for x in output.split(b'\n') if x.find(b'OUTPUT') == 0][0][10:].split(b' ')), 16) return i # Initial attack attempt: #engine=deadpool_dfa.Acquisition(targetbin='./wb_challenge', targetdata='./wb_challenge', goldendata='./wb_challenge.gold', # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, addresses=[0x21aa0,0xa0ac0], minfaultspercol=200) # Because of many false positives, we had to extend minfaultspercol to capture more traces # But looking at the resulting *.log (cut -c 10-30 *.log |sort|uniq) we see some distinct address ranges producing faults with the right pattern. # So we can target one of those address ranges and reduce the number of desired traces to the default for a much faster and determinitic attack: engine = deadpool_dfa.Acquisition(targetbin='./wb_challenge', targetdata='./wb_challenge', goldendata='./wb_challenge.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, addresses=[0x3b000, 0x3f000]) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack(tracefile): break
#!/usr/bin/env python3 import sys import deadpool_dfa import phoenixAES def processinput(iblock, blocksize): # hardcoded in spawn_drmless.py return (None, None) def processoutput(output, blocksize): # Typical output (Frida mem dump): #- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF #0x00000000 34 1a fa 02 f2 95 e6 fc 0b 08 9e 41 c6 30 27 4b 4..........A.0'K return int(output[output.find(b'0x00000000')+12:output.find(b'0x00000000')+59].replace(b' ', b''), 16) # Key found in 1m50s when addresses are restricted to the sweet spot: engine=deadpool_dfa.Acquisition(targetbin='./spawn_drmless.py', targetdata='./drmless', goldendata='drmless.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, maxleaf=2048, faults=[('nop', lambda x: 0x90)], addresses=(0x1c0000, 0x1d0000), verbose=2) # Key found in 12m40s when addresses are not specified: #engine=deadpool_dfa.Acquisition(targetbin='./spawn_drmless.py', targetdata='./drmless', goldendata='drmless.gold', # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, maxleaf=2048, faults=[('nop', lambda x: 0x90)], verbose=2) tracefiles=engine.run() for trace in tracefiles: if phoenixAES.crack_file(trace, encrypt=False): break
#!/usr/bin/env python3 import sys import deadpool_dfa import phoenixAES def processinput(iblock, blocksize): p='%0*x' % (2*blocksize, iblock) return [p[j*2:(j+1)*2] for j in range(len(p)//2)] def processoutput(output, blocksize): i=int(b''.join([x for x in output.split(b'\n') if x.find(b'OUTPUT')==0][0][10:].split(b' ')), 16) return i engine=deadpool_dfa.Acquisition(targetbin='./wb_challenge', targetdata='./wb_challenge', goldendata='./wb_challenge.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, addresses=[0x21aa0,0xa0ac0], minfaultspercol=200) tracefiles=engine.run() for tracefile in tracefiles: if phoenixAES.crack(tracefile): break
import sys import deadpool_dfa import phoenixAES def processinput(iblock, blocksize): p = '%0*x' % (2 * blocksize, iblock) return (None, [p[j * 2:(j + 1) * 2] for j in range(len(p) // 2)]) def processoutput(output, blocksize): return int(output, 16) engine = deadpool_dfa.Acquisition(targetbin='./DemoKey_table_encrypt', targetdata='DemoKey_table.bin', goldendata='DemoKey_table.bin.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, maxleaf=0x800, minleaf=0x100, outputbeforelastrounds=True) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack_file(tracefile): break
def processinput(iblock, blocksize): return [ "-key key.txt -in <(echo %0*x|xxd -r -p) -out >(xxd -p)" % (2 * blocksize, iblock) ] def processoutput(output, blocksize): return int( ''.join([x for x in output.decode().split('\n') if len(x) == 32][0]), 16) engine = deadpool_dfa.Acquisition(targetbin='./encryptECB', targetdata='key.txt', goldendata='key.txt.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, shell=True, minleaf=1, minleafnail=1, minfaultspercol=100, verbose=2) # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, shell=True, minleaf=1, minleafnail=1, minfaultspercol=150, verbose=2) tracefiles = engine.run() for tracefile in tracefiles: if phoenixAES.crack(tracefile): break
import sys import os import deadpool_dfa import phoenixAES import binascii import random def processinput(iblock, blocksize): p = '%0*x' % (2 * blocksize, iblock) return (None, [p]) def processoutput(output, blocksize): return int(output[:32], 16) engine = deadpool_dfa.Acquisition(targetbin='./main', targetdata='./main', goldendata='main.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, maxleaf=128, minleaf=1, verbose=2, addresses=(0x38000, 0x40000)) # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, maxleaf=128, minleaf=1, verbose=2, addresses=(0x15000, 0x65000)) tracefiles_sets = engine.run()
def processinput(iblock, blocksize): return (None, [ "--load-tables tables_karroumi_extenc.tbl --extEnc=1 --input-files <(echo %0*x|xxd -r -p) --out-file >(xxd -p)" % (2 * blocksize, iblock) ]) def processoutput(output, blocksize): return int( ''.join([x for x in output.decode().split('\n') if len(x) == 32][0]), 16) engine = deadpool_dfa.Acquisition(targetbin='./main', targetdata='tables_karroumi_extenc.tbl', goldendata='tables_karroumi_extenc.tbl.gold', maxleaf=64, minleaf=4, minleafnail=1, addresses=(0x57000, 0x5A000), dfa=phoenixAES, processinput=processinput, processoutput=processoutput, shell=True, verbose=2) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack_file(tracefile): break
def processoutput(output, blocksize): return int(b''.join(output.strip().split(b' ')), 16) # lazy settings: #engine=deadpool_dfa.Acquisition(targetbin='./whitebox', targetdata='./whitebox', goldendata='./whitebox.gold', # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, minleaf=1, minfaultspercol=100) # faster settings: #engine=deadpool_dfa.Acquisition(targetbin='./whitebox', targetdata='./whitebox', goldendata='./whitebox.gold', # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, # faults=[('nop', lambda x: 0x90)], maxleaf=32, minleaf=1, minleafnail=1, minfaultspercol=2, addresses=(0x45000,0x55000), debug=False) # damn faster settings: engine = deadpool_dfa.Acquisition(targetbin='./whitebox', targetdata='./whitebox', goldendata='./whitebox.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, maxleaf=1, minleaf=1, minfaultspercol=2, addresses=(0x47bf0, 0x47c00), debug=False) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack_file(tracefile): break
def processinput(iblock, blocksize): p = bytes.fromhex('%0*x' % (2 * blocksize, iblock)).decode('ascii') print(p) return (None, [p]) def processoutput(output, blocksize): num = int(binascii.hexlify(output[:16]), 16) if num != 138562705040537042133148046729108755018: print(num) return num engine = deadpool_dfa.Acquisition(targetbin='./whitebox', targetdata='./whitebox', goldendata='./whitebox.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, encrypt=True, verbose=True, faults=[('nop', lambda x: 0x90)], maxleaf=1024, minleaf=1, minleafnail=1) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack(tracefile): break
#!/usr/bin/env python3 import sys import deadpool_dfa import phoenixAES def processoutput(output, blocksize): return int( output[output.find(b'Output:') + 10:].rstrip().replace(b' ', b''), 16) engine = deadpool_dfa.Acquisition(targetbin='./nosuchcon_2013_whitebox_allenc', targetdata='wbt_allenc', goldendata='wbt_allenc.gold', dfa=phoenixAES, processoutput=processoutput, verbose=2) tracefiles = engine.run() for tracefile in tracefiles: if phoenixAES.crack(tracefile): break
import sys import deadpool_dfa import phoenixAES def processinput(iblock, blocksize): return (bytes.fromhex('%0*x' % (2*blocksize, iblock)),None) def processoutput(output, blocksize): idx = output.decode().find("encrypt: ") + 9 res = output[idx:-1] return int(res, 16) engine = deadpool_dfa.Acquisition(targetbin='./WhiteBoxTmp', targetdata='./WhiteBoxTmp', goldendata='WhiteBox', dfa=phoenixAES, processoutput=processoutput, processinput=processinput, encrypt=True, minleaf=0x1, minleafnail=0x1, maxleaf=0x100) tracefiles=engine.run() for tracefile in tracefiles[0]: if phoenixAES.crack_file(tracefile): break
#!/usr/bin/env python3 import sys import deadpool_dfa import phoenixAES def processinput(iblock, blocksize): p='%0*x' % (2*blocksize, iblock) return (None, [p[j*2:(j+1)*2] for j in range(len(p)//2)]) def processoutput(output, blocksize): return int([o[8:] for o in output.split(b'\n') if b"OUTPUT" in o][0].replace(b" ", b""), 16) #engine=deadpool_dfa.Acquisition(targetbin='./WB_LEE_CASE1_Client', targetdata='Tab.bin', goldendata='Tab.bin.gold', minfaultspercol=200, engine=deadpool_dfa.Acquisition(targetbin='./WB_LEE_CASE1_Client', targetdata='Tab.bin', goldendata='Tab.bin.gold', addresses=(0xC0000, 0xC3000), dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2) tracefiles_sets=engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack_file(tracefile): break
#!/usr/bin/env python3 import deadpool_dfa import phoenixAES import struct import re def processinput(iblock, blocksize): return (bytes.fromhex('%0*x' % (2*blocksize, iblock)), None) def processoutput(output, blocksize): result = re.search('Enter Message to encrypt: ([0-9a-f]+)', output.decode()).group(1) return int(result, 16) engine=deadpool_dfa.Acquisition(targetbin='./WhiteBox', targetdata='./WhiteBox', goldendata='./WhiteBox.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, minleaf=1, minleafnail=1) tracefiles_sets=engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack_file(tracefile): break
import struct def processinput(iblock, blocksize): return (bytes.fromhex('%0*x' % (2 * blocksize, iblock)), None) def processoutput(output, blocksize): return int.from_bytes(output, byteorder='big', signed=False) #engine=deadpool_dfa.Acquisition(targetbin='./main64', targetdata='./libnative-lib.so', goldendata='./libnative-lib.so.gold', # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, minleaf=1, minleafnail=1) # Limited address range to .rodata section for faster results: engine = deadpool_dfa.Acquisition(targetbin='./main64', targetdata='./libnative-lib.so', goldendata='./libnative-lib.so.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, minleaf=1, minleafnail=1, addresses=[0x6350, 0x2b490]) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack(tracefile): break
import sys, os import deadpool_dfa import phoenixAES def processinput(iblock, blocksize): return (bytes.fromhex('%0*x' % (2 * blocksize, iblock)), ["--stdin"]) def processoutput(output, blocksize): i = int(b''.join([x for x in output.split()]), 16) return i # Initial attack attempt: engine = deadpool_dfa.Acquisition( targetbin='./wb_patched', targetdata='./wb_data', goldendata='./mem.dump', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, maxleaf=0x100, minleaf=0x1, minleafnail=0x1, ) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack(tracefile, verbose=1): break
def processoutput(output, blocksize): return int(b''.join(output.strip().split(b' ')), 16) # lazy settings: #engine=deadpool_dfa.Acquisition(targetbin='./whitebox', targetdata='./whitebox', goldendata='./whitebox.gold', # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, minleaf=1, minfaultspercol=100) # faster settings: engine = deadpool_dfa.Acquisition(targetbin='./whitebox', targetdata='./whitebox', goldendata='./whitebox.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, faults=[('nop', lambda x: 0x90)], maxleaf=32, minleaf=1, minleafnail=1, minfaultspercol=2, addresses=(0x45000, 0x55000), debug=False) # damn faster settings: #engine=deadpool_dfa.Acquisition(targetbin='./whitebox', targetdata='./whitebox', goldendata='./whitebox.gold', # dfa=phoenixAES, processinput=processinput, processoutput=processoutput, verbose=2, # maxleaf=1, minleaf=1, minfaultspercol=2, addresses=(0x47bf0,0x47c00), debug=False) tracefiles_sets = engine.run() for tracefile in tracefiles_sets[0]: if phoenixAES.crack(tracefile): break
def processinput(iblock, blocksize): #p=b'%0*x' % (2*blocksize, iblock) # Requires python3.5 p = ('%0*x' % (2 * blocksize, iblock)).encode('utf8') open('foo', 'wb').write(binascii.unhexlify(p) * 4) return (None, ['-f', '-E', 'foo']) def processoutput(output, blocksize): return int(binascii.hexlify(output[:16]), 16) # Patch drmless to always return decrypted version: if not os.path.isfile('drmless.gold'): with open('drmless', 'rb') as finput, open('drmless.gold', 'wb') as foutput: foutput.write(finput.read(0x6C18) + b'\x01' + finput.read()[1:]) engine = deadpool_dfa.Acquisition(targetbin='./drmless', targetdata='./drmless', goldendata='drmless.gold', dfa=phoenixAES, processinput=processinput, processoutput=processoutput, maxleaf=1, addresses=[0x1C0000, 0x1C0020], faults=[('nop', lambda x: 0x90)], verbose=2) tracefiles_sets = engine.run()