diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..a65eee4
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "stalkerware-indicators"]
+ path = stalkerware-indicators
+ url = git@github.com:AssoEchap/stalkerware-indicators.git
diff --git a/Brewfile b/Brewfile
index 34d6f6d..ecb2398 100644
--- a/Brewfile
+++ b/Brewfile
@@ -4,8 +4,4 @@ cask "android-platform-tools"
brew "expect"
brew "libimobiledevice"
-brew "ideviceinstaller"
-
-brew "autoconf"
-brew "automake"
-brew "libtool"
+brew "ideviceinstaller"
\ No newline at end of file
diff --git a/config.py b/config.py
index 4ff522b..e02d9c8 100644
--- a/config.py
+++ b/config.py
@@ -1,10 +1,32 @@
import hashlib
import hmac
import os
+import secrets
import shlex
from pathlib import Path
from sys import platform
+import logging
+import logging.handlers as handlers
+
+def setup_logger():
+ """
+ Set up a logger with a rotating file handler.
+
+ The logger will write in a file named 'app.log' in the 'logs' directory.
+ The log file will rotate when it reaches 100,000 bytes, keeps a maximum of 30 files.
+
+ Returns:
+ logging.Logger: The configured logger object.
+ """
+ handler = handlers.RotatingFileHandler(
+ 'logs/app.log', maxBytes=100000,
+ backupCount=30)
+ logger = logging.getLogger(__name__)
+ logger.setLevel(logging.INFO)
+ logger.addHandler(handler)
+ return logger
+
DEV_SUPPRTED = ["android", "ios"] # 'windows', 'mobileos', later
THIS_DIR = Path(__file__).absolute().parent
@@ -16,6 +38,7 @@
}
spyware_list_file = "static_data/spyware.csv" # hand picked
+
# ---------------------------------------------------------
DEBUG = bool(int(os.getenv("DEBUG", "0")))
TEST = bool(int(os.getenv("TEST", "0")))
@@ -41,40 +64,38 @@
TITLE = {"title": "IPV Spyware Discovery (ISDi){}".format(" (test)" if TEST else "")}
+
APP_FLAGS_FILE = "static_data/app-flags.csv"
APP_INFO_SQLITE_FILE = "sqlite:///static_data/app-info.db"
# IOC stalkware indicators
-IOC_PATH = "data/stalkerware-indicators/"
-IOC_FILE = IOC_PATH + "ioc.yaml"
-
-# IOC stalkware indicators
-IOC_PATH = "data/stalkerware-indicators/"
-IOC_FILE = IOC_PATH + "ioc.yaml"
+IOC_PATH = "stalkerware-indicators"
+IOC_FILE = os.path.join(IOC_PATH, "ioc.yaml")
# we will resolve the database path using an absolute path to __FILE__ because
# there are a couple of sources of truth that may disagree with their "path
# relavitity". Needless to say, FIXME
-SQL_DB_PATH = "sqlite:///{}".format(str(THIS_DIR / "data/fieldstudy.db"))
-# SQL_DB_CONSULT_PATH = 'sqlite:///data/consultnotes.db' + ("~test" if TEST else "")
-
+SQL_DB_PATH = f"sqlite:///{str(THIS_DIR / 'data/fieldstudy.db')}"
+#SQL_DB_CONSULT_PATH = 'sqlite:///data/consultnotes.db' + ("~test" if TEST else "")
def set_test_mode(test):
- global TEST, APP_FLAGS_FILE, SQL_DB_PATH
- TEST = test
- if TEST:
- if not APP_FLAGS_FILE.endswith("~test"):
- APP_FLAGS_FILE = APP_FLAGS_FILE + "~test"
- if not SQL_DB_PATH.endswith("~test"):
- SQL_DB_PATH = SQL_DB_PATH + "~test"
+ """
+ Sets the test mode to the given value and returns the new values of APP_FLAGS_FILE and SQL_DB_PATH.
+ """
+ app_flags_file, sql_db_path = APP_FLAGS_FILE, SQL_DB_PATH
+ if test:
+ if not app_flags_file.endswith('~test'):
+ app_flags_file = APP_FLAGS_FILE + "~test"
+ if not sql_db_path.endswith('~test'):
+ sql_db_path = sql_db_path + "~test"
else:
- if APP_FLAGS_FILE.endswith("~test"):
- APP_FLAGS_FILE = APP_FLAGS_FILE.replace("~test", "")
- if SQL_DB_PATH.endswith("~test"):
- SQL_DB_PATH = SQL_DB_PATH.replace("~test", "")
-
+ if app_flags_file.endswith('~test'):
+ app_flags_file = app_flags_file.replace("~test", '')
+ if sql_db_path.endswith('~test'):
+ sql_db_path = sql_db_path.replace("~test", '')
+ return app_flags_file, sql_db_path
-set_test_mode(TEST)
+APP_FLAGS_FILE, SQL_DB_PATH = set_test_mode(TEST)
STATIC_DATA = THIS_DIR / "static_data"
@@ -117,10 +138,18 @@ def set_test_mode(test):
def open_or_create_random_key(fpath, keylen=32):
- def create():
- import secrets
+ """
+ Opens the file at the given path or creates a new file with a random key of the specified length.
+
+ Args:
+ fpath (str): The path to the file.
+ keylen (int, optional): The length of the random key. Defaults to 32.
- with fpath.open("wb") as f:
+ Returns:
+ bytes: The contents of the file as bytes.
+ """
+ def create():
+ with fpath.open('wb') as f:
f.write(secrets.token_bytes(keylen))
if not fpath.exists():
@@ -162,5 +191,5 @@ def error():
if len(ERROR_LOG) > 0:
e, ERROR_LOG = ERROR_LOG[0], ERROR_LOG[1:]
- print("ERROR: {}".format(e))
+ print(f"ERROR: {e}")
return e.replace("\n", "
")
diff --git a/data_process.py b/data_process.py
index 85bb609..34aa219 100644
--- a/data_process.py
+++ b/data_process.py
@@ -37,9 +37,9 @@ def create_app_flags_file():
sys.stderr.write("Concatenating...")
fulld = pd.concat(dlist)
sys.stderr.write("done\n")
- spyware = pd.read_csv(config.spyware_list_file, index_col='appId')
+ spyware = pd.read_csv(config.SPYWARE_LIST_FILE, index_col='appId')
fulld.loc[spyware.index, 'flag'] = 'spyware'
- print("Writing to the file: {}".format(config.APP_FLAGS_FILE))
+ print("Writing to the file: {config.APP_FLAGS_FILE}")
fulld.to_csv(config.APP_FLAGS_FILE)
diff --git a/isdi b/isdi
index c0262ea..9f67b86 100755
--- a/isdi
+++ b/isdi
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
-import logging
-import logging.handlers as handlers
+"""
+The mainfile of ISDi repo.
+"""
import webbrowser
from threading import Timer
@@ -8,24 +9,26 @@ import config
from db import init_db
from web import app, sa
+PORT = 6200 if not (config.TEST or config.DEBUG) else 6202
+HOST = "127.0.0.1" if config.DEBUG else "0.0.0.0"
+
def open_browser():
- webbrowser.open('http://127.0.0.1:' + str(PORT), new=0, autoraise=True)
+ """Opens a browser to make it easy to navigate to ISDi
+ """
+ if not config.TEST:
+ webbrowser.open('http://127.0.0.1:' + str(PORT), new=0, autoraise=True)
if __name__ == "__main__":
import sys
if 'TEST' in sys.argv[1:] or 'test' in sys.argv[1:]:
print("Running in test mode.")
config.set_test_mode(True)
- print("Checking mode = {}\nApp flags: {}\nSQL_DB: {}"
- .format(config.TEST, config.APP_FLAGS_FILE,
- config.SQL_DB_PATH))
- print("TEST={}".format(config.TEST))
+ print(f"Checking mode = {config.TEST}\n"
+ "App flags: {config.APP_FLAGS_FILE}\n"
+ "SQL_DB: {config.SQL_DB_PATH}")
+
+ print(f"TEST={config.TEST}")
init_db(app, sa, force=config.TEST)
- handler = handlers.RotatingFileHandler('logs/app.log', maxBytes=100000,
- backupCount=30)
- logger = logging.getLogger(__name__)
- logger.setLevel(logging.ERROR)
- logger.addHandler(handler)
- PORT = 6200 if not config.TEST else 6202
+ config.setup_logger()
Timer(1, open_browser).start()
- app.run(host="0.0.0.0", port=PORT, debug=config.DEBUG, use_reloader= False)
+ app.run(host=HOST, port=PORT, debug=config.DEBUG, use_reloader=config.DEBUG)
diff --git a/parse_dump.py b/parse_dump.py
index 792f5ad..1d188be 100644
--- a/parse_dump.py
+++ b/parse_dump.py
@@ -320,10 +320,14 @@ def get_data_usage(d, process_uid):
return {"foreground": "unknown", "background": "unknown"}
# FIXME: pandas.errors.ParserError: Error tokenizing data. C error: Expected 21 fields in line 556, saw 22
# parser error (tested on SM-G965U,Samsung,8.0.0)
+ try:
+ net_stats = pd.read_csv(io.StringIO(
+ '\n'.join(d['net_stats'])
+ ), on_bad_lines='warn')
+ except pd.errors.EmptyDataError:
+ config.logging.warning(f"No net_stats for {d['appId']} is empty and has been skipped.")
+ net_stats = pd.DataFrame()
- net_stats = pd.read_csv(
- io.StringIO("\n".join(d["net_stats"])), on_bad_lines="warn"
- )
d = net_stats.query('uid_tag_int == "{}"'.format(process_uid))[
["uid_tag_int", "cnt_set", "rx_bytes", "tx_bytes"]
].astype(int)
@@ -478,7 +482,6 @@ def load_file(self):
apps_plist = load(app_data)
d = pd.DataFrame(apps_plist)
d['appId'] = d['CFBundleIdentifier']
- # d.set_index('appId', inplace=True)
return d
except Exception as ex:
print(ex)
@@ -575,8 +578,9 @@ def info(self, appid):
# app = self.df.iloc[appidx,:].dropna()
app = self.df[self.df["CFBundleIdentifier"] == appid].squeeze().dropna()
party = app.ApplicationType.lower()
- if party in ["system", "user"]:
- print(f"{app["CFBundleName"]} ({app["CFBundleIdentifier"]}) is a {party} app and has permissions:")
+ permissions = []
+ if party in ["system", "user", "hidden"]:
+ print(f"{app['CFBundleName']} ({app['CFBundleIdentifier']}) is a {party} app and has permissions:")
# permissions are an array that returns the permission id and an explanation.
permissions = self.get_permissions(app)
res["permissions"] = [(p.capitalize(), r) for p, r in permissions]
@@ -622,7 +626,8 @@ def system_apps(self):
def installed_apps_titles(self) -> pd.DataFrame:
if self:
- return self.df.rename(index=str, columns={"CFBundleExecutable": "title"})
+ return self.df.rename(index=str,
+ columns={'CFBundleExecutable': 'title'}).set_index('appId')
def installed_apps(self):
# return self.df.index
@@ -646,5 +651,5 @@ def installed_apps(self):
print(json.dumps(ddump.info("ru.kidcontrol.gpstracker"), indent=2))
elif sys.argv[2] == "ios":
ddump = IosDump(fname)
- # print(ddump.installed_apps())
+ print(ddump.installed_apps())
print(ddump.installed_apps_titles().to_csv())
diff --git a/phone_scanner.py b/phone_scanner.py
index 06e0338..6151d38 100644
--- a/phone_scanner.py
+++ b/phone_scanner.py
@@ -86,7 +86,7 @@ def dump_path(self, serial, fkind="json"):
config.DUMP_DIR, "{}_{}.{}".format(hmac_serial, self.device_type, fkind)
)
- def app_details(self, serialno, appid):
+ def app_details(self, serialno, appid) -> (dict, dict):
try:
d = pd.read_sql(
"select * from apps where appid=?", self.app_info_conn, params=(appid,)
@@ -107,21 +107,20 @@ def app_details(self, serialno, appid):
info = ddump.info(appid)
- print("BEGIN APP INFO")
- print("info={}".format(info))
- print("END APP INFO")
+ config.logging.info('BEGIN APP INFO')
+ config.logging.info("info={}".format(info))
+ config.logging.info('END APP INFO')
# FIXME: sloppy iOS hack but should fix later, just add these to DF
# directly.
if self.device_type == "ios":
# TODO: add extra info about iOS? Like idevicediagnostics
# ioregentry AppleARMPMUCharger or IOPMPowerSource or
# AppleSmartBattery.
- d["permissions"] = pd.Series(info.get("permissions", ""))
- # d['permissions'] = [info.get('permissions','')]
- d["title"] = pd.Series(info.get("title", ""))
- # del info['permissions']
- print("AppInfo: ", info, appid, dfname, ddump)
- return d.fillna(""), info
+ d['permissions'] = pd.Series(info.get('permissions',''), dtype=object)
+ d['title'] = pd.Series(info.get('title',''))
+ del info['permissions']
+ d = d.fillna('').to_dict(orient='index').get(0, {})
+ return d, info
except KeyError as ex:
print(">>> Exception:::", ex, file=sys.stderr)
return pd.DataFrame([]), dict()
@@ -264,14 +263,14 @@ def get_apps(self, serialno: str, from_dump: bool=True) -> list:
self.installed_apps = installed_apps
return installed_apps
- def get_system_apps(self, serialno, from_dump=False):
+ def get_system_apps(self, serialno, from_dump=False) -> list:
if (not from_dump):
apps = self._get_apps_from_device(serialno, '-s')
else:
apps = [] # TODO: fix this later, not sure how to get from dump
return apps
- def get_offstore_apps(self, serialno, from_dump=False):
+ def get_offstore_apps(self, serialno, from_dump=False) -> list:
if from_dump:
return [] # TODO: fix this later, not sure how to get from dump
offstore = []
@@ -364,18 +363,12 @@ def uninstall(self, serial, appid):
)
return s != -1
- def app_details(self, serialno, appid):
+ def app_details(self, serialno, appid) -> (dict, dict):
d, info = super(AndroidScan, self).app_details(serialno, appid)
# part that requires android to be connected / store this somehow.
hf_recent, non_hf_recent, non_hf, stats = all_permissions(
self.dump_path(serialno), appid
)
- # print(f"Permissions:\n"\
- # f"hf_recent=\n{hf_recent}\n"\
- # f"non_hf_recent=\n{non_hf_recent}\n"\
- # f"no_hf=\n{non_hf}\n"\
- # f"stats=\n{stats}\n")
-
# FIXME: some appopps in non_hf_recent are not included in the
# output. maybe concat hf_recent with them?
info["Date of Scan"] = datetime.now().strftime(config.DATE_STR)
@@ -406,13 +399,15 @@ def app_details(self, serialno, appid):
),
axis=1,
)
-
# print("hf_recent['label']=", hf_recent['label'].tolist())
- # print(~hf_recent['timestamp'].str.contains('unknown'))
- d.at[0, "permissions"] = hf_recent["label"].tolist()
- non_hf_recent.drop("appId", axis=1, inplace=True)
- d.at[0, "non_hf_permissions_html"] = non_hf_recent.to_html()
-
+ #print(~hf_recent['timestamp'].str.contains('unknown'))
+ non_hf_recent.drop('appId', axis=1, inplace=True)
+ d = d.fillna('').to_dict(orient='index').get(0, {})
+ print(d)
+ # d.at[0, 'permissions'] = hf_recent['label'].tolist()
+ # d.at[0, 'non_hf_permissions_html'] = non_hf_recent.to_html()
+ d['permissions'] = hf_recent['label'].tolist()
+ d['non_hf_permissions_html'] = non_hf_recent.to_html()
print("App info dict:", d)
# hf_recent['label'] = hf_recent['label'].map(str) + " (last used by app: "+\
@@ -589,12 +584,13 @@ def _is_device(x):
cmd = "{}idevice_id -l | tail -n 1".format(self.cli)
self.serialno = None
s = catch_err(run_command(cmd), cmd=cmd, msg="")
+
d = [
line.strip()
for line in s.split("\n")
if line.strip() and _is_device(line.strip())
]
- print("Devices found:", d)
+ config.logging.info("Devices found:", d)
return d
def device_info(self, serial):
diff --git a/scripts/get-stalkerware-indicators.py b/scripts/get-stalkerware-indicators.py
index 365a40c..2964a53 100644
--- a/scripts/get-stalkerware-indicators.py
+++ b/scripts/get-stalkerware-indicators.py
@@ -51,7 +51,7 @@ def requirements():
try:
with open(config.APP_FLAGS_FILE, "r") as f:
reader = csv.reader(f)
- old_apps = [row[0] for row in csv.reader(f)]
+ old_apps = set([row[0] for row in csv.reader(f)])
except csv.Error as e:
print("Error parsing CSV app flags file: {}".format(e))
sys.exit(1)
@@ -62,7 +62,7 @@ def requirements():
try:
# append new apps to app-flags.csv for all ioc apps
with open(config.APP_FLAGS_FILE, "a") as f:
- writer = csv.writer(f)
+ writer = csv.writer(f, lineterminator='\n')
for element in ioc:
if 'packages' not in element:
continue
@@ -72,7 +72,7 @@ def requirements():
new_app_count += 1
if 'names' not in element:
element['names'] = []
- names = ','.join(element['names'])
+ names = ' / '.join(element['names'])
writer.writerow([app, "playstore", "spyware", names])
except csv.Error as e:
print("Error parsing CSV app flags file: {}".format(e))
diff --git a/scripts/ios_dependencies.sh b/scripts/ios_dependencies.sh
deleted file mode 100755
index c2198ae..0000000
--- a/scripts/ios_dependencies.sh
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/env bash
-echo -e "\033[31mDev-Jam 12/01/2015 - Script to build Libimobiledevice\033[0m"
-echo -e "\033[32m\033[1m\033[4m\033[5m\033[7mCreator Dev-Jam improved by matteyeux on 27/12/15\033[0m"
-
-#######################################################################
-#
-# Project......: autobuild.sh
-# Creator......: Dev-Jam remasterized for Matteyeux le 27/12/15
-#######################################################################
-
-
-
-function depends(){
-
- if [[ $(which apt-get) ]]; then
- sudo apt-get install -y git build-essential make autoconf \
- automake libtool openssl tar perl binutils gcc g++ \
- libc6-dev libssl-dev libusb-1.0-0-dev \
- libcurl4-gnutls-dev fuse libxml2-dev \
- libgcc1 libreadline-dev libglib2.0-dev libreadline-dev \
- libclutter-1.0-dev libzip-dev cython \
- libfuse-dev python-dev python2.7 \
- libncurses5 policykit-1
- else
- echo "Package manager is not supported"
- exit 1
- fi
-}
-
-function brew_install(){
- # Install Hombrew.
- if [[ ! -e $(which brew) ]]; then
- echo "Brew is not installed..."
- echo "installing brew..."
- sleep 1
- ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- else
- echo "Brew already installed"
- fi
-
- # Install command-line tools using Homebrew.
-
- # Ask for the administrator password upfront.
- sudo -v
-
- # Keep-alive: update existing `sudo` time stamp until the script has finished.
- while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
-
- # Make sure we’re using the latest Homebrew.
- brew update
-
- # Upgrade any already-installed formulae.
- brew upgrade
-
- # Install Development Packages;
- brew install libxml2
- brew install libzip
- brew install libplist
- brew update
- brew install openssl
- brew install usbmuxd
- ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/
- ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib
- brew install --HEAD libimobiledevice
- brew link --overwrite libimobiledevice
- brew install gnutls
-
-
- # Install Software;
- brew install automake
- brew install cmake
- brew install colormake
- brew install autoconf
- brew install libtool
- brew install pkg-config
- brew install gcc
- brew install libusb
- brew install glib
-
- # Install Optional;
- brew install Caskroom/cask/osxfuse
-
-
- # Install other useful binaries.
- brew install ack
- #brew install exiv2
- brew install git
-
- # Remove outdated versions from the cellar.
- brew cleanup
-
-}
-
-function build_libimobiledevice(){
- if [[ $(uname) == 'Darwin' ]]; then
- brew link openssl --force
- fi
- successlibs=()
- failedlibs=()
- libs=( "libplist" "libusbmuxd" "libimobiledevice" "usbmuxd" "libirecovery" \
- "ideviceinstaller" "libideviceactivation" "idevicerestore" "ifuse" )
-
- spinner() {
- local pid=$1
- local delay=0.75
- local spinstr='|/-\'
- echo "$pid" > "/tmp/.spinner.pid"
- while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
- local temp=${spinstr#?}
- printf " [%c] " "$spinstr"
- local spinstr=$temp${spinstr%"$temp"}
- sleep $delay
- printf "\b\b\b\b\b\b"
- done
- printf " \b\b\b\b"
- }
-
- buildlibs() {
- mkdir -p ./ios_deps && cd ios_deps
- for i in "${libs[@]}"
- do
- echo -e "\033[1;32mFetching $i..."
- git clone https://github.com/libimobiledevice/${i}.git
- cd $i
- echo -e "\033[1;32mConfiguring $i..."
- ./autogen.sh
- ./configure
- echo -e "\033[1;32mBuilding $i..."
- make && sudo make install
- echo -e "\033[1;32mInstalling $i..."
- cd ..
- done
- cd ..
- }
-
- buildlibs
- if [[ -e $(which ldconfig) ]]; then
- ldconfig
- else
- echo " "
- fi
-}
-
-if [[ $(uname) == 'Linux' ]]; then
- depends
-elif [[ $(uname) == 'Darwin' ]]; then
- brew_install
-fi
-build_libimobiledevice
-echo -e "\033[32m\033[1m\033[4m\033[5m\033[7mLibimobiledevice installed success Thanks for use Script\033[0m"
diff --git a/scripts/ios_scan.sh b/scripts/ios_scan.sh
deleted file mode 100755
index ca82bb2..0000000
--- a/scripts/ios_scan.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env bash
-
-
-python2=(which python2)
-if [[ "$?" != "0" ]]; then
- echo "You need python2 to be able to run this code"
- exit -1;
-fi
-
-
diff --git a/scripts/monitor_usb.py b/scripts/monitor_usb.py
new file mode 100644
index 0000000..5ab47e3
--- /dev/null
+++ b/scripts/monitor_usb.py
@@ -0,0 +1,22 @@
+from usbmonitor import USBMonitor
+from usbmonitor.attributes import ID_MODEL, ID_MODEL_ID, ID_VENDOR_ID
+import time
+import json
+
+device_info_str = lambda device_info: f"{device_info[ID_MODEL]} ({device_info[ID_MODEL_ID]} - {device_info[ID_VENDOR_ID]})"
+# Define the `on_connect` and `on_disconnect` callbacks
+on_connect = lambda device_id, device_info: print(f"Connected: {device_info_str(device_info=device_info)}")
+on_disconnect = lambda device_id, device_info: print(f"Disconnected: {device_info_str(device_info=device_info)}")
+
+# Create the USBMonitor instance
+monitor = USBMonitor()
+
+# Start the daemon
+# monitor.start_monitoring(on_connect=on_connect, on_disconnect=on_disconnect, check_every_seconds=2)
+monitor.check_changes(on_connect=on_connect, on_disconnect=on_disconnect)
+print(f"Available devices: {json.dumps(monitor.get_available_devices(), indent=2)}")
+time.sleep(5)
+# ... Rest of your code ...
+
+# If you don't need it anymore stop the daemon
+# monitor.stop_monitoring()
diff --git a/stalkerware-indicators b/stalkerware-indicators
new file mode 160000
index 0000000..3f72171
--- /dev/null
+++ b/stalkerware-indicators
@@ -0,0 +1 @@
+Subproject commit 3f7217116dde26808b017c111c1df218bc5b1dc5
diff --git a/static_data/app-flags.csv b/static_data/app-flags.csv
index 05595f4..3b01658 100644
--- a/static_data/app-flags.csv
+++ b/static_data/app-flags.csv
@@ -5156,3 +5156,13 @@ com.probit.flare,playstore,spyware,
com.camhart.netcountable,playstore,spyware,
com.contentwatch.ghoti.cp2.child,playstore,spyware,
com.timeon.litclient,playstore,spyware,
+com.surebrec,playstore,spyware,Cerberus
+com.ssurebrec,playstore,spyware,Cerberus
+com.tutorial.instalao,playstore,spyware,MeuSpy
+com.aisistem.instalao,playstore,spyware,MeuSpy
+br.com.appfornecedor.legal,playstore,spyware,MeuSpy
+com.mtf.download,playstore,spyware,MobileTrackerFree / MonitorLoverman / MTrack / CellTracker / TrackMobil
+iiw.orqjtwbkx,playstore,spyware,MonitorChecker / AndrMonitor / AndroidMon / Dromon
+efexmsz.mzuooelftl,playstore,spyware,MonitorChecker / AndrMonitor / AndroidMon / Dromon
+com.wisemo.wsmguest.v18,playstore,spyware,
+org.findmykids.child,playstore,spyware,
diff --git a/web/view/details.py b/web/view/details.py
index d43eea3..530cdf4 100644
--- a/web/view/details.py
+++ b/web/view/details.py
@@ -9,8 +9,6 @@ def app_details(device):
appid = request.args.get('appId')
ser = request.args.get('serial')
d, info = sc.app_details(ser, appid)
- d = d.fillna('')
- d = d.to_dict(orient='index').get(0, {})
d['appId'] = appid
# detect apple and put the key into d.permissions
diff --git a/web/view/scan.py b/web/view/scan.py
index 1705107..e1c5412 100644
--- a/web/view/scan.py
+++ b/web/view/scan.py
@@ -98,13 +98,14 @@ def scan():
"debugging is turned on on the device, and then scan again."
error += "{} Please follow the setup instructions here, if needed."
- if device == 'ios':
- # go through pairing process and do not scan until it is successful.
- isconnected, reason = sc.setup()
- template_d["error"] = error.format(reason)
- template_d["currently_scanned"] = currently_scanned
- if not isconnected:
- return render_template("main.html", **template_d), 201
+
+ # if device == 'ios':
+ # # go through pairing process and do not scan until it is successful.
+ # isconnected, reason = sc.setup()
+ # template_d["error"] = error.format(reason)
+ # template_d["currently_scanned"] = currently_scanned
+ # if not isconnected:
+ # return render_template("main.html", **template_d), 201
# TODO: model for 'devices scanned so far:' device_name_map['model']
# and save it to scan_res along with device_primary_user.
@@ -115,6 +116,8 @@ def scan():
print(d)
device_name_print = f"{d['device_model']} ({d['device_primary_user']})"
device_name_map = d
+ else:
+ print("ERROR: Could not find device info:", d)
else:
device_name_print, device_name_map = sc.device_info(serial=ser)