Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add miio-extract-tokens tool for extracting tokens from sqlite databases #77

Merged
merged 3 commits into from
Sep 14, 2017

Conversation

rytilahti
Copy link
Owner

@rytilahti rytilahti commented Sep 14, 2017

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:

± miio-extract-tokens backup/backup.tar
Opened backup/backup.tar
Extracting to /tmp/tmpqvfj2l1x
Reading tokens from Android DB
Gateway (lumi.gateway.v3) at 192.168.XXX. token: 91c52a27eff00b95XX (mac: 28:6C:07:XX, ssid: XXX)
room1 (yeelink.light.color1) at 192.168.XXX. token: a37905aa9a587faXX (mac: F0:B4:29:XX, ssid: XXX)
room2 (yeelink.light.color1) at 192.168.XXX. token: 86b130eac015b2bd2dXX (mac: 28:6C:07:XX, ssid: XXX)
Flower Care (hhcc.plantmonitor.v1) at 134.XXX.XXX. token: 124f90d87b4b9XX (mac: C4:7C:8D:XX, ssid: )
Mi Robot Vacuum (rockrobo.vacuum.v1) at 192.168.XXX. token: 476e6b70343055XXX (mac: 28:6C:07:XX, ssid: XXX)

…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.


if __name__ == "__main__":
main()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (105 > 79 characters)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (106 > 79 characters)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (112 > 79 characters)

click.echo("Saving db to %s" % fp)
fp.write(db.read())

def read_tokens(db):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

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))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (104 > 79 characters)

ip = dev['ZLOCALIP']
click.echo("device at %s. token: %s" % (ip, token))
dump_raw(dev)
raise NotImplementedError("Please report the previous output to developers")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (80 > 79 characters)

raw = {k: dev[k] for k in dev.keys()}
click.echo(pf(raw))

def decrypt_ztoken(ztoken):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

from Crypto.Cipher import AES
from pprint import pformat as pf

def dump_raw(dev):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

import tarfile
import tempfile
import sqlite3
import binascii

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'binascii' imported but unused

@coveralls
Copy link

coveralls commented Sep 14, 2017

Coverage Status

Coverage decreased (-1.3%) to 33.316% when pulling 3be9f4c on token_extractor into 688add1 on master.

@coveralls
Copy link

coveralls commented Sep 14, 2017

Coverage Status

Coverage decreased (-1.3%) to 33.333% when pulling 2000fab on token_extractor into 688add1 on master.

* 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')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 '';")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (119 > 79 characters)

@coveralls
Copy link

coveralls commented Sep 14, 2017

Coverage Status

Coverage decreased (-1.5%) to 33.088% when pulling fdfb5de on token_extractor into 688add1 on master.

Copy link
Collaborator

@syssi syssi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants