Plan realizacji publikacji: FinPhishGuard
Ostatnia aktualizacja: 2026-05-12 Cel: pierwsza submisja w ~5 miesięcy
Faza 0: Przygotowanie (Tydzień 1-2)
0.0 Weryfikacja dostępności ataków ← BLOKUJE Fazę 3
Przed jakąkolwiek implementacją sprawdź:
| Artefakt | Akcja | Jeśli niedostępny |
|---|---|---|
| Lee 2023 GAN logos (kod / próbki) | Szukaj GitHub autorów; napisz email do Jehyun Lee (SUTD) | Zawęź EXP-3 do PGD + diffusion; przeformułuj H1 |
| Hao 2024 LogoMorph (kod) | Szukaj GitHub: gangw / logomorph | Stable Diffusion img2img jako substytut (słabszy) |
| LogoSENSE format adnotacji | Sklonuj repo, sprawdź czy COCO/VOC JSON, czy logo crops są dostępne | Wytnij crops ręcznie z bounding box |
⚠️ Nie zaczynaj Fazy 3 bez potwierdzenia dostępności przynajmniej PGD + jednego z: GAN lub diffusion.
0.1 Środowisko
# Python stack
pip install torch torchvision transformers
pip install clip-by-openai # lub: pip install git+https://github.com/openai/CLIP
pip install detectron2 # Faster R-CNN baseline
pip install timm # ViT modele
pip install playwright # headless browser (M4 timing)
pip install paddlepaddle paddleocr # M3 OCR
pip install lightgbm # M1 URL
pip install esprima # M4 JS AST parsing
pip install foolbox advertorch # adversarial attacks0.2 Pobranie datasetów
| Dataset | Skąd | Action | Priorytet |
|---|---|---|---|
| Phishpedia Labelled Logo (30,649 bounding box) | sites.google.com/view/phishpedia-site → Google Drive | pobierz → M2a training | ⭐⭐⭐ |
| Phishpedia Phishing (29,496 stron) | j.w. | pobierz → end-to-end eval | ⭐⭐⭐ |
| Phishpedia Target List (181 marek) | j.w. / github.com/lindsey98/Phishpedia | pobierz → seed Brand KB | ⭐⭐⭐ |
| Ji & Kim 2025 (19,131 stron) | arXiv paper → szukaj GitHub/Zenodo link | pobierz / napisz do autorów | ⭐⭐⭐ |
| LogoSENSE | github.com/AhmetSalihBozkir/LogoSENSE | clone → użyj jako test set | ⭐⭐ |
| PhiUSIIL | UCI ML Repository | wget → M1 training | ⭐⭐ |
| PhishTank | phishtank.com/developer_info.php | API key | ⭐ |
| Alexa top-10k benign | github.com/nicklockwood/Alexa-top-1m lub CommonCrawl | pobierz ≥5,000 benign URLs → wymagane do EXP-5 (243 benign z Ji & Kim niewystarczające) | ⭐⭐⭐ |
0.3 Bazowe modele (download weights)
import clip
model, preprocess = clip.load("ViT-B/32", download_root="./models/clip")
from transformers import AutoModel
roberta = AutoModel.from_pretrained("roberta-base", cache_dir="./models/roberta")0.4 Budowa Financial Brand KB
Punkt startowy — Phishpedia Target List (181 marek, gotowe logo):
git clone https://github.com/lindsey98/Phishpedia
# → src/phishpedia/expand_targetlist/ zawiera logo per markaRozszerzenie do 150+ marek finansowych:
scripts/
collect_logos.py # scraper oficjalnych stron + EUIPO API
build_kb.py # CLIP encode → save embeddings
Dla każdej marki: pobierz 3-5 wariantów logo (pełne, icon, dark/light). Docelowo: 100 marek × 5 wariantów = 500 logo.
Faza 1: M2a — Logo Localization (Tydzień 2-3)
Cel: Deformable DETR lub Faster R-CNN wykrywający regiony logo na screenshotach stron.
Kroki
-
Przygotowanie danych:
- Primary train: Phishpedia Labelled Logo Dataset (30,649 stron z bounding box) — pobierz z Google Drive
- Test set: LogoSENSE (1,979 stron) — jako held-out test (inne źródło = lepszy generalization test)
- Val split: 10% z Phishpedia (3,064 stron)
- Weryfikacja formatu adnotacji: COCO JSON? VOC XML? → konwertuj do COCO jeśli potrzeba
- Augmentacja: random crop, flip, brightness (nie zmieniaj kształtu logo!)
-
Baseline: Faster R-CNN (detectron2, szybszy start):
from detectron2 import model_zoo cfg = get_cfg() cfg.merge_from_file(model_zoo.get_config_file("COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml")) cfg.DATASETS.TRAIN = ("logosense_train",) cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 # tylko "logo_region" -
Alternatywa: Deformable DETR (jeśli Faster R-CNN niewystarczający):
- github.com/fundamentalvision/Deformable-DETR
- Fine-tune z pretrained COCO weights
-
Ewaluacja EXP-1:
- [email protected], [email protected] na LogoSENSE test
- Baseline: Faster R-CNN (Phishpedia Lin 2021 — ta sama metryka mAP, właściwe porównanie)
- Uwaga: HOG+SVM Bozkir 2020 raportuje accuracy klasyfikatora (94.3%) — nieporównywalny z mAP; nie używaj jako baseline numerycznego
Czas: ~1 tydzień (GPU training ~4-8h)
Output: models/logo_detector.pth + EXP-1 wyniki
Faza 2: M2b — CLIP Brand Matching (Tydzień 3-4)
Cel: CLIP zero-shot matching logo regionu do brand KB.
Kroki
-
Budowa KB:
import clip, torch brand_texts = { "PayPal": "PayPal blue and white payment service logo", "Revolut": "Revolut geometric logo dark background", "PKO BP": "PKO BP Polish bank blue logo", # ... 150+ marek } text_tokens = clip.tokenize(list(brand_texts.values())) with torch.no_grad(): text_embeddings = clip_model.encode_text(text_tokens) torch.save({"brands": list(brand_texts.keys()), "embeddings": text_embeddings}, "models/brand_kb.pt") -
Prompt engineering (iteracyjne):
- Testuj różne opisy:
"[brand] logo"vs"a photo of [brand] corporate logo"vs"[brand] brand symbol" - Mierz top-1 accuracy na logo crops z LogoSENSE
- Testuj różne opisy:
-
Few-shot extension (dla marek z logo w KB):
- CLIP image embeddings z 3-5 logo → average → dodaj do KB
- Porównaj: zero-shot (text only) vs few-shot (text + images)
-
EXP-2: CLIP vs ResNet-50 triplet (PhishIntention approach)
- Baseline: wytrenuj ResNet-50 z triplet loss na LogoSENSE
- Porównaj: Top-1, Top-5 accuracy na logo crops
Czas: ~1 tydzień
Output: models/brand_kb.pt + EXP-2 wyniki
Faza 3: M2c — Adversarial Hardening (Tydzień 4-7) ← najdłuższa
Cel: Fine-tuned ViT + PGD adversarial training odporny na GAN/diffusion logos.
Krok 3.1: Generowanie adversarial logo dataset
A1-wb: PGD attacks (white-box):
import torchattacks
attack = torchattacks.PGD(model, eps=8/255, alpha=2/255, steps=40)
x_adv = attack(logo_crops, labels) # ~5000 adversarial logo samplesA1-bb: GAN logos (Lee 2023 — zależy od Fazy 0.0):
- Jeśli kod Lee 2023 dostępny: użyj bezpośrednio
- Jeśli niedostępny: perturbation-based generator (nie DCGAN — Lee 2023 trenuje generator przeciwko Siamese discriminator, nie generatywny model obrazów)
# Schemat perturbation generator (uproszczony Lee 2023) generator = PerturbationGenerator(backbone="vit") # produkuje delta, nie pełny obraz discriminator = SiameseResNet50() # frozen, target model # Cel: min ||delta||_inf s.t. discriminator(x+delta) ≠ brand_x - ⚠️ DCGAN / StyleGAN2 to generatywne modele obrazów — to NIE jest atak z Lee 2023; nie używaj jako substytutu bez opisania różnicy w papierze
- Cel: ~2,000 adversarial perturbation samples
A2: Diffusion logos (Hao 2024 LogoMorph — zależy od Fazy 0.0):
- Jeśli LogoMorph kod dostępny: użyj bezpośrednio
- Jeśli niedostępny: Stable Diffusion img2img jako słabszy substytut
strength=0.3(mała zmiana), prompt:"corporate logo, clean design"- Opisać w papierze jako “LogoMorph-inspired” — nie twierdzić że to oryginalna metoda
- Cel: ~2,000 diffusion adversarial samples
Krok 3.2: Adversarial training
# Mixed batch training
for epoch in range(50):
for batch in dataloader:
x, y = batch
# Mix: 30% clean, 20% PGD, 20% GAN, 15% diffusion, 15% aug
x_pgd = pgd_attack(model, x[:n_pgd], y[:n_pgd])
x_mix = torch.cat([x_clean, x_pgd, x_gan, x_diff, x_aug])
y_mix = torch.cat([y_clean, y_pgd, y_gan, y_diff, y_aug])
loss = criterion(model(x_mix), y_mix)
loss.backward()
optimizer.step()Krok 3.3: EXP-3 Adversarial robustness
Dla każdej klasy ataku:
- Evasion rate = % logo poprawnie sklasyfikowanych przez adversary (im niższy tym lepiej)
- Porównanie: ResNet-50 no hardening vs CLIP zero-shot vs ViT PGD-hardened
Oczekiwane wyniki (scenariusz: black-box transfer attack — GAN trenowany na ResNet-Siamese, testowany na CLIP/ViT):
| Model | Clean acc | PGD transfer evasion | GAN transfer evasion | Diffusion transfer evasion |
|---|---|---|---|---|
| ResNet-50 baseline | ~95% | ~60-80%* | ~42-95%** | ~50-80%* |
| CLIP zero-shot | ~88-92%* | ~20-35%* | ~15-40%* (H1) | ~20-35%* |
| ViT PGD-hardened | ~85-90%* | ~10-20%* | ~20-30%* | ~15-25%* |
* Hipoteza — do weryfikacji empirycznej
** Lee 2023: black-box GViT→Siamese = min 42% evasion; white-box matching = >95% — tabela zakłada black-box transfer scenario zgodnie z H1
⚠️ Nie pokazuj white-box i black-box w tej samej kolumnie bez oznaczenia scenariusza
Czas: ~3 tygodnie (GAN/diffusion generation CPU-intensive)
Output: models/adversarial_verifier.pth + EXP-3 wyniki
Faza 4: M3 — Content Brand Extractor (Tydzień 5-6, równolegle z Fazą 3)
Cel: NER extraction brand name z HTML + cross-check z URL.
Kroki
-
Opcja A — Zero-shot Qwen (rekomendowana jako pierwsza):
# Brak danych treningowych — użyj dostępnego lokalnego modelu from openai import OpenAI # lub lokalny endpoint Qwen def extract_brands_llm(html_snippet): prompt = f"""Extract financial brand names (banks, payment services, fintech) from this HTML. Return JSON list of brand names only. HTML: {html_snippet[:2000]}""" response = client.chat.completions.create( model="qwen3-6-27b", # dostępny lokalnie messages=[{"role": "user", "content": prompt}] ) return parse_brands(response.choices[0].message.content)- Zalety: brak cold-start data, natychmiastowy start, dobra jakość dla znanych marek
- Wady: latencja ~200-400ms (vs ~30ms RoBERTa), koszt per query
- Sprawdź najpierw tę opcję przed fine-tuningiem
-
Opcja B — Fine-tune RoBERTa-base (jeśli Opcja A niewystarczająca dla latencji):
from transformers import RobertaForTokenClassification model = RobertaForTokenClassification.from_pretrained( "roberta-base", num_labels=len(ENTITY_TYPES) ) # Silver labels: użyj Opcji A na 1,000 HTML snippets → manualna weryfikacja ~100 # Fine-tune na silver-labeled HTML snippets- Wymaga silver label generation przez Opcję A + ~100 manualna weryfikacja
- Latencja: ~30ms; lepsza dla deployment
-
OCR integration (PaddleOCR):
- Wyciągnij tekst z header region (top 20% screenshotu)
- Przekaż do NER pipeline razem z HTML text
-
URL cross-check:
from Levenshtein import distance def brand_url_mismatch(detected_brand, url_domain): brand_root = normalize(detected_brand) # "PayPal" → "paypal" domain_root = extract_root(url_domain) # "paypal-secure.ru" → "paypal-secure" dist = distance(brand_root, domain_root) return dist > MISMATCH_THRESHOLD # → phishing signal
Czas: ~2 tygodnie
Output: models/brand_ner.pt + walidacja na subset Ji & Kim 2025
Faza 5: M4 — DOM Timing Analyzer (Tydzień 6-7)
Cel: Detekcja delayed rendering. Architektura dwuwarstwowa: M4a (statyczna, <10ms) → M4b (dynamic fallback, ~500ms).
Krok 5.1: M4a — Static CSS/JS Analysis (naprawdę statyczna, bez uruchamiania strony)
from bs4 import BeautifulSoup
import esprima, re
HIDDEN_CSS = re.compile(
r'(opacity\s*:\s*0|display\s*:\s*none|visibility\s*:\s*hidden'
r'|clip-path\s*:\s*inset\s*\(|z-index\s*:\s*-\d+)',
re.IGNORECASE
)
TIMING_JS = re.compile(r'set(Timeout|Interval)\s*\(', re.IGNORECASE)
def analyze_dom_static(html: str) -> float:
"""Czyta HTML source bez wykonania. <10ms."""
soup = BeautifulSoup(html, 'html.parser')
score = 0.0
for img in soup.find_all('img'):
src = img.get('src', '')
style = img.get('style', '') + ' ' + img.get('class', [''])[0]
if any(b in src.lower() for b in BRAND_KEYWORDS):
if HIDDEN_CSS.search(style):
score += 0.4 # logo hidden via CSS → suspicious
for script in soup.find_all('script'):
js = script.string or ''
if TIMING_JS.search(js):
try:
ast = esprima.parseScript(js, tolerant=True)
score += detect_delayed_logo_js(ast) # setTimeout > 200ms na logo nodes
except Exception:
score += 0.1 # parse error na logo-related script → mild signal
return min(score, 1.0)Zakres M4a: nieopakowany CSS/JS bez webpack/obfuskacji. Opisać w Limitations.
Krok 5.2: M4b — Dynamic Fallback (Playwright, uruchamiany tylko gdy M4a niekonkluzywne)
from playwright.async_api import async_playwright
async def analyze_dom_dynamic(url: str) -> float:
"""Uruchamiana TYLKO gdy M4a score w przedziale [0.2, 0.6] (niekonkluzywne).
Resource Timing API — wymaga wykonania strony (~500ms)."""
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
logo_timings = []
page.on("response", lambda r: logo_timings.append(
{"url": r.url, "start": r.timing["startTime"]}
) if is_logo_resource(r.url) else None)
await page.goto(url, timeout=5000)
dom_ready = await page.evaluate("document.readyState")
await page.wait_for_timeout(2500)
if logo_timings:
logo_start = min(t["start"] for t in logo_timings)
dom_content_loaded = await page.evaluate(
"performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart"
)
delay = logo_start - dom_content_loaded
if delay > 300: # logo pobrane >300ms po DOMContentLoaded → red flag
return min(0.3 + delay / 10000, 0.9)
return 0.0Podział odpowiedzialności z M2d: M4a+M4b = detekcja sygnatur timing ATTACK w kodzie/zachowaniu. M2d (SSIM delta w M2) = weryfikacja wizualna braku logo na screenshocie. Komplementarne — różne sygnały.
Krok 5.3: EXP-4 (syntetyczny dataset)
Stwórz ≥ 1,000 syntetycznych stron phishingowych (200+ per delay class):
- CSS curtain
clip-path: inset()z delay: 0ms, 500ms, 1s, 2s, 5s, 10s - JS
setTimeoutz różnymi delay - Mieszane (CSS + JS)
- Obfuskowana wersja (webpack-like) jako upper-bound failure case
FPR test: 500 legalnych stron z legalnymi lazy-load delays (obrazy, CDN).
Mierz: recall M4a, recall M4a+M4b vs Yuan 2026 PoC (1 extra screenshot).
Czas: ~2 tygodnie
Output: models/dom_analyzer.py + syntetyczny dataset + EXP-4
Faza 6: Fuzja i EXP End-to-End (Tydzień 8-9)
Krok 6.0: Deduplication (przed EXP-5)
# URL-level deduplication: Phishpedia train ↔ Ji & Kim 2025 test
phishpedia_urls = load_urls("data/phishpedia_labelled_logo/urls.txt")
ji_kim_urls = load_urls("data/ji_kim_2025/phishing_urls.txt")
overlap = set(phishpedia_urls) & set(ji_kim_urls)
print(f"Overlap: {len(overlap)} URLs ({len(overlap)/len(ji_kim_urls)*100:.1f}% of test set)")
# Usuń nakładające się próbki z Ji & Kim przed EXP-5
ji_kim_clean = [u for u in ji_kim_urls if u not in overlap]Zgłoś rozmiar overlapu w papierze (Section 6.1 Dataset). Jeśli overlap > 5% — rozważ alternatywny split.
Krok 6.1: Implementacja fuzji
class FinPhishGuard:
def __init__(self, weights=None):
# Wagi uczone na dev set (grid search), nie hardcoded
# Punkt startowy: [0.25, 0.40, 0.25, 0.10] — do zastąpienia przez learned weights
self.w = weights or [0.25, 0.40, 0.25, 0.10]
def predict(self, url, html, screenshot):
p_url = self.m1_url.predict(url)
if p_url > 0.95: # Fast exit
return "PHISHING", {"url": p_url}
logo_boxes = self.m2a_detector.detect(screenshot)
p_visual = self.m2b_clip.match(logo_boxes, screenshot)
if p_visual < self.tau_high:
p_visual = self.m2c_verifier.verify(logo_boxes, screenshot)
p_content = self.m3_ner.extract_and_check(html, screenshot, url)
p_timing = self.m4a_static.analyze(html) # M4a zawsze
if 0.2 < p_timing < 0.6: # M4b tylko gdy niekonkluzywne
p_timing = max(p_timing, await self.m4b_dynamic.analyze(url))
w1, w2, w3, w4 = self.w
s = w1*p_url + w2*p_visual + w3*p_content + w4*p_timing
return "PHISHING" if s > self.threshold else "LEGITIMATE"Uczenie wag na dev set:
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
# Zbierz p_url, p_visual, p_content, p_timing dla dev split
X_dev = np.column_stack([p_urls, p_visuals, p_contents, p_timings])
y_dev = labels_dev
meta = LogisticRegression(C=1.0, max_iter=1000).fit(X_dev, y_dev)
learned_weights = meta.coef_[0] / meta.coef_[0].sum() # normalizuj
print("Learned weights:", learned_weights)Krok 6.2: Threshold calibration
- Na Ji & Kim 2025 validation split: ROC curve → wybierz threshold @ FPR=5%
- Oddzielne kalibracje: ogólny dataset + financial brand subset
Krok 6.3: EXP-5 End-to-End
Uruchom PhishIntention, KnowPhish i FinPhishGuard na:
- Ji & Kim 2025 (19,131 phishing) + ≥5,000 benign z Alexa top-10k (pobrane w Fazie 0)
- Adversarial test set (A1-A3)
Testy statystyczne (obowiązkowe):
from sklearn.metrics import f1_score
from statsmodels.stats.contingency_tables import mcnemar
import numpy as np
# McNemar test: FinPhishGuard vs KnowPhish
b = ((y_fpg == y_true) & (y_knowphish != y_true)).sum() # FPG correct, KP wrong
c = ((y_fpg != y_true) & (y_knowphish == y_true)).sum() # FPG wrong, KP correct
result = mcnemar([[0, b], [c, 0]], exact=True)
print(f"McNemar p-value: {result.pvalue:.4f}")
# Bootstrap 95% CI dla F1
def bootstrap_f1(y_true, y_pred, n=1000):
scores = []
for _ in range(n):
idx = np.random.choice(len(y_true), len(y_true), replace=True)
scores.append(f1_score(y_true[idx], y_pred[idx]))
return np.percentile(scores, [2.5, 97.5])
ci = bootstrap_f1(y_true, y_fpg_pred)
print(f"FinPhishGuard F1 95% CI: [{ci[0]:.3f}, {ci[1]:.3f}]")Krok 6.4: EXP-6 Brand breakdown
⚠️ Nakład pracy: 2-3 tygodnie, wymaga drugiej osoby (interrater reliability)
- Manualna klasyfikacja 500–1,000 phishing stron z Ji & Kim 2025 per brand tier (Tier 1–4)
- Dwie osoby etykietują niezależnie → Cohen’s κ ≥ 0.80 jako próg jakości
- Rozbieżności: konsensus przez trzecią osobę lub wykluczenie
- Porównaj recall: Banks (Tier 1) vs Payments (Tier 2) vs Cards+Mobile (Tier 3) vs Fintech (Tier 4)
- Zaplanuj ten krok równolegle z Fazą 3 (nie na końcu) — inaczej opóźni Fazę 6
Krok 6.5: EXP-7 Latency
Trzy architektury brand matching do porównania (H5):
import time, numpy as np
def benchmark(fn, n=200):
times = []
for _ in range(n):
t0 = time.perf_counter()
fn()
times.append((time.perf_counter() - t0) * 1000)
return {
"p50": np.percentile(times, 50),
"p95": np.percentile(times, 95),
"p99": np.percentile(times, 99),
}
# Moduły FinPhishGuard (per-module latency)
for name, module in [("M1 URL", m1), ("M2a DETR", m2a),
("M2b CLIP", m2b), ("M2c ViT-PGD", m2c),
("M3 NER", m3), ("M4a static", m4a)]:
print(name, benchmark(module.predict))
# H5: Porównanie architektur brand matching
print("\n=== Brand Matching Architecture Comparison (H5) ===")
print("CLIP ViT-B/32 (lokalny):", benchmark(clip_match))
print("Qwen3-6-27B zero-shot (lokalny):", benchmark(qwen_match)) # dostępny lokalnie
print("Lee MLLM cloud API (GPT-4V):", benchmark(mllm_api_match)) # jeśli dostępny
print("FinPhishGuard end-to-end:", benchmark(finphishguard.predict))Środowisko benchmark: CPU-only (laptop konsumencki) + GPU (jeśli dostępne). Raportuj oddzielnie.
Czas: ~2 tygodnie Output: wszystkie wyniki EXP-1 do EXP-7
Faza 7: Pisanie papieru (Tydzień 10-13)
Kolejność pisania (nie chronologiczna)
- Sekcja 4 System Design (najpierw — architektura gotowa) → 1 tydzień
- Sekcja 6 Evaluation (wyniki eksperymentów → tabele + wykresy) → 1 tydzień
- Sekcja 2 Related Work (referencje zebrane) → 3-4 dni
- Sekcja 3 Threat Model → 2 dni
- Sekcja 5 Brand KB → 1-2 dni
- Sekcja 7 Discussion → 2 dni
- Sekcja 1 Introduction + Abstract (na końcu — znamy wyniki) → 3 dni
- Sekcja 8 Conclusion → 1 dzień
Narzędzia
- LaTeX (Overleaf lub lokalne)
- Template: ACSAC/USENIX Security IEEE/ACM format
- Wykresy: matplotlib + seaborn (ROC curves, ablation bar charts, Grad-CAM heatmaps)
- Tabele: booktabs LaTeX
Faza 8: Submisja (Tydzień 14)
Pre-submission checklist
- Abstract ≤ 250 słów
- Wszystkie twierdzenia mają eksperymenty
- Limitations sekcja zawiera uczciwe ograniczenia
- Reproducibility: kod + dataset links dostępne (GitHub)
- Ethics: screenshoty phishing stron — GDPR compliance (nie przechowuj > 30 dni)
- Double-blind (jeśli venue wymaga): usuń self-citations, afiliacje
- Page limit: sprawdź venue (ACSAC: 11 stron + refs, USENIX: 13 + refs)
Target venues z deadline
| Venue | Deadline 2026/2027 | Wynik | Prestiż | Status |
|---|---|---|---|---|
| RAID 2026 | ~maj 2026 | wrzesień | B+ | ⚠️ Prawdopodobnie minął (dziś 12.05.2026) — zweryfikuj |
| ACSAC 2026 | ~czerwiec 2026 | grudzień | B+ | ✅ Realistyczny jeśli submisja do końca czerwca |
| CCS 2026 | ~maj 2026 | październik | A+ | ⚠️ Deadline maj — prawdopodobnie minął |
| USENIX Security 2027 (Feb cycle) | luty 2027 | sierpień | A | ✅ Główny target jeśli ACSAC odpada |
| IEEE S&P 2027 | sierpień 2026 | maj 2027 | A+ | ✅ Realistyczny z pełnymi wynikami |
| NDSS 2027 | ~wrzesień 2026 | luty | A | ✅ Dobry backup dla USENIX |
Rekomendacja (zaktualizowana): ACSAC 2026 (czerwiec) jako first target — jedyny realny w krótkim terminie. USENIX Security 2027 (luty) jako główny cel jeśli potrzeba więcej czasu na eksperymenty. Zweryfikuj aktualne deadliny na stronach konferencji.
Harmonogram zbiorczy
Tydzień 1: Faza 0.0 — weryfikacja dostępności ataków (BLOKUJE Fazę 3)
EXP-6 labeling START równolegle (2-3 tygodnie, druga osoba)
Tydzień 1-2: Faza 0 — środowisko, datasety (w tym: Alexa 5k benign), KB Tier1
Tydzień 2-3: Faza 1 — M2a logo localization + EXP-1
Tydzień 3-4: Faza 2 — M2b CLIP matching + EXP-2 + EXP-7 latency H5 (CLIP vs Qwen)
Tydzień 3-6: EXP-6 labeling (równolegle, 2-3 tygodnie) ← zaplanować wcześnie
Tydzień 4-7: Faza 3 — M2c adversarial hardening + EXP-3 ← krytyczna ścieżka
Tydzień 5-6: Faza 4 — M3 content NER (Opcja A: Qwen zero-shot, równolegle)
Tydzień 6-7: Faza 5 — M4a static + M4b dynamic + EXP-4 (≥1,000 stron)
Tydzień 8: Krok 6.0 — deduplication Phishpedia ↔ Ji & Kim
Tydzień 8-9: Faza 6 — fuzja + learned weights + EXP-5 (bootstrap CI, McNemar)
Tydzień 9: EXP-6 brand breakdown (dane z labeling gotowe)
Tydzień 10-13: Faza 7 — pisanie
Tydzień 14: Faza 8 — submisja
─────────────────────────────────────────────────────────────
Łącznie: ~14 tygodni (3.5 miesiąca) optymistyczny, 16-18 tygodni (4-4.5 mies.) realistyczny
⚠️ EXP-6 labeling i Faza 3 (GAN) to główne ryzyka czasowe — zaczynaj je w Tygodniu 1
Ryzyka i mitygacje
| Ryzyko | Prawdopodobieństwo | Mitygacja |
|---|---|---|
| LogoSENSE dataset niedostępny | średnie | Kontakt z autorami; alternatywnie: zbierz własne loga z LogoSENSE stron |
| Ji & Kim 2025 dataset niedostępny | niskie | Poproś autorów; PhiUSIIL jako backup benchmark |
| GAN logo generation niedostępny (Lee 2023 brak kodu) | wysokie | Zawęź EXP-3 do PGD + diffusion; przeformułuj H1 na “transfer PGD attack”; opisz w Limitations |
| CLIP nie daje wystarczającej separacji | niskie | Few-shot extension; fallback: triplet-ResNet |
| Wyniki nie pobijają KnowPhish na clean | średnie | Akceptowalne jeśli pobijamy na adversarial — to nasza główna teza |
| Przekroczenie page limit | wysokie | Skróć sekcję related work; przenieś ablation do appendix |