import re
import math
from collections import Counter

FILE = "rphost.exe_16460.dmp"

CHUNK_SIZE = 1024 * 1024  # 1MB
TOP_REGIONS = 10
TOP_STRINGS = 5

TEXT_THRESHOLD = 0.4
DATA_THRESHOLD = 0.9
ENTROPY_THRESHOLD = 6.0


def entropy(chunk):
    if not chunk:
        return 0
    counts = Counter(chunk)
    total = len(chunk)
    return -sum((c/total) * math.log2(c/total) for c in counts.values())


print("Loading dump...")
with open(FILE, "rb") as f:
    data = f.read()

print("Analyzing...")

results = []

for i in range(0, len(data), CHUNK_SIZE):
    chunk = data[i:i+CHUNK_SIZE]

    # --- TEXT DENSITY (UTF-16 ASCII) ---
    text_count = sum(
        1 for j in range(0, len(chunk)-1, 2)
        if 32 <= chunk[j] <= 126 and chunk[j+1] == 0
    )
    text_density = text_count / (len(chunk)/2) if len(chunk) else 0

    # --- DATA DENSITY ---
    non_zero = sum(1 for b in chunk if b != 0)
    data_density = non_zero / len(chunk) if len(chunk) else 0

    # --- ENTROPY ---
    e = entropy(chunk)

    results.append({
        "offset": i,
        "text_density": text_density,
        "data_density": data_density,
        "entropy": e
    })

# --- сортируем по "интересности" ---
def score(r):
    return (
        r["text_density"] * 2 +
        r["data_density"] +
        r["entropy"] / 8
    )

results.sort(key=score, reverse=True)

print("\n=== TOP REGIONS ===")

# --- объединяем регионы ---
merged = []
visited = set()

for r in results:
    offset = r["offset"]

    if offset in visited:
        continue

    if (r["text_density"] < TEXT_THRESHOLD and
        r["data_density"] < DATA_THRESHOLD and
        r["entropy"] < ENTROPY_THRESHOLD):
        continue

    start = offset
    end = offset + CHUNK_SIZE

    visited.add(offset)

    # расширяем вправо
    next_offset = offset + CHUNK_SIZE
    while True:
        next_r = next((x for x in results if x["offset"] == next_offset), None)
        if not next_r:
            break

        if (next_r["text_density"] >= TEXT_THRESHOLD or
            next_r["data_density"] >= DATA_THRESHOLD or
            next_r["entropy"] >= ENTROPY_THRESHOLD):

            visited.add(next_offset)
            end += CHUNK_SIZE
            next_offset += CHUNK_SIZE
        else:
            break

    merged.append((start, end))

# сортируем по размеру
merged.sort(key=lambda x: x[1] - x[0], reverse=True)

for start, end in merged[:TOP_REGIONS]:
    size_mb = (end - start) / (1024 * 1024)
    print(f"\nRegion {hex(start)} - {hex(end)} (~{size_mb:.1f} MB)")

    region = data[start:end]

    # --- ищем строки ---
    strings = re.findall(rb'(?:[\x20-\x7E]\x00){10,}', region)
    decoded = [s.decode('utf-16le', errors='ignore') for s in strings]

    decoded.sort(key=len, reverse=True)

    if decoded:
        print("Top strings:")
        for s in decoded[:TOP_STRINGS]:
            print(f"  len={len(s)}: {s[:200]}")
    else:
        print("No large text strings found (likely binary structure)")