Security Research

Telegram Desktop Local Session Reuse: a Reproduction That Should Not Have Happened

#Malware#Threat Intelligence#Sample Analysis
A copper-orange Telegram paper plane badge being replicated onto a dark glass panel against a near-black teal-blue dossier background, symbolizing local session replication bypassing authentication

The reproduction result exceeded what I understood to be possible. Telegram’s device authentication — phone verification, SMS code, 2FA password — seemed, to me, well-designed and complete. But when the tdata directory was copied to another Mac and the client launched, the login screen never appeared. This was not 2FA being cracked. The entire reuse path never entered a stage where credentials were requested.

This Should Not Have Happened

On July 15, a colleague sent me an analysis they had written: a macOS stealer that collects wallet databases, Keychain credentials, and browser data — and also copies the Telegram Desktop tdata session directory. One finding in their analysis grabbed my attention: after restoring the tdata to another Mac, Telegram restored the logged-in state directly, with no authentication step triggered at any point.

My first reaction: this shouldn’t happen.

Telegram’s device authentication is not thoughtless. When a new device attempts to log in, the server requires phone verification, an SMS code, and — if 2FA is enabled — the two-factor password. The flow is, by design, complete. An unauthorized device should not be able to bypass it.

So seeing this conclusion, my instinct was skepticism. Based on what I knew about Telegram’s authentication, copying tdata should at most bypass some local caching; the server should detect the environment change when the session is restored and trigger re-authentication. If this were just a claim without a reproduction, I’d lean toward thinking some variable was missed.

But the reproduction was done. And not just once — it was done on both of Telegram’s macOS clients: the Qt-based cross-platform Telegram Desktop, and the Swift-native Telegram for macOS.

I decided to work through this myself. Not as a review, but as an attempt to understand: why does a result that should not be possible, actually occur?

The tdata Directory: What Gets Copied

Telegram Desktop persists its login state in ~/Library/Application Support/Telegram Desktop/tdata/. This directory is the client’s on-disk session dataset — it contains key material, session state, and mapping structures needed to maintain the logged-in state across restarts.

The stealer’s logic for copying this directory is explicit:

std::string src = app_support + "Telegram Desktop/tdata/";
std::string dst = staging + "tg/";

copy_file(src + "key_datas", dst + "key_datas");

std::vector<std::string> names = list_directory_names(src);
for (const std::string& name : names) {
    if (contains(names, name + "s")) {
        copy_file(src + name + "s", dst + name + "s");
        copy_file(src + name + "/maps", dst + name + "/maps");
    }
}

This is not a casual scan for a few file names. The code copies key_datas first, then iterates through the directory looking for paired session files and their corresponding maps subdirectories. Together, these files form the complete dataset the client needs to reconstruct the logged-in state.

The Reproduction: Authentication Bypassed

Telegram Desktop

In an isolated environment (macOS 12.7 / Telegram Desktop 4.16), my colleague restored the tdata files copied from the victim’s machine to the correct path.

The client was launched. The login screen did not appear.

No phone number prompt. No SMS code. No 2FA password prompt. The client restored the original account’s logged-in state directly, then began syncing chat history.

I have to record this honestly: seeing this result, I still felt the need to check whether something had been missed. Because in my understanding, Telegram’s device authentication should not permit this path. But the reproduction environment was clean — no cached data, no residual auth tokens, nothing pre-configured. Just a verbatim copy of the tdata.

One distinction needs to be made clear: session reuse is not the same as cracking 2FA.

Telegram’s two-factor authentication protects the “new device authorization” flow — when a device that has never been authorized initiates a login, the server verifies the phone number, SMS code, and 2FA password. But when an attacker directly restores local session data that already represents an authorized state, the client itself is in a “logged-in” state. It does not re-trigger the full authentication flow. The entire reuse path never enters the stage where credentials are needed.

In other words: 2FA did not fail. It was bypassed — not because the attacker guessed the password, but because the attacker took a path that never leads to a password prompt.

Telegram for macOS: One More Layer of Risk

In addition to Telegram Desktop, Telegram distributes a separate native macOS client — Telegram for macOS (the Swift-native version, available through the App Store or direct download from telegram.org). Tests on this client showed the same behavior: local session files can be copied and restored on another Mac, and the authentication flow is bypassed in the same way.

But the native client exhibited one behavioral difference from Telegram Desktop that I feel compelled to flag.

In my colleague’s tests, when the server detected anomalous login behavior and triggered its security mechanism, Telegram Desktop was forcibly logged out and its local data cleared. Telegram for macOS behaved differently — the client, once flagged by the security mechanism, could no longer send or receive new messages, but the interface remained open, and the locally cached chat history was still browsable.

This means the macOS native client presents two blind spots in this attack scenario: not only is the session invisible through the “new device” dimension that users typically rely on, but even after server-side detection kicks in, cached chat history remains exposed.

The Device List Blind Spot: No New Record

One easy-to-miss detail from the reproduction: the copied session did not reliably appear as a clear, distinct new device entry in the active sessions list.

This means that even if the victim proactively checks Telegram’s active sessions list, they may not immediately realize that their local session data has been copied.

When the original and the reproduced device are used concurrently over extended periods, the server may invalidate one of the sessions due to AuthKey conflicts or abnormal behavior patterns, forcing a re-login. But in shorter, intermittent access tests, the session was not immediately terminated. The attacker uses the same AuthKey as the victim, and the behavioral difference from “normal user continuing from a new IP” is minimal — making automated detection difficult.

From tdata to Programmable API Sessions

Beyond directly restoring the desktop client, there is a more subtle exploitation path. Once tdata is obtained, the attacker can combine open-source libraries (opentele, Telethon, etc.), the already-authorized AuthKey, and official client API parameters to convert the local login state into a programmable Telegram API session.

The resulting API session can read conversations, retrieve historical messages, and send messages. Because it reuses the original authorization, no new device record appears. Scripts can operate with short, intermittent connections — no long-lived connection is necessary, reducing the risk of triggering an immediate abnormal logout.

Passcode: The Only Local Defense, but Not on Its Own

Telegram Desktop offers a local protection mechanism — the Passcode. If the user has enabled it in client settings, the attacker may still be prompted for this password after restoring the session.

But this defense needs to be evaluated within the full attack chain. The stealer simultaneously collects data from macOS Keychain, Apple Notes, and browser password managers. These locations may happen to contain the user’s Telegram Passcode, or passwords reused across multiple services.

An Honest Record

Having written this, I want to say a few things plainly.

This reproduction result broke my existing understanding of Telegram’s device authentication mechanism. Before this analysis, if someone had asked me “what happens if Telegram’s tdata is copied to another computer,” my likely answer would have been: the server will detect an AuthKey-environment mismatch and require re-authentication. That answer is wrong.

But what was wrong was not my technical understanding of the authentication flow — the descriptions of phone verification, SMS codes, and 2FA are technically correct. What was wrong was the unexamined premise I had accepted: that the client would, on startup, detect an environment change and trigger re-authentication. In reality, Telegram’s desktop client treats “local files are intact” as equivalent to “the legitimate user is operating this device,” with no built-in detection for the scenario where files have been copied to a different machine.

This made me re-examine something: how to handle it when a security conclusion conflicts with intuition.

My approach: do not dismiss a test result because intuition says “this shouldn’t happen.” Intuition is a starting point for cognition, not an endpoint. If the test design and reproduction environment are sound, what needs correction is the assumption behind the intuition — not the test conclusion.

Telegram’s local session reuse is not a design flaw — the desktop client’s design premise has always been “the local filesystem is secure.” The problem is that this premise ceases to hold once malicious code gains file access, and the client does not respond when the premise is broken. This is a classic case of the consistency gap: an inconsistency between the security assumption at the implementation layer (filesystem access is controlled) and the actual state at the trust layer (the attacker has file access).

After testing both Telegram Desktop and Telegram for macOS, it is clear that this risk is not specific to one client implementation — it is inherent to the desktop local session persistence model. The macOS native client’s different anomaly response — refusing to force-logout — further expands the risk surface.

For Telegram desktop clients that are rarely opened, this problem is especially insidious: a user may log in once on a particular device and then go months without opening it. The attacker has an ample time window to read chat history, and the next time the user opens the client, there will be no “suspicious login” notification — because from the server’s perspective, it is still “the same device.”