check smali
This commit is contained in:
parent
3d7764d958
commit
4f197877ca
2 changed files with 107 additions and 1 deletions
|
|
@ -2,12 +2,16 @@ import zipfile
|
||||||
import io
|
import io
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
import sqlite3
|
||||||
|
import tempfile
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from getpass import getpass
|
from getpass import getpass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
from .androzoo import download_apk
|
from .androzoo import download_apk
|
||||||
from .data import ApkData, load_from_directory
|
from .data import ApkData, load_from_directory
|
||||||
from .analysis import analyze
|
from .analysis import analyze
|
||||||
|
|
@ -130,7 +134,7 @@ def main():
|
||||||
print(entry.to_string())
|
print(entry.to_string())
|
||||||
else:
|
else:
|
||||||
with (args.output_dir / sha256).open("w") as file:
|
with (args.output_dir / sha256).open("w") as file:
|
||||||
file.write(entry)
|
file.write(entry.to_string())
|
||||||
|
|
||||||
if apks:
|
if apks:
|
||||||
if args.json:
|
if args.json:
|
||||||
|
|
@ -231,3 +235,104 @@ def collect_to_db():
|
||||||
)
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
load_from_directory(args.dir, args.db, args.androzoo_list)
|
load_from_directory(args.dir, args.db, args.androzoo_list)
|
||||||
|
|
||||||
|
|
||||||
|
def check_smali():
|
||||||
|
parser = ArgumentParser(
|
||||||
|
prog="Smalli Check",
|
||||||
|
description="Check if duplicated classes have distinct smali",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--db",
|
||||||
|
help="Path to the database storing the results",
|
||||||
|
type=Path,
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
key_parser = parser.add_mutually_exclusive_group(required=False)
|
||||||
|
key_parser.add_argument(
|
||||||
|
"--api-key-file",
|
||||||
|
help="The path to a file containing the Androzoo API key",
|
||||||
|
type=Path,
|
||||||
|
)
|
||||||
|
key_parser.add_argument(
|
||||||
|
"--api-key", help="The Androzoo API key (Usage NOT recommanded)", type=str
|
||||||
|
)
|
||||||
|
SECRET_STORAGE_IMPORTED = False
|
||||||
|
try:
|
||||||
|
import secretstorage
|
||||||
|
|
||||||
|
SECRET_STORAGE_IMPORTED = True
|
||||||
|
|
||||||
|
key_parser.add_argument(
|
||||||
|
"--api-key-keyring-id",
|
||||||
|
help="The ID of the Androzoo API key in the secret service storage",
|
||||||
|
type=str,
|
||||||
|
)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
pass
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
api_key = ""
|
||||||
|
if args.api_key:
|
||||||
|
api_key = args.api_key
|
||||||
|
if args.api_key_file:
|
||||||
|
with args.api_key_file.open("r") as file:
|
||||||
|
api_key = file.read().strip()
|
||||||
|
if SECRET_STORAGE_IMPORTED and not api_key:
|
||||||
|
if args.api_key_keyring_id:
|
||||||
|
key_id = args.api_key_keyring_id
|
||||||
|
else:
|
||||||
|
key_id = "androzoo"
|
||||||
|
try:
|
||||||
|
with secretstorage.dbus_init() as connection:
|
||||||
|
collection = secretstorage.get_default_collection(connection)
|
||||||
|
item = next(collection.search_items({"Title": key_id}))
|
||||||
|
item.unlock()
|
||||||
|
api_key = item.get_secret().decode("utf-8").strip()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if not api_key:
|
||||||
|
api_key = getpass(prompt="Androzoo API key: ").strip()
|
||||||
|
|
||||||
|
with sqlite3.connect(args.db) as conn:
|
||||||
|
apks = list(
|
||||||
|
map(
|
||||||
|
lambda t: t[0],
|
||||||
|
conn.execute("SELECT sha256 FROM data WHERE nb_duplicate_classes >= 1"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
data = {}
|
||||||
|
for sha256 in apks:
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||||
|
d = Path(tmpdirname)
|
||||||
|
apk_bin = download_apk(sha256, api_key, logfile=None)
|
||||||
|
if apk_bin is None:
|
||||||
|
continue
|
||||||
|
with (d / "app.apk").open("wb") as fp:
|
||||||
|
fp.write(apk_bin)
|
||||||
|
with zipfile.ZipFile(io.BytesIO(apk_bin)) as apk:
|
||||||
|
json_data[sha256] = {}
|
||||||
|
entry = analyze(apk, sha256, json_out=json_data[sha256])
|
||||||
|
subprocess.run(["apktool", "d", "app.apk", "-o", "apktool_out"], cwd=d)
|
||||||
|
smalli_dirs = []
|
||||||
|
for dex in json_data[sha256]["class_dex"]:
|
||||||
|
if dex == "classes.dex":
|
||||||
|
smalli_dirs.append(out / "apktool_out" / "smali")
|
||||||
|
else:
|
||||||
|
smalli_dirs.append(
|
||||||
|
out / "apktool_out" / "smali_" + dex.removesuffix(".dex")
|
||||||
|
)
|
||||||
|
dist_dup_classes = set()
|
||||||
|
for cl in json_data[sha256]["duplicated_classes"]:
|
||||||
|
cl_f = cl.removesuffix(";").removeprefix("L") + ".smali"
|
||||||
|
smali = None
|
||||||
|
for cdir in smalli_dirs:
|
||||||
|
if (cdir / cl_f).exists():
|
||||||
|
with (cdir / cl_f).open() as file:
|
||||||
|
smali_new = file.read()
|
||||||
|
if smali is None:
|
||||||
|
smali = smali_new
|
||||||
|
elif smali != smali_new:
|
||||||
|
dist_dup_classes.add(cl)
|
||||||
|
json_data[sha256]["redef_classes"] = list(dist_dup_classes)
|
||||||
|
print(json.dumps(json_data))
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,4 @@ build-backend = "poetry.core.masonry.api"
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
scan = 'android_class_shadowing_scanner.__init__:main'
|
scan = 'android_class_shadowing_scanner.__init__:main'
|
||||||
collect-scan = 'android_class_shadowing_scanner.__init__:collect_to_db'
|
collect-scan = 'android_class_shadowing_scanner.__init__:collect_to_db'
|
||||||
|
check-class-redef = 'android_class_shadowing_scanner.__init__:check_smali'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue