added material

This commit is contained in:
Jeremy Janella
2026-05-09 23:21:13 -04:00
commit 8da2d2fd6f
369 changed files with 3468754 additions and 0 deletions
@@ -0,0 +1,430 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading data from: label_flipping_dataset.npz\n",
"Data loaded successfully.\n",
"X_train shape: (700, 2), y_train shape: (700,)\n",
"Unique classes in training data: [0 1]\n"
]
}
],
"source": [
"import numpy as np\n",
"import json\n",
"import requests\n",
"from sklearn.linear_model import LogisticRegression\n",
"import os\n",
"\n",
"dataset_filename = \"label_flipping_dataset.npz\"\n",
"random_seed = 1337 # Seed for reproducibility in attack & model training\n",
"np.random.seed(random_seed) # Apply seed globally if needed, or pass to functions\n",
"\n",
"# >>> IMPORTANT: SET THIS VARIABLE TO YOUR SPAWNED INSTANCE IP AND PORT<<<\n",
"evaluator_base_url = \"http://154.57.164.78:32553\" # CHANGE THIS\n",
"# Example: evaluator_base_url = \"http://10.10.10.1:5555\"\n",
"\n",
"# Attack Configuration\n",
"TARGET_CLASS_TO_POISON = 0 # We want to make the model bad at identifying Class 0\n",
"NEW_LABEL_FOR_POISONED = 1 # We want it to predict Class 1 instead\n",
"POISON_FRACTION = 0.60\n",
"\n",
"# Load Data\n",
"print(f\"Loading data from: {dataset_filename}\")\n",
"try:\n",
" data = np.load(dataset_filename)\n",
" X_train = data[\"Xtr\"]\n",
" y_train = data[\"ytr\"]\n",
" X_test = data[\"Xte\"]\n",
" y_test = data[\"yte\"]\n",
" print(\"Data loaded successfully.\")\n",
" print(f\"X_train shape: {X_train.shape}, y_train shape: {y_train.shape}\")\n",
" unique_classes_train = np.unique(y_train)\n",
" print(f\"Unique classes in training data: {unique_classes_train}\")\n",
" if (\n",
" TARGET_CLASS_TO_POISON not in unique_classes_train\n",
" or NEW_LABEL_FOR_POISONED not in unique_classes_train\n",
" ):\n",
" print(\"Warning: Target or new label class not found in training data.\")\n",
" data.close()\n",
"except FileNotFoundError:\n",
" print(f\"Error: Dataset file '{dataset_filename}' not found.\")\n",
" raise\n",
"except KeyError as e:\n",
" print(f\"Error: Could not find expected array key '{e}' in the .npz file.\")\n",
" raise\n",
"except Exception as e:\n",
" print(f\"An unexpected error occurred during data loading: {e}\")\n",
" raise"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# def targeted_flip_labels(y, poison_percentage, target_class, new_class, seed=1337):\n",
"def targeted_class_label_flip(y_train, target_class, new_label, poison_fraction, seed):\n",
" if not 0 <= poison_fraction <= 1:\n",
" raise ValueError(\"poison_fraction must be between 0 and 1.\")\n",
" if target_class == new_label:\n",
" raise ValueError(\"target_class and new_label cannot be the same.\")\n",
" # Ensure target_class and new_label are present in y_train\n",
" unique_labels = np.unique(y_train)\n",
" if target_class not in unique_labels:\n",
" raise ValueError(f\"target_class ({target_class}) does not exist in y_train.\")\n",
" if new_label not in unique_labels:\n",
" raise ValueError(f\"new_label ({new_label}) does not exist in y_train.\")\n",
" \n",
" # Identify indices belonging to the target class\n",
" target_indices = np.where(y_train == target_class)[0]\n",
" n_target_samples = len(target_indices)\n",
"\n",
" if n_target_samples == 0:\n",
" print(f\"Warning: No samples found for target_class {target_class}. No labels flipped.\")\n",
" return y_train.copy(), np.array([], dtype=int)\n",
" \n",
" # Calculate the number of labels to flip within the target class\n",
" n_to_flip = int(n_target_samples * poison_fraction)\n",
"\n",
" if n_to_flip == 0:\n",
" print(f\"Warning: Poison percentage ({poison_fraction * 100:.1f}%) is too low \"\n",
" f\"to flip any labels in the target class (size {n_target_samples}).\")\n",
" return y_train.copy(), np.array([], dtype=int)\n",
"\n",
" # Use a dedicated random number generator instance with the specified seed\n",
" rng_instance = np.random.default_rng(seed)\n",
"\n",
" # Randomly select indices from the target_indices subset to flip\n",
" # These are indices relative to the target_indices array\n",
" indices_within_target_set_to_flip = rng_instance.choice(\n",
" n_target_samples, size=n_to_flip, replace=False\n",
" )\n",
" # Map these back to the original array indices\n",
" flipped_indices = target_indices[indices_within_target_set_to_flip]\n",
"\n",
" # Create a copy to avoid modifying the original array\n",
" y_poisoned = y_train.copy()\n",
"\n",
" # Perform the flip for the selected indices to the new class label\n",
" y_poisoned[flipped_indices] = new_label\n",
"\n",
" print(f\"Targeting Class {target_class} for flipping to Class {new_label}.\")\n",
" print(f\"Identified {n_target_samples} samples of Class {target_class}.\")\n",
" print(f\"Attempting to flip {poison_fraction * 100:.1f}% ({n_to_flip} samples) of these.\")\n",
" print(f\"Successfully flipped {len(flipped_indices)} labels.\")\n",
"\n",
" return y_poisoned, flipped_indices"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Targeting Class 0 for flipping to Class 1.\n",
"Identified 347 samples of Class 0.\n",
"Attempting to flip 60.0% (208 samples) of these.\n",
"Successfully flipped 208 labels.\n",
"\n",
"--- Post-Attack Checks ---\n",
"Attack function executed, 208 label(s) flipped.\n",
"Indices of flipped labels in training data (first 10): [672 170 374 91 1 224 145 644 233 27]\n",
"Original labels at flipped indices (first 10): [0 0 0 0 0 0 0 0 0 0]\n",
"Poisoned labels at flipped indices (first 10): [1 1 1 1 1 1 1 1 1 1]\n",
"Shape of poisoned labels array: (700,)\n"
]
}
],
"source": [
"# Execute the attack\n",
"y_train_poisoned, flipped_idx = targeted_class_label_flip(\n",
" y_train,\n",
" target_class=TARGET_CLASS_TO_POISON,\n",
" new_label=NEW_LABEL_FOR_POISONED,\n",
" poison_fraction=POISON_FRACTION,\n",
" seed=random_seed,\n",
")\n",
"\n",
"# Basic Checks\n",
"print(\"\\n--- Post-Attack Checks ---\")\n",
"if flipped_idx.size > 0:\n",
" print(f\"Attack function executed, {len(flipped_idx)} label(s) flipped.\")\n",
" print(f\"Indices of flipped labels in training data (first 10): {flipped_idx[:10]}\")\n",
" print(f\"Original labels at flipped indices (first 10): {y_train[flipped_idx[:10]]}\")\n",
" print(\n",
" f\"Poisoned labels at flipped indices (first 10): {y_train_poisoned[flipped_idx[:10]]}\"\n",
" )\n",
" print(f\"Shape of poisoned labels array: {y_train_poisoned.shape}\")\n",
"else:\n",
" print(\n",
" \"Attack function ran, but no labels were flipped (check settings and warnings).\"\n",
" )\n",
" print(\"Proceeding with potentially unpoisoned labels.\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"--- Training Model on Poisoned Labels ---\n",
"Logistic Regression model trained successfully.\n"
]
}
],
"source": [
"# %%\n",
"# Train Model using Logistic Regression (Same as before)\n",
"print(\"\\n--- Training Model on Poisoned Labels ---\")\n",
"model = LogisticRegression(random_state=random_seed, solver=\"liblinear\")\n",
"\n",
"try:\n",
" # Train on original features but poisoned labels\n",
" model.fit(X_train, y_train_poisoned)\n",
" print(\"Logistic Regression model trained successfully.\")\n",
"except Exception as e:\n",
" print(f\"Error during model training: {e}\")\n",
" raise"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"--- Extracting Model Parameters ---\n",
"Extracted weights shape: (1, 2)\n",
"Extracted intercept shape: (1,)\n"
]
}
],
"source": [
"print(\"\\n--- Extracting Model Parameters ---\")\n",
"try:\n",
" weights = model.coef_\n",
" intercept = model.intercept_\n",
" print(f\"Extracted weights shape: {weights.shape}\")\n",
" print(f\"Extracted intercept shape: {intercept.shape}\")\n",
" weights_list = weights.tolist()\n",
" intercept_list = intercept.tolist()\n",
" parameters_extracted = True\n",
"except Exception as e:\n",
" print(f\"An unexpected error occurred during parameter extraction: {e}\")\n",
" weights_list = None\n",
" intercept_list = None\n",
" parameters_extracted = False"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Checking evaluator health at: http://154.57.164.78:32553/health\n",
"\n",
"--- Health Check Response ---\n",
"Status: healthy\n",
"Message: Evaluator API running.\n"
]
}
],
"source": [
"health_check_url = f\"{evaluator_base_url}/health\"\n",
"print(f\"Checking evaluator health at: {health_check_url}\")\n",
"if \"<EVALUATOR_IP>\" in evaluator_base_url:\n",
" print(\"\\n--- WARNING ---\")\n",
" print(\n",
" \"Please update the 'evaluator_base_url' variable with the correct IP and Port before running!\"\n",
" )\n",
" print(\"-------------\")\n",
"else:\n",
" try:\n",
" response = requests.get(health_check_url, timeout=10)\n",
" response.raise_for_status()\n",
" health_status = response.json()\n",
" print(\"\\n--- Health Check Response ---\")\n",
" print(f\"Status: {health_status.get('status', 'N/A')}\")\n",
" print(f\"Message: {health_status.get('message', 'No message received.')}\")\n",
" if health_status.get(\"status\") != \"healthy\":\n",
" print(\n",
" \"\\nWarning: Evaluator service reported an unhealthy status. It might still be starting up or encountered an issue (like loading data).\"\n",
" )\n",
" except requests.exceptions.ConnectionError as e:\n",
" print(f\"\\nConnection Error: Could not connect to {health_check_url}.\")\n",
" print(\"Please check:\")\n",
" print(\" 1. The evaluator URL (IP address and port) is correct.\")\n",
" print(\" 2. The evaluator Docker container is running.\")\n",
" print(\n",
" \" 3. There are no network issues (firewalls, etc.) blocking the connection.\"\n",
" )\n",
" except requests.exceptions.Timeout:\n",
" print(f\"\\nTimeout Error: The request to {health_check_url} timed out.\")\n",
" print(\n",
" \"The server might be taking too long to respond or there could be network issues.\"\n",
" )\n",
" except requests.exceptions.RequestException as e:\n",
" print(f\"\\nError during health check request: {e}\")\n",
" print(\"Check the URL format and ensure the server is running.\")\n",
" except json.JSONDecodeError:\n",
" print(\"\\nError: Could not decode JSON response from health check.\")\n",
" print(\"The server might have sent an invalid response.\")\n",
" print(\n",
" f\"Raw response status: {response.status_code}, Raw response text: {response.text}\"\n",
" )\n",
" except Exception as e:\n",
" print(f\"\\nAn unexpected error occurred during health check: {e}\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Attempting submission to: http://154.57.164.78:32553/evaluate_targeted\n",
"Payload preview: {\n",
" \"coef\": [\n",
" [\n",
" 0.5122360892231508,\n",
" -0.22736468024302808\n",
" ]\n",
" ],\n",
" \"intercept\": [\n",
" 1.59578101904743\n",
" ]\n",
"}\n",
"\n",
"--- Evaluator Response ---\n",
"========== Attack Successful! ==========\n",
"Overall Accuracy evaluated: 0.6100\n",
"Accuracy on Class 0 samples: 0.2353\n",
"Message: Attack successful! Model accuracy on Class 0 (0.2353) is below threshold. Overall accuracy (0.6100) maintained.\n",
"\n",
"FLAG: HTB{l4b3l_fl1pp1ng_targeted_pwnz}\n",
"======================================\n"
]
}
],
"source": [
"evaluator_url = f\"{evaluator_base_url}/evaluate_targeted\"\n",
"print(f\"\\nAttempting submission to: {evaluator_url}\")\n",
"\n",
"if not parameters_extracted:\n",
" print(\"Error: Cannot submit - parameters not extracted.\")\n",
"elif \"<EVALUATOR_IP>\" in evaluator_base_url or \"<PORT>\" in evaluator_base_url:\n",
" print(\"\\n--- WARNING: Update evaluator_base_url ---\")\n",
"else:\n",
" payload = {\"coef\": weights_list, \"intercept\": intercept_list}\n",
" print(f\"Payload preview: {json.dumps(payload, indent=2)}\")\n",
"\n",
" try:\n",
" response = requests.post(evaluator_url, json=payload, timeout=30)\n",
" response.raise_for_status()\n",
" result = response.json()\n",
"\n",
" print(\"\\n--- Evaluator Response ---\")\n",
" if result.get(\"success\"):\n",
" print(f\"{'=' * 10} Attack Successful! {'=' * 10}\")\n",
" oa_str = (\n",
" f\"{result.get('overall_accuracy', 'N/A'):.4f}\"\n",
" if isinstance(result.get(\"overall_accuracy\"), (int, float))\n",
" else \"N/A\"\n",
" )\n",
" c0a_str = (\n",
" f\"{result.get('class0_accuracy', 'N/A'):.4f}\"\n",
" if isinstance(result.get(\"class0_accuracy\"), (int, float))\n",
" else \"N/A\"\n",
" ) # Get Class 0 Accuracy\n",
" print(f\"Overall Accuracy evaluated: {oa_str}\")\n",
" print(f\"Accuracy on Class 0 samples: {c0a_str}\") # Display Class 0 Accuracy\n",
" print(f\"Message: {result.get('message', 'N/A')}\")\n",
" print(f\"\\nFLAG: {result.get('flag')}\")\n",
" print(f\"{'=' * 38}\")\n",
" else:\n",
" print(\"Evaluation Failed.\")\n",
" oa_val = result.get(\"overall_accuracy\")\n",
" c0a_val = result.get(\"class0_accuracy\") # Get Class 0 Accuracy\n",
" oa_str = f\"{oa_val:.4f}\" if oa_val is not None else \"N/A\"\n",
" c0a_str = (\n",
" f\"{c0a_val:.4f}\" if c0a_val is not None else \"N/A\"\n",
" ) # Get Class 0 Accuracy\n",
"\n",
" print(f\"Overall Accuracy evaluated: {oa_str}\")\n",
" print(f\"Accuracy on Class 0 samples: {c0a_str}\") # Display Class 0 Accuracy\n",
" print(f\"Message: {result.get('message', 'No message provided.')}\")\n",
" print(\n",
" \"\\nHints: Did the attack significantly reduce accuracy specifically for Class 0 samples?\"\n",
" )\n",
" print(\"Did the overall accuracy remain above the required threshold?\")\n",
" print(\"Consider adjusting the POISON_FRACTION.\")\n",
"\n",
" except requests.exceptions.ConnectionError:\n",
" print(f\"\\nConnection Error: Could not connect to {evaluator_url}.\")\n",
" except requests.exceptions.Timeout:\n",
" print(f\"\\nTimeout Error: Request to {evaluator_url} timed out.\")\n",
" except requests.exceptions.RequestException as e:\n",
" print(f\"\\nError during submission request: {e}\")\n",
" if e.response is not None:\n",
" print(f\"Server Response Status Code: {e.response.status_code}\")\n",
" try:\n",
" print(f\"Server Response Body: {e.response.json()}\")\n",
" except json.JSONDecodeError:\n",
" print(f\"Server Response Body (non-JSON): {e.response.text}\")\n",
" except Exception as e:\n",
" print(f\"\\nAn unexpected error occurred during submission: {e}\")"
]
}
],
"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": 4
}