From d1fb8b3760e956bcd430145b245c56e67edf89c3 Mon Sep 17 00:00:00 2001 From: Zeecka Date: Wed, 10 Dec 2025 22:23:54 +0100 Subject: [PATCH] Lint --- aperisolve/analyzers/binwalk.py | 2 +- aperisolve/analyzers/image_resize.py | 172 ++++++++++++++++++--------- 2 files changed, 117 insertions(+), 57 deletions(-) diff --git a/aperisolve/analyzers/binwalk.py b/aperisolve/analyzers/binwalk.py index 908f713..32d6fec 100644 --- a/aperisolve/analyzers/binwalk.py +++ b/aperisolve/analyzers/binwalk.py @@ -43,7 +43,7 @@ def analyze_binwalk(input_img: Path, output_dir: Path) -> None: # Remove the extracted directory if extracted_dir.exists(): shutil.rmtree(extracted_dir) - + if len(stderr) > 0: err = { "binwalk": { diff --git a/aperisolve/analyzers/image_resize.py b/aperisolve/analyzers/image_resize.py index 1a8f5e7..05d3645 100644 --- a/aperisolve/analyzers/image_resize.py +++ b/aperisolve/analyzers/image_resize.py @@ -1,7 +1,6 @@ """Image size bruteforcer for common PNG sizes.""" import zlib -import shutil from pathlib import Path from .utils import update_data @@ -10,75 +9,128 @@ EXPECTED_SIZES = [ # ------------------------- # ICONS (Square) # ------------------------- - (16, 16), (20, 20), (24, 24), (28, 28), - (32, 32), (48, 48), (64, 64), (72, 72), - (96, 96), (128, 128), (192, 192), (256, 256), - (384, 384), (512, 512), (768, 768), (1024, 1024), - (1536, 1536), (2048, 2048), (4096, 4096), - + (16, 16), + (20, 20), + (24, 24), + (28, 28), + (32, 32), + (48, 48), + (64, 64), + (72, 72), + (96, 96), + (128, 128), + (192, 192), + (256, 256), + (384, 384), + (512, 512), + (768, 768), + (1024, 1024), + (1536, 1536), + (2048, 2048), + (4096, 4096), # ------------------------- # 1:1 Square (General) # ------------------------- - (300, 300), (500, 500), (800, 800), (1000, 1000), - (1500, 1500), (2000, 2000), (2500, 2500), (3000, 3000), - + (300, 300), + (500, 500), + (800, 800), + (1000, 1000), + (1500, 1500), + (2000, 2000), + (2500, 2500), + (3000, 3000), # ------------------------- # 4:3 Aspect (Classic Screens) # ------------------------- - (320, 240), (640, 480), (800, 600), (960, 720), - (1024, 768), (1280, 960), (1600, 1200), (2048, 1536), - (2560, 1920), (3200, 2400), (4096, 3072), - + (320, 240), + (640, 480), + (800, 600), + (960, 720), + (1024, 768), + (1280, 960), + (1600, 1200), + (2048, 1536), + (2560, 1920), + (3200, 2400), + (4096, 3072), # ------------------------- # 3:2 Aspect (Photography) # ------------------------- - (600, 400), (900, 600), (1200, 800), (1500, 1000), - (1800, 1200), (2400, 1600), (3000, 2000), (3600, 2400), - (4500, 3000), (6000, 4000), - + (600, 400), + (900, 600), + (1200, 800), + (1500, 1000), + (1800, 1200), + (2400, 1600), + (3000, 2000), + (3600, 2400), + (4500, 3000), + (6000, 4000), # ------------------------- # 16:9 Aspect (Video / Web) # ------------------------- - (426, 240), (640, 360), (854, 480), (960, 540), - (1280, 720), (1366, 768), (1600, 900), (1920, 1080), - (2560, 1440), (3200, 1800), (3440, 1935), (3840, 2160), - (5120, 2880), (7680, 4320), (10240, 5760), - + (426, 240), + (640, 360), + (854, 480), + (960, 540), + (1280, 720), + (1366, 768), + (1600, 900), + (1920, 1080), + (2560, 1440), + (3200, 1800), + (3440, 1935), + (3840, 2160), + (5120, 2880), + (7680, 4320), + (10240, 5760), # ------------------------- # 16:10 Aspect (Laptops) # ------------------------- - (1280, 800), (1440, 900), (1680, 1050), - (1920, 1200), (2560, 1600), (2880, 1800), - (3840, 2400), (5120, 3200), - + (1280, 800), + (1440, 900), + (1680, 1050), + (1920, 1200), + (2560, 1600), + (2880, 1800), + (3840, 2400), + (5120, 3200), # ------------------------- # Mobile Portrait (9:16) # ------------------------- - (720, 1280), (1080, 1920), (1440, 2560), - (2160, 3840), (1440, 2960), (1080, 2400), - (1170, 2532), (1284, 2778), (1290, 2796), - + (720, 1280), + (1080, 1920), + (1440, 2560), + (2160, 3840), + (1440, 2960), + (1080, 2400), + (1170, 2532), + (1284, 2778), + (1290, 2796), # ------------------------- # Social Media Sizes # ------------------------- # Instagram - (1080, 1080), (1080, 1350), (1080, 1920), - + (1080, 1080), + (1080, 1350), + (1080, 1920), # Facebook - (1200, 628), (1200, 1200), - + (1200, 628), + (1200, 1200), # Twitter/X - (1200, 675), (1500, 500), - + (1200, 675), + (1500, 500), # YouTube Thumbnails - (1280, 720), (1920, 1080), - + (1280, 720), + (1920, 1080), # ------------------------- # Banners / Headers # ------------------------- - (1600, 500), (1920, 500), (2560, 700), - (3000, 1000), (3840, 1200), - + (1600, 500), + (1920, 500), + (2560, 700), + (3000, 1000), + (3840, 1200), # ------------------------- # Print-like Digital Sizes # ------------------------- @@ -87,10 +139,12 @@ EXPECTED_SIZES = [ (3508, 4961), # A3 @ 300 DPI (4961, 7016), # A2 @ 300 DPI (7016, 9933), # A1 @ 300 DPI - ] -def calc_checksum(header_chunk, width_bytes, height_bytes): + +def calc_checksum( + header_chunk: bytearray, width_bytes: bytearray, height_bytes: bytearray +) -> bytearray: """ Calculates the CRC32 of the IHDR chunk with new dimensions. header_chunk: The full IHDR chunk (Type + Data). @@ -99,7 +153,8 @@ def calc_checksum(header_chunk, width_bytes, height_bytes): new_header = header_chunk[:4] + width_bytes + height_bytes + header_chunk[12:] # Calculate CRC and return as 4 bytes (Big Endian) - return bytearray((zlib.crc32(new_header) & 0xffffffff).to_bytes(4, byteorder='big')) + return bytearray((zlib.crc32(new_header) & 0xFFFFFFFF).to_bytes(4, byteorder="big")) + def analyze_image_resize(input_img: Path, output_dir: Path) -> None: """ @@ -122,20 +177,23 @@ def analyze_image_resize(input_img: Path, output_dir: Path) -> None: b = bytearray(f) # Find IHDR start - IHDR = b.find(b'\x49\x48\x44\x52') + IHDR = b.find(b"\x49\x48\x44\x52") if IHDR == -1: logs.append("Failure: PNG header (IHDR) not found.") - update_data(output_dir, {"image_resize": {"status": "error", "error": "PNG header not found."}}) + update_data( + output_dir, + {"image_resize": {"status": "error", "error": "PNG header not found."}}, + ) return # Calculate Chunk Length (The 4 bytes BEFORE IHDR tag) - chunk_length = int.from_bytes((b[IHDR- 4: IHDR]), byteorder="big") + 4 + chunk_length = int.from_bytes((b[IHDR - 4 : IHDR]), byteorder="big") + 4 # Extract Target CRC (The 4 bytes AFTER the chunk data) - target_crc = b[IHDR + chunk_length:IHDR + chunk_length + 4] + target_crc = b[IHDR + chunk_length : IHDR + chunk_length + 4] # Isolate the header chunk (Type + Data) - header_chunk = b[IHDR:IHDR + chunk_length] + header_chunk = b[IHDR : IHDR + chunk_length] logs.append(f"Target CRC found: 0x{target_crc.hex()}") @@ -146,8 +204,8 @@ def analyze_image_resize(input_img: Path, output_dir: Path) -> None: width, height = size # Convert dimensions to 4-byte Big Endian arrays - width_bytes = bytearray(width.to_bytes(4, byteorder='big')) - height_bytes = bytearray(height.to_bytes(4, byteorder='big')) + width_bytes = bytearray(width.to_bytes(4, byteorder="big")) + height_bytes = bytearray(height.to_bytes(4, byteorder="big")) # Check if this size matches the file's CRC if target_crc == calc_checksum(header_chunk, width_bytes, height_bytes): @@ -162,14 +220,16 @@ def analyze_image_resize(input_img: Path, output_dir: Path) -> None: output_path = output_dir / img_name # Splicing: [Start...IHDR+4] + [W] + [H] + [IHDR+12...End] - full_png_data = b[:IHDR+4] + width_bytes + height_bytes + b[IHDR+12:] + full_png_data = ( + b[: IHDR + 4] + width_bytes + height_bytes + b[IHDR + 12 :] + ) # Write the recovered file to disk with output_path.open("wb") as out_f: out_f.write(full_png_data) recovered_image = Path(output_dir.name) / img_name - break # Stop looking after finding the match + break # Stop looking after finding the match if not match_found: logs.append("Failure: No matching dimensions found.") @@ -178,7 +238,7 @@ def analyze_image_resize(input_img: Path, output_dir: Path) -> None: output_data = { "image_resize": { # Key name must match your module name in AperiSolve "status": "ok", - "output": logs + "output": logs, } } if recovered_image: @@ -187,4 +247,4 @@ def analyze_image_resize(input_img: Path, output_dir: Path) -> None: except Exception as e: update_data(output_dir, {"image_resize": {"status": "error", "error": str(e)}}) - return None \ No newline at end of file + return None