diff --git a/README.md b/README.md index 1d128337..94b9c3b7 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy - [How to Create a Reverse Shell in Python](https://www.thepythoncode.com/article/create-reverse-shell-python). ([code](ethical-hacking/reverse_shell)) - [How to Encrypt and Decrypt Files in Python](https://www.thepythoncode.com/article/encrypt-decrypt-files-symmetric-python). ([code](ethical-hacking/file-encryption)) - [How to Make a Subdomain Scanner in Python](https://www.thepythoncode.com/article/make-subdomain-scanner-python). ([code](ethical-hacking/subdomain-scanner)) + - [How to use Steganography to Hide Secret Data in Images in Python](https://www.thepythoncode.com/article/hide-secret-data-in-images-using-steganography-python). ([code](ethical-hacking/steganography)) - ### [Machine Learning](https://www.thepythoncode.com/topic/machine-learning) - ### [Natural Language Processing](https://www.thepythoncode.com/topic/nlp) diff --git a/ethical-hacking/steganography/README.md b/ethical-hacking/steganography/README.md new file mode 100644 index 00000000..0af2a8ce --- /dev/null +++ b/ethical-hacking/steganography/README.md @@ -0,0 +1,15 @@ +# [How to use Steganography to Hide Secret Data in Images in Python](https://www.thepythoncode.com/article/hide-secret-data-in-images-using-steganography-python) +To run this: +- `pip3 install -r requimements.txt` +- To encode some data to the imag `image.PNG` and decode it right away: + ``` + python steganography image.PNG "This is some secret data." + ``` + This will write another image with data encoded in it and **outputs:** + ``` + [*] Maximum bytes to encode: 125028 + [*] Encoding data... + [+] Decoding... + [+] Decoded data: This is some secret data. + ``` +- You can isolate encoding and decoding processes in two different Python files, which makes more sense. diff --git a/ethical-hacking/steganography/encoded_image.PNG b/ethical-hacking/steganography/encoded_image.PNG new file mode 100644 index 00000000..73464816 Binary files /dev/null and b/ethical-hacking/steganography/encoded_image.PNG differ diff --git a/ethical-hacking/steganography/image.PNG b/ethical-hacking/steganography/image.PNG new file mode 100644 index 00000000..97bab740 Binary files /dev/null and b/ethical-hacking/steganography/image.PNG differ diff --git a/ethical-hacking/steganography/requirements.txt b/ethical-hacking/steganography/requirements.txt new file mode 100644 index 00000000..6f1e5232 --- /dev/null +++ b/ethical-hacking/steganography/requirements.txt @@ -0,0 +1,2 @@ +opencv-python +numpy \ No newline at end of file diff --git a/ethical-hacking/steganography/steganography.py b/ethical-hacking/steganography/steganography.py new file mode 100644 index 00000000..94b770ac --- /dev/null +++ b/ethical-hacking/steganography/steganography.py @@ -0,0 +1,92 @@ +import cv2 +import numpy as np +import sys + + +def to_bin(data): + """Convert `data` to binary format as string""" + if isinstance(data, str): + return ''.join([ format(ord(i), "08b") for i in data ]) + elif isinstance(data, bytes) or isinstance(data, np.ndarray): + return [ format(i, "08b") for i in data ] + elif isinstance(data, int) or isinstance(data, np.uint8): + return format(data, "08b") + else: + raise TypeError("Type not supported.") + + +def encode(image_name, secret_data): + # read the image + image = cv2.imread(image_name) + # maximum bytes to encode + n_bytes = image.shape[0] * image.shape[1] * 3 // 8 + print("[*] Maximum bytes to encode:", n_bytes) + if len(secret_data) > n_bytes: + raise ValueError("[!] Insufficient bytes, need bigger image or less data.") + print("[*] Encoding data...") + # add stopping criteria + secret_data += "=====" + data_index = 0 + # convert data to binary + binary_secret_data = to_bin(secret_data) + # size of data to hide + data_len = len(binary_secret_data) + + for row in image: + for pixel in row: + # convert RGB values to binary format + r, g, b = to_bin(pixel) + # modify the least significant bit only if there is still data to store + if data_index < data_len: + # least significant red pixel bit + pixel[0] = int(r[:-1] + binary_secret_data[data_index], 2) + data_index += 1 + if data_index < data_len: + # least significant green pixel bit + pixel[1] = int(g[:-1] + binary_secret_data[data_index], 2) + data_index += 1 + if data_index < data_len: + # least significant blue pixel bit + pixel[2] = int(b[:-1] + binary_secret_data[data_index], 2) + data_index += 1 + # if data is encoded, just break out of the loop + if data_index >= data_len: + break + return image + + +def decode(image_name): + print("[+] Decoding...") + # read the image + image = cv2.imread(image_name) + binary_data = "" + for row in image: + for pixel in row: + r, g, b = to_bin(pixel) + binary_data += r[-1] + binary_data += g[-1] + binary_data += b[-1] + + # split by 8-bits + all_bytes = [ binary_data[i: i+8] for i in range(0, len(binary_data), 8) ] + # convert from bits to characters + decoded_data = "" + for byte in all_bytes: + decoded_data += chr(int(byte, 2)) + if decoded_data[-5:] == "=====": + break + return decoded_data[:-5] + + +if __name__ == "__main__": + input_image = sys.argv[1] + output_image = f"encoded_{input_image}" + secret_data = sys.argv[2] + + # encode the data into the image + encoded_image = encode(image_name=input_image, secret_data=secret_data) + # save the output image (encoded image) + cv2.imwrite(output_image, encoded_image) + # decode the secret data from the image + decoded_data = decode(output_image) + print("[+] Decoded data:", decoded_data) \ No newline at end of file