{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Leakage and Forensics \nThese 2 challenges were quite easy, they required a basic understanding of how to feed data to recurrent networks(the first) and understanding how to read tensorflow models(the second).","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nimport requests\nfrom IPython.display import Image as Ima\nfrom IPython.display import clear_output, display\nfrom PIL import Image as Im\nfrom torch.utils.data import Dataset, DataLoader\nimport torch\nimport joblib\nimport matplotlib.pyplot as plt\nimport json\nimport base64\nimport shutil\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n\ndir_name = \"/kaggle/input/ai-village-ctf\"","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2022-09-11T22:49:13.548092Z","iopub.execute_input":"2022-09-11T22:49:13.548879Z","iopub.status.idle":"2022-09-11T22:49:15.479257Z","shell.execute_reply.started":"2022-09-11T22:49:13.548775Z","shell.execute_reply":"2022-09-11T22:49:15.478057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# A helper function for tracking flags. You could do it yourself, but why?\n\ndef add_flag(challenge_id: str, flag: str) -> str:\n    try:\n        submission_path = \"/kaggle/working/submission.csv\"\n        template_path = f\"{dir_name}/submission.csv\"\n        if not os.path.isfile(submission_path) :\n            shutil.copyfile(template_path, submission_path)\n        flags = pd.read_csv(submission_path, index_col=\"challenge_id\")\n        valid = flags.index.to_list()\n        if challenge_id in valid:\n            flags.at[challenge_id] = flag\n            flags.to_csv(submission_path)\n            print(\"Flag saved. If you want to update the scoreboard, click 'submit' on the right. Remember that you can only update your score on the scoreboard 50 times per day\")\n        else:\n            print(\"Invalid challenge_id\")\n    except:\n        print(\"We had trouble saving that flag. Keep a copy of it and contact the CTF organizers.\")","metadata":{"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2022-09-11T22:49:15.481489Z","iopub.execute_input":"2022-09-11T22:49:15.482725Z","iopub.status.idle":"2022-09-11T22:49:15.491831Z","shell.execute_reply.started":"2022-09-11T22:49:15.482675Z","shell.execute_reply":"2022-09-11T22:49:15.490785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Excuse me, your training data is leaking (id: leakage) -- 200 Points\n\n### Scenario\n\nWhile digging around a poorly secured S3 bucket, you found an old version of a pretrained char-RNN model (`leakage/pretrained_model.pt`). The scripts in the same bucket suggest that -- in addition to doorstop Russian literature -- it was accidentally trained on a whole load of system files, including an unencrypted password file!  Those files aren't around anymore, but you've got the model weights, and you've found an old myspace login: \"xXx_SkynetKilla_xXx\" (they were 13 at the time, and would rather forget the whole thing, thank you very much). Can you recover their password?\n","metadata":{}},{"cell_type":"code","source":"import torch\nfrom torch import nn\nfrom torch.nn import functional as F\n#model structure\nclass LM(nn.Module):\n    def __init__(self):\n        super(LM, self).__init__()\n        self.E = nn.Embedding(256, 32)\n        self.LSTM = nn.LSTM(32,128, 2, batch_first=True, dropout=.1)\n        self.predict = nn.Sequential(\n            nn.Linear(128, 128),\n            nn.LayerNorm(128),\n            nn.ELU(),\n            nn.Linear(128, 256)\n        )\n    def forward(self, x):\n        h = self.E(x)\n        h = self.LSTM(h)[0][:,-1,:]\n        h = self.predict(h)\n        return h\n\ndef featurize(s):\n    return torch.Tensor([[int(ord(x)) for x in s]]).long()\n\nmodel = LM()\n#load trained model\nmodel.load_state_dict(torch.load(\"../input/ai-village-ctf/leakage/pretrained_model.pt\"))\n#see what is next char for the given username\nchr(torch.argmax(model(featurize(\"xXx_SkynetKilla_xXx\"))))","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:49:15.493401Z","iopub.execute_input":"2022-09-11T22:49:15.493719Z","iopub.status.idle":"2022-09-11T22:49:15.630300Z","shell.execute_reply.started":"2022-09-11T22:49:15.493690Z","shell.execute_reply":"2022-09-11T22:49:15.629479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We see \":\"\n\nit's likely that the passwords were saved in \"username:password\" format.","metadata":{}},{"cell_type":"code","source":"username=featurize(\"xXx_SkynetKilla_xXx\")\nh = model.E(username)\nh,m = model.LSTM(h)\nres=\"\"\nfor i in range(50):\n    char=chr(torch.argmax(model.predict(h[:,-1,:])))\n    #print(char)\n    res+=char\n    if char==\"}\":\n        print(res)\n        break\n    h = model.E(torch.Tensor([[int(ord(char))]]).long())\n    h,m=model.LSTM(h,m)","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:49:15.632940Z","iopub.execute_input":"2022-09-11T22:49:15.633713Z","iopub.status.idle":"2022-09-11T22:49:15.659655Z","shell.execute_reply.started":"2022-09-11T22:49:15.633678Z","shell.execute_reply":"2022-09-11T22:49:15.658430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Sunmit result\ntry:\n    r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"leakage\", \"submission\": res[1:]}))\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:49:15.661503Z","iopub.execute_input":"2022-09-11T22:49:15.662287Z","iopub.status.idle":"2022-09-11T22:49:16.340660Z","shell.execute_reply.started":"2022-09-11T22:49:15.662240Z","shell.execute_reply":"2022-09-11T22:49:16.339235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"leakage\", r.text.split(\"The flag is \")[1].replace(\".\",\"\"))\nr.text.split(\"The flag is \")[1].replace(\".\",\"\")","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:49:16.342209Z","iopub.execute_input":"2022-09-11T22:49:16.342673Z","iopub.status.idle":"2022-09-11T22:49:16.378416Z","shell.execute_reply.started":"2022-09-11T22:49:16.342628Z","shell.execute_reply":"2022-09-11T22:49:16.377209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# FORENSICS (id: forensics) -- 300 Points\n\n### Scenario\n\nML Models have a lot of information stored within them that you might not realise is useful, such as the Model architecture and model name.\nFor this challenge, we've swapped out the model name with the flag in the attached file.\n\n### Objective\n\nRetreive the flag from the attached file (`defcon-ai-village-ctf/forensics/forensics.h5`). Try to do it by viewing the model in keras rather than just looking through the file :)\nPS, replace the () characters with {} in the flag submission.","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nnew_model = tf.keras.models.load_model('../input/ai-village-ctf/forensics/forensics.h5')\nnew_model.name","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:50:25.875116Z","iopub.execute_input":"2022-09-11T22:50:25.875558Z","iopub.status.idle":"2022-09-11T22:50:27.126653Z","shell.execute_reply.started":"2022-09-11T22:50:25.875521Z","shell.execute_reply":"2022-09-11T22:50:27.125267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Well this was straightforward","metadata":{}},{"cell_type":"code","source":"\nflag=new_model.name.replace(\"(\",\"{\").replace(\")\",\"}\")\n\ntry:\n    r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"forensics\", \"submission\": flag}))\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:50:31.570874Z","iopub.execute_input":"2022-09-11T22:50:31.571667Z","iopub.status.idle":"2022-09-11T22:50:32.301911Z","shell.execute_reply.started":"2022-09-11T22:50:31.571620Z","shell.execute_reply":"2022-09-11T22:50:32.300774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"forensics\", r.text.split(\"The flag is \")[1].replace(\".\",\"\"))\nr.text.split(\"The flag is \")[1].replace(\".\",\"\")","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:50:35.347775Z","iopub.execute_input":"2022-09-11T22:50:35.348205Z","iopub.status.idle":"2022-09-11T22:50:35.362380Z","shell.execute_reply.started":"2022-09-11T22:50:35.348167Z","shell.execute_reply":"2022-09-11T22:50:35.361503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Horrible one liner for Forensics","metadata":{}},{"cell_type":"code","source":"add_flag(\"forensics\",requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"forensics\", \"submission\":tf.keras.models.load_model('../input/ai-village-ctf/forensics/forensics.h5').name.replace(\"(\",\"{\").replace(\")\",\"}\")})).text.split(\"The flag is \")[1].replace(\".\",\"\"))","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:51:48.587676Z","iopub.execute_input":"2022-09-11T22:51:48.588069Z","iopub.status.idle":"2022-09-11T22:51:50.343388Z","shell.execute_reply.started":"2022-09-11T22:51:48.588038Z","shell.execute_reply":"2022-09-11T22:51:50.342191Z"},"trusted":true},"execution_count":null,"outputs":[]}]}