{"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":"# It is results that matter or is it?\n\nIn these two challenges we have to get bad scores or grades and make them good by tampering data.\n\nIn Honorstudent we have an image of an F grade and we have to fake it so that it is recognized as an A, but beware changing too much will get us caught.\n\nIn Bad to Good we have the grades,abscences,demerits and scores for a class out of four taken by Henry.\nBy tampering the data of that one class we have to make Henry be classified as a good student with a high score.","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","execution":{"iopub.status.busy":"2022-09-10T00:28:07.952157Z","iopub.execute_input":"2022-09-10T00:28:07.952603Z","iopub.status.idle":"2022-09-10T00:28:07.960110Z","shell.execute_reply.started":"2022-09-10T00:28:07.952553Z","shell.execute_reply":"2022-09-10T00:28:07.958744Z"},"jupyter":{"source_hidden":true},"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,"execution":{"iopub.status.busy":"2022-09-10T00:28:07.961717Z","iopub.execute_input":"2022-09-10T00:28:07.962086Z","iopub.status.idle":"2022-09-10T00:28:07.978549Z","shell.execute_reply.started":"2022-09-10T00:28:07.962053Z","shell.execute_reply":"2022-09-10T00:28:07.977336Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Honorstudent (id: honorstudent) -- 300 Points\n","metadata":{}},{"cell_type":"markdown","source":"This challenge was quite easy, adding gaussian noise was the correct answer to get an A from the original F","metadata":{}},{"cell_type":"code","source":"Ima(filename=f'{dir_name}/honorstudent/f.png')","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:07.980308Z","iopub.execute_input":"2022-09-10T00:28:07.981245Z","iopub.status.idle":"2022-09-10T00:28:07.996910Z","shell.execute_reply.started":"2022-09-10T00:28:07.981197Z","shell.execute_reply":"2022-09-10T00:28:07.995638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(1000):\n    \n    #always seed for reproducibility of experiments\n    np.random.seed(i)\n    \n    #load image\n    img = Im.open(f'{dir_name}/honorstudent/f.png')\n    pix = np.array(img)\n    \n    #add random gaussian noise\n    pix = pix + np.random.normal(0,100,pix.shape)\n    \n    #clip image to pixel values range(0,255)\n    pix = np.clip(pix,a_min=0,a_max=255).astype('uint8')\n    img = Im.fromarray(pix)\n    \n    #save image and upload it\n    img.save(\"f.png\")\n\n    with open(\"f.png\", \"rb\") as f:\n        try:\n            r = requests.post(\"https://honorstudent.fly.dev/score\", files={\"data_file\": f})\n            if \"Way to apply yourself\" in r.text:\n                print(i,r.text)\n                break\n            print(r.text)\n        except requests.exceptions.ConnectionError:\n            print(\"Connection problems. Contact the CTF organizers.\")","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:07.998409Z","iopub.execute_input":"2022-09-10T00:28:07.999250Z","iopub.status.idle":"2022-09-10T00:28:08.223045Z","shell.execute_reply.started":"2022-09-10T00:28:07.999210Z","shell.execute_reply":"2022-09-10T00:28:08.221898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Ima(filename=\"f.png\")","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.225837Z","iopub.execute_input":"2022-09-10T00:28:08.226425Z","iopub.status.idle":"2022-09-10T00:28:08.232238Z","shell.execute_reply.started":"2022-09-10T00:28:08.226390Z","shell.execute_reply":"2022-09-10T00:28:08.231453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This feels like an underwelming A, but tricking a model can be easier then tricking human eye. \n\nGetting a good looking A starting from that F in so little space would be difficult without rounding a bit the upper part.\n\nAnyway It is results that matters here, the F is an A now. So let's get praised again.","metadata":{}},{"cell_type":"code","source":"r.text[:r.text.index(\"!\")+1]","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.233350Z","iopub.execute_input":"2022-09-10T00:28:08.233930Z","iopub.status.idle":"2022-09-10T00:28:08.245090Z","shell.execute_reply.started":"2022-09-10T00:28:08.233896Z","shell.execute_reply":"2022-09-10T00:28:08.243784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"honorstudent\", r.text.split(\"yourself! \")[1])\nr.text.split(\"yourself! \")[1]","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.246929Z","iopub.execute_input":"2022-09-10T00:28:08.247676Z","iopub.status.idle":"2022-09-10T00:28:08.264040Z","shell.execute_reply.started":"2022-09-10T00:28:08.247628Z","shell.execute_reply":"2022-09-10T00:28:08.262836Z"},"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":"Let's get Henry an homecoming ticket. First we need to read the data and understand it.","metadata":{}},{"cell_type":"code","source":"scores=pd.read_csv(f\"{dir_name}/bad2good/math.csv\")\nscores.head()","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.265994Z","iopub.execute_input":"2022-09-10T00:28:08.267076Z","iopub.status.idle":"2022-09-10T00:28:08.283010Z","shell.execute_reply.started":"2022-09-10T00:28:08.267031Z","shell.execute_reply":"2022-09-10T00:28:08.281816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that we have 4 fields that may be intersting to work with, Grade,Absences,Demerits and Score.\n2 of them seems to be good if the value is high (Grade,Score), and 2 are better with low values (Absences,Demerits).\nLet's try changing only Henri's values.\n(Setting Score>100 gets caught as tampering, I tried manually some values and reached the ones in the cell below)","metadata":{}},{"cell_type":"code","source":"scores.loc[scores[\"FirstName\"]==\"Henry\",\"Absences\"]=-350\nscores.loc[scores[\"FirstName\"]==\"Henry\",\"Demerits\"]=-350\nscores.loc[scores[\"FirstName\"]==\"Henry\",\"Score\"]=100\nscores.loc[scores[\"FirstName\"]==\"Henry\",\"Grade\"]=10000","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.284429Z","iopub.execute_input":"2022-09-10T00:28:08.284805Z","iopub.status.idle":"2022-09-10T00:28:08.293395Z","shell.execute_reply.started":"2022-09-10T00:28:08.284755Z","shell.execute_reply":"2022-09-10T00:28:08.292521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"scores.to_csv(\"math.csv\",index=False)","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.296091Z","iopub.execute_input":"2022-09-10T00:28:08.296457Z","iopub.status.idle":"2022-09-10T00:28:08.306453Z","shell.execute_reply.started":"2022-09-10T00:28:08.296423Z","shell.execute_reply":"2022-09-10T00:28:08.305542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Henry I don't know if you'll get a homecoming ticket to your home....","metadata":{}},{"cell_type":"code","source":"# Submit tampered data\nwith open(\"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":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.307892Z","iopub.execute_input":"2022-09-10T00:28:08.308931Z","iopub.status.idle":"2022-09-10T00:28:08.541256Z","shell.execute_reply.started":"2022-09-10T00:28:08.308896Z","shell.execute_reply":"2022-09-10T00:28:08.540371Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Max score should be 100.\n\nWell, Henry maybe you are just Harry in disguise because your score seems magic.\n\nHopefully you will get your invitation to Hogwarts soon.\n\nGood luck.","metadata":{}},{"cell_type":"code","source":"add_flag(\"bad_to_good\", r.text.split(\"student! \")[1])\nr.text.split(\"student! \")[1]","metadata":{"execution":{"iopub.status.busy":"2022-09-10T00:28:08.542868Z","iopub.execute_input":"2022-09-10T00:28:08.543419Z","iopub.status.idle":"2022-09-10T00:28:08.557129Z","shell.execute_reply.started":"2022-09-10T00:28:08.543386Z","shell.execute_reply":"2022-09-10T00:28:08.555877Z"},"trusted":true},"execution_count":null,"outputs":[]}]}