hch-dev
Reorganized and renamed Version folders
e6bbf5e
Raw
History Blame Contribute Delete
6.99 kB
import os
import sys
import time
import asyncio
import torch
import torch.nn.functional as F
import timm
from torchvision import transforms
from PIL import Image
from playwright.async_api import async_playwright
class ProductionAnalyzer:
def __init__(self, model_path="models/production_resnet_ema.pth", model_name="resnet18", num_classes=2):
"""
Initializes the ResNet18 production model on available hardware.
"""
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"🖥️ Initializing backend hardware: {self.device}")
# 1. Initialize the ResNet18 architecture base
print(f"🏗️ Building network architecture: {model_name}...")
self.model = timm.create_model(model_name, pretrained=False, num_classes=num_classes)
# 2. Safety check for the weights file
if not os.path.exists(model_path):
raise FileNotFoundError(f"❌ Could not find weight file at: {model_path}\n"
f"Please ensure it is placed inside the 'models' folder.")
print(f"📥 Loading ResNet18 weights from {model_path}...")
state_dict = torch.load(model_path, map_location=self.device, weights_only=True)
# 3. 🛠️ FIXED: Strip wrapper prefixes and safely drop training metadata keys
clean_state_dict = {}
for key, value in state_dict.items():
if key == "n_averaged":
continue # Skip the training counter metadata so PyTorch doesn't throw an error
clean_key = key.replace('module.', '')
clean_state_dict[clean_key] = value
self.model.load_state_dict(clean_state_dict)
# 4. Lock the model for evaluation mode
self.model.eval()
self.model.to(self.device)
print("✅ ResNet18 Engine successfully loaded and locked for inference.")
# 5. Define standard normalizations expected by ResNet18
self.transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
# Alphabetical class mapping (0: Legit, 1: Phishing)
self.class_names = ["Legit", "Phishing"]
def analyze_image(self, image_path):
"""
Feeds the captured screenshot into the ResNet18 neural network.
"""
try:
image = Image.open(image_path).convert('RGB')
input_tensor = self.transform(image).unsqueeze(0).to(self.device)
with torch.no_grad():
logits = self.model(input_tensor)
probabilities = F.softmax(logits[0], dim=0)
confidence, predicted_idx = torch.max(probabilities, 0)
return {
"prediction": self.class_names[predicted_idx.item()],
"confidence": f"{confidence.item() * 100:.2f}%"
}
except Exception as e:
return {"error": f"Model inference failed: {str(e)}"}
async def capture_screenshot(url, output_path="temp_inference.png"):
"""
Launches a headless browser to safely capture a screenshot of the live URL.
"""
if not url.startswith('http://') and not url.startswith('https://'):
url = 'https://' + url
print(f"🌐 Navigating to: {url} ...")
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
viewport={'width': 1280, 'height': 720},
ignore_https_errors=True, # Bypasses broken SSL certifications on malicious sites
accept_downloads=False
)
page = await context.new_page()
try:
# 12-second timeout to handle slow/malicious servers
await page.goto(url, timeout=12000, wait_until='domcontentloaded')
await asyncio.sleep(1) # Brief pause to let visual components load completely
await page.screenshot(path=output_path)
return output_path
except Exception as e:
print(f"❌ Failed to reach or capture the website: {e}")
return None
finally:
await page.close()
await browser.close()
async def main():
print("=" * 45)
print("🛡️ CHIMERA 2.0 LIVE URL DETECTOR ENGINE")
print("=" * 45)
try:
analyzer = ProductionAnalyzer()
except Exception as e:
print(e)
return
TEMP_IMG = "temp_inference.png"
try:
while True:
print("\n" + "-" * 45)
url_input = input("🔗 Enter URL to inspect (or type 'exit' to quit): ").strip()
if url_input.lower() == 'exit':
print("Shutting down engine...")
break
if not url_input:
continue
start_time = time.time()
# Step 1: Capture screenshot via Playwright
screenshot_file = await capture_screenshot(url_input, TEMP_IMG)
if screenshot_file and os.path.exists(screenshot_file):
# Step 2: Pass screenshot into ResNet18
print("🔍 Running Deep Learning Visual Inspection...")
result = analyzer.analyze_image(screenshot_file)
total_time = time.time() - start_time
# Step 3: Output results safely
print("\n" + "=" * 35)
print("📊 LIVE DETECTION REPORT")
print("=" * 35)
if "error" in result:
print(f"Result: {result['error']}")
else:
status_prefix = "🚨 ALERT!!" if result['prediction'] == "Phishing" else "✅ CLEAR:"
print(f"Verdict : {status_prefix} {result['prediction']}")
print(f"Confidence : {result['confidence']}")
print(f"Total Time : {total_time:.2f} seconds")
print("=" * 35)
if os.path.exists(TEMP_IMG):
os.remove(TEMP_IMG)
else:
print("❌ Inspection aborted. Visual fingerprint could not be gathered.")
except KeyboardInterrupt:
print("\nExiting execution gracefully...")
finally:
if os.path.exists(TEMP_IMG):
os.remove(TEMP_IMG)
if __name__ == "__main__":
if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
asyncio.run(main())