mithril-security/NonSuspiciousImageDecoder
1
1import gradio as gr2import cv23import io4import pandas as pd5 6from LSBSteg import LSBSteg7 8 9def convert(file):10 print(f"Converting file {file}")11 in_img = cv2.imread(file, cv2.IMREAD_UNCHANGED)12 lsbsteg = LSBSteg(in_img)13 data = lsbsteg.decode_binary()14 bytes = io.BytesIO(data)15 dataframe = pd.read_parquet(bytes)16 17 # dataframe.to_csv('output.csv')18 return dataframe.head(20)19 20 21with gr.Blocks() as demo:22 gr.Markdown("""23 ## Non-Suspicious image decoder24 25 This tool shows the extraction a dataframe hidden inside an image.26 27 There are a few ways to hide data in a PNG file, notably:28 * adding it after the end of the file (after the PNG IEND chunk), so that it gets29 ignored by image viewers30 * adding it as comments in the PNG file (tEXt chunks)31 32 These methods are kind of easy to spot! Also, a lot of software, browsers, image upload33 websites etc often just strip them.34 35 So, here, we have a different, more thoughtful (and arguably cooler) method.36 37 This class hides the data using a basic kind of **[steganography](https://en.wikipedia.org/wiki/Steganography)**:38 it hides it in the39 *least significant bits* of the raw (uncompressed) picture: tiny differences in the red, green and blue40 channel of the image encodes the data we're interested in.41 42 This means the resulting picture43 looks **very close to the original image**; and for the data we hide here, it is **imperceptible44 to the naked eye**.45 46 The resulting PNG file will probably get a little bit bigger as a result, since PNG uses compression,47 which will have a harder time when we have our stolen data injected in the image. This is48 not that much of a problem since it stays <100Ko, so it's not that noticeable.49 50 """)51 with gr.Row():52 im = gr.Image(label="Input image file", type="filepath")53 54 def preprocess(encoding: str) -> str:55 # We do our own preprocessing because gradio's deletes PNG metadata :(56 import tempfile57 import base6458 59 content = encoding.split(";")[1]60 image_encoded = content.split(",")[1]61 png_content = base64.b64decode(image_encoded)62 file_obj = tempfile.NamedTemporaryFile(63 delete=False,64 suffix=".input.png",65 )66 file_obj.write(png_content)67 return file_obj.name68 69 im.preprocess = preprocess70 df_out = gr.Dataframe(71 label="Output dataframe (first 20 rows)", max_rows=20, overflow_row_behaviour="paginate"72 )73 gr.Markdown("Click on the example below to get the data from the associated colab notebook :)")74 gr.Examples(75 examples=["sample-picture.png"],76 inputs=[im],77 outputs=[df_out],78 fn=convert,79 cache_examples=True,80 )81 # file_out = gr.File(label="Full output CSV file")82 btn = gr.Button(value="Extract")83 # demo = gr.Interface(convert, im, im_2)84 btn.click(convert, inputs=[im], outputs=[df_out])85 86 # example_img = os.path.join(os.path.dirname(__file__), "example-picture.png")87 88if __name__ == "__main__":89 demo.launch()90 