trueseeing 2.2.2__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.2 → trueseeing-2.2.5}/Dockerfile +1 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/PKG-INFO +9 -6
- {trueseeing-2.2.2 → trueseeing-2.2.5}/README.md +4 -2
- {trueseeing-2.2.2 → trueseeing-2.2.5}/pyproject.toml +3 -1
- trueseeing-2.2.5/trueseeing/__init__.py +2 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/api.py +7 -2
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/__init__.py +3 -2
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/android/asm.py +61 -15
- trueseeing-2.2.2/trueseeing/app/cmd/android/exploit.py → trueseeing-2.2.5/trueseeing/app/cmd/android/engage.py +430 -62
- trueseeing-2.2.2/trueseeing/app/cmd/android/device.py → trueseeing-2.2.5/trueseeing/app/cmd/android/recon.py +57 -132
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/android/search.py +25 -118
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/android/show.py +34 -63
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/config.py +30 -2
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/info.py +7 -14
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/scan.py +2 -2
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/search.py +1 -1
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/inspect.py +212 -69
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/shell.py +15 -8
- trueseeing-2.2.5/trueseeing/core/analyze.py +65 -0
- trueseeing-2.2.5/trueseeing/core/android/analyze/flow.py +357 -0
- trueseeing-2.2.5/trueseeing/core/android/analyze/nat.py +44 -0
- trueseeing-2.2.5/trueseeing/core/android/analyze/op.py +55 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/android/asm.py +64 -11
- trueseeing-2.2.5/trueseeing/core/android/context.py +469 -0
- trueseeing-2.2.5/trueseeing/core/android/db.py +160 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/android/device.py +14 -8
- trueseeing-2.2.5/trueseeing/core/android/model.py +68 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/context.py +64 -14
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/db.py +6 -6
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/env.py +5 -1
- {trueseeing-2.2.2 → 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.2 → trueseeing-2.2.5}/trueseeing/core/model/issue.py +3 -5
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/scan.py +1 -1
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/store.py +6 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/tools.py +26 -17
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/ui.py +103 -8
- trueseeing-2.2.5/trueseeing/libs/android/store.0.sql +11 -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.2 → trueseeing-2.2.5}/trueseeing/libs/store.s.sql +1 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/sig/__init__.py +1 -2
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/sig/android/crypto.py +61 -60
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/sig/android/fingerprint.py +15 -15
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/sig/android/manifest.py +8 -8
- trueseeing-2.2.5/trueseeing/sig/android/nat.py +93 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/sig/android/privacy.py +15 -15
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/sig/android/security.py +76 -74
- 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.2/trueseeing/__init__.py +0 -2
- trueseeing-2.2.2/trueseeing/core/android/analysis/flow.py +0 -331
- trueseeing-2.2.2/trueseeing/core/android/analysis/smali.py +0 -144
- trueseeing-2.2.2/trueseeing/core/android/context.py +0 -216
- trueseeing-2.2.2/trueseeing/core/android/db.py +0 -187
- trueseeing-2.2.2/trueseeing/core/android/model/code.py +0 -55
- trueseeing-2.2.2/trueseeing/libs/android/store.0.sql +0 -4
- trueseeing-2.2.2/trueseeing/libs/android/store.1.sql +0 -77
- {trueseeing-2.2.2 → trueseeing-2.2.5}/.dockerignore +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/.github/workflows/deploy.yaml +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/.github/workflows/lint.yaml +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/.github/workflows/publish.yaml +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/.github/workflows/stale.yaml +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/.gitignore +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/COPYING +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/__init__.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/alias.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/analyze.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/android/__init__.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/report.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/cmd/show.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/app/scan.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/__init__.py +0 -0
- {trueseeing-2.2.2/trueseeing/core/android/analysis → trueseeing-2.2.5/trueseeing/core/android/analyze}/__init__.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/android/store.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/android/tools.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/config.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/cvss.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/exc.py +0 -0
- {trueseeing-2.2.2/trueseeing/core/android/model → trueseeing-2.2.5/trueseeing/core/ios}/__init__.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/model/__init__.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/model/cmd.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/model/sig.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/report.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/core/z.py +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/LICENSE.md +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/android/abe.jar +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/android/apkeditor.jar +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/android/apksigner.jar +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/android/frida-app.smali +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/android/frida-scriptdir.config +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/android/nsc.xml +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/files.0.sql +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/public_suffix_list.dat +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/store.0.sql +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/template/report.html +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/libs/tlds.txt +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/py.typed +0 -0
- {trueseeing-2.2.2 → trueseeing-2.2.5}/trueseeing/sig/android/__init__.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
|
|
@@ -16,7 +16,6 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (G
|
|
|
16
16
|
Requires-Dist: lxml~=5.0
|
|
17
17
|
Requires-Dist: pyyaml~=6.0
|
|
18
18
|
Requires-Dist: jinja2~=3.1
|
|
19
|
-
Requires-Dist: attrs~=23.2
|
|
20
19
|
Requires-Dist: pypubsub~=4.0
|
|
21
20
|
Requires-Dist: termcolor~=2.4
|
|
22
21
|
Requires-Dist: progressbar2~=4.3
|
|
@@ -25,6 +24,8 @@ Requires-Dist: asn1crypto~=1.5
|
|
|
25
24
|
Requires-Dist: zstandard~=0.22
|
|
26
25
|
Requires-Dist: aiohttp~=3.9
|
|
27
26
|
Requires-Dist: lief~=0.14
|
|
27
|
+
Requires-Dist: pyaxmlparser~=0.3
|
|
28
|
+
Requires-Dist: prompt-toolkit~=3.0
|
|
28
29
|
Requires-Dist: mypy~=1.7 ; extra == "dev"
|
|
29
30
|
Requires-Dist: pyproject-flake8~=6.1 ; extra == "dev"
|
|
30
31
|
Requires-Dist: typing_extensions~=4.1 ; extra == "dev"
|
|
@@ -38,7 +39,7 @@ Provides-Extra: dev
|
|
|
38
39
|

|
|
39
40
|

|
|
40
41
|
|
|
41
|
-
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.
|
|
42
43
|
|
|
43
44
|
## Capability
|
|
44
45
|
|
|
@@ -50,6 +51,8 @@ Currently we can:
|
|
|
50
51
|
* Copy in/out app data through debug interface
|
|
51
52
|
* Search for certain calls/consts/sput/iput
|
|
52
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))
|
|
53
56
|
* etc.
|
|
54
57
|
|
|
55
58
|
## Installation
|
|
@@ -83,7 +86,7 @@ Alternatively, you can install our package with pip as follows. This form of ins
|
|
|
83
86
|
You can interactively scan/analyze/patch/etc. apps -- making it the ideal choice for manual analysis:
|
|
84
87
|
|
|
85
88
|
$ trueseeing target.apk
|
|
86
|
-
[+] trueseeing 2.2.
|
|
89
|
+
[+] trueseeing 2.2.5
|
|
87
90
|
ts[target.apk]> ?
|
|
88
91
|
...
|
|
89
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
|
|
@@ -22,7 +22,6 @@ dependencies = [
|
|
|
22
22
|
"lxml~=5.0",
|
|
23
23
|
"pyyaml~=6.0",
|
|
24
24
|
"jinja2~=3.1",
|
|
25
|
-
"attrs~=23.2",
|
|
26
25
|
"pypubsub~=4.0",
|
|
27
26
|
"termcolor~=2.4",
|
|
28
27
|
"progressbar2~=4.3",
|
|
@@ -31,6 +30,8 @@ dependencies = [
|
|
|
31
30
|
"zstandard~=0.22",
|
|
32
31
|
"aiohttp~=3.9",
|
|
33
32
|
"lief~=0.14",
|
|
33
|
+
"pyaxmlparser~=0.3",
|
|
34
|
+
"prompt-toolkit~=3.0",
|
|
34
35
|
]
|
|
35
36
|
requires-python = ">=3.9"
|
|
36
37
|
dynamic = ['version', 'description']
|
|
@@ -59,6 +60,7 @@ module = [
|
|
|
59
60
|
"jinja2",
|
|
60
61
|
"pubsub",
|
|
61
62
|
"asn1crypto.*",
|
|
63
|
+
"pyaxmlparser.*",
|
|
62
64
|
]
|
|
63
65
|
ignore_missing_imports = true
|
|
64
66
|
|
|
@@ -4,15 +4,18 @@ 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
|
|
11
11
|
from trueseeing.core.model.issue import Issue, IssueConfidence
|
|
12
12
|
|
|
13
|
+
ModifierEvent = Literal['begin', 'end']
|
|
14
|
+
|
|
13
15
|
CommandEntrypoint = Callable[[deque[str]], Coroutine[Any, Any, None]]
|
|
14
16
|
CommandlineEntrypoint = Callable[[str], Coroutine[Any, Any, None]]
|
|
15
17
|
CommandPatternEntrypoints = Union[CommandEntrypoint, CommandlineEntrypoint]
|
|
18
|
+
ModifierListenerEntrypoint = Callable[[ModifierEvent, str], Coroutine[Any, Any, None]]
|
|
16
19
|
SignatureEntrypoint = Callable[[], Coroutine[Any, Any, None]]
|
|
17
20
|
FormatHandlerEntrypoint = Callable[[str], Optional[Context]]
|
|
18
21
|
ConfigGetterEntrypoint = Callable[[], Any]
|
|
@@ -22,6 +25,7 @@ if TYPE_CHECKING:
|
|
|
22
25
|
e: CommandEntrypoint
|
|
23
26
|
n: str
|
|
24
27
|
d: str
|
|
28
|
+
t: Set[str]
|
|
25
29
|
|
|
26
30
|
class CommandEntry(Entry):
|
|
27
31
|
pass
|
|
@@ -34,7 +38,7 @@ if TYPE_CHECKING:
|
|
|
34
38
|
pass
|
|
35
39
|
|
|
36
40
|
class ModifierEntry(Entry):
|
|
37
|
-
|
|
41
|
+
e: Optional[ModifierListenerEntrypoint] # type: ignore[misc]
|
|
38
42
|
|
|
39
43
|
class ConfigEntry(TypedDict):
|
|
40
44
|
g: ConfigGetterEntrypoint
|
|
@@ -62,6 +66,7 @@ if TYPE_CHECKING:
|
|
|
62
66
|
class CommandHelper(Protocol):
|
|
63
67
|
def get_target(self) -> Optional[str]: ...
|
|
64
68
|
def require_target(self, msg: Optional[str] = None) -> str: ...
|
|
69
|
+
def get_context_type(self) -> Optional[Set[ContextType]]: ...
|
|
65
70
|
@overload
|
|
66
71
|
def get_context(self) -> Context: ...
|
|
67
72
|
@overload
|
|
@@ -1,18 +1,19 @@
|
|
|
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
|
|
11
|
-
from trueseeing.core.model.cmd import CommandMixin
|
|
12
13
|
from trueseeing.core.tools import get_public_subclasses, get_missing_methods, discover_modules_under
|
|
13
14
|
|
|
14
15
|
for mod in discover_modules_under('trueseeing.app.cmd'):
|
|
15
16
|
m = import_module(mod)
|
|
16
|
-
for c in get_public_subclasses(m, Command,
|
|
17
|
+
for c in get_public_subclasses(m, Command, 'CommandMixin'): # type:ignore[type-abstract]
|
|
17
18
|
assert not get_missing_methods(c)
|
|
18
19
|
yield c
|
|
@@ -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:
|
|
@@ -47,16 +49,24 @@ class AssembleCommand(CommandMixin):
|
|
|
47
49
|
ui.fatal('need root path')
|
|
48
50
|
|
|
49
51
|
import os
|
|
52
|
+
import re
|
|
50
53
|
import time
|
|
51
54
|
from tempfile import TemporaryDirectory
|
|
52
55
|
from trueseeing.core.android.asm import APKAssembler
|
|
53
56
|
from trueseeing.core.android.tools import move_apk
|
|
54
57
|
|
|
55
58
|
root = args.popleft()
|
|
56
|
-
origapk =
|
|
59
|
+
origapk = re.sub(r'(\.x?apk)$', r'\1.orig', apk)
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
stem = re.sub(r'\.x?apk$', '', apk)
|
|
62
|
+
for typ in ['apk', 'xapk']:
|
|
63
|
+
print(origapk, f'{stem}.{typ}.orig')
|
|
64
|
+
if os.path.exists(f'{stem}.{typ}.orig') and not cmd.endswith('!'):
|
|
65
|
+
ui.fatal('backup file exists; force (!) to overwrite')
|
|
66
|
+
|
|
67
|
+
if apk.endswith('.xapk'):
|
|
68
|
+
ui.warn('assembling xapk is not supported; assembling as merged apk')
|
|
69
|
+
apk = apk.replace('.xapk', '.apk')
|
|
60
70
|
|
|
61
71
|
opts = self._helper.get_effective_options(self._helper.get_modifiers(args))
|
|
62
72
|
|
|
@@ -140,7 +150,7 @@ class AssembleCommand(CommandMixin):
|
|
|
140
150
|
at = time.time()
|
|
141
151
|
|
|
142
152
|
with TemporaryDirectory() as td:
|
|
143
|
-
await APKDisassembler.disassemble_to_path(apk, td, nodex=nodex)
|
|
153
|
+
await APKDisassembler.disassemble_to_path(apk, td, nodex=nodex, merge=apk.endswith('.xapk'))
|
|
144
154
|
|
|
145
155
|
if not archive:
|
|
146
156
|
with FileTransferProgressReporter('disassemble: writing').scoped() as progress:
|
|
@@ -185,7 +195,7 @@ class AssembleCommand(CommandMixin):
|
|
|
185
195
|
|
|
186
196
|
at = time.time()
|
|
187
197
|
extracted = 0
|
|
188
|
-
context = self._helper.get_context()
|
|
198
|
+
context = self._helper.get_context()
|
|
189
199
|
q = context.store().query()
|
|
190
200
|
|
|
191
201
|
if not archive:
|
|
@@ -206,7 +216,7 @@ class AssembleCommand(CommandMixin):
|
|
|
206
216
|
if subformat in ['gz']:
|
|
207
217
|
kwargs.update(dict(compresslevel=3))
|
|
208
218
|
|
|
209
|
-
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]
|
|
210
220
|
now = int(time.time())
|
|
211
221
|
for path,blob in q.file_enum(pat=pat, regex=True):
|
|
212
222
|
target = os.path.join('files', *path.split('/'))
|
|
@@ -215,6 +225,7 @@ class AssembleCommand(CommandMixin):
|
|
|
215
225
|
|
|
216
226
|
bf = BytesIO(blob)
|
|
217
227
|
ti = tarfile.TarInfo(name=target)
|
|
228
|
+
ti.size = len(blob)
|
|
218
229
|
ti.uname = 'root'
|
|
219
230
|
ti.gname = 'root'
|
|
220
231
|
ti.mode = 0o600
|
|
@@ -231,3 +242,38 @@ class AssembleCommand(CommandMixin):
|
|
|
231
242
|
return 'tar:gz'
|
|
232
243
|
else:
|
|
233
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)))
|