Skip to content

Instantly share code, notes, and snippets.

@Hoikas
Created January 14, 2012 08:46
Show Gist options
  • Save Hoikas/1610737 to your computer and use it in GitHub Desktop.
Save Hoikas/1610737 to your computer and use it in GitHub Desktop.
from hashlib import md5
from optparse import OptionParser # argparse sucks
import struct
import sys
parser = OptionParser()
parser.add_option("-s", "--source", dest="source",
help="SOURCE file containing known good data", metavar="SOURCE",
default="read.dat")
parser.add_option("-o", "--output", dest="output",
help="OUTPUT file containing questionable data", metavar="OUTPUT",
default="write.dat")
def read(source, output, byteCount, le):
hack = {
'Source: ': source.read(byteCount),
'Output: ': output.read(byteCount),
}
for key in hack:
# Helpful with eap's net data
if le:
bo = "<"
else:
bo = ">"
if byteCount == 1:
type = "B"
elif byteCount == 2:
type = "H"
elif byteCount == 4:
type = "I"
elif byteCount == 8:
type = "Q"
data, = struct.unpack(bo + type, hack[key])
print("\t%s %s" % (key, hex(data)))
return True
def _read_safe_string(stream):
info, = struct.unpack("<H", stream.read(2))
info &= ~0xf000
if info == 0:
return ""
buf = stream.read(info)
if (buf[0] & 0x80):
string = ""
for i in range(len(buf)):
string += chr(struct.pack("B", (~buf[i] & 0xFF))[0])
else:
string = str(buf)
return string
def read_safe_string(source, output):
hack = {
'Source: ': source,
'Output: ': output,
}
for key in hack:
string = _read_safe_string(hack[key])
print("\t%s '%s'" % (key, string))
return True
def read_uoid(source, output):
hack = {
'Source: ': source,
'Output: ': output,
}
for key in hack:
stream = hack[key]
cf, = struct.unpack("B", stream.read(1))
# Begin plLocation
pageID, = struct.unpack("<I", stream.read(4))
stream.read(2) # Flags
# End plLocation
# Begin LoadMask
if cf & 0x02:
stream.read(1)
# End LoadMask
pCreId, = struct.unpack("<H", stream.read(2))
objId, = struct.unpack("<I", stream.read(4))
name = _read_safe_string(stream)
if cf & 0x01:
cloneId = struct.unpack("<I", stream.read(4))
clonePlayerId = struct.unpack("<I", stream.read(4))
else:
cloneId = 0
clonePlayerId = 0
if cloneId or clonePlayerId:
print("\t%s [Page:%08X] [pCreId:%04X] [Obj:%s] [CloneId:%i] [ClonePlayer:%i]" % (key, pageID, pCreId, name, cloneId, clonePlayerId))
else:
print("\t%s [Page:%08X] [pCreId:%04X] [Obj:%s]" % (key, pageID, pCreId, name))
return True
def run_cmd(source, output, cmd):
if cmd == "read8()":
# Who cares about BO here?
return read(source, output, 1, True)
elif cmd == "readle16()":
return read(source, output, 2, True)
elif cmd == "readle32()":
return read(source, output, 4, True)
elif cmd == "readle64()":
return read(source, output, 8, True)
elif cmd == "readbe16()":
return read(source, output, 2, False)
elif cmd == "readbe32()":
return read(source, output, 4, False)
elif cmd == "readbe64()":
return read(source, output, 8, False)
elif cmd == "readsafestring()":
return read_safe_string(source, output)
elif cmd == "readuoid()":
return read_uoid(source, output)
else:
print("\tWARNING: I don't know that command!")
return True
if __name__ == "__main__":
(options, args) = parser.parse_args()
try:
source = open(options.source, "rb")
output = open(options.output, "rb")
except:
print("ERROR: Invalid file specified")
sys.exit()
# Quick compare the files
sBuf = source.read()
oBuf = output.read()
if md5(sBuf) == md5(oBuf):
print("Files have equivalent hashes, so they're probably the same...")
sys.exit()
source.seek(0)
output.seek(0)
running = True
while (running):
cmd = input("PyBufDebug> ")
running = run_cmd(source, output, cmd.lower())
source.close()
output.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment