[SHEHZADE//ABDULLAH ANSARI]
Red Team Consultant @ Google | MS in Cybersecurity @ NYU
● Notice //GitHub (@shehzade) is temporarily suspended pending an automated false-positive review. All tools are hosted on this Code Mirror and available on request (contact); GitHub links will return once reinstated.
PUBLIC MIRRORPython
AI-driven badge OSINT, credential harvesting, and calibrated CR80 card cloning for physical red teams.
$
git clone https://shehzade.io/repos/lanyard.git
Copy
Source ZIP (1.35 MB)
180 lines · 6.5 KB
| 1 | import json |
| 2 | import sqlite3 |
| 3 | from pathlib import Path |
| 4 | |
| 5 | from lanyard.vision.models import BadgeFinding |
| 6 | |
| 7 | |
| 8 | class Database: |
| 9 | def __init__(self, db_path: Path | str): |
| 10 | self.db_path = Path(db_path) |
| 11 | self.db_path.parent.mkdir(parents=True, exist_ok=True) |
| 12 | self._init_tables() |
| 13 | |
| 14 | def _get_conn(self) -> sqlite3.Connection: |
| 15 | conn = sqlite3.connect(self.db_path) |
| 16 | conn.row_factory = sqlite3.Row |
| 17 | return conn |
| 18 | |
| 19 | def _init_tables(self) -> None: |
| 20 | with self._get_conn() as conn: |
| 21 | conn.execute(""" |
| 22 | CREATE TABLE IF NOT EXISTS images ( |
| 23 | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| 24 | image_url TEXT UNIQUE, |
| 25 | post_url TEXT, |
| 26 | post_author TEXT, |
| 27 | post_caption TEXT, |
| 28 | analyzed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
| 29 | ) |
| 30 | """) |
| 31 | conn.execute(""" |
| 32 | CREATE TABLE IF NOT EXISTS findings ( |
| 33 | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| 34 | image_id INTEGER, |
| 35 | has_badge INTEGER, |
| 36 | confidence REAL, |
| 37 | badge_type TEXT, |
| 38 | employee_name TEXT, |
| 39 | company_name TEXT, |
| 40 | department_or_role TEXT, |
| 41 | id_or_badge_number TEXT, |
| 42 | security_features TEXT, |
| 43 | summary TEXT, |
| 44 | crop_path TEXT, |
| 45 | original_path TEXT, |
| 46 | template_path TEXT, |
| 47 | card_corners TEXT, |
| 48 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
| 49 | FOREIGN KEY (image_id) REFERENCES images(id) |
| 50 | ) |
| 51 | """) |
| 52 | try: |
| 53 | conn.execute("ALTER TABLE images ADD COLUMN post_author TEXT") |
| 54 | except Exception: |
| 55 | pass |
| 56 | try: |
| 57 | conn.execute("ALTER TABLE images ADD COLUMN post_caption TEXT") |
| 58 | except Exception: |
| 59 | pass |
| 60 | try: |
| 61 | conn.execute("ALTER TABLE findings ADD COLUMN template_path TEXT") |
| 62 | except Exception: |
| 63 | pass |
| 64 | try: |
| 65 | conn.execute("ALTER TABLE findings ADD COLUMN card_corners TEXT") |
| 66 | except Exception: |
| 67 | pass |
| 68 | conn.commit() |
| 69 | |
| 70 | def is_image_analyzed(self, image_url: str) -> bool: |
| 71 | with self._get_conn() as conn: |
| 72 | cur = conn.execute("SELECT id FROM images WHERE image_url = ?", (image_url,)) |
| 73 | return cur.fetchone() is not None |
| 74 | |
| 75 | def record_image( |
| 76 | self, |
| 77 | image_url: str, |
| 78 | post_url: str | None = None, |
| 79 | post_author: str | None = None, |
| 80 | post_caption: str | None = None, |
| 81 | ) -> int: |
| 82 | with self._get_conn() as conn: |
| 83 | cur = conn.execute( |
| 84 | """ |
| 85 | INSERT OR IGNORE INTO images (image_url, post_url, post_author, post_caption) |
| 86 | VALUES (?, ?, ?, ?) |
| 87 | """, |
| 88 | (image_url, post_url or "", post_author or "", post_caption or ""), |
| 89 | ) |
| 90 | conn.commit() |
| 91 | if cur.lastrowid and cur.lastrowid > 0: |
| 92 | return cur.lastrowid |
| 93 | cur = conn.execute("SELECT id FROM images WHERE image_url = ?", (image_url,)) |
| 94 | row = cur.fetchone() |
| 95 | return row["id"] if row else -1 |
| 96 | |
| 97 | def record_finding( |
| 98 | self, |
| 99 | image_id: int, |
| 100 | finding: BadgeFinding, |
| 101 | crop_path: str | None = None, |
| 102 | original_path: str | None = None, |
| 103 | template_path: str | None = None, |
| 104 | ) -> int: |
| 105 | corners_json = json.dumps(finding.card_corners.model_dump()) if finding.card_corners else None |
| 106 | with self._get_conn() as conn: |
| 107 | cur = conn.execute( |
| 108 | """ |
| 109 | INSERT INTO findings ( |
| 110 | image_id, has_badge, confidence, badge_type, |
| 111 | employee_name, company_name, department_or_role, |
| 112 | id_or_badge_number, security_features, summary, |
| 113 | crop_path, original_path, template_path, card_corners |
| 114 | ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) |
| 115 | """, |
| 116 | ( |
| 117 | image_id, |
| 118 | 1 if finding.has_badge else 0, |
| 119 | finding.confidence, |
| 120 | finding.badge_type, |
| 121 | finding.employee_name, |
| 122 | finding.company_name, |
| 123 | finding.department_or_role, |
| 124 | finding.id_or_badge_number, |
| 125 | json.dumps(finding.security_features), |
| 126 | finding.summary, |
| 127 | crop_path or "", |
| 128 | original_path or "", |
| 129 | template_path or "", |
| 130 | corners_json, |
| 131 | ), |
| 132 | ) |
| 133 | conn.commit() |
| 134 | return cur.lastrowid or -1 |
| 135 | |
| 136 | def update_finding_cr80( |
| 137 | self, |
| 138 | finding_id: int, |
| 139 | template_path: str, |
| 140 | card_corners: dict | None = None, |
| 141 | ) -> None: |
| 142 | with self._get_conn() as conn: |
| 143 | if card_corners is not None: |
| 144 | conn.execute( |
| 145 | "UPDATE findings SET template_path = ?, card_corners = ? WHERE id = ?", |
| 146 | (template_path, json.dumps(card_corners), finding_id), |
| 147 | ) |
| 148 | else: |
| 149 | conn.execute( |
| 150 | "UPDATE findings SET template_path = ? WHERE id = ?", |
| 151 | (template_path, finding_id), |
| 152 | ) |
| 153 | conn.commit() |
| 154 | |
| 155 | def get_all_badge_findings(self) -> list[dict]: |
| 156 | with self._get_conn() as conn: |
| 157 | cur = conn.execute(""" |
| 158 | SELECT f.*, i.image_url, i.post_url, i.post_author, i.post_caption |
| 159 | FROM findings f |
| 160 | JOIN images i ON f.image_id = i.id |
| 161 | WHERE f.has_badge = 1 |
| 162 | ORDER BY f.confidence DESC, f.id DESC |
| 163 | """) |
| 164 | rows = cur.fetchall() |
| 165 | results = [] |
| 166 | for r in rows: |
| 167 | item = dict(r) |
| 168 | try: |
| 169 | item["security_features"] = json.loads(item.get("security_features") or "[]") |
| 170 | except Exception: |
| 171 | item["security_features"] = [] |
| 172 | if item.get("card_corners"): |
| 173 | try: |
| 174 | item["card_corners"] = json.loads(item["card_corners"]) |
| 175 | except Exception: |
| 176 | item["card_corners"] = None |
| 177 | else: |
| 178 | item["card_corners"] = None |
| 179 | results.append(item) |
| 180 | return results |