added material
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
@@ -0,0 +1,183 @@
|
||||
{
|
||||
"white_box": [
|
||||
{
|
||||
"num_words": 0,
|
||||
"evasion_rate": 7.03125,
|
||||
"evaded": 9,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 5,
|
||||
"evasion_rate": 41.40625,
|
||||
"evaded": 53,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 10,
|
||||
"evasion_rate": 74.21875,
|
||||
"evaded": 95,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 15,
|
||||
"evasion_rate": 96.09375,
|
||||
"evaded": 123,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 20,
|
||||
"evasion_rate": 100.0,
|
||||
"evaded": 128,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 25,
|
||||
"evasion_rate": 100.0,
|
||||
"evaded": 128,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 30,
|
||||
"evasion_rate": 100.0,
|
||||
"evaded": 128,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 35,
|
||||
"evasion_rate": 100.0,
|
||||
"evaded": 128,
|
||||
"total": 128
|
||||
},
|
||||
{
|
||||
"num_words": 40,
|
||||
"evasion_rate": 100.0,
|
||||
"evaded": 128,
|
||||
"total": 128
|
||||
}
|
||||
],
|
||||
"black_box": [],
|
||||
"top_good_words": [
|
||||
[
|
||||
"lor",
|
||||
50.94243874392973
|
||||
],
|
||||
[
|
||||
"\u00fc",
|
||||
47.57124794469911
|
||||
],
|
||||
[
|
||||
"...",
|
||||
45.80542826853246
|
||||
],
|
||||
[
|
||||
"da",
|
||||
45.69836416734876
|
||||
],
|
||||
[
|
||||
"later",
|
||||
29.966140437605727
|
||||
],
|
||||
[
|
||||
"doing",
|
||||
26.220372882905004
|
||||
],
|
||||
[
|
||||
"really",
|
||||
25.47121937196488
|
||||
],
|
||||
[
|
||||
"ask",
|
||||
24.722065861024724
|
||||
],
|
||||
[
|
||||
"cos",
|
||||
23.598335594614515
|
||||
],
|
||||
[
|
||||
"lol",
|
||||
23.598335594614515
|
||||
],
|
||||
[
|
||||
"said",
|
||||
23.22375883914445
|
||||
],
|
||||
[
|
||||
"..",
|
||||
22.795692105601425
|
||||
],
|
||||
[
|
||||
"sure",
|
||||
21.35087506179409
|
||||
],
|
||||
[
|
||||
"k",
|
||||
20.78902109332076
|
||||
],
|
||||
[
|
||||
"come",
|
||||
20.601736303054754
|
||||
],
|
||||
[
|
||||
"morning",
|
||||
19.852568039913795
|
||||
],
|
||||
[
|
||||
"thing",
|
||||
19.103414528973666
|
||||
],
|
||||
[
|
||||
"feel",
|
||||
17.97968426256344
|
||||
],
|
||||
[
|
||||
"oh",
|
||||
17.230540005274868
|
||||
],
|
||||
[
|
||||
"going",
|
||||
16.980825074033003
|
||||
]
|
||||
],
|
||||
"word_impacts": [
|
||||
[
|
||||
"lor",
|
||||
7.131785940645545
|
||||
],
|
||||
[
|
||||
"\u00fc",
|
||||
7.036803994633465
|
||||
],
|
||||
[
|
||||
"...",
|
||||
6.98438558531918
|
||||
],
|
||||
[
|
||||
"da",
|
||||
6.981145003801362
|
||||
],
|
||||
[
|
||||
"later",
|
||||
6.394759474192664
|
||||
],
|
||||
[
|
||||
"doing",
|
||||
6.206539871713527
|
||||
],
|
||||
[
|
||||
"really",
|
||||
6.165373493147777
|
||||
],
|
||||
[
|
||||
"ask",
|
||||
6.122846010746446
|
||||
],
|
||||
[
|
||||
"cos",
|
||||
6.056288389188433
|
||||
],
|
||||
[
|
||||
"lol",
|
||||
6.056288389188438
|
||||
]
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "33563458-e157-4771-bd54-7676036c1d73",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Base message: 'England v Macedonia - dont miss the goals/team news. Txt ur national team to 87077 eg ENGLAND to 87077 Try:WALES, SCOTLAND 4txt/ú1.20 POBOXox36504W45WQ 16+'\n",
|
||||
"Budget: 25\n",
|
||||
"\n",
|
||||
"Final message: 'England v Macedonia - dont miss the goals/team news. Txt ur national team to 87077 eg ENGLAND to 87077 Try:WALES, SCOTLAND 4txt/ú1.20 POBOXox36504W45WQ 16+ later home morning fine nice lunch meeting happy'\n",
|
||||
"Words used: 8\n",
|
||||
"Final classification: ham (spam prob: 0.1077)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import requests\n",
|
||||
"import random\n",
|
||||
"import numpy as np\n",
|
||||
"from typing import List, Tuple\n",
|
||||
"\n",
|
||||
"# Seed for reproducibility\n",
|
||||
"random.seed(1337)\n",
|
||||
"np.random.seed(1337)\n",
|
||||
"\n",
|
||||
"# Get challenge from server\n",
|
||||
"host = \"http://154.57.164.78:31757\"\n",
|
||||
"ch = requests.get(f\"{host}/challenge\", timeout=10).json()\n",
|
||||
"base, budget = ch[\"base_message\"], int(ch[\"max_added_words\"])\n",
|
||||
"\n",
|
||||
"def predict(host, text):\n",
|
||||
" r = requests.post(f\"{host}/predict\", json={\"text\": text}, timeout=15)\n",
|
||||
" data = r.json()\n",
|
||||
" return data[\"label\"], float(data[\"spam_probability\"])\n",
|
||||
"\n",
|
||||
"vocab = list(dict.fromkeys([\n",
|
||||
" # salutations and courtesy\n",
|
||||
" \"hello\", \"hi\", \"dear\", \"please\", \"thanks\", \"thankyou\", \"regards\", \"sincerely\",\n",
|
||||
" \"kind\", \"wishes\", \"best\", \"appreciate\", \"welcome\", \"friend\", \"family\",\n",
|
||||
" # everyday context\n",
|
||||
" \"meeting\", \"tomorrow\", \"today\", \"later\", \"morning\", \"night\", \"home\", \"work\",\n",
|
||||
" \"office\", \"schedule\", \"confirm\", \"call\", \"reply\", \"message\", \"note\", \"update\",\n",
|
||||
" # positive tone\n",
|
||||
" \"happy\", \"birthday\", \"congratulations\", \"joy\", \"peace\", \"smile\", \"care\",\n",
|
||||
" \"support\", \"help\", \"good\", \"great\", \"wonderful\", \"awesome\", \"nice\", \"cool\",\n",
|
||||
" \"fine\", \"okay\",\n",
|
||||
" # social\n",
|
||||
" \"lunch\", \"dinner\", \"coffee\", \"weekend\", \"party\", \"invite\", \"visit\", \"enjoy\",\n",
|
||||
" # misc\n",
|
||||
" \"true\", \"honest\", \"trust\", \"safe\", \"project\", \"team\"\n",
|
||||
"]))\n",
|
||||
"\n",
|
||||
"def estimate_word_impacts(\n",
|
||||
" host: str, base_msg: str, words: List[str]\n",
|
||||
") -> List[Tuple[str, float]]:\n",
|
||||
" _, base_prob = predict(host, base_msg)\n",
|
||||
" impacts: List[Tuple[str, float]] = []\n",
|
||||
" for w in words:\n",
|
||||
" augmented = f\"{base_msg} {w}\"\n",
|
||||
" _, new_prob = predict(host, augmented)\n",
|
||||
" impacts.append((w, base_prob - new_prob))\n",
|
||||
" impacts.sort(key=lambda x: x[1], reverse=True)\n",
|
||||
" return impacts\n",
|
||||
"\n",
|
||||
"def greedy_compose(\n",
|
||||
" host: str, base_msg: str, top_words: List[str], budget: int, target_label: str\n",
|
||||
") -> Tuple[str, int, float]:\n",
|
||||
" augmented = base_msg\n",
|
||||
" used = 0\n",
|
||||
" for w in top_words:\n",
|
||||
" if used >= budget:\n",
|
||||
" break\n",
|
||||
" augmented = f\"{augmented} {w}\"\n",
|
||||
" used += 1\n",
|
||||
" label, prob = predict(host, augmented)\n",
|
||||
" if label == target_label:\n",
|
||||
" return augmented, used, prob\n",
|
||||
" label, prob = predict(host, augmented)\n",
|
||||
" return augmented, used, prob\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"if __name__ == \"__main__\":\n",
|
||||
" print(f\"Base message: '{base}'\\nBudget: {budget}\")\n",
|
||||
"\n",
|
||||
" #Estimate which words help reduce spam probability\n",
|
||||
" impacts = estimate_word_impacts(host, base, vocab)\n",
|
||||
" top_words = [w for w, delta in impacts if delta > 0]\n",
|
||||
"\n",
|
||||
" #Try to fix the message using greedy approach\n",
|
||||
" final_msg, used, final_prob = greedy_compose(host, base, top_words, budget, target_label=\"ham\")\n",
|
||||
" final_label, _ = predict(host, final_msg)\n",
|
||||
"\n",
|
||||
" print(f\"\\nFinal message: '{final_msg}'\")\n",
|
||||
" print(f\"Words used: {used}\")\n",
|
||||
" print(f\"Final classification: {final_label} (spam prob: {final_prob:.4f})\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f010b0d4-4ed5-4dbc-b62b-845e6b137b5e",
|
||||
"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
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -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