diff --git a/__init__.py b/__init__.py index 32df9aa..29a8234 100755 --- a/__init__.py +++ b/__init__.py @@ -1,6 +1,8 @@ #! /usr/bin/python # -*- coding: utf-8 -*- +## 2008 Massive Blowout + import sys import struct @@ -111,29 +113,9 @@ def assert_in(a, *b): ## Binary stuff ## -def bin(i): - """Return the binary representation of i""" - - r = [] - while i > 0: - r.append(i % 2) - i = i >> 1 - r.reverse() - s = ''.join(str(x) for x in r) - return s - class BitVector: def __init__(self, i=0, length=None): - if type(i) == type(''): - self._val = 0 - for c in i: - self._val <<= 8 - self._val += ord(c) - if length is not None: - self._len = length - else: - self._len = len(i) * 8 - else: + if type(i) == type(1): self._val = i if length is not None: self._len = length @@ -142,6 +124,15 @@ class BitVector: while i > 0: i >>= 1 self._len += 1 + else: + self._val = 0 + for c in i: + self._val <<= 8 + self._val += ord(c) + if length is not None: + self._len = length + else: + self._len = len(i) * 8 def __len__(self): return self._len @@ -161,6 +152,8 @@ class BitVector: return BitVector(i & mask, length=l) def __iter__(self): + """Iterate from LSB to MSB""" + v = self._val for i in xrange(self._len): yield int(v & 1) @@ -195,6 +188,16 @@ class BitVector: else: raise ValueError("Can't extend with this type yet") + def bitstr(self): + bits = [str(x) for x in self] + bits.reverse() + return ''.join(bits) + + +def bin(i, bits=None): + """Return the binary representation of i""" + + return BitVector(i, bits).bitstr() ## diff --git a/crypto.py b/crypto.py index a2e2621..48c6b7c 100644 --- a/crypto.py +++ b/crypto.py @@ -1,7 +1,7 @@ #! /usr/bin/python ## Codebreaking tools -## 2007 Neale Pickett +## 2007 Massive Blowout ## I should get an LAUR for this so we can share it. from sets import Set diff --git a/gapstr.py b/gapstr.py index 7764f68..2552388 100755 --- a/gapstr.py +++ b/gapstr.py @@ -1,5 +1,7 @@ #! /usr/bin/python +## 2008 Massive Blowout + """Functions to treat a list as a string with gaps. Lists should have only string and integer items. @@ -122,9 +124,9 @@ class GapString: def __xor__(self, mask): if isinstance(mask, int): mask = [mask] - masklen = len(mask) - if isinstance(mask, str): + if isinstance(mask, str) or isinstance(mask, GapString): mask = [ord(c) for c in mask] + masklen = len(mask) new = self.__class__(drop=self.drop) for i in self.contents: diff --git a/ip.py b/ip.py index 62c6b03..c6f3b81 100755 --- a/ip.py +++ b/ip.py @@ -1,5 +1,8 @@ #! /usr/bin/python +## IP resequencing + protocol reversing skeleton +## 2008 Massive Blowout + import StringIO import struct import socket @@ -351,6 +354,9 @@ def demux(*pcs): ## Binary protocol stuff ## +class NeedMoreData(Exception): + pass + class Packet(UserDict.DictMixin): """Base class for a packet from a binary protocol. @@ -455,12 +461,20 @@ class Packet(UserDict.DictMixin): data = self.parse(data) if self.opcode <> None: - f = getattr(self, 'opcode_%s' % self.opcode) + try: + f = getattr(self, 'opcode_%s' % self.opcode) + except AttributeError: + f = self.opcode_unknown if not self.opcode_desc and f.__doc__: self.opcode_desc = f.__doc__.split('\n')[0] f() return data + def opcode_unknown(self): + """Unknown opcode""" + + raise AttributeError('Opcode %d unknown' % self.opcode) + class Session: """Base class for a binary protocol session.""" @@ -468,6 +482,9 @@ class Session: # Override this, duh Packet = Packet + def __init__(self): + self.pending = {} + def handle(self, chunk): """Handle a data burst. @@ -475,11 +492,20 @@ class Session: """ - data = chunk.gapstr() - while data: - p = self.Packet(chunk.first) - data = p.handle(data) - self.process(p) + saddr = chunk.first.saddr + try: + (first, data) = self.pending[saddr] + except KeyError: + first = chunk.first + data = gapstr.GapString() + data.extend(chunk.gapstr()) + try: + while data: + p = self.Packet(first) + data = p.handle(data) + self.process(p) + except NeedMoreData: + self.pending[saddr] = (first, data) def process(self, packet): """Process a packet. @@ -493,3 +519,14 @@ class Session: packet.show() + def done(self): + """Called when all packets have been handled""" + + return + + def handle_packets(self, collection): + """Handle a collection of packets""" + + for chunk in resequence(collection): + self.handle(chunk) + self.done()