StackZero
  • Homepage
  • Cryptography and Privacy
  • Ethical Hacking
  • Reverse Engineering
  • Contacts
  • About Me
No Result
View All Result
StackZero
No Result
View All Result

How to Hide Messages in Pictures with Python: Steganography

May 21, 2022
in Cryptography and Privacy
0 0
How to Hide Messages in Pictures with Python: Steganography
0
SHARES
389
VIEWS
Share on FacebookShare on Twitter

Before implementing steganography in python, we need to understand what exactly is.

Steganography is the practice of hiding information in plain sight.
The word steganography comes from the Greek words steganos, meaning “covered” or “secret,” and graphein, meaning “writing.”

Digital steganography can involve hiding information in digital images, audio files, and even video files.
The advantage of digital steganography over traditional methods is that the message can be hidden in a file that is already in plain sight.
For example, someone can hide a message in an image that is posted on a website. The recipient can see the message only if knows how to look for it.

In order to have an additional level of security, the sender can encrypt the message before using some steganography technique.

Steganography can be used for a variety of purposes, including sending secret messages, sharing sensitive information, and watermarking digital files.

Table of Contents

Toggle
  • Overview of the Steganography technique
  • Implementation of Steganography in Python
    • Imports and global
    • Methods
    • The main
    • Put all together
    • Usage
  • Conclusion and improvements

Overview of the Steganography technique

Looking at the hex of an image value, we can see that png and jpg files end always with the same byte sequence.
In our case, we are on a Linux machine, so we’ll check with xxd,  but any hex editor would be ok:

xxd -i image.jpg

The output will be something similar to this

  .....
  0xef, 0x47, 0xf7, 0x94, 0x70, 0x51, 0xec, 0xa2, 0x9f, 0x4a, 0x7d, 0xe6,
  0xa8, 0x73, 0xff, 0x00, 0xc7, 0x3f, 0xff, 0xd9

Doing that with many images, we can see that the last three bytes are a kind of terminator for a jpg. So the viewer will read no further.

The same process can be done with png and we’ll see an output similar to this

  ...
  0xfc, 0xab, 0x38, 0x9d, 0x9d, 0xa2, 0xee, 0x3d, 0xc0, 0x77, 0xfe, 0xd1,
  0xef, 0xbf, 0xe8, 0x1f, 0x77, 0xc3, 0x86, 0x0d, 0x1b, 0x36, 0x6c, 0xb8,
  0x3c, 0xfc, 0x6f, 0x44, 0x3a, 0x0e, 0x7e, 0xe2, 0x52, 0x24, 0x49, 0x00,
  0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82

In this case, the ending sequence is composed of the last 12 bytes.

What we are going to do, it’s just appending our secret text to the image.

Implementation of Steganography in Python

Imports and global

In order to write the script for steganography in python, we just need Python 3 without installing external libraries.

The next step is to create a global dictionary containing the ending sequences for the two extensions we want to manage.

import sys
import os

file_end = {
    ".png": b'\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82',
    ".jpg": b'\x3f\xff\xd9'
}

Methods

The idea is just to write three methods:

  • append_secret
  • retrieve_secret
  • clear_secret
def append_secret(filename, file_extension, secret):
    with open(f"{filename}{file_extension}", "ab") as f:
        f.write(bytes(secret, encoding="utf-8"))

This code opens a file in “append binary” mode and writes a secret to it.

def retrieve_secret(filename, file_extension):
    if not file_extension in file_end:
        print("Format not supported!")
    else:
        with open(f"{filename}{file_extension}", 'rb') as f:
            buff = bytes(f.read())
            index = buff.index(file_end[file_extension])

            return buff[index+len(file_end[file_extension]):].decode('utf-8')

The program will check if the file extension is in the dictionary “file_end”.
If it is, the program will open the file and read it as a byte array.
It will then look for the index of the file ending in the byte array.
Once it finds the index, it will decode the byte array from that point onwards (the secret) and return it out as a string.

def clear_secret(filename, file_extension):

    if not file_extension in file_end:
        print("Format not supported!")
    else:
        buff = ''
        with open(f"{filename}{file_extension}", 'rb+') as f:
            buff = bytes(f.read())
            index = buff.index(file_end[file_extension])

            f.truncate(index+len(file_end[file_extension]))

The code will read the file, find the index of the image terminator, and then truncate the file at that index.

At this point, we just need to use them in the main.

The main

In the main, we want to use the script in 3 ways:

  • Append: will append the secret to the image
  • Retrieve: will retrieve the secret from the file
  • Clear: will clear the secret
if __name__=="__main__":
    request = sys.argv[1]
    filename, file_extension = os.path.splitext(sys.argv[2])

    if request == "r":
        secret = retrieve_secret(filename, file_extension)
        print(secret)
    
    elif request == "a":
        append_secret(filename, file_extension, sys.argv[3])
    
    elif request == "c":
        clear_secret(filename, file_extension)
    
    else:
        print("[!] Wrong request, please use 'r' or 'a'")

Put all together

import sys
import os

file_end = {
    ".png": b'\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82',
    ".jpg": b'\x3f\xff\xd9'
}

def retrieve_secret(filename, file_extension):
    if not file_extension in file_end:
        print("Format not supported!")
    else:
        with open(f"{filename}{file_extension}", 'rb') as f:
            buff = bytes(f.read())
            index = buff.index(file_end[file_extension])

            return buff[index+len(file_end[file_extension]):].decode('utf-8')

def append_secret(filename, file_extension, secret):
    with open(f"{filename}{file_extension}", "ab") as f:
        f.write(bytes(secret, encoding="utf-8"))

def clear_secret(filename, file_extension):

    if not file_extension in file_end:
        print("Format not supported!")
    else:
        buff = ''
        with open(f"{filename}{file_extension}", 'rb+') as f:
            buff = bytes(f.read())
            index = buff.index(file_end[file_extension])

            f.truncate(index+len(file_end[file_extension]))

if __name__=="__main__":
    request = sys.argv[1]
    filename, file_extension = os.path.splitext(sys.argv[2])

    if request == "r":
        secret = retrieve_secret(filename, file_extension)
        print(secret)
    
    elif request == "a":
        append_secret(filename, file_extension, sys.argv[3])
    
    elif request == "c":
        clear_secret(filename, file_extension)
    
    else:
        print("[!] Wrong request, please use 'r' or 'a'")

Usage

Append:

python3 main.py a image.jpg "Secret phrase"

Retrieve:

python3 main.py r image.jpg

Clear:

python3 main.py c image.jpg

Conclusion and improvements

This technique is perfect for keeping secrets safe, and it’s a lot of fun to do. Give it a try and see for yourself!

Surely steganography in python is not the state of art for security, but hardly someone will check the hex values of a picture.

If you want another level of security, try an XOR encoding on the message, maybe you will like this article.

How malware evasion works – 2 simple techniques in practice
Trending
How malware evasion works – 2 simple techniques in practice

Tags: hidejpgmessagepngprivacypyrhonsecuritysteganography
Previous Post

How to Easily Create a zip password cracker in Just Seconds!

Next Post

Python to Exe: Ultimate Guide for Windows

Next Post
Python to Exe: Ultimate Guide for Windows

Python to Exe: Ultimate Guide for Windows

You might also like

Cryptographic functions

Cryptographic Hash Functions in Python: Secure Your Data Easily

November 3, 2024
Malware Obfuscation Techniques: All That You Need To Know

Malware Obfuscation Techniques: All That You Need To Know

March 25, 2024
How To Do Process Enumeration: An Alternative Way

How To Do Process Enumeration: An Alternative Way

March 4, 2024
How To Do DLL Injection: An In-Depth Cybersecurity Example

How To Do DLL Injection: An In-Depth Cybersecurity Example

February 8, 2024
Process Injection By Example: The Complete Guide

Process Injection By Example: The Complete Guide

January 24, 2024
How To Build Your Own: Python String Analysis for Malware Insights

How To Build Your Own: Python String Analysis for Malware Insights

November 10, 2023

StackZero

StackZero is a specialized technical blog dedicated to the realm of cybersecurity. It primarily provides insightful articles and comprehensive tutorials designed to educate readers on developing security tools. The blog encompasses a broad spectrum of subjects, starting from the foundational principles of cryptography and extending to more sophisticated areas such as exploitation and reverse engineering. This makes StackZero an invaluable resource for both beginners and professionals in the field of cybersecurity.
The blog covers a wide range of topics, from the basics of cryptography to the more advanced topics of exploitation and reverse engineering.

Tags

application security blind sqli blind sql injection bruteforce c cesar cipher command injection cryptography ctf cybersecurity debugging dom-based xss dvwa ethical-hacking ethical hacking exploitation file inclusion gdb hacking injection javascript malware malware analysis malware evasion network-security pentesting lab picoctf pico ctf python reflected xss reverse engineering sql sqli sql injection static analysis stored xss substitution substitution cipher vulnerable application web application security web exploitation web security windows windows api xss
  • About Me
  • Contacts
  • HomePage
  • Opt-out preferences
  • Privacy Policy
  • Terms and Conditions

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
Manage Cookie Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
View preferences
{title} {title} {title}
No Result
View All Result
  • Homepage
  • Cryptography and Privacy
  • Ethical Hacking
  • Reverse Engineering
  • Contacts
  • About Me