diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/__init__.py b/__init__.py index b34ae90..11c76bd 100644 --- a/__init__.py +++ b/__init__.py @@ -3,154 +3,8 @@ import binascii import sys import struct +from . import ip -stdch = ( - '␀·········␊··␍··' - '················' - ' !"#$%&\'()*+,-./' - '0123456789:;<=>?' - '@ABCDEFGHIJKLMNO' - 'PQRSTUVWXYZ[\]^_' - '`abcdefghijklmno' - 'pqrstuvwxyz{|}~·' - '················' - '················' - '················' - '················' - '················' - '················' - '················' - '················' -) - -decch = ( - '␀␁␂␃␄␅␆␇␈␉␊␋␌␍␎␏' - '␐␑␒␓␔␕␖␗␘␙␚·····' - '␠!"#$%&\'()*+,-./' - '0123456789:;<=>?' - '@ABCDEFGHIJKLMNO' - 'PQRSTUVWXYZ[\]^_' - '`abcdefghijklmno' - 'pqrstuvwxyz{|}~␡' - '················' - '················' - '················' - '················' - '················' - '················' - '················' - '················' -) - -cgach = ( - '□☺☻♥♦♣♠•◘○◙♂♀♪♫☼' - '►◄↕‼¶§▬↨↑↓→←∟↔▲▼' - ' !"#$%&\'()*+,-./' - '0123456789:;<=>?' - '@ABCDEFGHIJKLMNO' - 'PQRSTUVWXYZ[\]^_' - '`abcdefghijklmno' - 'pqrstuvwxyz{|}~⌂' - 'ÇüéâäàåçêëèïîìÄÅ' - 'ÉæÆôöòûùÿÖÜ¢£¥₧ƒ' - 'áíóúñѪº¿⌐¬½¼¡«»' - '░▒▓│┤╡╢╖╕╣║╗╝╜╛┐' - '└┴┬├─┼╞╟╚╔╩╦╠═╬╧' - '╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀' - 'αßΓπΣσµτΦΘΩδ∞φε∩' - '≡±≥≤⌠⌡÷≈°∙·√ⁿ²■¤' -) - -fluffych = ( - '·☺☻♥♦♣♠•◘○◙♂♀♪♫☼' - '►◄↕‼¶§▬↨↑↓→←∟↔▲▼' - ' !"#$%&\'()*+,-./' - '0123456789:;<=>?' - '@ABCDEFGHIJKLMNO' - 'PQRSTUVWXYZ[\]^_' - '`abcdefghijklmno' - 'pqrstuvwxyz{|}~⌂' - 'ÇüéâäàåçêëèïîìÄÅ' - 'ÉæÆôöòûùÿÖÜ¢£¥₧ƒ' - 'áíóúñѪº¿⌐¬½¼¡«»' - '░▒▓│┤╡╢╖╕╣║╗╝╜╛┐' - '└┴┬├─┼╞╟╚╔╩╦╠═╬╧' - '╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀' - 'αßΓπΣσµτΦΘΩδ∞φε∩' - '≡±≥≤⌠⌡÷≈°∀∃√ⁿ²■¤' -) - - -def unpack(fmt, buf): - """Unpack buf based on fmt, return the remainder.""" - - size = struct.calcsize(fmt) - vals = struct.unpack(fmt, bytes(buf[:size])) - return vals + (buf[size:],) - - -class HexDumper: - def __init__(self, output, charset=fluffych): - self.offset = 0 - self.last = None - self.elided = False - self.hexes = [] - self.chars = [] - self.charset = charset - self.output = output - - def _spit(self): - if self.chars == self.last: - if not self.elided: - self.output.write('*\n') - self.elided = True - self.hexes = [] - self.chars = [] - return - self.last = self.chars[:] - self.elided = False - - pad = 16 - len(self.chars) - self.hexes += [' '] * pad - - self.output.write('{:08x} '.format(self.offset - len(self.chars))) - self.output.write(' '.join(self.hexes[:8])) - self.output.write(' ') - self.output.write(' '.join(self.hexes[8:])) - self.output.write(' ') - self.output.write(''.join(self.chars)) - self.output.write('\n') - - self.hexes = [] - self.chars = [] - - def add(self, b): - if self.offset and self.offset % 16 == 0: - self._spit() - - if b is None: - h = '⬜' - c = '�' - else: - h = '{:02x}'.format(b) - c = self.charset[b] - self.chars.append(c) - self.hexes.append(h) - - self.offset += 1 - - def done(self): - self._spit() - self.output.write('{:08x}\n'.format(self.offset)) - - -def hexdump(buf, f=sys.stdout, charset=fluffych): - "Print a hex dump of buf" - - h = HexDumper(output=f, charset=charset) - for b in buf: - h.add(b) - h.done() def cstring(buf): @@ -160,10 +14,6 @@ def cstring(buf): return buf[:i] -def md5sum(txt): - return md5.new(txt).hexdigest() - - def assert_equal(a, b): assert a == b, ('%r != %r' % (a, b)) @@ -218,7 +68,7 @@ class BitVector: """Iterate from LSB to MSB""" v = self._val - for i in xrange(self._len): + for _ in range(self._len): yield int(v & 1) v >>= 1 @@ -282,7 +132,7 @@ import string b64alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' def from_b64(s, alphabet, codec='base64'): - tr = string.maketrans(alphabet, b64alpha) + tr = alphabet.maketrans(b64alpha) t = s.translate(tr) return t.decode(codec) @@ -330,3 +180,15 @@ def _registry(encoding): Esab64StreamReader, Esab64StreamWriter) codecs.register(_registry) + +def main(session): + s = None + reseq = ip.Dispatch(*sys.argv[1:]) + for _, d in reseq: + srv, first, chunk = d + if not s: + s = session(first) + s.handle(srv, first, chunk, reseq.last) + +Session = ip.Session +Packet = ip.Packet diff --git a/dumbdecode.py b/dumbdecode.py index 22caae5..81ce142 100755 --- a/dumbdecode.py +++ b/dumbdecode.py @@ -1,20 +1,12 @@ #! /usr/bin/python3 -import sys -from netarch import ip -from netarch import * +import netarch -class DumbPacket(ip.Packet): - def parse(self, data): - self.payload = data +class DumbPacket(netarch.Packet): + def parse(self, data): + self.payload = data -class DumbSession(ip.Session): - Packet = DumbPacket +class DumbSession(netarch.Session): + Packet = DumbPacket -s = None -reseq = ip.Dispatch(*sys.argv[1:]) -for h, d in reseq: - srv, first, chunk = d - if not s: - s = DumbSession(first) - s.handle(srv, first, chunk, reseq.last) +netarch.main(DumbSession) diff --git a/hexdump.py b/hexdump.py new file mode 100644 index 0000000..d84e1a1 --- /dev/null +++ b/hexdump.py @@ -0,0 +1,140 @@ +import sys + +stdch = ( + '␀·········␊··␍··' + '················' + ' !"#$%&\'()*+,-./' + '0123456789:;<=>?' + '@ABCDEFGHIJKLMNO' + 'PQRSTUVWXYZ[\\]^_' + '`abcdefghijklmno' + 'pqrstuvwxyz{|}~·' + '················' + '················' + '················' + '················' + '················' + '················' + '················' + '················' +) + +decch = ( + '␀␁␂␃␄␅␆␇␈␉␊␋␌␍␎␏' + '␐␑␒␓␔␕␖␗␘␙␚·····' + '␠!"#$%&\'()*+,-./' + '0123456789:;<=>?' + '@ABCDEFGHIJKLMNO' + 'PQRSTUVWXYZ[\\]^_' + '`abcdefghijklmno' + 'pqrstuvwxyz{|}~␡' + '················' + '················' + '················' + '················' + '················' + '················' + '················' + '················' +) + +cgach = ( + '□☺☻♥♦♣♠•◘○◙♂♀♪♫☼' + '►◄↕‼¶§▬↨↑↓→←∟↔▲▼' + ' !"#$%&\'()*+,-./' + '0123456789:;<=>?' + '@ABCDEFGHIJKLMNO' + 'PQRSTUVWXYZ[\\]^_' + '`abcdefghijklmno' + 'pqrstuvwxyz{|}~⌂' + 'ÇüéâäàåçêëèïîìÄÅ' + 'ÉæÆôöòûùÿÖÜ¢£¥₧ƒ' + 'áíóúñѪº¿⌐¬½¼¡«»' + '░▒▓│┤╡╢╖╕╣║╗╝╜╛┐' + '└┴┬├─┼╞╟╚╔╩╦╠═╬╧' + '╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀' + 'αßΓπΣσµτΦΘΩδ∞φε∩' + '≡±≥≤⌠⌡÷≈°∙·√ⁿ²■¤' +) + +fluffych = ( + '·☺☻♥♦♣♠•◘○◙♂♀♪♫☼' + '►◄↕‼¶§▬↨↑↓→←∟↔▲▼' + ' !"#$%&\'()*+,-./' + '0123456789:;<=>?' + '@ABCDEFGHIJKLMNO' + 'PQRSTUVWXYZ[\\]^_' + '`abcdefghijklmno' + 'pqrstuvwxyz{|}~⌂' + 'ÇüéâäàåçêëèïîìÄÅ' + 'ÉæÆôöòûùÿÖÜ¢£¥₧ƒ' + 'áíóúñѪº¿⌐¬½¼¡«»' + '░▒▓│┤╡╢╖╕╣║╗╝╜╛┐' + '└┴┬├─┼╞╟╚╔╩╦╠═╬╧' + '╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀' + 'αßΓπΣσµτΦΘΩδ∞φε∩' + '≡±≥≤⌠⌡÷≈°∀∃√ⁿ²■¤' +) + +class HexDumper: + def __init__(self, output, charset=fluffych): + self.offset = 0 + self.last = None + self.elided = False + self.hexes = [] + self.chars = [] + self.charset = charset + self.output = output + + def _spit(self): + if self.chars == self.last: + if not self.elided: + self.output.write('*\n') + self.elided = True + self.hexes = [] + self.chars = [] + return + self.last = self.chars[:] + self.elided = False + + pad = 16 - len(self.chars) + self.hexes += [' '] * pad + + self.output.write('{:08x} '.format(self.offset - len(self.chars))) + self.output.write(' '.join(self.hexes[:8])) + self.output.write(' ') + self.output.write(' '.join(self.hexes[8:])) + self.output.write(' ') + self.output.write(''.join(self.chars)) + self.output.write('\n') + + self.hexes = [] + self.chars = [] + + def add(self, b): + if self.offset and self.offset % 16 == 0: + self._spit() + + if b is None: + h = '⬜' + c = '�' + else: + h = '{:02x}'.format(b) + c = self.charset[b] + self.chars.append(c) + self.hexes.append(h) + + self.offset += 1 + + def done(self): + self._spit() + self.output.write('{:08x}\n'.format(self.offset)) + + +def hexdump(buf, f=sys.stdout, charset=fluffych): + "Print a hex dump of buf" + + h = HexDumper(output=f, charset=charset) + for b in buf: + h.add(b) + h.done() diff --git a/ip.py b/ip.py index 7b3a8d4..0043aaf 100644 --- a/ip.py +++ b/ip.py @@ -13,12 +13,20 @@ try: import pcap except ImportError: warnings.warn("Using slow pure-python pcap library") - import netarch.py_pcap as pcap + from . import py_pcap as pcap import os import cgi import urllib.parse -from netarch import unpack, hexdump -from netarch.trilobytes import TriloBytes +from .hexdump import hexdump +from .trilobytes import TriloBytes + +def unpack(fmt, buf): + """Unpack buf based on fmt, return the remainder.""" + + size = struct.calcsize(fmt) + vals = struct.unpack(fmt, bytes(buf[:size])) + return vals + (buf[size:],) + def unpack_nybbles(byte): return (byte >> 4, byte & 0x0F) @@ -65,7 +73,6 @@ class Frame: p) = unpack('!HHBBH6si6si', p) self.saddr = self.ar_sip self.daddr = self.ar_tip - self.__repr__ = self.__arp_repr__ elif self.eth_type == IP: # IP (self.ihlvers, @@ -146,18 +153,18 @@ class Frame: dst_addr = property(get_dst_addr) def __repr__(self): - return (' %s:%r(%08x) length %d>' % - (self.name, - self.src_addr, self.sport, self.seq, - self.dst_addr, self.dport, self.ack, - len(self.payload))) - - def __arp_repr__(self): - return ' %s(%s)>' % (self.name, - str_of_eth(self.ar_sha), - self.src_addr, - str_of_eth(self.ar_tha), - self.dst_addr) + if self.eth_type == ARP: + return ' %s(%s)>' % (self.name, + str_of_eth(self.ar_sha), + self.src_addr, + str_of_eth(self.ar_tha), + self.dst_addr) + else: + return (' %s:%r(%08x) length %d>' % + (self.name, + self.src_addr, self.sport, self.seq, + self.dst_addr, self.dport, self.ack, + len(self.payload))) class TCP_Recreate: closed = True @@ -360,16 +367,6 @@ class TCP_Resequence: return (xdi, first, gs) - def handle(self, pkt): - """Stub. - - This function will never be called, it is immediately overridden - by __init__. The current value of self.handle is the state. - """ - - raise NotImplementedError() - - def handle_handshake(self, pkt): if not self.first: self.first = pkt