{"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":"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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","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":{"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":"markdown","source":"## **The approach was to search for the characters that maximized the output of the classifier using various samples of the EMNIST and the Handwritten characters dataset. Then, after decreasing the search space use a loop to find the final word.**","metadata":{}},{"cell_type":"markdown","source":"Handwritten characters dataset","metadata":{}},{"cell_type":"code","source":"import cv2\n\nfor j in ['0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z']:\n    images = []\n    print(j)\n    x = cv2.imread(f'../input/handwritten-characters/Validation/{j}/100.jpg', cv2.IMREAD_GRAYSCALE)\n    x = cv2.resize(x, (32, 32))\n    x = x.reshape(32, 32, 1)/255\n    images.append(x)\n    images = np.array(images)\n\n    try:\n        response = requests.post(\"https://inference.fly.dev/score\", data = json.dumps({\"input\": images.tolist()}))\n        print(response.text)\n    except requests.exceptions.ConnectionError:\n        print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"scrolled":true,"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"EMNIST dataset","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv('/kaggle/input/emnist/emnist-balanced-train.csv', header=None)\ntrain_df.head()\n\nlabel_map = pd.read_csv(\"/kaggle/input/emnist/emnist-balanced-mapping.txt\", \n                        delimiter = ' ', \n                        index_col=0, \n                        header=None, \n                        squeeze=True)\n\nlabel_dictionary = {}\nfor index, label in enumerate(label_map):\n    label_dictionary[index] = chr(label)\n\nX_train = train_df.loc[:, 1:]\ny_train = train_df.loc[:, 0]\n\n# Sample entry number 42\nsample_image = X_train.iloc[42]\nsample_label = y_train.iloc[42]\nsample_image.shape, sample_label\n\nW = 28\nH = 28","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  Check the sample\nprint(\"Label entry 42:\", label_dictionary[sample_label])\nplt.imshow(sample_image.values.reshape(W, H), cmap=plt.cm.gray)\nplt.show()\n\ndef reshape_and_rotate(image):\n    W = 28\n    H = 28\n    image = image.reshape(W, H)\n    image = np.fliplr(image)\n    image = np.rot90(image)\n    return image\n\n# Rotate the letters\nprint(\"Label entry 42:\", label_dictionary[sample_label])\nplt.imshow(reshape_and_rotate(sample_image.values), cmap=plt.cm.gray)\nplt.show()\n\nX_train = np.apply_along_axis(reshape_and_rotate, 1, X_train.values)\ny_train = y_train.map(label_dictionary)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in ['0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z']:\n    print(i)\n    for j in range(42, 50):\n        images = []\n        x = X_train[y_train[y_train == i].index][j]/255\n        x = cv2.resize(x, (32, 32))\n        x = x.reshape(32, 32, 1)\n        images.append(x)\n        images = np.array(images)\n\n        try:\n            response = requests.post(\"https://inference.fly.dev/score\", data = json.dumps({\"input\": images.tolist()}))\n            print(response.text)\n        except requests.exceptions.ConnectionError:\n            print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"scrolled":true,"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# To try and get the flag (less than 1000 combinations)\nfirst = ['B', 'D', 3, 'S']\nsecond = ['A', 'I', 'J', 2,  3]\nthird = ['S', 'E', 'F', 'G']\nfourth = ['C', 'G']\nfifth = ['O', 0]\nsixth = ['M', 'W', 'N']\n\nfor i in first:\n    for j in second:\n        for k in third:\n            for l in fourth:\n                for m in fifth:\n                    for n in sixth:\n                        flag = 'FLAG{'\n                        flag = flag + str(i) + str(j) + str(k) + str(l) + str(m) + str(n) + '}'\n\n                        try:\n                            r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"inference\", \"submission\": flag}))\n                            if r.text != \"That doesn't look right. Try again.\":\n                                print(flag)\n                                answer = flag\n                                break\n                        except requests.exceptions.ConnectionError:\n                            print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    r = requests.post(\"http://flags.fly.dev:5000/score\", json=json.dumps({\"challenge_id\": \"inference\", \"submission\": answer}))\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(\"inference\", \"LYZ28PPB3VSXIBLAC0QOYCAEIL8NZ2ZMLN59G0EI9VZ3YPNJR74E3407WNPAMG1GMP97D5H4QXQSYWYG5FRMDF2UT6RW0}V2OMMGVS8J8YC5{X8FXPKK95Z5H3WOSRUZ\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}