{"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":"# Inference\nThis challenge required participants to find the flag in an unusual way.\nWe have a network that accepts 32x32 greyscale images and outputs 6 probabilities.\n\nWe have to find the inputs that maximize those probabilities.\n\nThose inputs are numbers and letters to compose the flag.","metadata":{}},{"cell_type":"code","source":"\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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2022-09-11T22:09:29.835868Z","iopub.execute_input":"2022-09-11T22:09:29.837050Z","iopub.status.idle":"2022-09-11T22:09:29.844473Z","shell.execute_reply.started":"2022-09-11T22:09:29.837008Z","shell.execute_reply":"2022-09-11T22:09:29.843256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def 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":{"_kg_hide-input":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2022-09-11T22:09:29.846804Z","iopub.execute_input":"2022-09-11T22:09:29.847679Z","iopub.status.idle":"2022-09-11T22:09:29.856404Z","shell.execute_reply.started":"2022-09-11T22:09:29.847632Z","shell.execute_reply":"2022-09-11T22:09:29.855524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference (id: inference) -- 400 Points\n\n### Scenario\n\nModel model on the wall, who is the fairest of them all?\n\n?gnidaer llits uoy era yhW .uoy htiw skcans thguorb ev'dluohs uoY .skcans rof pots t'noD .won oG .tsaf oG .niW .galf eht teG .ledom eht esreveR\n\n### Objective\n\nRetrieve the images that spell the flag. Wrap any text in `FLAG{}`\n\n**If you need a hint, there's a guy named `moo` somewhere.**","metadata":{}},{"cell_type":"code","source":"!pip install emnist","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:09:29.857886Z","iopub.execute_input":"2022-09-11T22:09:29.858430Z","iopub.status.idle":"2022-09-11T22:09:41.671538Z","shell.execute_reply.started":"2022-09-11T22:09:29.858400Z","shell.execute_reply":"2022-09-11T22:09:41.670190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from emnist import extract_training_samples\nimages, labels = extract_training_samples('letters')\nimages_digits, labels_digits = extract_training_samples('digits')","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:09:41.673464Z","iopub.execute_input":"2022-09-11T22:09:41.673862Z","iopub.status.idle":"2022-09-11T22:09:44.637767Z","shell.execute_reply.started":"2022-09-11T22:09:41.673825Z","shell.execute_reply":"2022-09-11T22:09:44.636687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seen={}","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:09:44.656365Z","iopub.execute_input":"2022-09-11T22:09:44.656744Z","iopub.status.idle":"2022-09-11T22:09:44.662132Z","shell.execute_reply.started":"2022-09-11T22:09:44.656710Z","shell.execute_reply":"2022-09-11T22:09:44.661043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bests=[0,0,0,0,0,0]\nscore_bests=[0,0,0,0,0,0]\nscore_current_letter=[0,0,0,0,0,0]\nfrom tqdm import tqdm\nfor l in np.unique(labels):\n    #print(\"letter :\",chr(l-1+ord(\"a\")))\n    score_current_letter=[0,0,0,0,0,0]\n    res=np.zeros(6,dtype=\"float\")\n    for i in range(3):\n        img=images[labels==l][i,:,:]#first samples\n\n        img = Im.fromarray(img).resize((32,32))\n\n        x=np.array(img).reshape((1,32,32,1))/255.0\n        seen[chr(ord(\"a\")+l-1)]=x\n        \n        try:\n            response = requests.post(\"https://inference.fly.dev/score\", data = json.dumps({\"input\": x.tolist()}))\n            temp=np.array([float(v) for v in response.text.split(\"[[\")[1].split(\"]]\")[0].split(\",\")])\n            score=temp.max()\n            position=temp.argmax()\n            if score_bests[position]<score:\n                score_bests[position]=score\n                bests[position]=chr(l+ord(\"a\")-1)\n                #print(\"improved\")\n            if score_current_letter[position]<score:\n                score_current_letter[position]=score\n        except requests.exceptions.ConnectionError:\n            print(\"Connection problems. Contact the CTF organizers.\")\n        #print()\n    print(bests,score_current_letter)\n    \n","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:09:44.664756Z","iopub.execute_input":"2022-09-11T22:09:44.665211Z","iopub.status.idle":"2022-09-11T22:10:04.471766Z","shell.execute_reply.started":"2022-09-11T22:09:44.665167Z","shell.execute_reply":"2022-09-11T22:10:04.470653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for l in np.unique(labels_digits):\n    #print(\"digit :\",l)\n    score_current_digit=[0,0,0,0,0,0]\n    res=np.zeros(6,dtype=\"float\")\n    for i in range(20):\n        img=images_digits[labels_digits==l][i,:,:]#first samples\n\n        img = Im.fromarray(img).resize((32,32))\n\n        x=np.array(img).reshape((1,32,32,1))/255.0\n        \n        seen[chr(ord(\"a\")+l-1)]=x\n        \n        try:\n            response = requests.post(\"https://inference.fly.dev/score\", data = json.dumps({\"input\": x.tolist()}))\n            temp=np.array([float(v) for v in response.text.split(\"[[\")[1].split(\"]]\")[0].split(\",\")])\n            score=temp.max()\n            position=temp.argmax()\n            if score_bests[position]<score:\n                score_bests[position]=score\n                bests[position]=f\"{l}\"\n                #print(\"improved\")\n            if score_current_digit[position]<score:\n                score_current_digit[position]=score\n        except requests.exceptions.ConnectionError:\n            print(\"Connection problems. Contact the CTF organizers.\")\n        #print()\n    print(bests,score_current_digit)\n    \n\n","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:10:27.668393Z","iopub.execute_input":"2022-09-11T22:10:27.668873Z","iopub.status.idle":"2022-09-11T22:11:18.529698Z","shell.execute_reply.started":"2022-09-11T22:10:27.668834Z","shell.execute_reply":"2022-09-11T22:11:18.528615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(bests)","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:10:10.681104Z","iopub.status.idle":"2022-09-11T22:10:10.681885Z","shell.execute_reply.started":"2022-09-11T22:10:10.681634Z","shell.execute_reply":"2022-09-11T22:10:10.681658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We get D35C0M , but many letters/digits can be confused if not written properly.\n\nWe are in the **AI Village Capture the Flag @ DEFCON** challenge, we can assume that D35C0M should be D3FC0N.\n","metadata":{}},{"cell_type":"code","source":"try:\n    r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"inference\", \"submission\": \"FLAG{D3FC0N}\"}))\n    print(r.text)\nexcept requests.exceptions.ConnectionError:\n    print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:10:10.683521Z","iopub.status.idle":"2022-09-11T22:10:10.683992Z","shell.execute_reply.started":"2022-09-11T22:10:10.683784Z","shell.execute_reply":"2022-09-11T22:10:10.683804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"inference\", r.text.split(\"The flag is \")[1][:-1])\nr.text.split(\"The flag is \")[1][:-1]","metadata":{"execution":{"iopub.status.busy":"2022-09-11T22:10:10.685511Z","iopub.status.idle":"2022-09-11T22:10:10.686601Z","shell.execute_reply.started":"2022-09-11T22:10:10.686354Z","shell.execute_reply":"2022-09-11T22:10:10.686384Z"},"trusted":true},"execution_count":null,"outputs":[]}]}