Last active
June 18, 2023 02:13
-
-
Save zuccaro/562548a7592f011a7b9a to your computer and use it in GitHub Desktop.
decrypts sqlite3 databases that are encrypted with System.Data.SQLite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def decryptSystemDataSQLite(file, password): | |
""" Decrypts a sqlite3 database encrypted with System.Data.SQLite """ | |
""" | |
System.Data.SQLite has built-in encryption that uses the Windows | |
Cryptography API, which is cool when you are on Windows but if you aren't, | |
you are shit outta luck working with these databases. | |
PyCrypto to the rescue! It works on most platforms. | |
Thanks to dlitz for making this kick-ass easy to use crypto lib. | |
For the original S.D.S code check out http://system.data.sqlite.org/index.html/artifact/e86de9c8c0008bb56fb04a49c9287c9440d4e8cd | |
To the extent possible under law, @zuccaro has waived all copyright and | |
related or neighboring rights to decryptSystemDataSQLite. | |
""" | |
from Crypto.Hash import SHA | |
from Crypto.Cipher import ARC4 | |
from struct import unpack | |
from tempfile import NamedTemporaryFile | |
ret = None | |
with open(file,'rb') as f: | |
key = SHA.new(password).digest()[:16] #win crypto api seems to use 16b | |
header = ARC4.new(key).decrypt(f.read(1024)) #preemptively read header | |
if header[0:15] == 'SQLite format 3': #sanity check, proceed if valid | |
declared_ps = unpack('>H',header[16:18])[0] #ushort_be @ 16 | |
if declared_ps == 1: #1 is a special page_size | |
declared_ps = 65536 #it actually means 64k | |
t = NamedTemporaryFile(delete=False,suffix='.sqlite') | |
f.seek(0) # be kind rewind | |
while True: | |
block = f.read(declared_ps) | |
if not block: #so pythonic | |
break #gtfo | |
t.write(ARC4.new(key).decrypt(block)) #reinitialize rc4 | |
t.close() # close temp file | |
ret = t.name # return temp file name | |
return ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you very much for the code.
If not wrong the line 25 has to be changed to compare bytes.
if header[0:15] == b'SQLite format 3':