2012-10-20 22:38:28 +00:00
import struct
2015-10-05 20:55:56 +00:00
fmtsLSB = [ None , " B " , " <H " , " <I " , " <I " , " <Q " , " <Q " , " <Q " , " <Q " ]
fmtsMSB = [ None , " B " , " >H " , " >I " , " >I " , " >Q " , " >Q " , " >Q " , " >Q " ]
sizes = [ 0 , 1 , 2 , 4 , 4 , 8 , 8 , 8 , 8 ]
masks = [ ( 1 << ( 8 * i ) ) - 1 for i in xrange ( 9 ) ]
def wtfo ( string ) :
outstr = [ ]
bitlen = len ( outstr ) * 8
for x in range ( 8 ) :
outstr . append ( shiftString ( string , x ) )
string = strBitReverse ( string )
for x in range ( 8 ) :
outstr . append ( shiftString ( string , x ) )
return outstr
def strBitReverse ( string ) :
# FIXME: this is really dependent upon python's number system. large strings will not convert well.
# FIXME: break up array of 8-bit numbers and bit-swap in the array
num = 0
bits = len ( string ) * 8
# convert to MSB number
for x in range ( len ( string ) ) :
ch = string [ x ]
#num |= (ord(ch)<<(8*x)) # this is LSB
num << = 8
num | = ord ( ch )
print ( hex ( num ) )
rnum = bitReverse ( num , bits )
print ( hex ( rnum ) )
# convert back from MSB number to string
out = [ ]
for x in range ( len ( string ) ) :
out . append ( chr ( rnum & 0xff ) )
rnum >> = 8
out . reverse ( )
print ( ' ' . join ( out ) . encode ( ' hex ' ) )
return ' ' . join ( out )
def strXorMSB ( string , xorval , size ) :
'''
lsb
pads end of string with 00
'''
out = [ ]
strlen = len ( string )
string + = " \x00 " * sizes [ size ]
for idx in range ( 0 , strlen , size ) :
tempstr = string [ idx : idx + sizes [ size ] ]
temp , = struct . unpack ( fmtsMSB [ size ] , tempstr )
temp ^ = xorval
temp & = masks [ size ]
tempstr = struct . pack ( fmtsMSB [ size ] , temp ) [ - size : ]
out . append ( tempstr )
return ' ' . join ( out )
def bitReverse ( num , bitcnt ) :
newnum = 0
for idx in range ( bitcnt ) :
newnum << = 1
newnum | = num & 1
num >> = 1
return newnum
2012-10-20 22:38:28 +00:00
def shiftString ( string , bits ) :
carry = 0
news = [ ]
for x in xrange ( len ( string ) - 1 ) :
newc = ( ( ord ( string [ x ] ) << bits ) + ( ord ( string [ x + 1 ] ) >> ( 8 - bits ) ) ) & 0xff
news . append ( " %c " % newc )
newc = ( ord ( string [ - 1 ] ) << bits ) & 0xff
news . append ( " %c " % newc )
return " " . join ( news )
2015-10-05 20:55:56 +00:00
def getNextByte_feedbackRegister7bitsMSB ( ) :
'''
this returns a byte of a 7 - bit feedback register stemming off bits 4 and 7
the register is 7 bits long , but we return a more usable 8 bits ( ie .
'''
global fbRegister
retval = 0
for x in range ( 8 ) : #MSB,
retval << = 1
retval | = ( fbRegister >> 6 ) # start with bit 7
nb = ( ( fbRegister >> 3 ) ^ ( fbRegister >> 6 ) ) & 1
fbRegister = ( ( fbRegister << 1 ) | nb ) & 0x7f # do shifting
#print "retval: %x fbRegister: %x bit7: %x nb: %x" % (retval, fbRegister, (fbRegister>>6), nb)
return retval
def getNextByte_feedbackRegister7bitsLSB ( ) :
'''
this returns a byte of a 7 - bit feedback register stemming off bits 4 and 7
the register is 7 bits long , but we return a more usable 8 bits ( ie .
'''
global fbRegister
retval = 0
for x in range ( 8 ) : #MSB,
retval >> = 1
retval | = ( ( fbRegister << 1 ) & 0x80 ) # start with bit 7
nb = ( ( fbRegister >> 3 ) ^ ( fbRegister >> 6 ) ) & 1
fbRegister = ( ( fbRegister << 1 ) | nb ) & 0x7f # do shifting
#print "retval: %x fbRegister: %x bit7: %x nb: %x" % (retval, fbRegister, (fbRegister>>6), nb)
return retval
def whitenData ( data , seed = 0xffff , getNextByte = getNextByte_feedbackRegister7bitsMSB ) :
global fbRegister
fbRegister = seed
carry = 0
news = [ ]
for x in xrange ( len ( data ) - 1 ) :
newc = ( ( ord ( data [ x ] ) ^ getNextByte ( ) ) & 0xff )
news . append ( " %c " % newc )
return " " . join ( news )
def findSyncWord ( byts , sensitivity = 4 , minpreamble = 2 ) :
'''
seek SyncWords from a raw bitstream .
assumes we capture at least two ( more likely 3 or more ) preamble bytes
'''
2012-10-20 22:38:28 +00:00
possDwords = [ ]
# find the preamble (if any)
2015-10-05 20:55:56 +00:00
while True : # keep searching through string until we don't find any more preamble bits to pick on
2012-10-20 22:38:28 +00:00
sbyts = byts
2015-10-05 20:55:56 +00:00
pidx = byts . find ( " \xaa " * minpreamble )
2012-10-20 22:38:28 +00:00
if pidx == - 1 :
2015-10-05 20:55:56 +00:00
pidx = byts . find ( " \x55 " * minpreamble )
byts = shiftString ( byts , 1 )
2012-10-20 22:38:28 +00:00
if pidx == - 1 :
return possDwords
# chop off the nonsense before the preamble
sbyts = byts [ pidx : ]
#print "sbyts: %s" % repr(sbyts)
# find the definite end of the preamble (ie. it may be sooner, but we know this is the end)
while ( sbyts [ 0 ] == ' \xaa ' and len ( sbyts ) > 2 ) :
sbyts = sbyts [ 1 : ]
#print "sbyts: %s" % repr(sbyts)
# now we look at the next 16 bits to narrow the possibilities to 8
# at this point we have no hints at bit-alignment aside from 0xaa vs 0x55
dwbits , = struct . unpack ( " >H " , sbyts [ : 2 ] )
#print "sbyts: %s" % repr(sbyts)
#print "dwbits: %s" % repr(dwbits)
if len ( sbyts ) > = 3 :
bitcnt = 0
# bits1 = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
# bits2 = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bits1 , = struct . unpack ( " >H " , sbyts [ : 2 ] )
bits1 = bits1 | ( ord ( ' \xaa ' ) << 16 )
bits1 = bits1 | ( ord ( ' \xaa ' ) << 24 )
bits1 << = 8
bits1 | = ( ord ( sbyts [ 2 ] ) )
#print "bits: %x" % (bits1)
bit = ( 5 * 8 ) - 2 # bytes times bits/byte #FIXME: MAGIC NUMBERS!?
while ( bits1 & ( 3 << bit ) == ( 2 << bit ) ) :
bit - = 2
#print "bit = %d" % bit
bits1 >> = ( bit - 16 )
#while (bits1 & 0x30000 != 0x20000): # now we align the end of the 101010 pattern with the beginning of the dword
# bits1 >>= 2
#print "bits: %x" % (bits1)
2015-10-05 20:55:56 +00:00
bitcount = min ( 2 * sensitivity , 17 )
for frontbits in xrange ( bitcount ) : # with so many bit-inverted systems, let's not assume we know anything about the bit-arrangement. \x55\x55 could be a perfectly reasonable preamble.
2012-10-20 22:38:28 +00:00
poss = ( bits1 >> frontbits ) & 0xffff
if not poss in possDwords :
possDwords . append ( poss )
byts = byts [ pidx + 1 : ]
return possDwords
2015-10-05 20:55:56 +00:00
def findSyncWordDoubled ( byts ) :
2012-10-20 22:38:28 +00:00
possDwords = [ ]
# find the preamble (if any)
bitoff = 0
pidx = byts . find ( " \xaa \xaa " )
if pidx == - 1 :
pidx = byts . find ( " \55 \x55 " )
bitoff = 1
if pidx == - 1 :
return [ ]
# chop off the nonsense before the preamble
byts = byts [ pidx : ]
# find the definite end of the preamble (ie. it may be sooner, but we know this is the end)
while ( byts [ 0 ] == ( ' \xaa ' , ' \x55 ' ) [ bitoff ] and len ( byts ) > 2 ) :
byts = byts [ 1 : ]
# now we look at the next 16 bits to narrow the possibilities to 8
# at this point we have no hints at bit-alignment
dwbits , = struct . unpack ( " >H " , byts [ : 2 ] )
if len ( byts ) > = 5 :
bitcnt = 0
# bits1 = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
# bits2 = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bits1 , = struct . unpack ( " >H " , byts [ : 2 ] )
bits1 = bits1 | ( ord ( ( ' \xaa ' , ' \x55 ' ) [ bitoff ] ) << 16 )
bits1 = bits1 | ( ord ( ( ' \xaa ' , ' \x55 ' ) [ bitoff ] ) << 24 )
bits1 << = 8
bits1 | = ( ord ( byts [ 2 ] ) )
bits1 >> = bitoff
bits2 , = struct . unpack ( " >L " , byts [ : 4 ] )
bits2 << = 8
bits2 | = ( ord ( byts [ 4 ] ) )
bits2 >> = bitoff
frontbits = 0
for frontbits in xrange ( 16 , 40 , 2 ) : #FIXME: if this doesn't work, try 16, then 18+frontbits
dwb1 = ( bits1 >> ( frontbits ) ) & 3
dwb2 = ( bits2 >> ( frontbits ) ) & 3
print " \t frontbits: %d \t \t dwb1: %s dwb2: %s " % ( frontbits , bin ( bits1 >> ( frontbits ) ) , bin ( bits2 >> ( frontbits ) ) )
if dwb2 != dwb1 :
break
# frontbits now represents our unknowns... let's go from the other side now
for tailbits in xrange ( 16 , - 1 , - 2 ) :
dwb1 = ( bits1 >> ( tailbits ) ) & 3
dwb2 = ( bits2 >> ( tailbits ) ) & 3
print " \t tailbits: %d \t \t dwb1: %s dwb2: %s " % ( tailbits , bin ( bits1 >> ( tailbits ) ) , bin ( bits2 >> ( tailbits ) ) )
if dwb2 != dwb1 :
tailbits + = 2
break
# now, if we have a double syncword, iinm, tailbits + frontbits >= 16
print " frontbits: %d \t \t tailbits: %d , bits: %s " % ( frontbits , tailbits , bin ( ( bits2 >> tailbits & 0xffffffff ) ) )
if ( frontbits + tailbits > = 16 ) :
tbits = bits2 >> ( tailbits & 0xffff )
tbits & = ( 0xffffffff )
print " tbits: %x " % tbits
poss = tbits & 0xffffffff
if poss not in possDwords :
possDwords . append ( poss )
else :
pass
# FIXME: what if we *don't* have a double-sync word? then we stop at AAblah or 55blah and take the next word?
possDwords . reverse ( )
return possDwords
#def test():
def visBits ( data ) :
pass
def getBit ( data , bit ) :
idx = bit / 8
bidx = bit % 8
char = data [ idx ]
return ( ord ( char ) >> ( 7 - bidx ) ) & 1
def detectRepeatPatterns ( data , size = 64 , minEntropy = .07 ) :
#FIXME: convert strings to bit arrays before comparing.
c1 = 0
c2 = 0
d1 = 0
p1 = 0
mask = ( 1 << size ) - 1
bitlen = 8 * len ( data )
while p1 < ( bitlen - size - 8 ) :
d1 << = 1
d1 | = getBit ( data , p1 )
d1 & = mask
#print bin(d1)
if c1 < ( size ) :
p1 + = 1
c1 + = 1
continue
d2 = 0
p2 = p1 + size
while p2 < ( bitlen ) :
d2 << = 1
d2 | = getBit ( data , p2 )
d2 & = mask
#print bin(d2)
if c2 < ( size ) :
p2 + = 1
c2 + = 1
continue
if d1 == d2 and d1 > 0 :
s1 = p1 - size
s2 = p2 - size
print " s1: %d \t p1: %d \t " % ( s1 , p1 )
print " s2: %d \t p2: %d \t " % ( s2 , p2 )
# complete the pattern until the numbers differ or meet
while True :
p1 + = 1
p2 + = 1
#print "s1: %d\t p1: %d\t " % (s1, p1)
#print "s2: %d\t p2: %d\t " % (s2, p2)
if p2 > = bitlen :
break
b1 = getBit ( data , p1 )
b2 = getBit ( data , p2 )
if p1 == s2 or b1 != b2 :
break
length = p1 - s1
c2 = 0
p2 - = size
bitSection , ent = bitSectString ( data , s1 , s1 + length )
if ent > minEntropy :
print " success: "
print " * bit idx1: %4d ( %4d bits) - ' %s ' %s " % ( s1 , length , bin ( d1 ) , bitSection . encode ( " hex " ) )
print " * bit idx2: %4d ( %4d bits) - ' %s ' " % ( s2 , length , bin ( d2 ) )
#else:
# print " * idx1: %d - '%s' * idx2: %d - '%s'" % (p1, d1, p2, d2)
p2 + = 1
p1 + = 1
def bitSectString ( string , startbit , endbit ) :
'''
bitsects a string . . . ie . chops out the bits from the middle of the string
returns the new string and the entropy ( ratio of 0 : 1 )
'''
ones = 0
zeros = 0
entropy = [ zeros , ones ]
s = ' '
bit = startbit
Bidx = bit / 8
bidx = ( bit % 8 )
while bit < endbit :
byte1 = ord ( string [ Bidx ] )
try :
byte2 = ord ( string [ Bidx + 1 ] )
except IndexError :
byte2 = 0
byte = ( byte1 << bidx ) & 0xff
byte | = ( byte2 >> ( 8 - bidx ) )
#calculate entropy over the byte
for bi in range ( 8 ) :
b = ( byte >> bi ) & 1
entropy [ b ] + = 1
bit + = 8
Bidx + = 1
if bit > endbit :
diff = bit - endbit
mask = ~ ( ( 1 << diff ) - 1 )
byte & = mask
s + = chr ( byte )
ent = ( min ( entropy ) + 1.0 ) / ( max ( entropy ) + 1 )
#print "entropy: %f" % ent
return ( s , ent )
def genBitArray ( string , startbit , endbit ) :
'''
bitsects a string . . . ie . chops out the bits from the middle of the string
returns the new string and the entropy ( ratio of 0 : 1 )
'''
binStr , ent = bitSectString ( string , startbit , endbit )
s = [ ]
for byte in binStr :
byte = ord ( byte )
for bitx in range ( 7 , - 1 , - 1 ) :
bit = ( byte >> bitx ) & 1
s . append ( bit )
return ( s , ent )
chars_top = [
" " , #000
" " , #001
" ^ " , #010
" / " , #011
" " , #100
" " , #101
" \\ " , #110
" - " , #111
]
chars_mid = [
" " , #000
" | " , #001
" # " , #010
" " , #011
" | " , #100
" # " , #101
" " , #110
" " , #110
]
chars_bot = [
" - " , #000
" / " , #001
" " , #010
" " , #011
" \\ " , #100
" V " , #101
" " , #110
" " , #110
]
def reprBitArray ( bitAry , width = 194 ) :
top = [ ]
mid = [ ]
bot = [ ]
arylen = len ( bitAry )
# top line
#FIXME: UGGGGLY and kinda broken.
fraction = 1.0 * arylen / width
expand = [ bitAry [ int ( x * fraction ) ] for x in xrange ( width ) ]
for bindex in xrange ( width ) :
bits = 0
if bindex > 0 :
bits + = ( expand [ bindex - 1 ] ) << ( 2 )
bits + = ( expand [ bindex ] ) << ( 1 )
if bindex < width - 1 :
bits + = ( expand [ bindex + 1 ] )
top . append ( chars_top [ bits ] )
mid . append ( chars_mid [ bits ] )
bot . append ( chars_bot [ bits ] )
tops = " " . join ( top )
mids = " " . join ( mid )
bots = " " . join ( bot )
return " \n " . join ( [ tops , mids , bots ] )
2015-10-05 20:55:56 +00:00
def invertBits ( data ) :
output = [ ]
ldata = len ( data )
off = 0
if ldata & 1 :
output . append ( chr ( ord ( data [ 0 ] ) ^ 0xff ) )
off = 1
if ldata & 2 :
output . append ( struct . pack ( " <H " , struct . unpack ( " <H " , data [ off : off + 2 ] ) [ 0 ] ^ 0xffff ) )
off + = 2
#method 1
#for idx in xrange( off, ldata, 4):
# output.append( struct.pack( "<I", struct.unpack( "<I", data[idx:idx+4] )[0] & 0xffff) )
#method2
count = ldata / 4
#print ldata, count
numlist = struct . unpack ( " < %d I " % count , data [ off : ] )
modlist = [ struct . pack ( " <L " , ( x ^ 0xffffffff ) ) for x in numlist ]
output . extend ( modlist )
return ' ' . join ( output )