From 801362d448dc5d1b65bd17790f39abef0ec2f4bb Mon Sep 17 00:00:00 2001 From: Alex Maestas Date: Wed, 26 Jun 2024 22:51:57 +0000 Subject: [PATCH 1/5] factor out the dump-line generation --- yxd.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/yxd.py b/yxd.py index 2e10c7b..365ad41 100644 --- a/yxd.py +++ b/yxd.py @@ -34,6 +34,17 @@ def styleDump(): else: print() +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): """ Dump hex. @@ -103,18 +114,10 @@ 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 quiet: + print(line, end="") # the line comes from makeDumpLine with a newline if it needs one + hexDumpOut += line offs = offs + blockSize except Exception as e: print(f"yxd.dump: {e}") From 7314183342c75c04ec5bdb854de33391bf05552b Mon Sep 17 00:00:00 2001 From: Alex Maestas Date: Wed, 26 Jun 2024 22:52:29 +0000 Subject: [PATCH 2/5] implement a somewhat-workable autoskip mode --- yxd.py | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/yxd.py b/yxd.py index 365ad41..bb6c148 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") @@ -45,7 +46,7 @@ def makeDumpLine(outFormat, hexOut, offsetOut, bAsc): else: return f"{offsetOut}{hexOut}{bAsc}\n" -def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): +def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False,autoSkip=False): """ Dump hex. @@ -66,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 @@ -81,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 = "" @@ -92,7 +97,13 @@ 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 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 "" @@ -115,10 +126,19 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False): hexOut += f"{hb[12]}{hb[13]} " hexOut += f"{hb[14]}{hb[15]}{dumpSEP2}" line = makeDumpLine(outFormat, hexOut, offsetOut, bAsc) - if not quiet: + if not autoSkip and not quiet: print(line, end="") # the line comes from makeDumpLine with a newline if it needs one + else: + if lastChunk is None or not thisChunkAllNulls: + autoSkipped = False + print(line, end="") + elif thisChunkAllNulls and lastChunkAllNulls: + if not autoSkipped: + print("*") + autoSkipped = True hexDumpOut += line offs = offs + blockSize + lastChunk = bChunk except Exception as e: print(f"yxd.dump: {e}") if outFormat == "ps": @@ -302,7 +322,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 @@ -312,6 +332,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): @@ -323,7 +344,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): @@ -363,7 +384,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: From f4930592155e75419ebddead37b49a48cd45934b Mon Sep 17 00:00:00 2001 From: Alex Maestas Date: Wed, 26 Jun 2024 22:52:49 +0000 Subject: [PATCH 3/5] fix up some textual nitpicks --- yxd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yxd.py b/yxd.py index bb6c148..b91a792 100644 --- a/yxd.py +++ b/yxd.py @@ -19,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(): """ @@ -76,7 +76,7 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False,a """ 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 @@ -395,4 +395,4 @@ def main(): yxdd.dump() if __name__ == '__main__': - main() \ No newline at end of file + main() From ec9c14038cd5cf4a2ac4c9e39d05fea623b38993 Mon Sep 17 00:00:00 2001 From: Alex Maestas Date: Wed, 26 Jun 2024 23:21:48 +0000 Subject: [PATCH 4/5] fix up alternating between all-nulls and not-all-nulls --- yxd.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/yxd.py b/yxd.py index b91a792..cc21b48 100644 --- a/yxd.py +++ b/yxd.py @@ -99,6 +99,8 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False,a 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 @@ -128,14 +130,16 @@ def dump(inBytes,baseAddr=0,dataLen=0,blockSize=16,outFormat="xxd",quiet=False,a 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 - else: - if lastChunk is None or not thisChunkAllNulls: - autoSkipped = False + elif not quiet: + if lastChunk is None: print(line, end="") - elif thisChunkAllNulls and lastChunkAllNulls: + elif lastChunkAllNulls and thisChunkAllNulls: if not autoSkipped: print("*") - autoSkipped = True + autoSkipped = True + else: + autoSkipped = False + print(line, end="") hexDumpOut += line offs = offs + blockSize lastChunk = bChunk From d5971059674a323e07a475a59eb44fa06742f034 Mon Sep 17 00:00:00 2001 From: Alex Maestas Date: Wed, 26 Jun 2024 23:35:09 +0000 Subject: [PATCH 5/5] force autoskip mode off when doing a postscript dump (immiscible options) --- yxd.py | 1 + 1 file changed, 1 insertion(+) diff --git a/yxd.py b/yxd.py index cc21b48..705bbde 100644 --- a/yxd.py +++ b/yxd.py @@ -372,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