Thêm “tin nhắn bí mật” vào hình ảnh bằng Python: Steganography

Trước khi triển khai Steganography trong python, chúng ta cần hiểu chính xác Steganography là gì.

Steganography là phương pháp che giấu thông tin trong dữ liệu rõ. Từ steganography xuất phát từ các từ tiếng Hy Lạp: steganos có nghĩa là “được bảo vệ” hoặc “bí mật” và graphein, có nghĩa là “viết”.

Steganography “kỹ thuật số” có thể liên quan đến việc ẩn thông tin trong hình ảnh, tệp âm thanh và thậm chí cả  video. Ưu điểm của Steganography “kỹ thuật số” so với các phương pháp truyền thống là tin nhắn có thể được ẩn trong một tệp đã được nhìn thấy bằng mắt. Ví dụ: ai đó có thể ẩn nội dung tin nhắn trong hình ảnh được đăng trên trang web. Người nhận chỉ có thể xem tin nhắn nếu biết cách giải mã nó.

Để tăng mức độ bảo mật, người gửi có thể mã hóa tin nhắn trước khi sử dụng một số kỹ thuật Steganography.

Steganography có thể được sử dụng cho nhiều mục đích khác nhau, bao gồm gửi tin nhắn bí mật, chia sẻ thông tin nhạy cảm và đánh dấu bản quyền các dữ liệu số.

Tổng quan về kỹ thuật Steganography

Nhìn vào hệ thập lục phân (hex) của hình ảnh, chúng ta có thể thấy rằng các tệp pngjpg luôn kết thúc bằng cùng một chuỗi byte.

Nếu dùng Linux, vì vậy chúng ta sẽ kiểm tra với lệnh xxd hoặc hoặc dùng phần mềm chỉnh sửa hex HxD trên Windows.

Khi dùng lệnh Linux xem hệ hex của file jpg: xxd -i image.jpg

Kết quả sẽ giống như thế này:

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

Khi dùng HxD mở hình ảnh trên Windows.

giau tin nhan vao Steganography

Dù dùng cách nào thì bạn cũng thấy FFD9 ở cuối cùng, đối với hình ảnh, các nội dung sau FF D9 đều sẽ không được đọc. Do đó ta dễ dàng thêm tin nhắn bí mất vào sau các vị trí này.

Quá trình tương tự có thể được thực hiện với png và chúng ta sẽ thấy kết quả tương tự như thế này

... 
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

Đối với file png, chuỗi kết thúc bao gồm 12 byte cuối cùng là: 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82

Triển khai Steganography trong Python

Để viết script cho steganography trong python, chúng ta chỉ cần Python 3 và không cần thêm các thư viện bên.

Bước tiếp theo là tạo một từ điển (dictionary) chứa các chuỗi kết thúc cho để phân biệt giữa file .png và .jpg

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

Phương thức:

Đoạn mã  bên dưới mở một tệp ở chế độ “append binary” và ghi nội dung bí mật vào đó.

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

Hàm này sẽ kiểm tra xem đuôi file (png, jpg) của hình ảnh có trong từ điển “file_end” hay không.

Nếu đúng, hàm này sẽ mở file và đọc nó dưới dạng một mảng byte.

Sau đó, nó sẽ tìm vị trí của tệp kết thúc bằng mảng byte.

Sau khi tìm thấy vị, nó sẽ giải mã mảng byte từ vị trí đó trở đi (sau vị trí đó là tin nhắn bí mật) và trả về dưới dạng một chuỗi.

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')

Hàm này sẽ đọc nội dung File ảnh, tìm vị trí kết thúc của file ảnh, xóa tất cả nội dung ở vị trí vị trí kết thúc của file ảnh ( xóa mã bí mật)

Lúc này chúng ta chỉ cần sử dụng chúng vào việc chính.

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]))

Hàm Main

Về cơ bản, chúng ta có 3 tính năng sau:

  • Append: sẽ thêm tin nhắn bí mật vào hình ảnh
  • Retrieve: sẽ hiển thị tin nhắn bí mật
  • Clear: sẽ xóa tin nhắn bí mật
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'")

Kết hợp các hàm lại với nhau ta sẽ có một chương trình tin nhắn vào hình ảnh bằng Python hoàn chỉnh:

Tạo file main.py với nội dung:

import sys
import os

file_end = {
    ".png": b'\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82',
    ".jpg": b'\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'")

Cách sử dụng Python thêm/đọc/xóa tin nhắn trong file ảnh

Chuẩn bị 1 tấm ảnh và đặt tên là anonyviet.jpg hoặc anonyviet.png

Thêm tin nhắn bí mật vào hình ảnh:

Linux:python main.py a anonyviet.jpg "tin nhắn bí mật"

Đọc tin nhắn bí mật trong file ảnh:

python main.py r anonyviet.jpg

Xóa tin nhắn đã thêm trong ảnh:

python main.py c anonyviet.jpg

Đây là kỹ thuật Steganography giúp ẩn giấy nội dung tin nhắn vào hình ảnh bằng Python, bạn có thể sáng chế thêm việc mã hóa code để người khác khi đọc được nội dung cũng không giải mã được trừ khi có Private Key. Đây là bài tập nâng cao, các bạn thử tự áp dụng vào thực tế nhé.

Giải thưởng:

05 bạn tìm được “Nội dung bí mật” trong tấm ảnh bên dưới và nhanh tay bình luận dưới bài viết này sẽ được tặng Card điện thoại 10K nha.

anonyviet

Bài viết đạt: 5/5 - (1 bình chọn)
Previous Post Next Post