Since Python seems to be the name of the game, and we're posting old stuff.
Here's something I made a long time ago.
This just breaks all of the XOR faux security on the fly. As long as it's BCB + XOR encrypted, you don't need the key.
Remember to XOR by 0xFF first, before applying this algorithm, if you're dealing with SGO.
def deleterepeat(s):
s = binascii.hexlify(s)
i = (s+s).find(s, 1, -1)
return binascii.unhexlify(s) if i == -1 else binascii.unhexlify(s[:i])
def stripBCBHead(imgxor):
return imgxor[imgxor.index(b"\x1A\x01") + 2:]
def freqtable(data, klen):
freqtable = {}
for x in range (0, klen):
curfreq = {}
for y in range (0, 256):
curfreq[y] = 0
freqtable[x] = curfreq
for nr in range(len(data)):
freqtable[nr % klen][data[nr]] += 1
return freqtable
def findXORkeyfreq(bcbdata, byte, confidence, maxlen):
data = stripBCBHead(bcbdata)
keyFound = False
key = bytearray()
debug = config.getint("main", "debug", fallback=0)
for curlen in reversed(range(4, maxlen+1)):
fqtable = freqtable(data, curlen)
key = bytearray(curlen)
avgconf1 = 0
for fqpos in sorted(fqtable):
sortedlist = sorted(fqtable[fqpos].items(), key=lambda x: x[1], reverse=True)
avgconf1 += 100 - sortedlist[1][1]/sortedlist[0][1]*100
key[fqpos] = sortedlist[0][0] ^ byte
avgconf1 = avgconf1/curlen
if (avgconf1 >= confidence):
key = deleterepeat(key)
return key
return b""
Call like:
findXORkeyfreq(bcbdata, 0xFF, 50, 32)
Recommend calling it on the biggest section or just foreach all sections until a key is found, etc...