mirror of https://github.com/dirtbags/netarch.git
Integrate GapString and a few tweaks
This commit is contained in:
parent
473d1fc440
commit
9d487edfb3
99
__init__.py
99
__init__.py
|
@ -10,47 +10,82 @@ def unpack(fmt, buf):
|
|||
"""Unpack buf based on fmt, return the rest as a string."""
|
||||
|
||||
size = struct.calcsize(fmt)
|
||||
vals = struct.unpack(fmt, buf[:size])
|
||||
vals = struct.unpack(fmt, str(buf[:size]))
|
||||
return vals + (buf[size:],)
|
||||
|
||||
|
||||
def to_printable(c):
|
||||
if c in printable:
|
||||
return c
|
||||
elif c == '\0':
|
||||
return '␀'
|
||||
elif c == '\r':
|
||||
return '␍'
|
||||
elif c == '\n':
|
||||
return ''
|
||||
else:
|
||||
return '·'
|
||||
class HexDumper:
|
||||
def __init__(self, fd=sys.stdout):
|
||||
self.fd = fd
|
||||
self.offset = 0
|
||||
self.buf = []
|
||||
|
||||
def _to_printable(self, c):
|
||||
if not c:
|
||||
return '◆'
|
||||
elif c in printable:
|
||||
return c
|
||||
elif c == '\0':
|
||||
return '␀'
|
||||
elif c == '\r':
|
||||
return '␍'
|
||||
elif c == '\n':
|
||||
return ''
|
||||
else:
|
||||
return '·'
|
||||
|
||||
|
||||
def _flush(self):
|
||||
if not self.buf:
|
||||
return
|
||||
|
||||
o = []
|
||||
for c in self.buf:
|
||||
if c:
|
||||
o.append('%02x' % ord(c))
|
||||
else:
|
||||
o.append('--')
|
||||
o += ([' '] * (16 - len(self.buf)))
|
||||
p = [self._to_printable(c) for c in self.buf]
|
||||
|
||||
self.fd.write('%08x ' % self.offset)
|
||||
|
||||
self.fd.write(' '.join(o[:8]))
|
||||
self.fd.write(' ')
|
||||
self.fd.write(' '.join(o[8:]))
|
||||
|
||||
self.fd.write(' ║')
|
||||
|
||||
self.fd.write(''.join(p))
|
||||
|
||||
self.fd.write('║\n')
|
||||
|
||||
self.buf = []
|
||||
self.offset += 16
|
||||
|
||||
def dump_chr(self, c):
|
||||
self.buf.append(c)
|
||||
if len(self.buf) == 16:
|
||||
self._flush()
|
||||
|
||||
def dump_drop(self):
|
||||
self.buf.append(None)
|
||||
if len(self.buf) == 16:
|
||||
self._flush()
|
||||
|
||||
def finish(self):
|
||||
self._flush()
|
||||
self.fd.write('%08x\n' % self.offset)
|
||||
|
||||
|
||||
def hexdump(buf, f=sys.stdout):
|
||||
"Print a hex dump of buf"
|
||||
|
||||
offset = 0
|
||||
d = HexDumper()
|
||||
|
||||
while buf:
|
||||
s = buf[:16]
|
||||
o = [('%02x' % ord(c)) for c in s] + ([' '] * (16 - len(s)))
|
||||
p = [to_printable(c) for c in s]
|
||||
|
||||
f.write('%08x ' % offset)
|
||||
|
||||
f.write(' '.join(o[:8]))
|
||||
f.write(' ')
|
||||
f.write(' '.join(o[8:]))
|
||||
|
||||
f.write(' ║')
|
||||
|
||||
f.write(''.join(p))
|
||||
|
||||
f.write('║\n')
|
||||
|
||||
buf = buf[16:]
|
||||
offset += 16
|
||||
for c in buf:
|
||||
d.dump_chr(c)
|
||||
d.finish()
|
||||
|
||||
|
||||
def cstring(buf):
|
||||
|
|
|
@ -186,11 +186,10 @@ tabula_recta = caesars('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
|||
|
||||
|
||||
def xor(n, txt):
|
||||
out = ''
|
||||
for c in txt:
|
||||
o = ord(c) ^ n
|
||||
out += chr(o)
|
||||
return out
|
||||
if n == 0:
|
||||
return txt
|
||||
out = [(chr(ord(c) ^ n)) for c in txt]
|
||||
return ''.join(out)
|
||||
|
||||
def xors(txt):
|
||||
ret = []
|
||||
|
|
|
@ -48,7 +48,7 @@ class GapString:
|
|||
else:
|
||||
for c in i:
|
||||
d.dump_chr(c)
|
||||
d.flush()
|
||||
d.finish()
|
||||
|
||||
def extend(self, other):
|
||||
self.contents += other.contents
|
||||
|
@ -56,10 +56,14 @@ class GapString:
|
|||
|
||||
def __getslice__(self, start, end):
|
||||
end = min(self.length, end)
|
||||
start = min(self.length, start)
|
||||
|
||||
new = self.__class__(self.drop)
|
||||
new.contents = self.contents[:]
|
||||
new.length = end - start
|
||||
if new.length == 0:
|
||||
return new
|
||||
|
||||
l = self.length - new.length - start
|
||||
|
||||
# Trim off the beginning
|
||||
|
|
48
ip.py
48
ip.py
|
@ -5,6 +5,7 @@ import struct
|
|||
import socket
|
||||
import warnings
|
||||
import heapq
|
||||
import gapstr
|
||||
|
||||
|
||||
def unpack(fmt, buf):
|
||||
|
@ -110,18 +111,13 @@ class Frame:
|
|||
self.dst_addr, self.dport,
|
||||
len(self.payload))
|
||||
|
||||
|
||||
class Chunk:
|
||||
"""Chunk of frames, possibly with gaps.
|
||||
|
||||
Currently, gaps show up as a string of 0x33, ascii '3'.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, seq=None, drop='3'):
|
||||
# chr(0x33) == '3'. If you see a bunch of 3s, in the ascii or
|
||||
# the hex view, suspect a drop.
|
||||
assert len(drop) == 1, "Don't yet support len(drop) > 1"
|
||||
self.drop = drop
|
||||
def __init__(self, seq=None):
|
||||
self.collection = {}
|
||||
self.length = 0
|
||||
self.seq = seq
|
||||
|
@ -130,8 +126,8 @@ class Chunk:
|
|||
def add(self, frame):
|
||||
if not self.first:
|
||||
self.first = frame
|
||||
if self.seq is None:
|
||||
self.seq = frame.seq
|
||||
if self.seq is None:
|
||||
self.seq = frame.seq
|
||||
assert frame.seq >= self.seq, (frame.seq, self.seq)
|
||||
self.collection[frame.seq] = frame
|
||||
end = frame.seq - self.seq + len(frame.payload)
|
||||
|
@ -150,25 +146,35 @@ class Chunk:
|
|||
else:
|
||||
return '<Chunk (no frames)>'
|
||||
|
||||
def __str__(self):
|
||||
s = ''
|
||||
while len(s) < self.length:
|
||||
f = self.collection.get(self.seq + len(s))
|
||||
def gapstr(self, drop='?'):
|
||||
"""Return contents as a GapString"""
|
||||
|
||||
ret = gapstr.GapString(drop)
|
||||
while len(ret) < self.length:
|
||||
f = self.collection.get(self.seq + len(ret))
|
||||
if f:
|
||||
s += f.payload
|
||||
ret.append(f.payload)
|
||||
else:
|
||||
# This is where to fix it for len(drop) > 1.
|
||||
# This is also where to fix big inefficiency for dropped packets.
|
||||
s += self.drop
|
||||
return s
|
||||
# This is where to fix big inefficiency for dropped packets.
|
||||
l = 1
|
||||
while ((len(ret) + l < self.length) and
|
||||
(not (self.seq + len(ret) + l) in self.collection)):
|
||||
l += 1
|
||||
ret.append(l)
|
||||
return ret
|
||||
|
||||
def __str__(self):
|
||||
return str(self.gapstr())
|
||||
|
||||
def extend(self, other):
|
||||
self.seq = min(self.seq or other.seq, other.seq)
|
||||
for frame in other.collection.itervalues():
|
||||
self.add(frame)
|
||||
self.length = self.length + other.length
|
||||
if not self.first:
|
||||
self.first = other.first
|
||||
self.collection.update(other.collection)
|
||||
|
||||
def __add__(self, next):
|
||||
new = self.__class__(self.seq, self.drop)
|
||||
new = self.__class__(self.seq)
|
||||
new.extend(self)
|
||||
new.extend(next)
|
||||
return new
|
||||
|
|
Loading…
Reference in New Issue