{"id":13501276,"url":"https://github.com/carlospuenteg/File-Injector","last_synced_at":"2025-03-29T08:32:23.708Z","repository":{"id":61854482,"uuid":"555795415","full_name":"carlospuenteg/File-Injector","owner":"carlospuenteg","description":"File Injector is a script that allows you to store any file in an image using steganography","archived":false,"fork":false,"pushed_at":"2022-11-18T00:20:21.000Z","size":41491,"stargazers_count":434,"open_issues_count":1,"forks_count":26,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-10-31T20:39:34.164Z","etag":null,"topics":["extraction","file","file-injection","file-injector","files","image","image-manipulation","image-processing","injection","noise","numpy","photography","python","python3","steganography","storage"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carlospuenteg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-10-22T10:53:23.000Z","updated_at":"2024-10-13T04:07:23.000Z","dependencies_parsed_at":"2022-10-22T11:30:28.411Z","dependency_job_id":null,"html_url":"https://github.com/carlospuenteg/File-Injector","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospuenteg%2FFile-Injector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospuenteg%2FFile-Injector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospuenteg%2FFile-Injector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospuenteg%2FFile-Injector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carlospuenteg","download_url":"https://codeload.github.com/carlospuenteg/File-Injector/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246162092,"owners_count":20733351,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["extraction","file","file-injection","file-injector","files","image","image-manipulation","image-processing","injection","noise","numpy","photography","python","python3","steganography","storage"],"created_at":"2024-07-31T22:01:31.345Z","updated_at":"2025-03-29T08:32:18.699Z","avatar_url":"https://github.com/carlospuenteg.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# File Injector\n\n#### If you want to use a previous version (1.0.2 or lower), where you needed the original image to extract the file, you can download it [here](https://github.com/carlospuenteg/File-Injector/archive/refs/tags/v1.0.2.zip).\n\n## Index\n* [1. Description](#1-description)\n* [2. Getting Started](#2-getting-started)\n  * [Install requirements](#install-requirements)\n  * [Run the script](#run-the-script)\n  * [Choose input](#choose-input)\n    * [Choose a base image/audio](#choose-a-base-imageaudio)\n    * [Choose an input file](#choose-an-input-file)\n    * [Choose/Generate an encryption key](#choosegenerate-an-encryption-key)\n* [3. Results](#3-results)\n* [4. Examples of use](#4-examples-of-use)\n  * [Injection](#injection)\n  * [Extraction](#extraction)\n* [5. Configuration](#5-configuration)\n* [6. What it does](#6-what-it-does)\n* [7. How it works](#7-how-it-works)\n  * [Options](#options)\n  * [inject_file_func](#inject_file_func)\n  * [extract_file_func](#extract_file_func)\n  * [get_fernet](#get_fernet)\n  * [decrypt_content](#decrypt_content)\n  * [inject_file](#inject_file)\n  * [extract_file](#extract_file)\n\n\n\n## 1. Description\n\nFile Injector is a script that allows you to **store any file** (`.zip`, `.png`, `.txt`, `.gba`...) and its **filename** in an **image/audio** as **noise**, using [steganography](https://en.wikipedia.org/wiki/Steganography).\n\nYou can also choose to **encrypt** the input file before storing it.\n\nThen, to **extract** the file from the modified image/audio, you **DON'T need the original image/audio**, just the **encryption key** if the file has been encrypted.\n\n\n\n\n## 2. Getting Started\n\n### Install Requirements\n\n```bash\npython3 -m pip install -r requirements.txt\n```\n\nIf that doesn't work, you can try:\n\n```bash\npy -m pip install -r requirements.txt\n```\n\n\n### Run the script\n\n```bash\npython3 main.py\n```\n\n\n### Choose input\n\n#### Choose a base image/audio\n\n**Choose** a base image/audio for storing the file from the `files/base` folder.\n\nYou can also add your **own** images/audios to this folder. \n- The images can be `.png` or (`.jpg`/`.jpeg`), but they will be converted to `.png` when the script is run.\n- The audios have to be `.mp3` or `.wav`, but they will be converted to `.mp3` when the script is run.\n\n\n#### Choose an input file\n\n**Choose** a file to be stored in the image/audio from the `files/input` folder.\n\nYou can add your **own** files to this folder. They can be any type of files.\n\n\n#### Choose a modified image/audio\n\n**Choose** a modified image/audio for extracting the file from the `files/modified` folder.\n\nYou can also add your **own** modified images/audios to this folder.\n\n\n#### Choose/Generate an encryption key\n\nYou can **choose** a key from the `files/$encryption-keys` folder or **generate** one there.\n\nThe key file must have the `.key` extension\n\nYou don't need to choose a particular one when decrypting a file, it will be selected automatically from the folder.\n\n\n\n## 3. Results\n\nThis **17.1MP** image contains an **encrypted** **9MB** `.zip` file and its **filename** stored as noise.\n\n\u003cimg src=\"readme-assets/17'1MP_mod.png\" width=500\u003e\n\n\nThis **1.7MP** image contains an **encrypted** **0.93MB** `.zip` file and its **filename** stored as noise.\n\n\u003cimg src=\"readme-assets/1'7MP_mod.png\" width=500\u003e\n\n\nThis **42MB** audio file contains an **encrypted** **9MB** `.zip` file and its **filename** stored as noise.\n\nhttps://user-images.githubusercontent.com/65092569/202014519-24514110-4bd2-4c2b-9307-237964df0c2b.mp4\n\n\n\n\n\n## 4. Examples of use\n\n### Injection\n\n```text\n... File-Injector % python3 main.py\n[0] EXIT\n[1] Inject file\n[2] Extract file\n\nOption: 1\nFile to be stored: images.zip\nFilename of the base image: 2'2MP\nEncrypt the file? (y/n): y\n\nDo you want to use an existing key or generate a new one?\n[0] Existing key\n[1] New key\n\nOption: 1\nFilename of the new key file (blank for default): \nKey generated and saved to files/$encryption-keys/key9.key\n\nPreparing...\n\nModified bits per channel: 2\nImage modification: 1.56%\n\n✅ Storing... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [100.0%]\n\nGenerating random values...\n\nStoring random values...\n\nReshaping...\n\nModified image saved in files/modified-images/2'2MP_mod.png\n\nDone in 7.5892 seconds\n```\n\n### Extraction\n\n```\n... File-Injector % python3 main.py\n[0] EXIT\n[1] Inject file\n[2] Extract file\n\nOption: 2\nFilename of the modified image: 2'2MP_mod\n\nPreparing...\n\nRetrieving filename...\n\nRetrieving input file...\nDecrypted with \"files/$encryption-keys/key2.key\"\n\nOutput file saved in files/output-files/images.zip\n\nDone in 1.4083 seconds\n```\n\n\n\n## 5. [Configuration](config.py)\n\nYou can change the configuration in the [config.py](config.py) file.\n\n| Constant | Description | Default value |\n|-|-|-|\n| `MOD_PREFIX` | Prefix the modified image/audio will have | `\"\"` |\n| `MOD_SUFFIX` | Suffix the modified image/audio will have | `\"_mod\"` |\n| `STORE_RANDOM` | Store random data in the modified image so that the limit between the part with the stored data and the part without is not so obvious | `True` |\n| `TEST_MODE` | Enables/Disables Test Mode: Test with predefined images/audios and files | `True` |\n\n\n\n\n## 6. What it does\n\nThe **injection** is done by **storing** the file in the **X less significant bits** of each element of the array created by flattening the array of image/audio.\n- Each element has **8 bits** (if the base file is an **image**) or **16 bits** (if the base file is an **audio**)\n- This script changes from **1 to all** the bits of each element, depending on the **size** of the file to be stored compared to the base image/audio.\n- If you store a **bigger file** or if the **base image/audio is smaller**, **more bits** will be changed and the changes will be **more noticeable**.\n- If you store a **smaller file** or if the **base image/audio is bigger**, **less bits** will be changed and the changes will be **less noticeable**.\n- If the **base image/audio is too small** to store the file, the script will **stop** and **warn** you.\n- If you choose to **encrypt the file**, its **size will increase by ≈1/3**.\n\n\n\n\n## 7. How it works\n\n### Options\n\n| Option | Description |\n|-|-|\n| [0] EXIT | Exit the script |\n| [1] Inject file | Calls [`inject_file_func()`](#inject_file_func) |\n| [2] Extract file | Calls [`extract_file_func()`](#extract_file_func) |\n\n\n### [`inject_file_func()`](menu.py)\n\n1. If `TEST_MODE` == `True`, it will use the predefined base image/audio and input file. Otherwise, it will ask for the base image/audio and input file.\n2. Read the file (in bytes)\n3. Read the image/audio and store it in a numpy array\n4. Read the filename (in bytes)\n5. If the user wants to encrypt the file:\n   1. Get the key with [`get_fernet()`](#get_fernet)\n   2. Encrypt the file and filename\n6. Try to inject the file and filename in the image/audio with [`inject_file()`](#inject_file). \n   1. If the image/audio is too small to store the file, raise an error\n   2. Else, return the modified image/audio.\n7. Save the modified image/audio\n\n\n### [`extract_file_func()`](menu.py)\n\n1. If `TEST_MODE` == `True`, it will use the predefined modified image/audio. Otherwise, it will ask for the modified image/audio.\n2. Read the modified image/audio\n3. Extract file and filename as bytes with [`extract_file()`](#extract_file)\n4. If the file and filename have been encrypted (they start with `gAAAAA`), decrypt them with [`decrypt_content`](#decrypt_content)\n5. Decode the filename to **UTF-8**\n6. Save the file with the decoded filename\n\n\n### [`get_fernet()`](utils/cryptography.py)\n\n| Option | Description |\n|-|-|\n| [0] Existing key | Use an existing key |\n| [1] New key | Generate a new key |\n\n[0] Existing key\n1. Choose a key to use from the `files/$encryption-keys` folder\n\n[1] New key\n1. Choose a filename for the new key (or leave it blank for the default one (e.g. **key8.key**))\n2. Generate a new key and save it with the chosen filename\n3. Return the Fernet object with the new key\n\n\n### [`decrypt_content()`](utils/cryptography.py)\n\n1. For each key in the `files/$encryption-keys` folder:\n   1. Try to decrypt the file and filename with it\n   2. If **InvalidToken** is raised:\n      1. It means that the key is not the right one\n      2. Try with other key\n   3. Else, return the key\n2. If no key is found, raise an Exception\n\n\n### [`inject_file()`](utils/injection.py)\n\n| Parameter | Type | Description |\n|-|-|-|\n| `arr` | `np.ndarray` | Image/audio as a numpy array |\n| `file` | `bytes` | File as bytes |\n| `filename` | `bytes` | Filename as bytes |\n| `store_random` | `boolean` | Whether or not to store random data in the modified image/audio |\n\nReturns the **modified image/audio array** (`np.ndarray`, with same shape as `arr`)\n\n\n### [`extract_file()`](utils/injection.py)\n\n| Parameter | Type | Description |\n|-|-|-|\n| `mod_arr_flat` | `np.ndarray` | Flattened modified image/audio |\n\nReturns a **dictionary** with the extracted **file** and **filename**, both in (`bytes`) format","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlospuenteg%2FFile-Injector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarlospuenteg%2FFile-Injector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlospuenteg%2FFile-Injector/lists"}