Skip to content

Instantly share code, notes, and snippets.

@stek29
Last active May 9, 2024 23:37
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save stek29/8a7ac0e673818917525ec4031d77a713 to your computer and use it in GitHub Desktop.
Save stek29/8a7ac0e673818917525ec4031d77a713 to your computer and use it in GitHub Desktop.
Extract Telegram messages from db_sqlite PostBox – made for Telegram for macOS, but should work with Telegram for iOS
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@dborasn
Copy link

dborasn commented Sep 11, 2021

Nice one, thank you! Would be great to be able to export whole dialogues to CSV

@ElmovdM
Copy link

ElmovdM commented Jul 1, 2022

Awesome work! This works really great on SQLite db's pulled from iOS devices!

@chazer
Copy link

chazer commented Aug 30, 2022

Works like a charm
Thanks

For take decrypted db:

pip install mmh3 pycryptodome pycryptodomex
# extract key

key_file = os.path.expanduser(
    '~/Library/Group Containers/6N38VWS5BX.ru.keepcoder.Telegram/stable/.tempkeyEncrypted'
)
with open(key_file, 'rb') as f:
    tempkeyEnc = f.read()
    dbKey, dbSalt = tempkey_parse(tempkeyEnc, DEFAULT_PASSWORD)
    print(tempkey_pragma(dbKey, dbSalt))
brew install sqlcipher

sqlcipher ~/Library/Group\ Containers/6N38VWS5BX.ru.keepcoder.Telegram/stable/account-*/postbox/db/db_sqlite
# enter key

# save db as decrypted copy

$ sqlcipher postbox/db/db_sqlite
SQLite version 3.37.2 2022-01-06 13:25:41 (SQLCipher 4.5.1 community)
Enter ".help" for usage hints.
sqlite> PRAGMA user_version;
-1179143289
sqlite> PRAGMA cipher_plaintext_header_size=32;
sqlite> PRAGMA cipher_default_plaintext_header_size=32;
sqlite> PRAGMA key="x'*****************************'";
ok
sqlite> ATTACH DATABASE 'plaintext.db' AS plaintext KEY '';
sqlite> SELECT sqlcipher_export('plaintext');
sqlite> DETACH

@rostam2000
Copy link

Hi everyone,

thanks a lot for this script. I am having some problems in generating the right key from .tempkeyEncrypted. I am using chazer's script, which runs, but I believe returns me an incorrect key.
I am not sure I understand the def murmur(d): # seed from telegram return mmh3.hash(d, seed=-137723950) command properly. Could anyone please explain how I should obtain my own seed from Telegram? Also, should I leave DEFAULT_PASSWORD='no_matter_key' or should I populate it differently?

Many thanks!

@chazer
Copy link

chazer commented Oct 3, 2022

Seed -137723950 is the default value from Telegram sources, keep it.
If you setup password in Telegram app – use next code tempkey_parse(tempkeyEnc, 'your-password-here')
Right script output should be SQL code like this:
PRAGMA key="x'1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'";

@chicocvenancio
Copy link

I can't find the tempkeyEncrypted in the current app, there is a notificationsKey fille but it is json and using either it directly or just the data field did not yield results, getting ValueError: Data must be padded to 16 byte boundary in CBC mode instead.

Thanks for the script btw.

@stek29
Copy link
Author

stek29 commented Jan 7, 2023

@chicocvenancio notificationsKey is per account, you need instance level file .tempkeyEncrypted (notice the dot -- it's a hidden file).

~/Library/Group Containers/6N38VWS5BX.ru.keepcoder.Telegram/beta/account-*/notificationsKey -- the file you have found
~/Library/Group Containers/6N38VWS5BX.ru.keepcoder.Telegram/beta/.tempkeyEncrypted -- the file you need

@chicocvenancio
Copy link

@stek29 Thanks. it's in ~/Library/Group Containers/6N38VWS5BX.ru.keepcoder.Telegram/stable now but I did manage to decrypt it. Alas the messages I was trying to recover are not in the db. Kind of sad Telegram allows other parties to nuke the history with no possibility of recovery.

@drzraf
Copy link

drzraf commented Mar 26, 2023

Where did you find that seed value of -137723950 ?
I can't get the hash to match for a binlog file generated with tdlib-1.8.5.so

@stek29
Copy link
Author

stek29 commented Mar 26, 2023

@drzraf this is for native telegram clients for iOS/macOS/*OS, no idea on how tdlib does it.

@drzraf
Copy link

drzraf commented Mar 30, 2023

And do you remember where in GitHub did you encountered the reference to this seed's value (or was it done using bitwise operators in a loop)? Would help to later spot its counterpart of TG Desktop and TDLib.

@chazer
Copy link

chazer commented Mar 31, 2023

@drzraf just use search

@chazer
Copy link

chazer commented Mar 31, 2023

@stek29 Thanks. it's in ~/Library/Group Containers/6N38VWS5BX.ru.keepcoder.Telegram/stable now but I did manage to decrypt it. Alas the messages I was trying to recover are not in the db. Kind of sad Telegram allows other parties to nuke the history with no possibility of recovery.

@chicocvenancio
TimeMachine helps me here)

@stek29
Copy link
Author

stek29 commented Apr 2, 2023

there’s a tool called iLEAPP which now includes this code, but it’s targeted on iOS backup forensics

https://github.com/abrignoni/iLEAPP

@rohitcoder
Copy link

rohitcoder commented Apr 5, 2023

@chazer @stek29

I was trying to recover my message from postbox/db/db_sqlite and i followed all steps, it also generated a 40 MB file plaintext.db but when i tried to open that with https://inloop.github.io/sqlite-viewer/

I'm getting this kind of data, I was expecting plain text messages. Any suggestions here? I am using Telegram on my Mac

image

@stek29
Copy link
Author

stek29 commented Apr 6, 2023

@rohitcoder suggestion is to use the code literally in this gist to decode the database. they’re not in plaintext, they’re encoded in custom format

@DreadfulBot
Copy link

aww, I've got:
raise Exception (f'hash mismatch: {dbHash} != {calcHash}")
and mine crypted file was by path
/Group\ Containers/6N38VWS5BX.ru.keepcoder.Telegram/appstore/.tempkeyEncrypted
Anybody knows how to handle this?

@chazer
Copy link

chazer commented May 19, 2023

@DreadfulBot
Maybe you setup password for Telegram?
Try change 'no-matter-key' to it.

@DaveBombadil
Copy link

@stek29 @chazer

This is awesome!

I followed the instructions and managed to get a 90Mb "plaintext.db" file, and the instruction:

con = sqlite3.connect('plaintext.db')

does connect to the DB, But it crashes when trying to access any of the tables. For example:

OperationalError Traceback (most recent call last)
Input In [31], in <cell line: 1>()
----> 1 for idx, msg in get_all_messages(f=lambda idx: idx.timestamp > 1443989880):
2 if MessageFlags.Incoming in msg['flags'] and 'web versions of Telegram' in msg['text']:
3 print_message(idx, msg)

Input In [9], in get_all_messages(f, decode)
2 cur = con.cursor()
3 try:
----> 4 cur.execute("SELECT key, value FROM t7 ORDER BY key")
5 for key, value in cur:
6 idx = MessageIndex.from_bytes(key)

OperationalError: no such table: t7

Any ideas?

@fr0zenrain
Copy link

I see that passcode is not discussed here. If the user sets passcode, will it affect the generation of the key and the decryption of the final sqlite?

@stek29
Copy link
Author

stek29 commented Nov 8, 2023

@fr0zenrain local passcode is used instead of no-matter-key, if it’s set. This is different from 2FA password set on servers.
I’m not sure about iOS App digit passcode though.

@yunasc
Copy link

yunasc commented Feb 21, 2024

I wonder, is there a way to get tempkey on Windows?

@stek29
Copy link
Author

stek29 commented Mar 6, 2024

@yunasc what do you mean? there's only telegram desktop for windows, and it has no local database

@yunasc
Copy link

yunasc commented Mar 14, 2024

It has an encrypted sqlite DB. I'm using Unigram client which uses tdlib which has local database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment