From 7acef7d17b95af8b88a7a5d2c947ef2c01da81a8 Mon Sep 17 00:00:00 2001 From: itsme Date: Fri, 9 Jul 2021 17:13:12 +0200 Subject: added largefile support. added 'bankdump' subcommand, which uses 'readrec'. figured out .dat and .tad header bytes. replaced option with separate subcommand: . --- crodump.py | 205 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 153 insertions(+), 52 deletions(-) diff --git a/crodump.py b/crodump.py index 80daab9..148b3cf 100644 --- a/crodump.py +++ b/crodump.py @@ -7,6 +7,7 @@ from hexdump import hexdump, asasc, tohex, unhex, strescape from koddecoder import kodecode from readers import ByteReader import zlib +from collections import defaultdict """ python3 crodump.py crodump chechnya_proverki_ul_2012 @@ -32,23 +33,50 @@ def enumunreferenced(ranges, filesize): class Datafile: """ Represent a single .dat with it's .tad index file """ - def __init__(self, dat, tad, need_decode=False): + def __init__(self, name, dat, tad): + self.name = name self.dat = dat self.tad = tad - self.need_decode = need_decode - + self.readdathdr() self.readtad() self.dat.seek(0, io.SEEK_END) self.datsize = self.dat.tell() + + def readdathdr(self): + self.dat.seek(0) + hdrdata = self.dat.read(19) + + magic, self.hdrunk, self.version, self.encoding, self.blocksize = struct.unpack("<8sH5sHH", hdrdata) + if magic != b"CroFile\x00": + print("unknown magic: ", magic) + raise Exception("not a Crofile") + self.use64bit = self.version == b'01.03' + + # blocksize + # 0040 -> Bank + # 0400 -> Index or Sys + # 0200 -> Stru or Sys + + # encoding + # 0000 + # 0001 --> 'KOD encoded' + # 0002 + # 0003 --> encrypted + def readtad(self): self.tad.seek(0) hdrdata = self.tad.read(2*4) - self.tadhdr = struct.unpack("<2L", hdrdata) + self.nrdeleted, self.firstdeleted = struct.unpack("<2L", hdrdata) indexdata = self.tad.read() - self.tadidx = [ struct.unpack_from("<3L", indexdata, 12*_) for _ in range(len(indexdata)//12) ] + if self.use64bit: + # 01.03 has 64 bit file offsets + self.tadidx = [ struct.unpack_from("" % i) + else: + print("%5d: %s" % (i, toout(args, data))) + else: + if data is None: + xref["None"] += 1 + elif not len(data): + xref["Empty"] += 1 + else: + xref["%02x" % data[0]] += 1 + nerr = 0 + except IndexError: + break + except Exception as e: + print("%5d: <%s>" % (i, e)) + nerr += 1 + if nerr > 5: + break + if args.stats: + print("-- stats --") + for k, v in xref.items(): + print("%5d * %s" % (v, k)) def incdata(data, s): """ @@ -359,9 +432,23 @@ def kod_hexdump(args): def cro_dump(args): """ handle 'crodump' subcommand """ db = Database(args.dbdir) - db.dump(args) +def stru_dump(args): + """ handle 'strudump' subcommand """ + db = Database(args.dbdir) + db.strudump(args) + +def bank_dump(args): + """ hexdump all records """ + if args.maxrecs: + args.maxrecs = int(args.maxrecs, 0) + else: + # an arbitrarily large number. + args.maxrecs = 0xFFFFFFFF + + db = Database(args.dbdir) + db.bankdump(args) def destruct(args): """ @@ -396,21 +483,35 @@ def main(): ko.add_argument('filename', type=str, nargs='?', help="dump either stdin, or the specified file") ko.set_defaults(handler=kod_hexdump) - cro = subparsers.add_parser('crodump', help='CROdumper') - cro.add_argument('--verbose', '-v', action='store_true') - cro.add_argument('--kodecode', '-k', action='store_true') - cro.add_argument('--ascdump', '-a', action='store_true') - cro.add_argument('--nokod', '-n', action='store_true') - cro.add_argument('--struonly', action='store_true') - cro.add_argument('--nodecompress', action='store_false', dest='decompress', default='true') - cro.add_argument('dbdir', type=str) - cro.set_defaults(handler=cro_dump) - - des = subparsers.add_parser('destruct', help='Stru dumper') - des.add_argument('--verbose', '-v', action='store_true') - des.add_argument('--ascdump', '-a', action='store_true') - des.add_argument('--type', '-t', type=int, help='what type of record to destruct') - des.set_defaults(handler=destruct) + p = subparsers.add_parser('crodump', help='CROdumper') + p.add_argument('--verbose', '-v', action='store_true') + p.add_argument('--kodecode', '-k', action='store_true') + p.add_argument('--ascdump', '-a', action='store_true') + p.add_argument('--nokod', '-n', action='store_true') + p.add_argument('--nodecompress', action='store_false', dest='decompress', default='true') + p.add_argument('dbdir', type=str) + p.set_defaults(handler=cro_dump) + + p = subparsers.add_parser('bankdump', help='BANKdumper') + p.add_argument('--verbose', '-v', action='store_true') + p.add_argument('--ascdump', '-a', action='store_true') + p.add_argument('--maxrecs', '-n', type=str, help="max nr or recots to output") + p.add_argument('--stats', action='store_true', help='calc table stats from the first byte of each record') + p.add_argument('dbdir', type=str) + p.set_defaults(handler=bank_dump) + + p = subparsers.add_parser('strudump', help='STRUdumper') + p.add_argument('--verbose', '-v', action='store_true') + p.add_argument('--ascdump', '-a', action='store_true') + p.add_argument('dbdir', type=str) + p.set_defaults(handler=stru_dump) + + + p = subparsers.add_parser('destruct', help='Stru dumper') + p.add_argument('--verbose', '-v', action='store_true') + p.add_argument('--ascdump', '-a', action='store_true') + p.add_argument('--type', '-t', type=int, help='what type of record to destruct') + p.set_defaults(handler=destruct) args = parser.parse_args() -- cgit v1.2.3