added material
This commit is contained in:
@@ -0,0 +1,329 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "e5181b56-34a6-4c2e-8045-137f8190ad56",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"[*] Starting white-box phase...\n",
|
||||
"[*] Downloading model...\n",
|
||||
"[+] Model loaded: 89972 features\n",
|
||||
" Attacking review wb_0... Done (6 words)\n",
|
||||
" Attacking review wb_1... Done (3 words)\n",
|
||||
" Attacking review wb_2... Done (3 words)\n",
|
||||
" Attacking review wb_3... Done (4 words)\n",
|
||||
" Attacking review wb_4... Done (6 words)\n",
|
||||
" Attacking review wb_5... Done (11 words)\n",
|
||||
" Attacking review wb_6... Done (5 words)\n",
|
||||
" Attacking review wb_7... Done (4 words)\n",
|
||||
" Attacking review wb_8... Done (24 words)\n",
|
||||
" Attacking review wb_9... Done (7 words)\n",
|
||||
"[+] White-box phase: 10/10 completed\n",
|
||||
"[+] White-box phase completed successfully!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import requests\n",
|
||||
"import pickle\n",
|
||||
"import numpy as np\n",
|
||||
"from typing import List, Dict, Tuple\n",
|
||||
"\n",
|
||||
"SEED = 1337\n",
|
||||
"np.random.seed(SEED)\n",
|
||||
"\n",
|
||||
"BASE_URL = \"http://154.57.164.67:30687\"\n",
|
||||
"\n",
|
||||
"class WhiteBoxAttacker:\n",
|
||||
" def __init__(self, base_url: str):\n",
|
||||
" self.base_url = base_url\n",
|
||||
" self.model = None\n",
|
||||
" self.vectorizer = None\n",
|
||||
" self.feature_names = None\n",
|
||||
" self.classes = None\n",
|
||||
"\n",
|
||||
" def download_model(self):\n",
|
||||
" print(\"[*] Downloading model...\")\n",
|
||||
" r = requests.get(f\"{self.base_url}/model/download\")\n",
|
||||
" r.raise_for_status()\n",
|
||||
"\n",
|
||||
" with open(\"/tmp/model.pkl\", \"wb\") as f:\n",
|
||||
" f.write(r.content)\n",
|
||||
"\n",
|
||||
" with open(\"/tmp/model.pkl\", \"rb\") as f:\n",
|
||||
" bundle = pickle.load(f)\n",
|
||||
"\n",
|
||||
" self.model = bundle[\"classifier\"]\n",
|
||||
" self.vectorizer = bundle[\"vectorizer\"]\n",
|
||||
" self.feature_names = bundle[\"feature_names\"]\n",
|
||||
" self.classes = bundle[\"classes\"]\n",
|
||||
" print(f\"[+] Model loaded: {len(self.feature_names)} features\")\n",
|
||||
"\n",
|
||||
" def calculate_word_scores(self, target_class: str) -> List[Tuple[str, float]]:\n",
|
||||
" target_idx = self.classes.index(target_class)\n",
|
||||
" other_idx = 1 - target_idx\n",
|
||||
"\n",
|
||||
" scores = []\n",
|
||||
" for i, feature in enumerate(self.feature_names):\n",
|
||||
" if \" \" in feature:\n",
|
||||
" continue\n",
|
||||
" target_prob = np.exp(self.model.feature_log_prob_[target_idx][i])\n",
|
||||
" other_prob = np.exp(self.model.feature_log_prob_[other_idx][i])\n",
|
||||
" score = target_prob / (other_prob + 1e-10)\n",
|
||||
" scores.append((feature, score))\n",
|
||||
"\n",
|
||||
" scores.sort(key=lambda x: x[1], reverse=True)\n",
|
||||
" return scores\n",
|
||||
"\n",
|
||||
" def attack_review(self, text: str, target: str, max_words: int) -> Tuple[str, int]:\n",
|
||||
" word_scores = self.calculate_word_scores(target)\n",
|
||||
"\n",
|
||||
" augmented = text\n",
|
||||
" for num_words in range(1, max_words + 1):\n",
|
||||
" words_to_add = [w for w, _ in word_scores[:num_words]]\n",
|
||||
" augmented = text + \" \" + \" \".join(words_to_add)\n",
|
||||
"\n",
|
||||
" vec = self.vectorizer.transform([augmented])\n",
|
||||
" prediction = self.model.predict(vec)[0]\n",
|
||||
"\n",
|
||||
" if prediction == target:\n",
|
||||
" return augmented, num_words\n",
|
||||
"\n",
|
||||
" return augmented, max_words\n",
|
||||
"\n",
|
||||
" def solve_whitebox(self) -> Dict:\n",
|
||||
" print(\"\\n[*] Starting white-box phase...\")\n",
|
||||
"\n",
|
||||
" r = requests.get(f\"{self.base_url}/challenge/whitebox\")\n",
|
||||
" r.raise_for_status()\n",
|
||||
" challenge = r.json()\n",
|
||||
"\n",
|
||||
" reviews = challenge[\"reviews\"]\n",
|
||||
" max_words = challenge[\"max_added_words\"]\n",
|
||||
"\n",
|
||||
" self.download_model()\n",
|
||||
"\n",
|
||||
" solutions = []\n",
|
||||
" for review in reviews:\n",
|
||||
" print(f\" Attacking review {review['id']}...\", end=\" \")\n",
|
||||
" augmented, words_used = self.attack_review(\n",
|
||||
" review[\"text\"], review[\"target_sentiment\"], max_words\n",
|
||||
" )\n",
|
||||
" solutions.append({\"id\": review[\"id\"], \"augmented_text\": augmented})\n",
|
||||
" print(f\"Done ({words_used} words)\")\n",
|
||||
"\n",
|
||||
" r = requests.post(\n",
|
||||
" f\"{self.base_url}/submit/whitebox\", json={\"solutions\": solutions}\n",
|
||||
" )\n",
|
||||
" r.raise_for_status()\n",
|
||||
" result = r.json()\n",
|
||||
"\n",
|
||||
" if \"results\" in result:\n",
|
||||
" successes = sum(1 for r in result[\"results\"] if r.get(\"success\", False))\n",
|
||||
" print(f\"[+] White-box phase: {successes}/10 completed\")\n",
|
||||
"\n",
|
||||
" return result\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" wb_attacker = WhiteBoxAttacker(BASE_URL)\n",
|
||||
" wb_result = wb_attacker.solve_whitebox()\n",
|
||||
"\n",
|
||||
" if not wb_result.get(\"phase_complete\", False):\n",
|
||||
" print(\"[-] Failed to complete white-box phase\")\n",
|
||||
" return\n",
|
||||
"\n",
|
||||
" print(\"[+] White-box phase completed successfully!\")\n",
|
||||
"\n",
|
||||
"if __name__ == \"__main__\":\n",
|
||||
" main()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"id": "ca580733-0f7d-401b-bd10-a29586b9f4b9",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"[*] Starting black-box phase...\n",
|
||||
" Attacking review bb_0... Done (22 words, 73 queries total)\n",
|
||||
" Attacking review bb_1... Done (40 words, 164 queries total)\n",
|
||||
" Attacking review bb_2... Done (20 words, 235 queries total)\n",
|
||||
" Attacking review bb_3... Done (17 words, 303 queries total)\n",
|
||||
" Attacking review bb_4... Done (4 words, 358 queries total)\n",
|
||||
" Attacking review bb_5... Done (38 words, 447 queries total)\n",
|
||||
" Attacking review bb_6... Done (40 words, 538 queries total)\n",
|
||||
" Attacking review bb_7... Done (4 words, 593 queries total)\n",
|
||||
" Attacking review bb_8... Done (13 words, 657 queries total)\n",
|
||||
" Attacking review bb_9... Done (6 words, 714 queries total)\n",
|
||||
"[+] Black-box phase: 10/10 completed\n",
|
||||
"\n",
|
||||
"============================================================\n",
|
||||
"[+] SUCCESS! All challenges completed!\n",
|
||||
"[+] Flag: HTB{f34tur3_0bfu5c4t10n_m45t3r3d}\n",
|
||||
"============================================================\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import requests\n",
|
||||
"import numpy as np\n",
|
||||
"from typing import List, Dict, Tuple\n",
|
||||
"\n",
|
||||
"SEED = 1337\n",
|
||||
"np.random.seed(SEED)\n",
|
||||
"\n",
|
||||
"BASE_URL = \"http://154.57.164.67:30687\"\n",
|
||||
"\n",
|
||||
"class BlackBoxAttacker:\n",
|
||||
" def __init__(self, base_url: str):\n",
|
||||
" self.base_url = base_url\n",
|
||||
" self.word_impacts = {}\n",
|
||||
" self.query_count = 0\n",
|
||||
"\n",
|
||||
" def predict(self, text: str) -> Dict:\n",
|
||||
" self.query_count += 1\n",
|
||||
" r = requests.post(f\"{self.base_url}/predict\", json={\"text\": text})\n",
|
||||
" r.raise_for_status()\n",
|
||||
" return r.json()\n",
|
||||
"\n",
|
||||
" def estimate_word_impacts(\n",
|
||||
" self, base_text: str, vocabulary: List[str]\n",
|
||||
" ) -> List[Tuple[str, float]]:\n",
|
||||
" base_pred = self.predict(base_text)\n",
|
||||
" base_pos_prob = base_pred[\"positive_probability\"]\n",
|
||||
"\n",
|
||||
" impacts = []\n",
|
||||
" for word in vocabulary:\n",
|
||||
" augmented = base_text + \" \" + word\n",
|
||||
" pred = self.predict(augmented)\n",
|
||||
" impact = pred[\"positive_probability\"] - base_pos_prob\n",
|
||||
" impacts.append((word, impact))\n",
|
||||
"\n",
|
||||
" impacts.sort(key=lambda x: x[1], reverse=True)\n",
|
||||
" return impacts\n",
|
||||
"\n",
|
||||
" def attack_review(self, text: str, max_words: int) -> Tuple[str, int]:\n",
|
||||
" positive_vocabulary = [\n",
|
||||
" \"excellent\", \"amazing\", \"wonderful\", \"fantastic\", \"brilliant\",\n",
|
||||
" \"outstanding\", \"superb\", \"magnificent\", \"perfect\", \"exceptional\",\n",
|
||||
" \"masterpiece\", \"genius\", \"beautiful\", \"stunning\", \"remarkable\",\n",
|
||||
" \"awesome\", \"incredible\", \"phenomenal\", \"spectacular\", \"marvelous\",\n",
|
||||
" \"great\", \"good\", \"love\", \"loved\", \"best\", \"favorite\", \"enjoyed\",\n",
|
||||
" \"recommend\", \"highly\", \"definitely\", \"must\", \"liked\", \"appreciate\",\n",
|
||||
" \"admire\", \"adore\", \"enjoy\", \"compelling\", \"engaging\", \"captivating\",\n",
|
||||
" \"mesmerizing\", \"powerful\", \"touching\", \"moving\", \"inspiring\",\n",
|
||||
" \"uplifting\", \"heartwarming\", \"clever\", \"witty\", \"funny\", \"hilarious\",\n",
|
||||
" \"entertaining\"\n",
|
||||
" ]\n",
|
||||
"\n",
|
||||
" impacts = self.estimate_word_impacts(text, positive_vocabulary[:50])\n",
|
||||
"\n",
|
||||
" augmented = text\n",
|
||||
" for i, (word, impact) in enumerate(impacts, 1):\n",
|
||||
" if i > max_words:\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" augmented = augmented + \" \" + word\n",
|
||||
" pred = self.predict(augmented)\n",
|
||||
"\n",
|
||||
" if pred[\"label\"] == \"positive\":\n",
|
||||
" return augmented, i\n",
|
||||
"\n",
|
||||
" if impacts:\n",
|
||||
" top_words = [w for w, _ in impacts[:10]]\n",
|
||||
" words_to_add = []\n",
|
||||
" while len(words_to_add) < max_words:\n",
|
||||
" words_to_add.extend(top_words)\n",
|
||||
" augmented = text + \" \" + \" \".join(words_to_add[:max_words])\n",
|
||||
"\n",
|
||||
" return augmented, max_words\n",
|
||||
"\n",
|
||||
" def solve_blackbox(self) -> Dict:\n",
|
||||
" print(\"\\n[*] Starting black-box phase...\")\n",
|
||||
"\n",
|
||||
" r = requests.get(f\"{self.base_url}/challenge/blackbox\")\n",
|
||||
" r.raise_for_status()\n",
|
||||
" challenge = r.json()\n",
|
||||
"\n",
|
||||
" reviews = challenge[\"reviews\"]\n",
|
||||
" max_words = challenge[\"max_added_words\"]\n",
|
||||
"\n",
|
||||
" solutions = []\n",
|
||||
" for review in reviews:\n",
|
||||
" print(f\" Attacking review {review['id']}...\", end=\" \")\n",
|
||||
" augmented, words_used = self.attack_review(review[\"text\"], max_words)\n",
|
||||
" solutions.append({\"id\": review[\"id\"], \"augmented_text\": augmented})\n",
|
||||
" print(f\"Done ({words_used} words, {self.query_count} queries total)\")\n",
|
||||
"\n",
|
||||
" r = requests.post(\n",
|
||||
" f\"{self.base_url}/submit/blackbox\", json={\"solutions\": solutions}\n",
|
||||
" )\n",
|
||||
" r.raise_for_status()\n",
|
||||
" result = r.json()\n",
|
||||
"\n",
|
||||
" if \"results\" in result:\n",
|
||||
" successes = sum(1 for r in result[\"results\"] if r.get(\"success\", False))\n",
|
||||
" print(f\"[+] Black-box phase: {successes}/10 completed\")\n",
|
||||
"\n",
|
||||
" return result\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" bb_attacker = BlackBoxAttacker(BASE_URL)\n",
|
||||
" bb_result = bb_attacker.solve_blackbox()\n",
|
||||
"\n",
|
||||
" if bb_result.get(\"flag\"):\n",
|
||||
" print(\"\\n\" + \"=\" * 60)\n",
|
||||
" print(\"[+] SUCCESS! All challenges completed!\")\n",
|
||||
" print(f\"[+] Flag: {bb_result['flag']}\")\n",
|
||||
" print(\"=\" * 60)\n",
|
||||
" else:\n",
|
||||
" print(\"[-] Failed to complete black-box phase\")\n",
|
||||
"\n",
|
||||
"if __name__ == \"__main__\":\n",
|
||||
" main()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0b9ce2a6-d30d-466c-9e79-e4054b13b4ce",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Reference in New Issue
Block a user