trueseeing 2.2.4__tar.gz → 2.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- trueseeing-2.2.5/.github/FUNDING.yml +14 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/Dockerfile +1 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/PKG-INFO +7 -5
- {trueseeing-2.2.4 → trueseeing-2.2.5}/README.md +4 -2
- trueseeing-2.2.5/trueseeing/__init__.py +2 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/api.py +3 -1
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/__init__.py +2 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/android/asm.py +48 -10
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/android/engage.py +104 -42
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/android/recon.py +12 -8
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/android/search.py +8 -8
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/android/show.py +6 -6
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/inspect.py +117 -37
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/shell.py +10 -8
- trueseeing-2.2.5/trueseeing/core/analyze.py +65 -0
- {trueseeing-2.2.4/trueseeing/core/android/analysis → trueseeing-2.2.5/trueseeing/core/android/analyze}/flow.py +1 -1
- trueseeing-2.2.5/trueseeing/core/android/analyze/nat.py +44 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/android/asm.py +31 -6
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/android/context.py +60 -13
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/android/db.py +26 -2
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/android/device.py +1 -1
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/android/model.py +10 -2
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/context.py +13 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/db.py +6 -6
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/env.py +5 -1
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/ext.py +44 -14
- trueseeing-2.2.5/trueseeing/core/ios/analyze.py +74 -0
- trueseeing-2.2.5/trueseeing/core/ios/context.py +107 -0
- trueseeing-2.2.5/trueseeing/core/ios/db.py +60 -0
- trueseeing-2.2.5/trueseeing/core/ios/model.py +15 -0
- trueseeing-2.2.5/trueseeing/core/ios/store.py +34 -0
- trueseeing-2.2.5/trueseeing/core/ios/swift.py +120 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/scan.py +1 -1
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/tools.py +1 -1
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/ui.py +28 -8
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/android/store.0.sql +1 -0
- trueseeing-2.2.5/trueseeing/libs/android/store.1.sql +2 -0
- trueseeing-2.2.5/trueseeing/libs/ios/store.0.sql +1 -0
- trueseeing-2.2.5/trueseeing/libs/ios/store.1.sql +2 -0
- trueseeing-2.2.5/trueseeing/sig/android/__init__.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/sig/android/crypto.py +1 -1
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/sig/android/fingerprint.py +1 -1
- trueseeing-2.2.5/trueseeing/sig/android/nat.py +93 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/sig/android/privacy.py +1 -1
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/sig/android/security.py +1 -1
- trueseeing-2.2.5/trueseeing/sig/ios/__init__.py +0 -0
- trueseeing-2.2.5/trueseeing/sig/ios/base.py +880 -0
- trueseeing-2.2.4/trueseeing/__init__.py +0 -2
- {trueseeing-2.2.4 → trueseeing-2.2.5}/.dockerignore +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/.github/workflows/deploy.yaml +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/.github/workflows/lint.yaml +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/.github/workflows/publish.yaml +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/.github/workflows/stale.yaml +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/.gitignore +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/COPYING +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/pyproject.toml +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/__init__.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/alias.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/analyze.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/android/__init__.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/config.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/info.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/report.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/scan.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/search.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/cmd/show.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/app/scan.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/__init__.py +0 -0
- {trueseeing-2.2.4/trueseeing/core/android/analysis → trueseeing-2.2.5/trueseeing/core/android/analyze}/__init__.py +0 -0
- {trueseeing-2.2.4/trueseeing/core/android/analysis → trueseeing-2.2.5/trueseeing/core/android/analyze}/op.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/android/store.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/android/tools.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/config.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/cvss.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/exc.py +0 -0
- {trueseeing-2.2.4/trueseeing/core/model → trueseeing-2.2.5/trueseeing/core/ios}/__init__.py +0 -0
- {trueseeing-2.2.4/trueseeing/sig/android → trueseeing-2.2.5/trueseeing/core/model}/__init__.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/model/cmd.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/model/issue.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/model/sig.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/report.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/store.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/core/z.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/LICENSE.md +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/android/abe.jar +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/android/apkeditor.jar +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/android/apksigner.jar +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/android/frida-app.smali +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/android/frida-scriptdir.config +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/android/nsc.xml +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/files.0.sql +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/public_suffix_list.dat +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/store.0.sql +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/store.s.sql +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/template/report.html +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/libs/tlds.txt +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/py.typed +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/sig/__init__.py +0 -0
- {trueseeing-2.2.4 → trueseeing-2.2.5}/trueseeing/sig/android/manifest.py +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# These are supported funding model platforms
|
|
2
|
+
|
|
3
|
+
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
4
|
+
patreon: # Replace with a single Patreon username
|
|
5
|
+
open_collective: # Replace with a single Open Collective username
|
|
6
|
+
ko_fi: # Replace with a single Ko-fi username
|
|
7
|
+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
8
|
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
+
liberapay: # Replace with a single Liberapay username
|
|
10
|
+
issuehunt: # Replace with a single IssueHunt username
|
|
11
|
+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
12
|
+
polar: # Replace with a single Polar username
|
|
13
|
+
buy_me_a_coffee: alterakey
|
|
14
|
+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: trueseeing
|
|
3
|
-
Version: 2.2.
|
|
4
|
-
Summary: Trueseeing is a non-decompiling Android application vulnerability scanner.
|
|
3
|
+
Version: 2.2.5
|
|
4
|
+
Summary: Trueseeing is a non-decompiling iOS/Android application vulnerability scanner.
|
|
5
5
|
Keywords: android,security,pentest,hacking
|
|
6
6
|
Author-email: Takahiro Yoshimura <alterakey@protonmail.com>
|
|
7
7
|
Requires-Python: >=3.9
|
|
@@ -39,7 +39,7 @@ Provides-Extra: dev
|
|
|
39
39
|

|
|
40
40
|

|
|
41
41
|
|
|
42
|
-
trueseeing is a fast, accurate and resillient vulnerability scanner for Android apps. We operate on the Dalvik VM level -- i.e. we don't care if the target app is obfuscated or not.
|
|
42
|
+
trueseeing is a fast, accurate and resillient vulnerability scanner for iOS/Android apps. We operate on the Dalvik VM level for Android -- i.e. we don't care if the target app is obfuscated or not.
|
|
43
43
|
|
|
44
44
|
## Capability
|
|
45
45
|
|
|
@@ -51,6 +51,8 @@ Currently we can:
|
|
|
51
51
|
* Copy in/out app data through debug interface
|
|
52
52
|
* Search for certain calls/consts/sput/iput
|
|
53
53
|
* Deduce constants/typesets for args of op
|
|
54
|
+
* Scan API/private calls for native codes (NB: you need [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
|
|
55
|
+
* Scan iOS apps for basic vulnerabilities (NB: you need [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
|
|
54
56
|
* etc.
|
|
55
57
|
|
|
56
58
|
## Installation
|
|
@@ -84,7 +86,7 @@ Alternatively, you can install our package with pip as follows. This form of ins
|
|
|
84
86
|
You can interactively scan/analyze/patch/etc. apps -- making it the ideal choice for manual analysis:
|
|
85
87
|
|
|
86
88
|
$ trueseeing target.apk
|
|
87
|
-
[+] trueseeing 2.2.
|
|
89
|
+
[+] trueseeing 2.2.5
|
|
88
90
|
ts[target.apk]> ?
|
|
89
91
|
...
|
|
90
92
|
ts[target.apk]> i # show generic information
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
|
8
|
-
trueseeing is a fast, accurate and resillient vulnerability scanner for Android apps. We operate on the Dalvik VM level -- i.e. we don't care if the target app is obfuscated or not.
|
|
8
|
+
trueseeing is a fast, accurate and resillient vulnerability scanner for iOS/Android apps. We operate on the Dalvik VM level for Android -- i.e. we don't care if the target app is obfuscated or not.
|
|
9
9
|
|
|
10
10
|
## Capability
|
|
11
11
|
|
|
@@ -17,6 +17,8 @@ Currently we can:
|
|
|
17
17
|
* Copy in/out app data through debug interface
|
|
18
18
|
* Search for certain calls/consts/sput/iput
|
|
19
19
|
* Deduce constants/typesets for args of op
|
|
20
|
+
* Scan API/private calls for native codes (NB: you need [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
|
|
21
|
+
* Scan iOS apps for basic vulnerabilities (NB: you need [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
|
|
20
22
|
* etc.
|
|
21
23
|
|
|
22
24
|
## Installation
|
|
@@ -50,7 +52,7 @@ Alternatively, you can install our package with pip as follows. This form of ins
|
|
|
50
52
|
You can interactively scan/analyze/patch/etc. apps -- making it the ideal choice for manual analysis:
|
|
51
53
|
|
|
52
54
|
$ trueseeing target.apk
|
|
53
|
-
[+] trueseeing 2.2.
|
|
55
|
+
[+] trueseeing 2.2.5
|
|
54
56
|
ts[target.apk]> ?
|
|
55
57
|
...
|
|
56
58
|
ts[target.apk]> i # show generic information
|
|
@@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
|
|
|
4
4
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from collections import deque
|
|
7
|
-
from typing import Any, TypedDict, Protocol, Optional, Callable, Coroutine, Union, List, Mapping, overload, Literal
|
|
7
|
+
from typing import Any, TypedDict, Protocol, Optional, Callable, Coroutine, Union, List, Mapping, overload, Literal, Set
|
|
8
8
|
from typing_extensions import deprecated
|
|
9
9
|
from trueseeing.core.context import Context, ContextType
|
|
10
10
|
from trueseeing.core.android.context import APKContext
|
|
@@ -25,6 +25,7 @@ if TYPE_CHECKING:
|
|
|
25
25
|
e: CommandEntrypoint
|
|
26
26
|
n: str
|
|
27
27
|
d: str
|
|
28
|
+
t: Set[str]
|
|
28
29
|
|
|
29
30
|
class CommandEntry(Entry):
|
|
30
31
|
pass
|
|
@@ -65,6 +66,7 @@ if TYPE_CHECKING:
|
|
|
65
66
|
class CommandHelper(Protocol):
|
|
66
67
|
def get_target(self) -> Optional[str]: ...
|
|
67
68
|
def require_target(self, msg: Optional[str] = None) -> str: ...
|
|
69
|
+
def get_context_type(self) -> Optional[Set[ContextType]]: ...
|
|
68
70
|
@overload
|
|
69
71
|
def get_context(self) -> Context: ...
|
|
70
72
|
@overload
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from typing import TYPE_CHECKING
|
|
3
|
+
from functools import cache
|
|
3
4
|
|
|
4
5
|
if TYPE_CHECKING:
|
|
5
6
|
from typing import Type, Iterator
|
|
6
7
|
from trueseeing.api import Command
|
|
7
8
|
|
|
9
|
+
@cache
|
|
8
10
|
def discover() -> Iterator[Type[Command]]:
|
|
9
11
|
from trueseeing.api import Command
|
|
10
12
|
from importlib import import_module
|
|
@@ -23,19 +23,21 @@ class AssembleCommand(CommandMixin):
|
|
|
23
23
|
|
|
24
24
|
def get_commands(self) -> CommandMap:
|
|
25
25
|
return {
|
|
26
|
-
'ca':dict(e=self._assemble, n='ca[!] /path', d='assemble as target from path'),
|
|
27
|
-
'ca!':dict(e=self._assemble),
|
|
28
|
-
'cd':dict(e=self._disassemble, n='cd[s][!] /path', d='disassemble target into path'),
|
|
29
|
-
'cd!':dict(e=self._disassemble),
|
|
30
|
-
'cds':dict(e=self._disassemble_nodex),
|
|
31
|
-
'cds!':dict(e=self._disassemble_nodex),
|
|
32
|
-
'
|
|
33
|
-
'
|
|
26
|
+
'ca':dict(e=self._assemble, n='ca[!] /path', d='assemble as target from path', t={'apk'}),
|
|
27
|
+
'ca!':dict(e=self._assemble, t={'apk'}),
|
|
28
|
+
'cd':dict(e=self._disassemble, n='cd[s][!] /path', d='disassemble target into path', t={'apk'}),
|
|
29
|
+
'cd!':dict(e=self._disassemble, t={'apk'}),
|
|
30
|
+
'cds':dict(e=self._disassemble_nodex, t={'apk'}),
|
|
31
|
+
'cds!':dict(e=self._disassemble_nodex, t={'apk'}),
|
|
32
|
+
'cm':dict(e=self._merge, n='cm[!] [output.apk]', d='merge slices into a plain apk', t={'xapk'}),
|
|
33
|
+
'cm!':dict(e=self._merge, t={'xapk'}),
|
|
34
|
+
'co':dict(e=self._export_context, n='co[!] /path [pat]', d='export codebase', t={'apk'}),
|
|
35
|
+
'co!':dict(e=self._export_context, t={'apk'}),
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
def get_options(self) -> OptionMap:
|
|
37
39
|
return {
|
|
38
|
-
'nocache':dict(n='nocache', d='do not replicate content before build [ca]')
|
|
40
|
+
'nocache':dict(n='nocache', d='do not replicate content before build [ca]', t={'apk'}),
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
async def _assemble(self, args: deque[str]) -> None:
|
|
@@ -214,7 +216,7 @@ class AssembleCommand(CommandMixin):
|
|
|
214
216
|
if subformat in ['gz']:
|
|
215
217
|
kwargs.update(dict(compresslevel=3))
|
|
216
218
|
|
|
217
|
-
with tarfile.open(root, 'w:{}'.format(subformat), **kwargs) as tf: # type: ignore[
|
|
219
|
+
with tarfile.open(root, 'w:{}'.format(subformat), **kwargs) as tf: # type: ignore[call-overload]
|
|
218
220
|
now = int(time.time())
|
|
219
221
|
for path,blob in q.file_enum(pat=pat, regex=True):
|
|
220
222
|
target = os.path.join('files', *path.split('/'))
|
|
@@ -223,6 +225,7 @@ class AssembleCommand(CommandMixin):
|
|
|
223
225
|
|
|
224
226
|
bf = BytesIO(blob)
|
|
225
227
|
ti = tarfile.TarInfo(name=target)
|
|
228
|
+
ti.size = len(blob)
|
|
226
229
|
ti.uname = 'root'
|
|
227
230
|
ti.gname = 'root'
|
|
228
231
|
ti.mode = 0o600
|
|
@@ -239,3 +242,38 @@ class AssembleCommand(CommandMixin):
|
|
|
239
242
|
return 'tar:gz'
|
|
240
243
|
else:
|
|
241
244
|
return None
|
|
245
|
+
|
|
246
|
+
async def _merge(self, args: deque[str]) -> None:
|
|
247
|
+
target = self._helper.require_target('need target')
|
|
248
|
+
|
|
249
|
+
cmd = args.popleft()
|
|
250
|
+
|
|
251
|
+
import os
|
|
252
|
+
import time
|
|
253
|
+
from tempfile import TemporaryDirectory
|
|
254
|
+
from trueseeing.core.android.asm import APKAssembler
|
|
255
|
+
from trueseeing.core.android.tools import move_apk
|
|
256
|
+
|
|
257
|
+
if args:
|
|
258
|
+
outfn = args.popleft()
|
|
259
|
+
else:
|
|
260
|
+
outfn = target.replace('.xapk', '.apk')
|
|
261
|
+
|
|
262
|
+
origfn = outfn.replace('.apk', '.apk.orig')
|
|
263
|
+
|
|
264
|
+
if os.path.exists(origfn) and not cmd.endswith('!'):
|
|
265
|
+
ui.fatal('backup file exists; force (!) to overwrite')
|
|
266
|
+
|
|
267
|
+
ui.info('merging slices {target} -> {outfn}'.format(target=target, outfn=outfn))
|
|
268
|
+
|
|
269
|
+
at = time.time()
|
|
270
|
+
|
|
271
|
+
with TemporaryDirectory() as td:
|
|
272
|
+
apk, sig = await APKAssembler.merge_slices(target, td)
|
|
273
|
+
|
|
274
|
+
if os.path.exists(outfn):
|
|
275
|
+
move_apk(outfn, origfn)
|
|
276
|
+
|
|
277
|
+
move_apk(apk, outfn)
|
|
278
|
+
|
|
279
|
+
ui.success('done ({t:.02f} sec.)'.format(t=(time.time() - at)))
|
|
@@ -22,37 +22,40 @@ class EngageCommand(CommandMixin):
|
|
|
22
22
|
|
|
23
23
|
def get_commands(self) -> CommandMap:
|
|
24
24
|
return {
|
|
25
|
-
'xtq':dict(e=self._engage_tamper_discard, n='xtq', d='engage: discard changes'),
|
|
26
|
-
'xtx':dict(e=self._engage_tamper_apply, n='xtx[!]', d='engage: apply and rebuild apk'),
|
|
27
|
-
'xtx!':dict(e=self._engage_tamper_apply),
|
|
28
|
-
'xtf':dict(e=self._engage_tamper_inject_frida, n='xtf[!] [config]', d='engage; inject frida gadget'),
|
|
29
|
-
'xtf!':dict(e=self._engage_tamper_inject_frida),
|
|
30
|
-
'xtfs':dict(e=self._engage_tamper_inject_frida_scriptdir, n='xtfs[!] [path]', d='engage; inject frida gadget in script dir mode'),
|
|
31
|
-
'xtfs!':dict(e=self._engage_tamper_inject_frida_scriptdir),
|
|
32
|
-
'xtn':dict(e=self._engage_tamper_disable_pinning, n='xtn', d='engage: patch NSC to disable SSL/TLS pinning'),
|
|
33
|
-
'xtd':dict(e=self._engage_tamper_enable_debug, n='xtd', d='engage: make debuggable'),
|
|
34
|
-
'xtb':dict(e=self._engage_tamper_enable_backup, n='xtb', d='engage: make backupable'),
|
|
35
|
-
'xtt':dict(e=self._engage_tamper_patch_target_api_level, n='xtt[!] <api level>', d='engage: patch target api level'),
|
|
36
|
-
'xtt!':dict(e=self._engage_tamper_patch_target_api_level),
|
|
37
|
-
'xco':dict(e=self._engage_device_copyout, n='xco[!] package [data.tar]', d='engage: copy-out package data'),
|
|
38
|
-
'xco!':dict(e=self._engage_device_copyout),
|
|
39
|
-
'xci':dict(e=self._engage_device_copyin, n='xci[!] package [data.tar]', d='engage: copy-in package data'),
|
|
40
|
-
'xci!':dict(e=self._engage_device_copyin),
|
|
41
|
-
'xpd':dict(e=self._engage_deploy_package, n='xpd[!]', d='engage: deploy target package'),
|
|
42
|
-
'xpd!':dict(e=self._engage_deploy_package),
|
|
43
|
-
'xpu':dict(e=self._engage_undeploy_package, n='xpu', d='engage: remove target package'),
|
|
44
|
-
'xz':dict(e=self._engage_fuzz_intent, n='xz[!] "am-cmdline-template" [output.txt]', d='engage: fuzz intent'),
|
|
45
|
-
'xz!':dict(e=self._engage_fuzz_intent),
|
|
46
|
-
'xzr':dict(e=self._engage_fuzz_command, n='xzr[!] "cmdline-template" [output.txt]', d='engage: fuzz cmdline'),
|
|
47
|
-
'xzr!':dict(e=self._engage_fuzz_command),
|
|
48
|
-
'xg':dict(e=self._engage_grab_package, n='xg[!] package [output.apk]', d='engage: grab package'),
|
|
49
|
-
'xg!':dict(e=self._engage_grab_package),
|
|
25
|
+
'xtq':dict(e=self._engage_tamper_discard, n='xtq', d='engage: discard changes', t={'apk'}),
|
|
26
|
+
'xtx':dict(e=self._engage_tamper_apply, n='xtx[!]', d='engage: apply and rebuild apk', t={'apk'}),
|
|
27
|
+
'xtx!':dict(e=self._engage_tamper_apply, t={'apk'}),
|
|
28
|
+
'xtf':dict(e=self._engage_tamper_inject_frida, n='xtf[!] [config]', d='engage; inject frida gadget', t={'apk'}),
|
|
29
|
+
'xtf!':dict(e=self._engage_tamper_inject_frida, t={'apk'}),
|
|
30
|
+
'xtfs':dict(e=self._engage_tamper_inject_frida_scriptdir, n='xtfs[!] [path]', d='engage; inject frida gadget in script dir mode', t={'apk'}),
|
|
31
|
+
'xtfs!':dict(e=self._engage_tamper_inject_frida_scriptdir, t={'apk'}),
|
|
32
|
+
'xtn':dict(e=self._engage_tamper_disable_pinning, n='xtn', d='engage: patch NSC to disable SSL/TLS pinning', t={'apk'}),
|
|
33
|
+
'xtd':dict(e=self._engage_tamper_enable_debug, n='xtd', d='engage: make debuggable', t={'apk'}),
|
|
34
|
+
'xtb':dict(e=self._engage_tamper_enable_backup, n='xtb', d='engage: make backupable', t={'apk'}),
|
|
35
|
+
'xtt':dict(e=self._engage_tamper_patch_target_api_level, n='xtt[!] <api level>', d='engage: patch target api level', t={'apk'}),
|
|
36
|
+
'xtt!':dict(e=self._engage_tamper_patch_target_api_level, t={'apk'}),
|
|
37
|
+
'xco':dict(e=self._engage_device_copyout, n='xco[!] package [data.tar]', d='engage: copy-out package data', t={'apk'}),
|
|
38
|
+
'xco!':dict(e=self._engage_device_copyout, t={'apk'}),
|
|
39
|
+
'xci':dict(e=self._engage_device_copyin, n='xci[!] package [data.tar]', d='engage: copy-in package data', t={'apk'}),
|
|
40
|
+
'xci!':dict(e=self._engage_device_copyin, t={'apk'}),
|
|
41
|
+
'xpd':dict(e=self._engage_deploy_package, n='xpd[!]', d='engage: deploy target package', t={'apk'}),
|
|
42
|
+
'xpd!':dict(e=self._engage_deploy_package, t={'apk'}),
|
|
43
|
+
'xpu':dict(e=self._engage_undeploy_package, n='xpu', d='engage: remove target package', t={'apk'}),
|
|
44
|
+
'xz':dict(e=self._engage_fuzz_intent, n='xz[!] "am-cmdline-template" [output.txt]', d='engage: fuzz intent', t={'apk'}),
|
|
45
|
+
'xz!':dict(e=self._engage_fuzz_intent, t={'apk'}),
|
|
46
|
+
'xzr':dict(e=self._engage_fuzz_command, n='xzr[!] "cmdline-template" [output.txt]', d='engage: fuzz cmdline', t={'apk'}),
|
|
47
|
+
'xzr!':dict(e=self._engage_fuzz_command, t={'apk'}),
|
|
48
|
+
'xg':dict(e=self._engage_grab_package, n='xg[!] package [output.apk]', d='engage: grab package', t={'apk'}),
|
|
49
|
+
'xg!':dict(e=self._engage_grab_package, t={'apk'}),
|
|
50
|
+
'xs':dict(e=self._engage_frida_start_server, n='xs[!] [config]', d='engage: start frida-server (!: force)', t={'apk'}),
|
|
51
|
+
'xs!':dict(e=self._engage_frida_start_server, t={'apk'}),
|
|
52
|
+
'xk':dict(e=self._engage_frida_kill_server, n='xk', d='engage: kill frida server', t={'apk'}),
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
def get_options(self) -> OptionMap:
|
|
53
56
|
return {
|
|
54
|
-
'vers':dict(n='vers=X.Y.Z', d='specify frida-gadget version to use [xf,xfs]'),
|
|
55
|
-
'w':dict(n='wNAME=FN', d='wordlist, use as {NAME} [xz]'),
|
|
57
|
+
'vers':dict(n='vers=X.Y.Z', d='specify frida-gadget version to use [xf,xfs]', t={'apk'}),
|
|
58
|
+
'w':dict(n='wNAME=FN', d='wordlist, use as {NAME} [xz]', t={'apk'}),
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
async def _engage_tamper_discard(self, args: deque[str]) -> None:
|
|
@@ -84,6 +87,10 @@ class EngageCommand(CommandMixin):
|
|
|
84
87
|
from trueseeing.core.android.asm import APKAssembler
|
|
85
88
|
from trueseeing.core.android.tools import move_apk
|
|
86
89
|
|
|
90
|
+
if apk.endswith('.xapk'):
|
|
91
|
+
ui.warn('patching xapk as merged apk')
|
|
92
|
+
apk = apk.replace('.xapk', '.apk')
|
|
93
|
+
|
|
87
94
|
origapk = apk.replace('.apk', '.apk.orig')
|
|
88
95
|
|
|
89
96
|
if os.path.exists(origapk) and not cmd.endswith('!'):
|
|
@@ -509,6 +516,7 @@ class EngageCommand(CommandMixin):
|
|
|
509
516
|
ui.info(f'copying out: {target} -> {outfn}')
|
|
510
517
|
|
|
511
518
|
import time
|
|
519
|
+
from shlex import quote
|
|
512
520
|
from subprocess import CalledProcessError
|
|
513
521
|
from trueseeing.core.tools import invoke_passthru
|
|
514
522
|
from trueseeing.core.android.device import AndroidDevice
|
|
@@ -527,7 +535,7 @@ class EngageCommand(CommandMixin):
|
|
|
527
535
|
with toolchains() as tc:
|
|
528
536
|
await invoke_passthru('java -jar {abe} unpack {outfn}.ab {outfn} 1'.format(
|
|
529
537
|
abe=tc['abe'],
|
|
530
|
-
outfn=outfn,
|
|
538
|
+
outfn=quote(outfn),
|
|
531
539
|
))
|
|
532
540
|
except CalledProcessError:
|
|
533
541
|
ui.warn('unpack failed (did you give the correct password?); trying the next method')
|
|
@@ -556,18 +564,18 @@ class EngageCommand(CommandMixin):
|
|
|
556
564
|
|
|
557
565
|
tfn0 = self._generate_tempfilename_for_device()
|
|
558
566
|
ui.info('copying internal storage')
|
|
559
|
-
await dev.invoke_adb_passthru(f
|
|
560
|
-
await dev.invoke_adb_passthru(f'pull {tfn0} {outfn0}')
|
|
567
|
+
await dev.invoke_adb_passthru(f"shell 'run-as {target} tar -cv . > {tfn0}'")
|
|
568
|
+
await dev.invoke_adb_passthru(f'pull {tfn0} {quote(outfn0)}')
|
|
561
569
|
await dev.invoke_adb_passthru(f'shell rm -f {tfn0}')
|
|
562
570
|
ui.success(f'copied out: {outfn0}')
|
|
563
571
|
|
|
564
572
|
ui.info('copying external storage')
|
|
565
573
|
tfn1 = self._generate_tempfilename_for_device()
|
|
566
574
|
try:
|
|
567
|
-
await dev.invoke_adb_passthru(f
|
|
575
|
+
await dev.invoke_adb_passthru(f"shell 'cd /storage/emulated/0/Android/ && tar -cv data/{target} obb/{target} > {tfn1}'")
|
|
568
576
|
except CalledProcessError:
|
|
569
577
|
ui.warn('detected errors during extraction from external storage (may indicate partial extraction)')
|
|
570
|
-
await dev.invoke_adb_passthru(f'pull {tfn1} {outfn1}')
|
|
578
|
+
await dev.invoke_adb_passthru(f'pull {tfn1} {quote(outfn1)}')
|
|
571
579
|
await dev.invoke_adb_passthru(f'shell rm -f {tfn1}')
|
|
572
580
|
ui.success(f'copied out: {outfn1}')
|
|
573
581
|
|
|
@@ -602,6 +610,7 @@ class EngageCommand(CommandMixin):
|
|
|
602
610
|
ui.info(f'copying in: {fn} -> {target}')
|
|
603
611
|
|
|
604
612
|
import time
|
|
613
|
+
from shlex import quote
|
|
605
614
|
from subprocess import CalledProcessError
|
|
606
615
|
from trueseeing.core.tools import invoke_passthru
|
|
607
616
|
from trueseeing.core.android.device import AndroidDevice
|
|
@@ -621,14 +630,14 @@ class EngageCommand(CommandMixin):
|
|
|
621
630
|
with toolchains() as tc:
|
|
622
631
|
await invoke_passthru('java -jar {abe} pack-kk {fn} {fn}.ab 1'.format(
|
|
623
632
|
abe=tc['abe'],
|
|
624
|
-
fn=fn,
|
|
633
|
+
fn=quote(fn),
|
|
625
634
|
))
|
|
626
635
|
except CalledProcessError:
|
|
627
636
|
ui.warn('pack failed; trying the next method')
|
|
628
637
|
else:
|
|
629
638
|
ui.success('pack success')
|
|
630
639
|
ui.info('initiating a restore on device; give "1" as the password if asked')
|
|
631
|
-
await dev.invoke_adb_passthru(f'restore {fn}.ab')
|
|
640
|
+
await dev.invoke_adb_passthru(f'restore {quote(fn)}.ab')
|
|
632
641
|
ui.success(f'copied in: {fn}')
|
|
633
642
|
success = True
|
|
634
643
|
finally:
|
|
@@ -645,21 +654,21 @@ class EngageCommand(CommandMixin):
|
|
|
645
654
|
|
|
646
655
|
ui.info('copying internal storage')
|
|
647
656
|
if not os.path.exists(fn0):
|
|
648
|
-
ui.warn('data not found: {fn0}')
|
|
657
|
+
ui.warn(f'data not found: {fn0}')
|
|
649
658
|
else:
|
|
650
659
|
tfn0 = self._generate_tempfilename_for_device()
|
|
651
|
-
await dev.invoke_adb_passthru(f'push {fn0} {tfn0}')
|
|
652
|
-
await dev.invoke_adb_passthru(f
|
|
660
|
+
await dev.invoke_adb_passthru(f'push {quote(fn0)} {tfn0}')
|
|
661
|
+
await dev.invoke_adb_passthru(f"shell 'run-as {target} tar -xv < {tfn0}; rm -f {tfn0}'")
|
|
653
662
|
ui.success(f'copied in: {fn}')
|
|
654
663
|
success = True
|
|
655
664
|
|
|
656
665
|
ui.info('copying external storage')
|
|
657
666
|
if not os.path.exists(fn1):
|
|
658
|
-
ui.warn('data not found: {fn1}')
|
|
667
|
+
ui.warn(f'data not found: {fn1}')
|
|
659
668
|
else:
|
|
660
669
|
tfn1 = self._generate_tempfilename_for_device()
|
|
661
|
-
await dev.invoke_adb_passthru(f'push {fn1} {tfn1}')
|
|
662
|
-
await dev.invoke_adb_passthru(f
|
|
670
|
+
await dev.invoke_adb_passthru(f'push {quote(fn1)} {tfn1}')
|
|
671
|
+
await dev.invoke_adb_passthru(f"shell 'cd /storage/emulated/0/Android/ && tar -xv < {tfn1}; rm -f {tfn1}'")
|
|
663
672
|
ui.success(f'copied in: {fn1}')
|
|
664
673
|
success = True
|
|
665
674
|
|
|
@@ -775,6 +784,7 @@ class EngageCommand(CommandMixin):
|
|
|
775
784
|
apk = context.target
|
|
776
785
|
|
|
777
786
|
from time import time
|
|
787
|
+
from shlex import quote
|
|
778
788
|
from pubsub import pub
|
|
779
789
|
from trueseeing.core.ui import AndroidInstallProgressReporter
|
|
780
790
|
from trueseeing.core.android.device import AndroidDevice
|
|
@@ -798,7 +808,7 @@ class EngageCommand(CommandMixin):
|
|
|
798
808
|
with AndroidInstallProgressReporter().scoped():
|
|
799
809
|
pub.sendMessage('progress.android.adb.begin', what='installing ... ')
|
|
800
810
|
try:
|
|
801
|
-
async for l in dev.invoke_adb_streaming(f'install --no-streaming {apk}', redir_stderr=True):
|
|
811
|
+
async for l in dev.invoke_adb_streaming(f'install --no-streaming {quote(apk)}', redir_stderr=True):
|
|
802
812
|
pub.sendMessage('progress.android.adb.update')
|
|
803
813
|
if b'failure' in l.lower():
|
|
804
814
|
ui.stderr('')
|
|
@@ -907,7 +917,7 @@ class EngageCommand(CommandMixin):
|
|
|
907
917
|
ui.warn('target has only one slice; using apk format')
|
|
908
918
|
outfn = outfn.replace('.xapk', '.apk')
|
|
909
919
|
ui.info('getting {nr} slice'.format(nr=len(splits)))
|
|
910
|
-
await dev.invoke_adb('pull {path}/base.apk {outfn}'.format(path=quote(basepath.decode()), outfn=outfn))
|
|
920
|
+
await dev.invoke_adb('pull {path}/base.apk {outfn}'.format(path=quote(basepath.decode()), outfn=quote(outfn)))
|
|
911
921
|
else:
|
|
912
922
|
if outfn.endswith('.apk'):
|
|
913
923
|
ui.warn('target has multiple slices; using xapk format')
|
|
@@ -949,6 +959,58 @@ class EngageCommand(CommandMixin):
|
|
|
949
959
|
assert manifest is not None
|
|
950
960
|
return ET.tostring(manifest) # type: ignore[no-any-return]
|
|
951
961
|
|
|
962
|
+
async def _engage_frida_start_server(self, args: deque[str]) -> None:
|
|
963
|
+
cmd = args.popleft()
|
|
964
|
+
context: APKContext = self._helper.get_context().require_type('apk')
|
|
965
|
+
|
|
966
|
+
pkg = context.get_package_name()
|
|
967
|
+
scripts = list(args)
|
|
968
|
+
|
|
969
|
+
force = cmd.endswith('!')
|
|
970
|
+
|
|
971
|
+
ui.info("starting frida-server")
|
|
972
|
+
|
|
973
|
+
from time import time
|
|
974
|
+
from shlex import quote
|
|
975
|
+
from trueseeing.core.android.device import AndroidDevice
|
|
976
|
+
from trueseeing.core.tools import invoke_passthru
|
|
977
|
+
from pathlib import Path
|
|
978
|
+
|
|
979
|
+
at = time()
|
|
980
|
+
dev = AndroidDevice()
|
|
981
|
+
|
|
982
|
+
if force:
|
|
983
|
+
ui.warn("killing frida-server if any")
|
|
984
|
+
await dev.invoke_adb("shell 'killall frida-server || exit 0'")
|
|
985
|
+
await dev.invoke_adb("shell 'cd /data/local/tmp && ./frida-server &'")
|
|
986
|
+
|
|
987
|
+
ui.info(f"starting frida on {pkg}")
|
|
988
|
+
scripts_str = []
|
|
989
|
+
for s in scripts:
|
|
990
|
+
p = Path(s)
|
|
991
|
+
if p.is_file():
|
|
992
|
+
scripts_str.append(f"-l {quote(str(p))}")
|
|
993
|
+
elif p.is_dir():
|
|
994
|
+
scripts_str.extend([f"-l {quote(str(m))}" for m in p.rglob('*.js')])
|
|
995
|
+
else:
|
|
996
|
+
ui.warn(f"ignoring unknown path: {p}")
|
|
997
|
+
await invoke_passthru(f"frida -U {pkg} {' '.join(scripts_str)}")
|
|
998
|
+
|
|
999
|
+
ui.success("done ({t:.2f} sec.)".format(t=time() - at))
|
|
1000
|
+
|
|
1001
|
+
async def _engage_frida_kill_server(self, args: deque[str]) -> None:
|
|
1002
|
+
from time import time
|
|
1003
|
+
from trueseeing.core.android.device import AndroidDevice
|
|
1004
|
+
|
|
1005
|
+
ui.info("killing frida-server")
|
|
1006
|
+
|
|
1007
|
+
at = time()
|
|
1008
|
+
dev = AndroidDevice()
|
|
1009
|
+
|
|
1010
|
+
await dev.invoke_adb('shell killall frida-server')
|
|
1011
|
+
|
|
1012
|
+
ui.success("done ({t:.2f} sec.)".format(t=time() - at))
|
|
1013
|
+
|
|
952
1014
|
class InvalidResponseError(Exception):
|
|
953
1015
|
pass
|
|
954
1016
|
|
|
@@ -44,7 +44,9 @@ class ReconCommand(CommandMixin):
|
|
|
44
44
|
'rwl!':dict(e=self._recon_watch_logcat),
|
|
45
45
|
'rwf':dict(e=self._recon_watch_fs, n='rwf', d='recon: watch filesystem'),
|
|
46
46
|
'rwt':dict(e=self._recon_watch_intent, n='rwt[!] [pat]', d='recon: watch intent'),
|
|
47
|
+
'rwt!':dict(e=self._recon_watch_intent),
|
|
47
48
|
'rwu':dict(e=self._recon_watch_ui, n='rwu[!] [pat|xp:xpath] [output.xml]', d='recon: watch device UI'),
|
|
49
|
+
'rwu!':dict(e=self._recon_watch_ui),
|
|
48
50
|
'rwx':dict(e=self._recon_watch_start, n='rwx', d='recon: start watching'),
|
|
49
51
|
'rp':dict(e=self._recon_list_packages, n='rp', d='recon: list installed packages'),
|
|
50
52
|
'ru':dict(e=self._recon_dump_ui, n='ru [output.xml]', d='recon: dump device UI'),
|
|
@@ -140,13 +142,15 @@ class ReconCommand(CommandMixin):
|
|
|
140
142
|
ui.fatal('nothing to watch (try d* beforehand)')
|
|
141
143
|
|
|
142
144
|
dev = AndroidDevice()
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
pkg: Optional[str] = None
|
|
146
|
+
if self._target_only:
|
|
147
|
+
ctx = self._get_apk_context()
|
|
148
|
+
pkg = ctx.get_package_name()
|
|
145
149
|
|
|
146
150
|
async def _log() -> None:
|
|
147
151
|
pid: Optional[int] = None
|
|
148
152
|
if self._watch_logcat or self._watch_intent:
|
|
149
|
-
if not pid:
|
|
153
|
+
if pkg and not pid:
|
|
150
154
|
d = await dev.invoke_adb('shell ps')
|
|
151
155
|
m = re.search(r'^[0-9a-zA-Z_]+ +([0-9]+) .*{}$'.format(pkg).encode(), d.encode(), re.MULTILINE)
|
|
152
156
|
if m:
|
|
@@ -155,7 +159,7 @@ class ReconCommand(CommandMixin):
|
|
|
155
159
|
|
|
156
160
|
async for l in dev.invoke_adb_streaming('logcat -T1'):
|
|
157
161
|
l = l.rstrip()
|
|
158
|
-
if not pid:
|
|
162
|
+
if pkg and not pid:
|
|
159
163
|
m = re.search(r' ([0-9]+):{}'.format(pkg).encode(), l)
|
|
160
164
|
if m:
|
|
161
165
|
pid = int(m.group(1))
|
|
@@ -264,7 +268,7 @@ class ReconCommand(CommandMixin):
|
|
|
264
268
|
if not m:
|
|
265
269
|
raise DumpFailedError(msg)
|
|
266
270
|
tmpfn = m.group(1)
|
|
267
|
-
return await dev.invoke_adb(f
|
|
271
|
+
return await dev.invoke_adb(f"shell 'cat {tmpfn}; rm {tmpfn}'")
|
|
268
272
|
except CalledProcessError as e:
|
|
269
273
|
raise DumpFailedError(e)
|
|
270
274
|
|
|
@@ -272,11 +276,11 @@ class ReconCommand(CommandMixin):
|
|
|
272
276
|
from subprocess import CalledProcessError
|
|
273
277
|
dev = AndroidDevice()
|
|
274
278
|
try:
|
|
275
|
-
async for msg in dev.invoke_adb_streaming(r
|
|
279
|
+
async for msg in dev.invoke_adb_streaming(r"shell 'while (true) do uiautomator dump /sdcard/dump-$(date +%s).xml; sleep {delay}; done'".format(delay=delay)):
|
|
276
280
|
m = re.search(r'dumped to: (/.*)', msg.decode())
|
|
277
281
|
if m:
|
|
278
282
|
tmpfn = m.group(1)
|
|
279
|
-
yield await dev.invoke_adb(f
|
|
283
|
+
yield await dev.invoke_adb(f"shell 'cat {tmpfn}; rm {tmpfn}'")
|
|
280
284
|
except CalledProcessError as e:
|
|
281
285
|
raise DumpFailedError(e)
|
|
282
286
|
|
|
@@ -288,7 +292,7 @@ class ReconCommand(CommandMixin):
|
|
|
288
292
|
|
|
289
293
|
dev = AndroidDevice()
|
|
290
294
|
try:
|
|
291
|
-
async for msg in dev.invoke_adb_streaming(r
|
|
295
|
+
async for msg in dev.invoke_adb_streaming(r"shell 'while (true) do (find -H /storage -mtime -{thres}s -print0 | xargs -0 ls -nlld); echo \"*\"; sleep {delay}; done'".format(delay=delay, thres=int(delay*3.))):
|
|
292
296
|
msg = msg.rstrip()
|
|
293
297
|
if not msg.startswith(b'*'):
|
|
294
298
|
m = re.fullmatch(r'(.*00) (.+?)'.encode('latin1'), msg)
|
|
@@ -20,14 +20,14 @@ class SearchCommand(CommandMixin):
|
|
|
20
20
|
|
|
21
21
|
def get_commands(self) -> CommandMap:
|
|
22
22
|
return {
|
|
23
|
-
'/c':dict(e=self._search_call, n='/c [pat]', d='search call for pattern'),
|
|
24
|
-
'/k':dict(e=self._search_const, n='/k insn [pat]', d='search consts for pattern'),
|
|
25
|
-
'/p':dict(e=self._search_put, n='/p[i] [pat]', d='search s/iputs for pattern'),
|
|
26
|
-
'/dp':dict(e=self._search_defined_package, n='/dp [pat]', d='search packages matching pattern'),
|
|
27
|
-
'/dc':dict(e=self._search_defined_class, n='/dc [pat]', d='search classes matching pattern'),
|
|
28
|
-
'/dcx':dict(e=self._search_derived_class, n='/dcx classpat [methpat]', d='search classes defining methods and extending ones matching patterns'),
|
|
29
|
-
'/dci':dict(e=self._search_implementing_class, n='/dci ifacepat [methpat]', d='search classes defining methods and implementing interfaces matching patterns'),
|
|
30
|
-
'/dm':dict(e=self._search_defined_method, n='/dm pat', d='search classes defining methods matching pattern'),
|
|
23
|
+
'/c':dict(e=self._search_call, n='/c [pat]', d='search call for pattern', t={'apk'}),
|
|
24
|
+
'/k':dict(e=self._search_const, n='/k insn [pat]', d='search consts for pattern', t={'apk'}),
|
|
25
|
+
'/p':dict(e=self._search_put, n='/p[i] [pat]', d='search s/iputs for pattern', t={'apk'}),
|
|
26
|
+
'/dp':dict(e=self._search_defined_package, n='/dp [pat]', d='search packages matching pattern', t={'apk'}),
|
|
27
|
+
'/dc':dict(e=self._search_defined_class, n='/dc [pat]', d='search classes matching pattern', t={'apk'}),
|
|
28
|
+
'/dcx':dict(e=self._search_derived_class, n='/dcx classpat [methpat]', d='search classes defining methods and extending ones matching patterns', t={'apk'}),
|
|
29
|
+
'/dci':dict(e=self._search_implementing_class, n='/dci ifacepat [methpat]', d='search classes defining methods and implementing interfaces matching patterns', t={'apk'}),
|
|
30
|
+
'/dm':dict(e=self._search_defined_method, n='/dm pat', d='search classes defining methods matching pattern', t={'apk'}),
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
async def _search_call(self, args: deque[str]) -> None:
|
|
@@ -26,10 +26,10 @@ class ShowCommand(CommandMixin):
|
|
|
26
26
|
|
|
27
27
|
def get_commands(self) -> CommandMap:
|
|
28
28
|
return {
|
|
29
|
-
'pd':dict(e=self._show_disasm, n='pd qualname', d='show disassembled class/method'),
|
|
30
|
-
'pk':dict(e=self._show_solved_constant, n='pk[!] 0xaddr index', d='guess and show what constant would flow into the index-th arg of op (!: try harder)'),
|
|
31
|
-
'pk!':dict(e=self._show_solved_constant),
|
|
32
|
-
'pt':dict(e=self._show_solved_typeset, n='pt 0xaddr index', d='guess and show what type would flow into the index-th arg of op'),
|
|
29
|
+
'pd':dict(e=self._show_disasm, n='pd qualname', d='show disassembled class/method', t={'apk'}),
|
|
30
|
+
'pk':dict(e=self._show_solved_constant, n='pk[!] 0xaddr index', d='guess and show what constant would flow into the index-th arg of op (!: try harder)', t={'apk'}),
|
|
31
|
+
'pk!':dict(e=self._show_solved_constant, t={'apk'}),
|
|
32
|
+
'pt':dict(e=self._show_solved_typeset, n='pt 0xaddr index', d='guess and show what type would flow into the index-th arg of op', t={'apk'}),
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
async def _show_disasm(self, args: deque[str]) -> None:
|
|
@@ -75,7 +75,7 @@ class ShowCommand(CommandMixin):
|
|
|
75
75
|
|
|
76
76
|
limit = self._helper.get_graph_size_limit(self._helper.get_modifiers(args))
|
|
77
77
|
|
|
78
|
-
from trueseeing.core.android.
|
|
78
|
+
from trueseeing.core.android.analyze.flow import DataFlow
|
|
79
79
|
with DataFlow.apply_max_graph_size(limit):
|
|
80
80
|
context = await self._helper.get_context().require_type('apk').analyze()
|
|
81
81
|
store = context.store()
|
|
@@ -112,7 +112,7 @@ class ShowCommand(CommandMixin):
|
|
|
112
112
|
|
|
113
113
|
limit = self._helper.get_graph_size_limit(self._helper.get_modifiers(args))
|
|
114
114
|
|
|
115
|
-
from trueseeing.core.android.
|
|
115
|
+
from trueseeing.core.android.analyze.flow import DataFlow
|
|
116
116
|
with DataFlow.apply_max_graph_size(limit):
|
|
117
117
|
context = await self._helper.get_context().require_type('apk').analyze()
|
|
118
118
|
store = context.store()
|