diff --git a/.gitignore b/.gitignore
index f056d4c..f52d357 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,7 @@ __pycache__/*
python-*.exe
build/*
dist/*
+Encoded/*
+Decoded/*
decoder*.spec
encoder*.spec
\ No newline at end of file
diff --git a/calc.html b/Examples/calc.html
similarity index 100%
rename from calc.html
rename to Examples/calc.html
diff --git a/example.html b/Examples/example.html
similarity index 100%
rename from example.html
rename to Examples/example.html
diff --git a/exampleCoffeeHouse.html b/Examples/exampleCoffeeHouse.html
similarity index 99%
rename from exampleCoffeeHouse.html
rename to Examples/exampleCoffeeHouse.html
index ad30cd7..1d95ab7 100644
--- a/exampleCoffeeHouse.html
+++ b/Examples/exampleCoffeeHouse.html
@@ -1,58 +1,58 @@
-
-
-
- The Coffee House
-
-
-
-
-
-
-
-
-
-
About Us
-
We are a cozy coffee shop located in the heart of the city. Our mission is to provide our customers with high-quality coffee, baked goods, and a welcoming atmosphere.
We are a cozy coffee shop located in the heart of the city. Our mission is to provide our customers with high-quality coffee, baked goods, and a welcoming atmosphere.
+
+
+
+
Our Menu
+
+
Espresso
+
Americano
+
Cappuccino
+
Latte
+
Mocha
+
Tea
+
Baked Goods
+
+
+
+
Contact Us
+
+
+
+
+
\ No newline at end of file
diff --git a/decoder.py b/decoder.py
index 8a0356d..0510fe8 100644
--- a/decoder.py
+++ b/decoder.py
@@ -6,6 +6,7 @@
import gzip
import io
from urllib.parse import unquote
+from readchar import readkey, key
import magic
@@ -22,7 +23,9 @@ def read_file(input_file, mode='rb', encoding=None):
return content
def write_file(output_file, content, mode='w', encoding=None):
- with open(output_file, mode, encoding=encoding) as f:
+ decoded_dir = "Decoded"
+ decoded_file_path = f"{decoded_dir}/{output_file}"
+ with open(decoded_file_path, mode, encoding=encoding) as f:
f.write(content)
class CustomHTMLParser(HTMLParser):
@@ -38,6 +41,7 @@ def parse_decoding_arguments():
parser.add_argument('input_html_file', type=str, help='Input HTML file')
parser.add_argument('output_file', type=str, help='Output file')
parser.add_argument('--cyberchef', action='store_true', help='Save CyberChef output to a file')
+ parser.add_argument('--step_mode', action='store_true', help='Decoder will do one step at a time and show what happens at each step')
return parser.parse_args()
def decode_base64(encoded_content):
@@ -85,10 +89,19 @@ def create_cyberchef_ops_json(encoding_steps):
return json.dumps(cyberchef_ops, indent=2)
-def decode_random_encoding(script_content):
+def step_mode(decoded_content_snippet, current_encoding_step, next_encoding_step):
+ print(f"\nCurrent encoding step: {current_encoding_step} -> {next_encoding_step}")
+ print(f"Decoded content snippet (first 500 characters): \n{decoded_content_snippet[:500]}")
+ print("Press ENTER key to proceed to the next decoding step...")
+ while True:
+ k = readkey()
+ if k == key.ENTER:
+ break
+
+def decode_random_encoding(script_content, step_mode_flag):
decoded_content = script_content
counters = {"base64": 0, "unicode": 0, "uri": 0, "gzip": 0}
- encoding_steps = []
+ encoding_steps = ["Encoded content"]
while True:
updated = False
@@ -99,6 +112,8 @@ def decode_random_encoding(script_content):
decoded_str = decode_base64(b64_match.group(2)).decode('utf-8')
decoded_content = decoded_content.replace(b64_match.group(0), decoded_str)
counters["base64"] += 1
+ if step_mode_flag:
+ step_mode(decoded_str, ''.join(encoding_steps[-1:]), "base64")
encoding_steps.append("base64")
updated = True
@@ -110,6 +125,8 @@ def decode_random_encoding(script_content):
if decoded_str != encoded_str:
decoded_content = decoded_content.replace(unicode_match.group(0), decoded_str)
counters["unicode"] += 1
+ if step_mode_flag:
+ step_mode(decoded_str, ''.join(encoding_steps[-1:]), "uricode")
encoding_steps.append("unicode")
updated = True
else:
@@ -118,6 +135,8 @@ def decode_random_encoding(script_content):
if decoded_uri_str != encoded_str:
decoded_content = decoded_content.replace(unicode_match.group(0), decoded_uri_str)
counters["uri"] += 1
+ if step_mode_flag:
+ step_mode(decoded_str, ''.join(encoding_steps[-1:]), "uri")
encoding_steps.append("uri")
updated = True
except Exception as e:
@@ -129,10 +148,14 @@ def decode_random_encoding(script_content):
decoded_str = decode_and_unzip_base64(gzip_match.group(1))
decoded_content = decoded_content.replace(gzip_match.group(0), decoded_str)
counters["gzip"] += 1
+ if step_mode_flag:
+ step_mode(decoded_str, ''.join(encoding_steps[-1:]), "gzip")
encoding_steps.append("gzip")
updated = True
if not updated:
+ print("decoded_content snippet:", decoded_content[:200]) # Print the first 200 characters of the decoded content
+ print("\nNo more encodings detected. Decoding complete.")
break
for key, value in counters.items():
@@ -144,7 +167,9 @@ def decode_random_encoding(script_content):
def scan_for_mime_types(output_file):
mime = magic.Magic(mime=True)
- with open(output_file, "rb") as f:
+ decoded_dir = "Decoded"
+ decoded_file_path = f"{decoded_dir}/{output_file}"
+ with open(decoded_file_path, "rb") as f:
content = f.read()
mime_type = mime.from_buffer(content)
print(f"MIME Type: {mime_type}")
@@ -186,7 +211,9 @@ def scan_for_mime_types(output_file):
def scan_for_script_tags(output_file):
mime = magic.Magic(mime=True)
- with open(output_file, "rb") as f:
+ decoded_dir = "Decoded"
+ decoded_file_path = f"{decoded_dir}/{output_file}"
+ with open(decoded_file_path, "rb") as f:
content = f.read()
mime_type = mime.from_buffer(content)
@@ -214,7 +241,7 @@ def scan_for_script_tags(output_file):
def decode_main(args):
script_content = extract_script_content(args.input_html_file)
- decoded_content, encoding_steps = decode_random_encoding(script_content)
+ decoded_content, encoding_steps = decode_random_encoding(script_content, args.step_mode)
write_file(args.output_file, decoded_content, mode='w', encoding='utf-8')
scan_for_mime_types(args.output_file)
scan_for_script_tags(args.output_file)
diff --git a/encoder.py b/encoder.py
index d452dde..068c258 100644
--- a/encoder.py
+++ b/encoder.py
@@ -17,9 +17,13 @@ def read_file(input_file, mode='rb', encoding=None):
content = f.read()
return content
-def write_file(output_file, content, mode='w', encoding=None):
- with open(output_file, mode, encoding=encoding) as f:
+def write_file(output_file, content, mode='w', encoding=None):
+ encoded_dir = "Encoded"
+ output_file_path = f"{encoded_dir}/{output_file}"
+ with open(output_file_path, mode, encoding=encoding) as f:
f.write(content)
+ print(f"Encoded content written to: {output_file_path}")
+ f.close()
def gzip_content(content):
compressed = gzip.compress(content)
@@ -83,18 +87,21 @@ def gzip_wrap_in_html(encoded_content):
def random_encoding(content):
html_content = content.decode('utf-8')
encoding_steps = random.randint(1, 10)
+ encoding_patterns = {
+ 'None': ('base64', 'unicode', 'uri'),
+ 'base64': ('unicode', 'uri'),
+ 'unicode': ('base64', 'uri'),
+ 'uri': ('base64', 'unicode')
+ }
prev_encoding = None
- prev_prev_encoding = None
-
+ encoding_flow = []
+
for _ in range(encoding_steps):
- encoding_types = ['base64', 'unicode', 'uri']
- if prev_encoding == 'unicode' and prev_prev_encoding != 'uri':
- encoding_type = random.choice(['base64', 'unicode'])
- elif prev_encoding == 'uri' and prev_prev_encoding != 'unicode':
- encoding_type = random.choice(['base64', 'uri'])
+ if prev_encoding is None:
+ encoding_type = random.choice(encoding_patterns.get('None'))
else:
- encoding_type = random.choice(encoding_types)
-
+ encoding_type = random.choice(encoding_patterns.get(prev_encoding))
+
if encoding_type == 'base64':
content = encode_base64(content)
html_content = base64_wrap_in_html(content)
@@ -108,8 +115,11 @@ def random_encoding(content):
html_content = unicode_wrap_in_html(content)
content = html_content.encode('utf-8')
- prev_prev_encoding = prev_encoding
prev_encoding = encoding_type
+ encoding_flow.append(encoding_type)
+
+ print(f"Total encoding steps: {encoding_steps}")
+ print(f"Random encoding flow: original -> {' -> '.join(encoding_flow)}")
return html_content
def main(args):
@@ -140,3 +150,4 @@ def main(args):
if __name__ == '__main__':
main(parse_arguments())
+
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index bc3665e..8b0d76a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
argparse
-python-magic
\ No newline at end of file
+python-magic
+readchar
\ No newline at end of file