Add miio-extract-tokens tool for extracting tokens from sqlite databases#77
Add miio-extract-tokens tool for extracting tokens from sqlite databases#77
Conversation
…ses. This is to simplify the process for token and device type extraction, and will probably later merged to the CLI tool to generate config files based on known devices. Tested to work fine on .tar files extracted from Android backups, support for Apple databases is incomplete. Related to #75.
mirobo/extract_tokens.py
Outdated
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() No newline at end of file |
|
|
||
| @click.command() | ||
| @click.argument('backup') | ||
| @click.option('--write-to-disk', type=click.File('wb'), help='writes sqlite3 db to a file for debugging') |
There was a problem hiding this comment.
line too long (105 > 79 characters)
mirobo/extract_tokens.py
Outdated
| is_android = conn.execute( | ||
| "SELECT name FROM sqlite_master WHERE type='table' AND name='devicerecord';").fetchone() is not None | ||
| is_apple = conn.execute( | ||
| "SELECT name FROM sqlite_master WHERE type='table' AND name='ZDEVICE'").fetchone() is not None |
There was a problem hiding this comment.
line too long (106 > 79 characters)
mirobo/extract_tokens.py
Outdated
| conn.row_factory = sqlite3.Row | ||
| with conn: | ||
| is_android = conn.execute( | ||
| "SELECT name FROM sqlite_master WHERE type='table' AND name='devicerecord';").fetchone() is not None |
There was a problem hiding this comment.
line too long (112 > 79 characters)
mirobo/extract_tokens.py
Outdated
| click.echo("Saving db to %s" % fp) | ||
| fp.write(db.read()) | ||
|
|
||
| def read_tokens(db): |
mirobo/extract_tokens.py
Outdated
| name = dev['name'] | ||
| ssid = dev['ssid'] | ||
| token = dev['token'] | ||
| click.echo("%s (%s) at %s. token: %s (mac: %s, ssid: %s)" % (name, model, ip, token, mac, ssid)) |
There was a problem hiding this comment.
line too long (104 > 79 characters)
mirobo/extract_tokens.py
Outdated
| ip = dev['ZLOCALIP'] | ||
| click.echo("device at %s. token: %s" % (ip, token)) | ||
| dump_raw(dev) | ||
| raise NotImplementedError("Please report the previous output to developers") |
There was a problem hiding this comment.
line too long (80 > 79 characters)
mirobo/extract_tokens.py
Outdated
| raw = {k: dev[k] for k in dev.keys()} | ||
| click.echo(pf(raw)) | ||
|
|
||
| def decrypt_ztoken(ztoken): |
mirobo/extract_tokens.py
Outdated
| from Crypto.Cipher import AES | ||
| from pprint import pformat as pf | ||
|
|
||
| def dump_raw(dev): |
mirobo/extract_tokens.py
Outdated
| import tarfile | ||
| import tempfile | ||
| import sqlite3 | ||
| import binascii |
* Refactor the code into a class for further use * add --dump-raw and --dump-all (prints devs without IP addrs, such as linked BT devices)
| @click.command() | ||
| @click.argument('backup') | ||
| @click.option('--write-to-disk', type=click.File('wb'), help='writes sqlite3 db to a file for debugging') | ||
| @click.option('--dump-all', is_flag=True, default=False, help='dump devices without ip addresses') |
There was a problem hiding this comment.
line too long (98 > 79 characters)
| is_android = self.conn.execute( | ||
| "SELECT name FROM sqlite_master WHERE type='table' AND name='devicerecord';").fetchone() is not None | ||
| is_apple = self.conn.execute( | ||
| "SELECT name FROM sqlite_master WHERE type='table' AND name='ZDEVICE'").fetchone() is not None |
There was a problem hiding this comment.
line too long (110 > 79 characters)
| self.conn.row_factory = sqlite3.Row | ||
| with self.conn: | ||
| is_android = self.conn.execute( | ||
| "SELECT name FROM sqlite_master WHERE type='table' AND name='devicerecord';").fetchone() is not None |
There was a problem hiding this comment.
line too long (116 > 79 characters)
| name = dev['name'] | ||
| token = dev['token'] | ||
| if ip or self.dump_all: | ||
| click.echo("%s\n\tModel: %s\n\tIP address: %s\n\tToken: %s\n\tMAC: %s" % (name, model, ip, token, mac)) |
There was a problem hiding this comment.
line too long (119 > 79 characters)
|
|
||
| def read_android(self): | ||
| click.echo("Reading tokens from Android DB") | ||
| c = self.conn.execute("SELECT * FROM devicerecord WHERE token IS NOT '';") |
There was a problem hiding this comment.
line too long (82 > 79 characters)
| name = dev['ZNAME'] | ||
| token = BackupDatabaseReader.decrypt_ztoken(dev['ZTOKEN']) | ||
| if ip or self.dump_all: | ||
| click.echo("%s\n\tModel: %s\n\tIP address: %s\n\tToken: %s\n\tMAC: %s" % (name, model, ip, token, mac)) |
There was a problem hiding this comment.
line too long (119 > 79 characters)
This is to simplify the process for token and device type extraction,
and will probably later merged to the CLI tool to generate config files
based on known devices.
Tested to work fine on .tar files extracted from Android backups
as well as sqlite DBs from both Android and Apple. Related to #75.
Example output: