ソースを参照

use newer version of sqlcipher

ppwwyyxx 10 年 前
コミット
8db2d6d11a

+ 5 - 1
README.md

@@ -15,6 +15,7 @@ __NEWS__: WeChat 6.0+ use silk to encode audio. The code is updated.
 + python-PIL
 + [PyQuery](https://pypi.python.org/pypi/pyquery/1.2.1)
 + [pysox](https://pypi.python.org/pypi/pysox/0.3.6.alpha)
++ [pysqlcipher](https://pypi.python.org/pypi/pysqlcipher)
 + numpy
 + python-csscompressor(optional)
 + adb and rooted android phone connected to PC
@@ -39,12 +40,15 @@ __NEWS__: WeChat 6.0+ use silk to encode audio. The code is updated.
 			+ Find IMEI in system settings
 		+ Decrypt database, will produce `decrypted.db`:
 		```
-		./decrypt-db.sh <path to EnMicroMsg.db> <imei> <uin>
+		./decrypt-db.py <path to EnMicroMsg.db> <imei> <uin>
 		```
 
+
 NOTE: you may need to try different ways to getting imei & uin,
 because things behave differently on different phones.
 
+Also, if the decryption doesn't work with pysqlcipher, maybe try the version of sqlcipher in `legacy`.
+
 
 + Get WeChat user resource directory from your phone to `resource` directory:
 	+ `./android-interact.sh res`

+ 5 - 5
android-interact.sh

@@ -18,7 +18,7 @@ adb root
 
 if [[ $1 == "uin" ]]; then
 	adb pull $MM_DIR/shared_prefs/system_config_prefs.xml 2>/dev/null
-	uin=$(grep 'default_uin' system_config_prefs.xml | $GREP -o 'value="[0-9]*' | cut -c 8-)
+	uin=$($GREP 'default_uin' system_config_prefs.xml | $GREP -o 'value="-\?[0-9]*' | cut -c 8-)
 	[[ -n $uin ]] || {
 		>&2 echo "Failed to get wechat uin. You can try other methods, or report a bug."
 		exit 1
@@ -26,7 +26,7 @@ if [[ $1 == "uin" ]]; then
 	rm system_config_prefs.xml
 	echo "Got wechat uin: $uin"
 elif [[ $1 == "imei" ]]; then
-	imei=$(adb shell dumpsys iphonesubinfo | grep 'Device ID' | $GREP -o '[0-9]\+')
+	imei=$(adb shell dumpsys iphonesubinfo | $GREP 'Device ID' | $GREP -o '[0-9]\+')
 	[[ -n $imei ]] || {
 		>&2 echo "Failed to get imei. You can try other methods, or report a bug."
 		exit 1
@@ -78,9 +78,9 @@ elif [[ $1 == "db" || $1 == "res" ]]; then
 	fi
 elif [[ $1 == "db-decrypt" ]]; then
 	echo "Getting uin..."
-	$0 uin | tail -n1 | grep -o '[0-9]*' | tee /tmp/uin
+	$0 uin | tail -n1 | $GREP -o '-\?[0-9]*' | tee /tmp/uin
 	echo "Getting imei..."
-	$0 imei | tail -n1 | grep -o '[0-9]*' | tee /tmp/imei
+	$0 imei | tail -n1 | $GREP -o '[0-9]*' | tee /tmp/imei
 	echo "Getting db..."
 	$0 db
 	echo "Decrypting db..."
@@ -90,7 +90,7 @@ elif [[ $1 == "db-decrypt" ]]; then
 		>&2 echo "Failed to get imei or uin. See README for manual methods."
 		exit 1
 	fi
-	./decrypt-db.sh EnMicroMsg.db $imei $uin
+	./decrypt-db.py EnMicroMsg.db $imei $uin
 	rm /tmp/{uin,imei}
 	echo "Done. See decrypted.db"
 else

+ 51 - 0
decrypt-db.py

@@ -0,0 +1,51 @@
+#!/usr/bin/env python2
+# -*- coding: UTF-8 -*-
+# File: decrypt-db.py
+# Author: Yuxin Wu <[email protected]>
+
+from argparse import ArgumentParser
+from pysqlcipher import dbapi2 as sqlite
+
+from hashlib import md5
+import sys
+import os
+
+def get_args():
+    parser = ArgumentParser()
+    parser.add_argument('db', help='path to EnMicroMsg.db')
+    parser.add_argument('imei', help='15 digit IMEI of your phone')
+    parser.add_argument('uin', help='WeChat UIN')
+    parser.add_argument('--output', help='output decrypted database',
+                        default='decrypted.db')
+    args = parser.parse_args()
+    return args
+
+def get_key(imei, uin):
+    a = md5(imei + uin)
+    return a.hexdigest()[:7]
+
+if __name__ == '__main__':
+    args = get_args()
+
+    output = args.output
+    if os.path.isfile(output):
+        print "{} already exists. Remove? (y/n)".format(args.output),
+        ans = raw_input()
+        if ans not in ['y', 'Y']:
+            print "Bye!"
+            sys.exit()
+        os.unlink(argsos.output)
+    key = get_key(args.imei, args.uin)
+    print "KEY: {}".format(key)
+
+    print "Dump decrypted database... "
+    conn = sqlite.connect(args.db)
+    c = conn.cursor()
+    c.execute("PRAGMA key = '" + key + "';")
+    c.execute("PRAGMA cipher_use_hmac = OFF;")
+    c.execute("PRAGMA cipher_page_size = 1024;")
+    c.execute("PRAGMA kdf_iter = 4000;")
+    c.execute("ATTACH DATABASE '" + args.output + "' AS db KEY '';")
+    c.execute("SELECT sqlcipher_export('db');" )
+    c.execute("DETACH DATABASE db;" )
+    c.close()

+ 3 - 1
decrypt-db.sh → legacy/decrypt-db.sh

@@ -32,11 +32,13 @@ echo "Use $version sqlcipher of $os."
 echo "Dump decrypted database... (Don't worry about libcrypt.so version warning.)"
 
 
-SQLCIPHER=./third-party/sqlcipher/$os/$version
+SQLCIPHER=./sqlcipher/$os/$version
 export LD_LIBRARY_PATH=$SQLCIPHER
 "$SQLCIPHER"/sqlcipher "$MSGDB" << EOF
 PRAGMA key='$KEY';
 PRAGMA cipher_use_hmac = off;
+PRAGMA cipher_page_size = 1024;
+PRAGMA kdf_iter = 4000;
 ATTACH DATABASE "$output" AS db KEY "";
 SELECT sqlcipher_export("db");
 DETACH DATABASE db;

+ 0 - 0
third-party/sqlcipher/LICENSE → legacy/sqlcipher/LICENSE


+ 0 - 0
third-party/sqlcipher/README.md → legacy/sqlcipher/README.md


+ 0 - 0
third-party/sqlcipher/darwin/64bit/.libs/sqlite3 → legacy/sqlcipher/darwin/64bit/.libs/sqlite3


+ 0 - 0
third-party/sqlcipher/darwin/64bit/sqlcipher → legacy/sqlcipher/darwin/64bit/sqlcipher


+ 0 - 0
third-party/sqlcipher/linux/32bit/libsqlcipher.so.0 → legacy/sqlcipher/linux/32bit/libsqlcipher.so.0


+ 0 - 0
third-party/sqlcipher/linux/32bit/sqlcipher → legacy/sqlcipher/linux/32bit/sqlcipher


+ 0 - 0
third-party/sqlcipher/linux/64bit/libsqlcipher.so.0 → legacy/sqlcipher/linux/64bit/libsqlcipher.so.0


+ 0 - 0
third-party/sqlcipher/linux/64bit/sqlcipher → legacy/sqlcipher/linux/64bit/sqlcipher