Skip to content

Commit

Permalink
Migrating to importlib
Browse files Browse the repository at this point in the history
  • Loading branch information
alterakey committed Jan 1, 2024
1 parent 6561a34 commit 9708a60
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 82 deletions.
70 changes: 38 additions & 32 deletions trueseeing/app/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,31 +822,35 @@ async def _use_framework(self, args: deque[str]) -> None:
if not args:
ui.fatal('need framework apk')

import os
from trueseeing.core.tools import invoke_passthru
from pkg_resources import resource_filename
from importlib.resources import as_file, files

apk = args.popleft()

await invoke_passthru(
'java -jar {apktool} if {apk}'.format(
apk=apk,
apktool=resource_filename(__name__, os.path.join('..', 'libs', 'apktool.jar')),
))
with as_file(files('trueseeing.libs').joinpath('apktool.jar')) as path:
await invoke_passthru(
'java -jar {apktool} if {apk}'.format(
apk=apk,
apktool=path,
))

async def _assemble_apk_from_path(self, wd: str, path: str) -> Tuple[str, str]:
import os
from pkg_resources import resource_filename
from importlib.resources import as_file, files
from trueseeing.core.sign import SigningKey
from trueseeing.core.tools import invoke_passthru
await invoke_passthru(
'(java -jar {apkeditor} b -i {path} -o {wd}/output.apk && java -jar {apksigner} sign --ks {keystore} --ks-pass pass:android {wd}/output.apk)'.format(
wd=wd, path=path,
apkeditor=resource_filename(__name__, os.path.join('..', 'libs', 'apkeditor.jar')),
apksigner=resource_filename(__name__, os.path.join('..', 'libs', 'apksigner.jar')),
keystore=await SigningKey().key(),
)
)

with as_file(files('trueseeing.libs').joinpath('apkeditor.jar')) as apkeditorpath:
with as_file(files('trueseeing.libs').joinpath('apksigner.jar')) as apksignerpath:
await invoke_passthru(
'(java -jar {apkeditor} b -i {path} -o {wd}/output.apk && java -jar {apksigner} sign --ks {keystore} --ks-pass pass:android {wd}/output.apk)'.format(
wd=wd, path=path,
apkeditor=apkeditorpath,
apksigner=apksignerpath,
keystore=await SigningKey().key(),
)
)

return os.path.join(wd, 'output.apk'), os.path.join(wd, 'output.apk.idsig')

def _move_apk(self, src: str, dest: str) -> None:
Expand Down Expand Up @@ -915,7 +919,7 @@ async def _disassemble(self, args: deque[str]) -> None:
import shutil
from tempfile import TemporaryDirectory
from trueseeing.core.tools import invoke_passthru
from pkg_resources import resource_filename
from importlib.resources import as_file, files

path = args.popleft()
apk = self._target
Expand All @@ -928,13 +932,14 @@ async def _disassemble(self, args: deque[str]) -> None:
at = time.time()

with TemporaryDirectory() as td:
await invoke_passthru(
'(java -jar {apkeditor} d -o {td}/f -i {apk} {s})'.format(
td=td, apk=apk,
s='-dex' if 's' in cmd else '',
apkeditor=resource_filename(__name__, os.path.join('..', 'libs', 'apkeditor.jar'))
with as_file(files(__name__).joinpath('libs').joinpath('apkeditor.jar')) as apkeditorpath:
await invoke_passthru(
'(java -jar {apkeditor} d -o {td}/f -i {apk} {s})'.format(
td=td, apk=apk,
s='-dex' if 's' in cmd else '',
apkeditor=apkeditorpath,
)
)
)

if os.path.exists(path):
shutil.rmtree(path)
Expand Down Expand Up @@ -1002,20 +1007,21 @@ async def _exploit_apply(self, args: deque[str]) -> None:

async def _prep_exploit(self, ctx: Context) -> None:
import os.path
from pkg_resources import resource_filename
from importlib.resources import as_file, files
from trueseeing.core.tools import invoke_passthru

ctx.create(exist_ok=True)

apk = os.path.join(ctx.wd, 'target.apk')
path = os.path.join(ctx.wd, 'p')
if not os.path.exists(path):
await invoke_passthru(
'(java -jar {apkeditor} d -o {path} -i {apk} -dex)'.format(
apk=apk, path=path,
apkeditor=resource_filename(__name__, os.path.join('..', 'libs', 'apkeditor.jar'))
with as_file(files('trueseeing.libs').joinpath('apkeditor.jar')) as apkeditorpath:
await invoke_passthru(
'(java -jar {apkeditor} d -o {path} -i {apk} -dex)'.format(
apk=apk, path=path,
apkeditor=apkeditorpath,
)
)
)

async def _exploit_disable_pinning(self, args: deque[str]) -> None:
self._require_target()
Expand All @@ -1027,7 +1033,7 @@ async def _exploit_disable_pinning(self, args: deque[str]) -> None:
import time
import shutil
import random
from pkg_resources import resource_filename
from importlib.resources import as_file, files
from trueseeing.core.context import Context

ui.info('disabling declarative TLS pinning {apk}'.format(apk=self._target))
Expand All @@ -1048,8 +1054,8 @@ async def _exploit_disable_pinning(self, args: deque[str]) -> None:

# XXX
path = os.path.join(context.wd, 'p', 'resources', 'package_1', 'res', 'xml', f'{key}.xml')
nscpath = resource_filename(__name__, os.path.join('..', 'libs', 'nsc.xml'))
shutil.copy(nscpath, path)
with as_file(files('trueseeing.libs').joinpath('nsc.xml')) as nscpath:
shutil.copy(nscpath, path)

# XXX
import lxml.etree as ET
Expand Down
5 changes: 2 additions & 3 deletions trueseeing/app/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,10 @@ def selected_on(self, switch: str) -> Set[str]:
class Shell:
@classmethod
def _version(cls) -> str:
from pkg_resources import get_distribution
version = get_distribution('trueseeing').version
from trueseeing import __version__
# ..............................................................................80
return (
f'Trueseeing {version}, the app vulnerability scanner\n'
f'Trueseeing {__version__}, the app vulnerability scanner\n'
'Copyright (C) 2017-23 Takahiro Yoshimura <[email protected]>\n' # noqa: E131
'All rights reserved. Licensed under the terms of GNU General Public License Version 3 or later.\n'
)
Expand Down
17 changes: 9 additions & 8 deletions trueseeing/core/asm.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ def __init__(self, context: Context, skip_resources: bool = False):

@classmethod
def _get_version(cls) -> str:
from pkg_resources import get_distribution
return get_distribution('trueseeing').version
from trueseeing import __version__
return __version__

def disassemble(self) -> None:
self._do()
Expand All @@ -44,8 +44,8 @@ def _do(self) -> None:
import sqlite3
import glob
import subprocess
import pkg_resources
import shutil
from importlib.resources import as_file, files
from trueseeing.core.literalquery import StorePrep

apk, archive = 'target.apk', 'store.db'
Expand All @@ -60,11 +60,12 @@ def _do(self) -> None:
c.execute('create table files(path text not null unique, blob bytes not null)')

with c:
_ = subprocess.run('java -jar {apkeditor} d -i {apk} -o files'.format(
apkeditor=pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'apkeditor.jar')),
apk=apk
), shell=True, capture_output=True)
os.chdir('files')
with as_file(files('trueseeing.libs').joinpath('apkeditor.jar')) as path:
_ = subprocess.run('java -jar {apkeditor} d -i {apk} -o files'.format(
apkeditor=path,
apk=apk
), shell=True, capture_output=True)
os.chdir('files')

def read_as_row(fn: str) -> Tuple[str, bytes]:
with open(fn, 'rb') as f:
Expand Down
21 changes: 12 additions & 9 deletions trueseeing/core/literalquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
from __future__ import annotations
from typing import TYPE_CHECKING

import os.path
import pkg_resources

from trueseeing.core.code.model import Op

if TYPE_CHECKING:
Expand All @@ -33,16 +30,22 @@ def __init__(self, c: Any) -> None:
self.c = c

def stage0(self) -> None:
with open(pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'store.s.sql')), 'r', encoding='utf-8') as f:
self.c.executescript(f.read())
from importlib.resources import as_file, files
with as_file(files('trueseeing.libs').joinpath('store.s.sql')) as path:
with open(path, 'r', encoding='utf-8') as f:
self.c.executescript(f.read())

def stage1(self) -> None:
with open(pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'store.0.sql')), 'r', encoding='utf-8') as f:
self.c.executescript(f.read())
from importlib.resources import as_file, files
with as_file(files('trueseeing.libs').joinpath('store.0.sql')) as path:
with open(path, 'r', encoding='utf-8') as f:
self.c.executescript(f.read())

def stage2(self) -> None:
with open(pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'store.1.sql')), 'r', encoding='utf-8') as f:
self.c.executescript(f.read())
from importlib.resources import as_file, files
with as_file(files('trueseeing.libs').joinpath('store.1.sql')) as path:
with open(path, 'r', encoding='utf-8') as f:
self.c.executescript(f.read())

class Query:
def __init__(self, store: Store) -> None:
Expand Down
18 changes: 10 additions & 8 deletions trueseeing/core/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ async def apply_multi(self, patches: List[Patch]) -> None:

async def _build(self, context: Context) -> None:
from tempfile import TemporaryDirectory
from pkg_resources import resource_filename

# XXX insecure
with TemporaryDirectory() as d:
Expand Down Expand Up @@ -78,12 +77,15 @@ async def _build(self, context: Context) -> None:
os.chdir(cwd)

from trueseeing.core.tools import invoke_passthru
await invoke_passthru('(cd {root} && java -jar {apkeditor} b -i files -o patched.apk && java -jar {apksigner} sign --ks {keystore} --ks-pass pass:android patched.apk && cp -a patched.apk {outpath})'.format(
root=d,
apkeditor=resource_filename(__name__, os.path.join('..', 'libs', 'apkeditor.jar')),
apksigner=resource_filename(__name__, os.path.join('..', 'libs', 'apksigner.jar')),
keystore=await SigningKey().key(),
outpath=self._outpath,
))
from importlib.resources import as_file, files
with as_file(files('trueseeing.libs').joinpath('apkeditor.jar')) as apkeditorpath:
with as_file(files('trueseeing.libs').joinpath('apksigner.jar')) as apksignerpath:
await invoke_passthru('(cd {root} && java -jar {apkeditor} b -i files -o patched.apk && java -jar {apksigner} sign --ks {keystore} --ks-pass pass:android patched.apk && cp -a patched.apk {outpath})'.format(
root=d,
apkeditor=apkeditorpath,
apksigner=apksignerpath,
keystore=await SigningKey().key(),
outpath=self._outpath,
))
copyfile(os.path.join(d, 'patched.apk'), self._outpath)
copyfile(os.path.join(d, 'patched.apk.idsig'), self._outpath + '.idsig')
11 changes: 6 additions & 5 deletions trueseeing/core/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,8 @@ def generate(self, f: TextIO) -> None:

class HTMLReportGenerator:
def __init__(self, context: Context) -> None:
import os.path
from jinja2 import Environment, FileSystemLoader
from pkg_resources import resource_filename
from trueseeing import __version__
self._context = context
self._template = Environment(loader=FileSystemLoader(resource_filename(__name__, os.path.join('..', 'libs', 'template'))), autoescape=True).get_template('report.html')
self._toolchain = dict(version=__version__)

def note(self, issue: Issue) -> None:
Expand Down Expand Up @@ -104,7 +100,12 @@ def generate(self, f: TextIO) -> None:
issues_low=len([_ for _ in issues if _['severity'] == 'Low']),
issues_info=len([_ for _ in issues if _['severity'] == 'Info'])
)
f.write(self._template.render(app=app, issues=issues, toolchain=self._toolchain))

from importlib.resources import as_file, files
from jinja2 import Environment, FileSystemLoader
with as_file(files('trueseeing.libs').joinpath('template')) as path:
template = Environment(loader=FileSystemLoader(path), autoescape=True).get_template('report.html')
f.write(template.render(app=app, issues=issues, toolchain=self._toolchain))

class JSONReportGenerator:
def __init__(self, context: Context) -> None:
Expand Down
17 changes: 9 additions & 8 deletions trueseeing/core/sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,16 @@ def __init__(self, path: str, outpath: str):
self._outpath = os.path.realpath(outpath)

async def resign(self) -> None:
from pkg_resources import resource_filename
from importlib.resources import as_file, files
with tempfile.TemporaryDirectory() as d:
await invoke_passthru(
"java -jar {apksigner} sign --ks {ks} --ks-pass pass:android --in {path} --out {d}/signed.apk".format(
d=d,
apksigner=resource_filename(__name__, os.path.join('..', 'libs', 'apksigner.jar')),
ks=await SigningKey().key(),
path=self._path,
with as_file(files('trueseeing.libs').joinpath('apksigner.jar')) as apksignerpath:
await invoke_passthru(
"java -jar {apksigner} sign --ks {ks} --ks-pass pass:android --in {path} --out {d}/signed.apk".format(
d=d,
apksigner=apksignerpath,
ks=await SigningKey().key(),
path=self._path,
)
)
)
shutil.copyfile(os.path.join(d, 'signed.apk'), self._outpath)
shutil.copyfile(os.path.join(d, 'signed.apk.idsig'), self._outpath.replace('.apk', '.apk.idsig'))
12 changes: 6 additions & 6 deletions trueseeing/signature/fingerprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
# XXX huge duplication
class TopLevelSuffixes:
def __init__(self) -> None:
import pkg_resources
with open(pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'tlds.txt')), 'r', encoding='utf-8') as f:
from importlib.resources import files
with files('trueseeing.libs').joinpath('tlds.txt').open('r', encoding='utf-8') as f:
self._re_tlds = re.compile('^(?:{})$'.format('|'.join(re.escape(l.strip()) for l in f if l and not l.startswith('#'))), flags=re.IGNORECASE)

def looks_public(self, names: List[str]) -> bool:
Expand All @@ -49,8 +49,8 @@ class PublicSuffixes:
_suffixes: Set[str] = set()

def __init__(self) -> None:
import pkg_resources
with open(pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'public_suffix_list.dat')), 'r', encoding='utf-8') as f:
from importlib.resources import files
with files('trueseeing.libs').joinpath('public_suffix_list.dat').open('r', encoding='utf-8') as f:
self._suffixes.update((l for l in f if l and not l.startswith('//')))

def looks_public(self, names: List[str]) -> bool:
Expand Down Expand Up @@ -248,8 +248,8 @@ def _analyzed(self, x: str, qn: Optional[str] = None) -> Iterable[Dict[str, Any]
yield dict(type_='possible FQDN', value=[hostlike])

async def detect(self) -> None:
import pkg_resources
with open(pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'tlds.txt')), 'r', encoding='utf-8') as f:
from importlib.resources import files
with files('trueseeing.libs').joinpath('tlds.txt').open('r', encoding='utf-8') as f:
self._re_tlds = re.compile('^(?:{})$'.format('|'.join(re.escape(l.strip()) for l in f if l and not l.startswith('#'))), flags=re.IGNORECASE)

with self._context.store() as store:
Expand Down
5 changes: 2 additions & 3 deletions trueseeing/signature/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import itertools
import re
import os

from trueseeing.signature.base import Detector
from trueseeing.core.issue import Issue
Expand Down Expand Up @@ -49,8 +48,8 @@ async def detect(self) -> None:

class ComponentNamePolicy:
def __init__(self) -> None:
import pkg_resources
with open(pkg_resources.resource_filename(__name__, os.path.join('..', 'libs', 'tlds.txt')), 'r', encoding='utf-8') as f:
from importlib.resources import files
with files('trueseeing.libs').joinpath('tlds.txt').open('r', encoding='utf-8') as f:
self._re_tlds = re.compile('^(?:{})$'.format('|'.join(re.escape(l.strip()) for l in f if l and not l.startswith('#'))), flags=re.IGNORECASE)

def looks_public(self, name: str) -> bool:
Expand Down

0 comments on commit 9708a60

Please sign in to comment.