diff --git a/yxd.py b/yxd.py index 2e10c7b..705bbde 100644 --- a/yxd.py +++ b/yxd.py @@ -7,6 +7,7 @@ parser = argparse.ArgumentParser(description="yxd - Yuu's heX Dumper") parser.add_argument('-f', help='File to open', dest='inFile') parser.add_argument('input', help='File to open', nargs='?') +parser.add_argument('-a', help='Autoskip mode', dest='autoSkip', action="store_true") parser.add_argument('-o', help='Offset to start within file', dest='startOffset', type=lambda x: int(x,0) ) parser.add_argument('-s', help='Size of buffer to dump', dest='bufferSize', type=lambda x: int(x,0) ) parser.add_argument('-r', help='Do a reverse hex dump', dest='reverseDump', action="store_true") @@ -18,7 +19,7 @@ parser.add_argument('--style', help='Show Current Hex Style', dest='dumpStyle', action="store_true") parser.add_argument('-v', help='Print Version Info', dest='printVersion', action="store_true") -versionInfo="yxd - Yuu's heX Dumper Version 20230831.0""" +versionInfo="yxd - Yuu's heX Dumper Version 20230831.0" def styleDump(): """ @@ -34,7 +35,18 @@ def styleDump(): else: print() -def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): +def makeDumpLine(outFormat, hexOut, offsetOut, bAsc): + """ + Produce an output line of the given format. + """ + if outFormat == "xx": + return f"{hexOut}; {offsetOut}{bAsc}\n" + elif outFormat == "ps": + return "".join(hexOut.split()) + else: + return f"{offsetOut}{hexOut}{bAsc}\n" + +def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False,autoSkip=False): """ Dump hex. @@ -55,6 +67,8 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): The format of hex dump format to do quiet : bool If true, don't print the output to the terminal + autoSkip : bool + If true, skip lines of nulls. Returns ------- hexDumpOut : str @@ -62,7 +76,7 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): """ dataLen = len(inBytes) if ( dataLen == 0 ) or ( dataLen > len(inBytes) ) else dataLen # Sanity check offs = 0 - hexDumpOut = "" + hexDumpOut = "" # Style dumpBytez = yc.bytez dumpOffstyle = yc.OFFSTYLE @@ -70,6 +84,8 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): dumpSEP1 = yc.SEP1 dumpSEP2 = yc.SEP2 dumpEOA = yc.EOA + lastChunk = None + autoSkipped = lastChunkAllNulls = thisChunkAllNulls = False if ( outFormat == "xxd" ) or ( outFormat == "xx" ) or ( outFormat == "ps" ): dumpBytez = {} dumpOffstyle = "" @@ -81,7 +97,15 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): try: hb = [] bAsc = "" + if autoSkip and lastChunk is not None and all(x == 0 for x in lastChunk): + lastChunkAllNulls = True + else: + lastChunkAllNulls = False bChunk = inBytes[offs:offs+blockSize] + if autoSkip and all(x == 0 for x in bChunk) and len(bChunk) == blockSize: + thisChunkAllNulls = True + else: + thisChunkAllNulls = False chunkBytes = 0 for b in bChunk: bFmt = f"{dumpBytez[b]}" if b in dumpBytez.keys() else "" @@ -103,19 +127,22 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): hexOut += f"{hb[10]}{hb[11]} " hexOut += f"{hb[12]}{hb[13]} " hexOut += f"{hb[14]}{hb[15]}{dumpSEP2}" - if outFormat == "xx": - if quiet == False: - print(f"{hexOut}; {offsetOut}{bAsc}") - hexDumpOut += f"{hexOut}; {offsetOut}{bAsc}\n" - elif outFormat == "ps": - if quiet == False: - print("".join(hexOut.split()),end="") - hexDumpOut += "".join(hexOut.split()) - else: - if quiet == False: - print(f"{offsetOut}{hexOut}{bAsc}") - hexDumpOut += f"{offsetOut}{hexOut}{bAsc}\n" + line = makeDumpLine(outFormat, hexOut, offsetOut, bAsc) + if not autoSkip and not quiet: + print(line, end="") # the line comes from makeDumpLine with a newline if it needs one + elif not quiet: + if lastChunk is None: + print(line, end="") + elif lastChunkAllNulls and thisChunkAllNulls: + if not autoSkipped: + print("*") + autoSkipped = True + else: + autoSkipped = False + print(line, end="") + hexDumpOut += line offs = offs + blockSize + lastChunk = bChunk except Exception as e: print(f"yxd.dump: {e}") if outFormat == "ps": @@ -299,7 +326,7 @@ class yxd: reverseDump(): do a reverse hex dump """ - def __init__(self, binData, amount=0, baseAddr=0, outFormat="xxd", color="default", blockSize=16, offset=0, quiet=False ): + def __init__(self, binData, amount=0, baseAddr=0, outFormat="xxd", color="default", blockSize=16, offset=0, quiet=False, autoSkip=False): self.binData = binData self.dataLen = len(binData) self.baseAddr = baseAddr @@ -309,6 +336,7 @@ def __init__(self, binData, amount=0, baseAddr=0, outFormat="xxd", color="defaul self.blockSize = blockSize self.amount = amount self.quiet = quiet + self.autoSkip = autoSkip if quiet != True: self.dump() def styleDump(self): @@ -320,7 +348,7 @@ def styleDump(self): else: print() def dump(self): - return dump(self.binData,self.baseAddr,self.dataLen,self.blockSize,self.outFormat) + return dump(self.binData,self.baseAddr,self.dataLen,self.blockSize,self.outFormat,autoSkip=self.autoSkip) def genPythonScript(self): genPythonScript(self.binData) def genShellcode(self): @@ -344,6 +372,7 @@ def main(): if args.xxFormat: hexStyle = "xx" if args.psFormat: + args.autoSkip = False hexStyle = "ps" bufferSize = args.bufferSize if args.bufferSize else 0 @@ -360,7 +389,7 @@ def main(): binData = sys.stdin.buffer.read() binSize = len(binData) - yxdd = yxd(binData, baseAddr=startOffset, outFormat=hexStyle, quiet=True) + yxdd = yxd(binData, baseAddr=startOffset, outFormat=hexStyle, quiet=True, autoSkip=args.autoSkip) if args.genPythonScript: yxdd.genPythonScript() elif args.genShellcode: @@ -371,4 +400,4 @@ def main(): yxdd.dump() if __name__ == '__main__': - main() \ No newline at end of file + main()