basic hexdumper

This commit is contained in:
Christoph J. Scherr 2023-09-08 14:30:55 +02:00 committed by Christoph J. Scherr
parent 778abfa7cc
commit 61dbf7a500
5 changed files with 177 additions and 29 deletions

View File

@ -3,7 +3,12 @@ This is a list of tasks that would be cool to add.
* Tasks * Tasks
** Basic ** Basic
*** Files *** Files
- ( ) Hex dumper - (-) Hex dumper
- (x) Dump basic files with format
- (x) Dump basic files with chars
- (x) Be able to dump larger files or put out an error
- ( ) Stop reading when read gets blocked /somehow/
- ( ) Install script to system
*** Networking *** Networking
- ( ) Mini curl - ( ) Mini curl
*** Packaging *** Packaging

View File

@ -406,37 +406,84 @@ don't like windows either, so no support for installing stuff on windows.
### A. Hexdumper ### A. Hexdumper
Difficulty: 3/5 Difficulty: 3/5
1. Dump the data of [data/metasyntactic.md](./data/metasyntactic.md) -- In 1. Dump the data of [data/metasyntactic.md](./data/metasyntactic.md) -- In
Hexadecimal. Hexadecimal.
2. Make the dumped Bytes look pretty, something like the example below: 2. Make the dumped Bytes look pretty, something like the example below:
3. Make use of command line arguments to add a help option (triggered with `-h` or
`--help`) and a `-C` or `--chars` option that adds another section that
prints the bytes interpreted as text. Those bytes that have no text
representation should be displayed as `.`. You may use the `argparse` library
to work with the arguments.
<details> <details>
<summary>Hexdump Example Display</summary> <summary>Hexdump Example Display</summary>
`data/metasyntactic.md` looks like this when hexdumped: `data/metasyntactic.md` should look like this when hexdumped:
```text ```text
Line Data Line Data
================================================= =================================================
0000000 ┃ 6f4e 6574 203a 6854 7369 6920 2073 6874 0000000 | 6f4e 6574 203a 6854 7369 6920 2073 6874
0000010 ┃ 2065 6957 696b 6570 6964 2061 6170 6567 0000010 | 2065 6957 696b 6570 6964 2061 6170 6567
0000020 ┃ 6620 726f 6d20 7465 7361 6e79 6174 7463 0000020 | 6620 726f 6d20 7465 7361 6e79 6174 7463
0000030 ┃ 6369 7620 7261 6169 6c62 7365 6920 206e 0000030 | 6369 7620 7261 6169 6c62 7365 6920 206e
0000040 ┃ 6e45 6c67 7369 2c68 3220 3230 2d33 3930 0000040 | 6e45 6c67 7369 2c68 3220 3230 2d33 3930
0000050 ┃ 302d 2e35 4620 6e69 2064 6874 0a65 7075 0000050 | 302d 2e35 4620 6e69 2064 6874 0a65 7075
0000060 ┃ 7420 206f 6164 6574 6f20 6972 6967 616e 0000060 | 7420 206f 6164 6574 6f20 6972 6967 616e
0000070 ┃ 206c 685b 7265 5d65 6828 7474 7370 2f3a 0000070 | 206c 685b 7265 5d65 6828 7474 7370 2f3a
0000080 ┃ 652f 2e6e 6977 696b 6570 6964 2e61 726f 0000080 | 652f 2e6e 6977 696b 6570 6964 2e61 726f
0000090 ┃ 2f67 6977 696b 4d2f 7465 7361 6e79 6174 0000090 | 2f67 6977 696b 4d2f 7465 7361 6e79 6174
00000a0 ┃ 7463 6369 765f 7261 6169 6c62 2965 0a2e 00000a0 | 7463 6369 765f 7261 6169 6c62 2965 0a2e
00000b0 ┃ 230a 4d20 7465 7361 6e79 6174 7463 6369 00000b0 | 230a 4d20 7465 7361 6e79 6174 7463 6369
00000c0 ┃ 7620 7261 6169 6c62 0a65 230a 2023 6f54 00000c0 | 7620 7261 6169 6c62 0a65 230a 2023 6f54
00000d0 ┃ 6c6f 0a73 460a 6f72 206d 6957 696b 6570 00000d0 | 6c6f 0a73 460a 6f72 206d 6957 696b 6570
00000e0 ┃ 6964 2c61 7420 6568 6620 6572 2065 6e65 00000e0 | 6964 2c61 7420 6568 6620 6572 2065 6e65
00000f0 ┃ 7963 6c63 706f 6465 6169 540a 6968 2073 00000f0 | 7963 6c63 706f 6465 6169 540a 6968 2073
0000100 ┃ 7261 6974 6c63 2065 7369 6120 6f62 7475 0000100 | 7261 6974 6c63 2065 7369 6120 6f62 7475
0000110 ┃ 6d20 7465 7361 6e79 6174 7463 6369 7620 0000110 | 6d20 7465 7361 6e79 6174 7463 6369 7620
...
```
And like this when hexdumped with `-C`:
```text
Line Data Text
======================================================================
0000000 | 6f4e 6574 203a 6854 7369 6920 2073 6874 |Note: This is th|
0000010 | 2065 6957 696b 6570 6964 2061 6170 6567 |e Wikipedia page|
0000020 | 6620 726f 6d20 7465 7361 6e79 6174 7463 | for metasyntact|
0000030 | 6369 7620 7261 6169 6c62 7365 6920 206e |ic variables in |
0000040 | 6e45 6c67 7369 2c68 3220 3230 2d33 3930 |English, 2023-09|
0000050 | 302d 2e35 4620 6e69 2064 6874 0a65 7075 |-05. Find the.up|
0000060 | 7420 206f 6164 6574 6f20 6972 6967 616e | to date origina|
0000070 | 206c 685b 7265 5d65 6828 7474 7370 2f3a |l [here](https:/|
0000080 | 652f 2e6e 6977 696b 6570 6964 2e61 726f |/en.wikipedia.or|
0000090 | 2f67 6977 696b 4d2f 7465 7361 6e79 6174 |g/wiki/Metasynta|
00000a0 | 7463 6369 765f 7261 6169 6c62 2965 0a2e |ctic_variable)..|
00000b0 | 230a 4d20 7465 7361 6e79 6174 7463 6369 |.# Metasyntactic|
00000c0 | 7620 7261 6169 6c62 0a65 230a 2023 6f54 | variable..## To|
00000d0 | 6c6f 0a73 460a 6f72 206d 6957 696b 6570 |ols..From Wikipe|
00000e0 | 6964 2c61 7420 6568 6620 6572 2065 6e65 |dia, the free en|
00000f0 | 7963 6c63 706f 6465 6169 540a 6968 2073 |cyclopedia.This |
... ...
``` ```
</details> </details>
<details>
<summary>Hints</summary>
</details>
<details>
<summary>Solution</summary>
[Code Example](./src/hexdumper.py)
</details>
### B. Packaging your hexdumper
1. Install `pip`, on debian based systems you can do that with `apt-get install
python3-pip`.

0
src/caesar.py Normal file → Executable file
View File

104
src/hexdumper.py Executable file
View File

@ -0,0 +1,104 @@
#!/usr/bin/env python3
import argparse
import os
import sys
# 2**30 bytes aka 1 Mebibyte
MAX_SIZE: int = 0x100000
def humanbytes(B):
"""Return the given bytes as a human friendly KB, MB, GB, or TB string."""
B = float(B)
KB = float(1024)
MB = float(KB ** 2) # 1,048,576
GB = float(KB ** 3) # 1,073,741,824
TB = float(KB ** 4) # 1,099,511,627,776
if B < KB:
return '{0} {1}'.format(B,'Bytes' if 0 == B > 1 else 'Byte')
elif KB <= B < MB:
return '{0:.2f} KB'.format(B / KB)
elif MB <= B < GB:
return '{0:.2f} MB'.format(B / MB)
elif GB <= B < TB:
return '{0:.2f} GB'.format(B / GB)
elif TB <= B:
return '{0:.2f} TB'.format(B / TB)
def main():
"""Dump a file"""
# arg parsing
parser = argparse.ArgumentParser(
prog="hexer",
description="Dumps data as hex"
)
parser.add_argument("file")
parser.add_argument("-c", "--chars", action="store_true")
args = parser.parse_args()
# open file
try:
file = open(args.file, "rb")
except Exception as e:
print(f"Could not open file '{args.file}': {e}")
sys.exit(1)
# check if the file has a reasonable size to dump
if 0 != os.path.getsize(args.file) > MAX_SIZE:
print(f"""The file you are trying to dump is larger than 1M.\n\
Actual size: {humanbytes(os.path.getsize(args.file))}\nrefusing to dump""")
sys.exit(2)
# print header
if args.chars:
print("Line Data Text")
print('=' * 68)
else:
print(f"Line Data")
print('=' * 48)
# every line should contain 16 bytes, so we need a loop that get's 16 bytes
# and then works with them
next: bytes = bytes(16)
index: int = 0
while len(next) == 16:
next = file.read(16)
if len(next) == 0:
# no data left to read
break
line: str = f"{index:07x} | "
# actual hexdumping
for i in range(16):
if i % 2 == 0:
if len(next) > i+1:
line += f"{next[i]:02x}{next[i+1]:02x} "
elif len(next) > i:
line += f"{next[i]:02x} "
else:
line += " "
else: continue
# if chars is enabled, print chars
if args.chars:
line += "| "
for b in next:
# special case for newline
if b == 0x0a:
line+= '' # official unicode symbol representing newlines
# only print regular characters
elif b > 0x20 and b < 0x7e:
line += chr(b)
elif b == 0x20:
line += '\u2420'
else:
line += '.'
print(line)
index += 16
if __name__ == "__main__":
main()

View File

@ -1,8 +0,0 @@
#!/usr/bin/env python3
import sys
def main():
# parse args
if __name__ == "__main__":
main()