reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,483 @@
#!/usr/bin/env python3
"""验证第二阶段辅助脚本和参考文件是否可用。"""
from __future__ import annotations
import json
import subprocess
import sys
import tempfile
from pathlib import Path
from typing import Any
def configure_utf8_stdio() -> None:
for stream in (sys.stdout, sys.stderr):
if hasattr(stream, "reconfigure"):
stream.reconfigure(encoding="utf-8")
configure_utf8_stdio()
SCRIPT_DIR = Path(__file__).resolve().parent
SKILL_DIR = SCRIPT_DIR.parent
def run_json(args: list[str]) -> dict[str, Any]:
completed = subprocess.run(
[sys.executable, "-X", "utf8", *args],
cwd=str(SKILL_DIR),
check=True,
capture_output=True,
text=True,
encoding="utf-8",
)
return json.loads(completed.stdout)
def check_references() -> dict[str, Any]:
required = {
"references/verification-workflow.md": ["进入条件", "动作分级", "真实网页", "成功样本基线", "evaluate_success_baseline.py", "5 次失败复盘门槛", "evaluate_verification_attempts.py"],
"references/browser-acquisition.md": ["用户手动成功样本", "至少 5 次成功样本", "每个新类型至少补到 2 次成功样本"],
"references/open-source-recipes.md": ["ddddocr", "OpenCV", "Whisper", "切片乱序", "analyze_tile_restore.py"],
"references/solver-platform-recipes.md": ["请求模板", "API key", "不默认发送", "授权 QA 对照"],
"references/motion-and-coordinate.md": ["坐标体系", "滑块轨迹", "真实网页执行前检查"],
"references/provider-execution-notes.md": ["极验", "Turnstile", "WAF"],
}
missing: list[str] = []
for relative, snippets in required.items():
path = SKILL_DIR / relative
if not path.exists():
missing.append(relative)
continue
content = path.read_text(encoding="utf-8")
for snippet in snippets:
if snippet not in content:
missing.append(f"{relative}:{snippet}")
return {"passed": not missing, "missing": missing}
def make_original_image(path: Path, rows: int, cols: int, tile_size: int) -> None:
from PIL import Image, ImageDraw
image = Image.new("RGB", (cols * tile_size, rows * tile_size), "white")
draw = ImageDraw.Draw(image)
for index in range(rows * cols):
row, col = divmod(index, cols)
left = col * tile_size
top = row * tile_size
color = (
30 + (index * 47) % 200,
40 + (index * 83) % 190,
50 + (index * 31) % 180,
)
draw.rectangle((left, top, left + tile_size - 1, top + tile_size - 1), fill=color)
draw.line((left, top, left + tile_size - 1, top + tile_size - 1), fill=(255, 255, 255), width=2)
draw.text((left + 3, top + 3), str(index), fill=(0, 0, 0))
image.save(path)
def scramble_image(original: Path, output: Path, rows: int, cols: int, tile_size: int, order_source_by_target: list[int]) -> None:
from PIL import Image
source = Image.open(original).convert("RGB")
tiles = []
for row in range(rows):
for col in range(cols):
left = col * tile_size
top = row * tile_size
tiles.append(source.crop((left, top, left + tile_size, top + tile_size)))
scrambled = Image.new("RGB", source.size)
for target_index, current_index in enumerate(order_source_by_target):
row, col = divmod(current_index, cols)
scrambled.paste(tiles[target_index], (col * tile_size, row * tile_size))
scrambled.save(output)
def images_equal(left: Path, right: Path) -> bool:
from PIL import Image, ImageChops
left_image = Image.open(left).convert("RGB")
right_image = Image.open(right).convert("RGB")
return ImageChops.difference(left_image, right_image).getbbox() is None
def check_tile_restore() -> dict[str, Any]:
try:
import PIL # noqa: F401
except ImportError:
return {"passed": False, "missing": ["Pillow"], "details": {}}
details: dict[str, Any] = {}
with tempfile.TemporaryDirectory() as tmp:
tmp_dir = Path(tmp)
cases = [
("3x3", 3, 3, 18, [1, 2, 0, 4, 5, 3, 7, 8, 6]),
("4x2", 4, 2, 18, [1, 0, 3, 2, 5, 4, 7, 6]),
]
for name, rows, cols, tile_size, order in cases:
original = tmp_dir / f"original-{name}.png"
scrambled = tmp_dir / f"scrambled-{name}.png"
restored = tmp_dir / f"restored-{name}.png"
make_original_image(original, rows, cols, tile_size)
scramble_image(original, scrambled, rows, cols, tile_size, order)
report = run_json(
[
"scripts/analyze_tile_restore.py",
"--image",
str(scrambled),
"--rows",
str(rows),
"--cols",
str(cols),
"--order-source-by-target",
",".join(str(item) for item in order),
"--output-image",
str(restored),
]
)
details[name] = {
"strategy": report["restore_strategy"],
"confidence": report["confidence"],
"image_equal": images_equal(original, restored),
"order": report["order_source_by_target"],
}
original = tmp_dir / "original-2x2.png"
scrambled = tmp_dir / "scrambled-2x2.png"
make_original_image(original, 2, 2, 24)
scramble_image(original, scrambled, 2, 2, 24, [1, 0, 3, 2])
image_only = run_json(
[
"scripts/analyze_tile_restore.py",
"--image",
str(scrambled),
"--rows",
"2",
"--cols",
"2",
]
)
details["image-only"] = {
"strategy": image_only["restore_strategy"],
"confidence": image_only["confidence"],
"order_len": len(image_only["order_source_by_target"] or []),
}
flat = tmp_dir / "flat.png"
from PIL import Image
Image.new("RGB", (48, 48), (120, 120, 120)).save(flat)
flat_report = run_json(
[
"scripts/analyze_tile_restore.py",
"--image",
str(flat),
"--rows",
"2",
"--cols",
"2",
]
)
details["flat"] = {
"strategy": flat_report["restore_strategy"],
"confidence": flat_report["confidence"],
"warnings": flat_report["warnings"],
}
passed = (
details["3x3"]["strategy"] == "page-order"
and details["3x3"]["image_equal"] is True
and details["4x2"]["strategy"] == "page-order"
and details["4x2"]["image_equal"] is True
and details["image-only"]["order_len"] == 4
and isinstance(details["image-only"]["confidence"], (int, float))
and details["flat"]["strategy"] == "manual-or-platform"
and details["flat"]["confidence"] <= 0.42
)
return {"passed": passed, "details": details, "missing": []}
def write_attempts(path: Path, captcha_type: str, attempts: list[dict[str, Any]], captcha_variant: str = "") -> None:
data = {
"authorization_scope": "授权测试目标",
"captcha_type": captcha_type,
"captcha_variant": captcha_variant,
"provider": "geetest" if captcha_type == "slider" else "custom-or-unknown",
"chosen_solution": f"open-source-{captcha_type}",
"attempts": attempts,
}
path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
def failed_attempt(status_overrides: dict[str, str] | None = None) -> dict[str, Any]:
diagnosis = {
"image": "ok",
"coordinates": "ok",
"track": "ok",
"tile_restore": "ok",
"browser_env": "ok",
"challenge_freshness": "ok",
}
if status_overrides:
diagnosis.update(status_overrides)
return {
"success": False,
"diagnosis_status": diagnosis,
"failure_reason": "服务端仍判定失败,离线诊断未发现明显异常",
}
def check_attempt_evaluation() -> dict[str, Any]:
details: dict[str, Any] = {}
with tempfile.TemporaryDirectory() as tmp:
tmp_dir = Path(tmp)
switch_path = tmp_dir / "switch.json"
write_attempts(switch_path, "slider", [failed_attempt() for _ in range(5)])
switch_report = run_json(["scripts/evaluate_verification_attempts.py", "--attempts", str(switch_path)])
details["switch"] = {
"switch_triggered": switch_report["switch_triggered"],
"route": switch_report["recommended_next_route"],
"decision": switch_report["escalation_decision"],
"send_request": switch_report["send_request"],
}
below_path = tmp_dir / "below.json"
write_attempts(below_path, "slider", [failed_attempt() for _ in range(4)])
below_report = run_json(["scripts/evaluate_verification_attempts.py", "--attempts", str(below_path)])
details["below_threshold"] = {
"switch_triggered": below_report["switch_triggered"],
"route": below_report["recommended_next_route"],
}
blocking_path = tmp_dir / "blocking.json"
write_attempts(blocking_path, "slider", [failed_attempt() for _ in range(4)] + [failed_attempt({"coordinates": "error"})])
blocking_report = run_json(["scripts/evaluate_verification_attempts.py", "--attempts", str(blocking_path)])
details["blocking"] = {
"switch_triggered": blocking_report["switch_triggered"],
"blocking_issue": blocking_report["blocking_issue"],
"route": blocking_report["recommended_next_route"],
}
success_path = tmp_dir / "success.json"
success_attempts = [failed_attempt() for _ in range(4)] + [failed_attempt()]
success_attempts[2]["success"] = True
write_attempts(success_path, "slider", success_attempts)
success_report = run_json(["scripts/evaluate_verification_attempts.py", "--attempts", str(success_path)])
details["success"] = {
"switch_triggered": success_report["switch_triggered"],
"route": success_report["recommended_next_route"],
}
tile_path = tmp_dir / "tile.json"
write_attempts(tile_path, "image-restore", [failed_attempt() for _ in range(5)], captcha_variant="tile-scramble")
tile_report = run_json(["scripts/evaluate_verification_attempts.py", "--attempts", str(tile_path)])
details["tile_scramble"] = {
"switch_triggered": tile_report["switch_triggered"],
"route": tile_report["recommended_next_route"],
"has_platform_candidates": bool(tile_report["platform_candidates"]),
}
special: dict[str, Any] = {}
for captcha_type in ["pow-challenge", "waf-challenge", "biometric-liveness"]:
path = tmp_dir / f"{captcha_type}.json"
write_attempts(path, captcha_type, [failed_attempt() for _ in range(5)])
report = run_json(["scripts/evaluate_verification_attempts.py", "--attempts", str(path)])
special[captcha_type] = {
"switch_triggered": report["switch_triggered"],
"decision": report["escalation_decision"],
"platform_candidates": report["platform_candidates"],
}
details["special_types"] = special
passed = (
details["switch"]["switch_triggered"] is True
and details["switch"]["route"] == "platform-control"
and details["switch"]["decision"] == "recommend-platform-control"
and details["switch"]["send_request"] is False
and details["below_threshold"]["switch_triggered"] is False
and details["blocking"]["switch_triggered"] is False
and details["blocking"]["blocking_issue"] == "coordinates"
and details["success"]["switch_triggered"] is False
and details["success"]["route"] == "optimize-current-route"
and details["tile_scramble"]["switch_triggered"] is True
and details["tile_scramble"]["has_platform_candidates"] is True
and all(item["switch_triggered"] is False for item in details["special_types"].values())
and all(item["decision"] == "ordinary-platform-not-recommended" for item in details["special_types"].values())
and all(not item["platform_candidates"] for item in details["special_types"].values())
)
return {"passed": passed, "details": details}
def write_success_samples(path: Path, samples: list[dict[str, Any]]) -> None:
data = {
"authorization_scope": "授权测试目标",
"provider": "custom-or-unknown",
"success_samples": samples,
}
path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
def success_sample(captcha_type: str, sample_id: str) -> dict[str, Any]:
return {
"sample_id": sample_id,
"success": True,
"captcha_type": captcha_type,
"provider": "custom-or-unknown",
"evidence": {
"success_signal": "UI/callback/response 显示验证成功",
"timeline": ["rendered", "user solved", "success observed"],
},
}
def check_success_baseline() -> dict[str, Any]:
details: dict[str, Any] = {}
with tempfile.TemporaryDirectory() as tmp:
tmp_dir = Path(tmp)
sufficient_path = tmp_dir / "success-sufficient.json"
write_success_samples(
sufficient_path,
[
success_sample("slider", "s1"),
success_sample("slider", "s2"),
success_sample("slider", "s3"),
success_sample("click-select", "c1"),
success_sample("click-select", "c2"),
],
)
sufficient = run_json(["scripts/evaluate_success_baseline.py", "--samples", str(sufficient_path)])
details["sufficient"] = {
"status": sufficient["success_baseline_status"],
"route": sufficient["recommended_next_route"],
"dynamic": sufficient["success_baseline_summary"]["has_dynamic_type_switch"],
}
insufficient_total_path = tmp_dir / "success-insufficient-total.json"
write_success_samples(
insufficient_total_path,
[
success_sample("slider", "s1"),
success_sample("slider", "s2"),
success_sample("slider", "s3"),
],
)
insufficient_total = run_json(["scripts/evaluate_success_baseline.py", "--samples", str(insufficient_total_path)])
details["insufficient_total"] = {
"status": insufficient_total["success_baseline_status"],
"missing_scopes": [item["scope"] for item in insufficient_total["missing_success_samples"]],
"send_request": insufficient_total["send_request"],
}
insufficient_type_path = tmp_dir / "success-insufficient-type.json"
write_success_samples(
insufficient_type_path,
[
success_sample("slider", "s1"),
success_sample("slider", "s2"),
success_sample("slider", "s3"),
success_sample("slider", "s4"),
success_sample("click-select", "c1"),
],
)
insufficient_type = run_json(["scripts/evaluate_success_baseline.py", "--samples", str(insufficient_type_path)])
details["insufficient_type"] = {
"status": insufficient_type["success_baseline_status"],
"missing": insufficient_type["missing_success_samples"],
}
passed = (
details["sufficient"]["status"] == "sufficient"
and details["sufficient"]["route"] == "ready-for-verification-flow"
and details["sufficient"]["dynamic"] is True
and details["insufficient_total"]["status"] == "insufficient"
and "total" in details["insufficient_total"]["missing_scopes"]
and details["insufficient_total"]["send_request"] is False
and details["insufficient_type"]["status"] == "insufficient"
and any(item.get("scope") == "captcha_type" and item.get("captcha_type") == "click-select" for item in details["insufficient_type"]["missing"])
)
return {"passed": passed, "details": details}
def main() -> int:
coord = run_json(
[
"scripts/map_coordinates.py",
"--image-size",
"300x150",
"--display-size",
"300x150",
"--point",
"120,75",
"--element-left",
"20",
"--element-top",
"80",
]
)
track = run_json(
[
"scripts/generate_motion_track.py",
"--mode",
"slider",
"--distance",
"128",
"--duration-ms",
"1100",
]
)
template = run_json(
[
"scripts/solver_request_template.py",
"--platform",
"2captcha",
"--captcha-type",
"token-widget",
"--provider",
"recaptcha",
]
)
assets = run_json(
[
"scripts/inspect_assets.py",
"--captcha-type",
"slider",
"--provided",
"background_or_screenshot",
"--provided",
"track_width",
]
)
success_baseline = check_success_baseline()
tile_restore = check_tile_restore()
attempt_eval = check_attempt_evaluation()
refs = check_references()
checks = {
"coordinate_mapping": coord["element_css"]["x"] == 120 and coord["page_css"]["x"] == 140,
"motion_track": track["mode"] == "slider" and len(track["points"]) >= 2,
"solver_template": template["send_request"] is False and "api_key" in template,
"asset_inspection": assets["ready_for_offline_flow"] is True,
"success_baseline": success_baseline["passed"],
"tile_restore": tile_restore["passed"],
"attempt_evaluation": attempt_eval["passed"],
"references": refs["passed"],
}
report = {
"passed": all(checks.values()),
"checks": checks,
"success_baseline": success_baseline,
"tile_restore": tile_restore,
"attempt_evaluation": attempt_eval,
"reference_missing": refs["missing"],
}
print(json.dumps(report, ensure_ascii=False, indent=2))
return 0 if report["passed"] else 1
if __name__ == "__main__":
raise SystemExit(main())