{"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":"# DeepFake\n\nIn this challenge the participants had to modify a video so that it didn't get caught by an anti deepfake classifier.\n\nTo solve this challenge I used again an iterative black box solution, but this time the search space is too big (1920x1080 video with 300 frames).\n\nTo avoid computing big noise matrixed I considered only the regions of the image close to the face, this is done by cutting a region of each frame of the video.\n\nThe second step was appluing the noise only to parts concerning the deepfake modification, this is done by checking if the pixel value changed between the previous and successive frames(with a certain treshold to consider the pixel changed), in this way it was possible to compute a mask where to apply the noise.\n\nThis solution was quite fast and was for sure faster than other blackbox solution I tried for several days.\n\nHere the Fake is the score assigned to this task","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-11T23:41:39.645395Z","iopub.execute_input":"2022-09-11T23:41:39.645904Z","iopub.status.idle":"2022-09-11T23:41:41.886888Z","shell.execute_reply.started":"2022-09-11T23:41:39.645805Z","shell.execute_reply":"2022-09-11T23:41:41.885866Z"},"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-11T23:41:41.888593Z","iopub.execute_input":"2022-09-11T23:41:41.890010Z","iopub.status.idle":"2022-09-11T23:41:41.899395Z","shell.execute_reply.started":"2022-09-11T23:41:41.889962Z","shell.execute_reply":"2022-09-11T23:41:41.898025Z"},"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":"code","source":"%%capture\n!pip install videoio","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:41:41.904873Z","iopub.execute_input":"2022-09-11T23:41:41.905831Z","iopub.status.idle":"2022-09-11T23:41:55.065796Z","shell.execute_reply.started":"2022-09-11T23:41:41.905777Z","shell.execute_reply":"2022-09-11T23:41:55.064287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper functions","metadata":{}},{"cell_type":"code","source":"from videoio import VideoWriter\ndef save_file(modified=True,modified_part=None):\n    writer = VideoWriter(\"out.mp4\", resolution=(1920,1080))\n    for frame in range(num_frames):\n        if modified:\n            temp=frames[frame].copy()\n            temp[230:580,650:1050,:]=modified_part[0][frame,:,:,:]\n            writer.write(temp)\n        else:\n            writer.write(frames[i])\n    writer.close()\n#prepare video and save \ndef prepare_video(modified):\n    modified_part=modified.astype(\"uint8\")\n    save_file(modified=True,modified_part=modified_part)\n","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:41:55.069912Z","iopub.execute_input":"2022-09-11T23:41:55.070515Z","iopub.status.idle":"2022-09-11T23:41:55.122176Z","shell.execute_reply.started":"2022-09-11T23:41:55.070444Z","shell.execute_reply":"2022-09-11T23:41:55.121172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\n\nmessage_holder={}\n# wrapper for the submission api for blackbox attack\ndef predict(x):\n    prepare_video(x)\n    del x\n    gc.collect()\n\n    with open(f\"out.mp4\", \"rb\") as f:\n        data = f.read()\n\n    b64_data = base64.urlsafe_b64encode(data).decode()\n    in_data = json.dumps({\"input\": b64_data})\n    failed=True\n    for i in range(10):\n        if not failed:\n            break\n        import time\n        time.sleep(1)\n        try:\n            r = requests.post(\"https://deepfake.fly.dev/score\", data=in_data)\n            \n            try:\n                score=float(r.text.split(\":\")[1].split(\"}\")[0])\n            except:\n                message_holder[\"flag\"]=r.text.split(\"message\\\": \\\"\")[1].split(\"\\\"}\")[0]\n                print(r.text)\n                score=1\n            failed=False\n        except:\n            print(\"failed ___ \",r.text)\n            score=1\n    return np.array([[score , 1-score]])","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:56:12.645889Z","iopub.execute_input":"2022-09-11T23:56:12.646353Z","iopub.status.idle":"2022-09-11T23:56:12.658182Z","shell.execute_reply.started":"2022-09-11T23:56:12.646316Z","shell.execute_reply":"2022-09-11T23:56:12.656594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare data","metadata":{}},{"cell_type":"code","source":"# Load video as numpy array\nfrom videoio import VideoReader\nimport base64\nimport numpy as np\nframes=[]\ndir_name = \"/kaggle/input/ai-village-ctf\"\nfor frame in VideoReader( f\"{dir_name}/deepfake/sample.mp4\"):\n    frames.append(np.array(frame))\nframes=np.array(frames)\nnum_frames = len(frames) \nheight, width,_ = frames[0].shape","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:56:14.710863Z","iopub.execute_input":"2022-09-11T23:56:14.711276Z","iopub.status.idle":"2022-09-11T23:56:22.535994Z","shell.execute_reply.started":"2022-09-11T23:56:14.711239Z","shell.execute_reply":"2022-09-11T23:56:22.534230Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#cut the region in which the face is within each frame\nbase=frames[:,230:580,650:1050,:]\nbase=base.reshape(1,*base.shape)","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:56:22.538430Z","iopub.execute_input":"2022-09-11T23:56:22.538824Z","iopub.status.idle":"2022-09-11T23:56:22.551131Z","shell.execute_reply.started":"2022-09-11T23:56:22.538787Z","shell.execute_reply":"2022-09-11T23:56:22.549705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#create an initial all false mask for modifying the video\nmask=np.zeros_like(base) \ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:56:22.552515Z","iopub.execute_input":"2022-09-11T23:56:22.552880Z","iopub.status.idle":"2022-09-11T23:56:22.738905Z","shell.execute_reply.started":"2022-09-11T23:56:22.552831Z","shell.execute_reply":"2022-09-11T23:56:22.737567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#place ones in the mask where we see considerable changes\n#pixels with at values different of at least 5 with the previous and the successive photogram\nthresh=5\nsuccessive=np.abs((base[0,0]-base[0,1]).sum(axis=-1))>thresh\n\ncurrent= successive\n\nmask[0,0,:,:,0]=current\nmask[0,0,:,:,1]=current\nmask[0,0,:,:,2]=current\n\nfor frame in range(300-2):\n    previous=np.abs((base[0,frame+1]-base[0,frame]).sum(axis=-1))>thresh\n    successive=np.abs((base[0,frame+1]-base[0,frame+2]).sum(axis=-1))>thresh\n    \n    current=previous & successive\n    \n    mask[0,frame+1,:,:,0]=current\n    mask[0,frame+1,:,:,1]=current\n    mask[0,frame+1,:,:,2]=current\n\n    \nprevious=np.abs((base[0,-2]-base[0,-1]).sum(axis=-1))>thresh\n\ncurrent=previous\n\nmask[0,-1,:,:,0]=current\nmask[0,-1,:,:,1]=current\nmask[0,-1,:,:,2]=current","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:56:22.741650Z","iopub.execute_input":"2022-09-11T23:56:22.742002Z","iopub.status.idle":"2022-09-11T23:56:25.508754Z","shell.execute_reply.started":"2022-09-11T23:56:22.741971Z","shell.execute_reply":"2022-09-11T23:56:25.507709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#iterative update of the image \nbest_score=1000\nlist_of_updates=[]\nfor i in range(10000):\n    if i<20:\n        var=20\n    else:\n        var=5\n    np.random.seed(161194+i)\n    if i!=0:\n        noise=np.random.normal(0,var,base.shape)*mask\n    else:\n        noise=0\n    score=predict(np.clip(base+noise,0,255))[0][0]\n    if score==1:\n        print(i,\"--- failed\")\n        if \"flag\" in message_holder:\n            print(i,\" --- finished\")\n            os.system(\"cp out.mp4 target.mp4\")\n            break#found flag\n        \n    if score<best_score*1.01: #Allows going back to avoid overshooting and give a chance to exit local minima\n        list_of_updates.append(i)\n        best_score=score\n        base=np.clip(base+noise,0,255)\n        print(i,\" --- \",score)\n        os.system(\"cp out.mp4 out_best.mp4\")","metadata":{"execution":{"iopub.status.busy":"2022-09-11T23:56:25.511407Z","iopub.execute_input":"2022-09-11T23:56:25.511831Z","iopub.status.idle":"2022-09-12T00:03:20.700947Z","shell.execute_reply.started":"2022-09-11T23:56:25.511787Z","shell.execute_reply":"2022-09-12T00:03:20.699592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(list_of_updates)","metadata":{"execution":{"iopub.status.busy":"2022-09-12T00:03:20.702712Z","iopub.execute_input":"2022-09-12T00:03:20.703199Z","iopub.status.idle":"2022-09-12T00:03:20.710538Z","shell.execute_reply.started":"2022-09-12T00:03:20.703150Z","shell.execute_reply":"2022-09-12T00:03:20.709255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open(f\"{dir_name}/deepfake/sample.mp4\", \"rb\") as f:\n    data = f.read()\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":{"execution":{"iopub.status.busy":"2022-09-12T00:03:20.712819Z","iopub.execute_input":"2022-09-12T00:03:20.713356Z","iopub.status.idle":"2022-09-12T00:03:24.715164Z","shell.execute_reply.started":"2022-09-12T00:03:20.713311Z","shell.execute_reply":"2022-09-12T00:03:24.714247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_flag(\"deepfake\", message_holder[\"flag\"])\nmessage_holder[\"flag\"]","metadata":{"execution":{"iopub.status.busy":"2022-09-12T00:07:19.688016Z","iopub.execute_input":"2022-09-12T00:07:19.688457Z","iopub.status.idle":"2022-09-12T00:07:19.701749Z","shell.execute_reply.started":"2022-09-12T00:07:19.688417Z","shell.execute_reply":"2022-09-12T00:07:19.700593Z"},"trusted":true},"execution_count":null,"outputs":[]}]}