trueseeing 2.2.4__tar.gz → 2.2.6__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.
Files changed (105) hide show
  1. trueseeing-2.2.6/.github/FUNDING.yml +14 -0
  2. {trueseeing-2.2.4 → trueseeing-2.2.6}/.github/workflows/deploy.yaml +1 -1
  3. {trueseeing-2.2.4 → trueseeing-2.2.6}/.github/workflows/lint.yaml +1 -1
  4. {trueseeing-2.2.4 → trueseeing-2.2.6}/.github/workflows/publish.yaml +1 -1
  5. trueseeing-2.2.6/Dockerfile +18 -0
  6. {trueseeing-2.2.4 → trueseeing-2.2.6}/PKG-INFO +16 -10
  7. {trueseeing-2.2.4 → trueseeing-2.2.6}/README.md +7 -2
  8. {trueseeing-2.2.4 → trueseeing-2.2.6}/pyproject.toml +6 -5
  9. trueseeing-2.2.6/trueseeing/__init__.py +2 -0
  10. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/api.py +3 -1
  11. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/__init__.py +2 -0
  12. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/android/asm.py +48 -11
  13. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/android/engage.py +497 -48
  14. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/android/recon.py +12 -8
  15. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/android/search.py +8 -8
  16. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/android/show.py +6 -6
  17. trueseeing-2.2.6/trueseeing/app/cmd/ios/engage.py +292 -0
  18. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/inspect.py +129 -38
  19. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/shell.py +18 -13
  20. trueseeing-2.2.6/trueseeing/core/analyze.py +65 -0
  21. {trueseeing-2.2.4/trueseeing/core/android/analysis → trueseeing-2.2.6/trueseeing/core/android/analyze}/flow.py +1 -1
  22. trueseeing-2.2.6/trueseeing/core/android/analyze/nat.py +44 -0
  23. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/android/asm.py +31 -6
  24. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/android/context.py +59 -13
  25. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/android/db.py +26 -2
  26. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/android/device.py +40 -1
  27. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/android/model.py +10 -2
  28. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/context.py +13 -0
  29. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/db.py +6 -6
  30. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/env.py +27 -1
  31. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/exc.py +3 -0
  32. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/ext.py +44 -14
  33. trueseeing-2.2.6/trueseeing/core/ios/analyze.py +74 -0
  34. trueseeing-2.2.6/trueseeing/core/ios/context.py +130 -0
  35. trueseeing-2.2.6/trueseeing/core/ios/db.py +60 -0
  36. trueseeing-2.2.6/trueseeing/core/ios/device.py +53 -0
  37. trueseeing-2.2.6/trueseeing/core/ios/model.py +15 -0
  38. trueseeing-2.2.6/trueseeing/core/ios/store.py +34 -0
  39. trueseeing-2.2.6/trueseeing/core/ios/swift.py +120 -0
  40. trueseeing-2.2.6/trueseeing/core/nat.py +47 -0
  41. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/scan.py +1 -1
  42. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/tools.py +30 -17
  43. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/ui.py +106 -10
  44. trueseeing-2.2.6/trueseeing/core/z.py +9 -0
  45. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/android/store.0.sql +1 -0
  46. trueseeing-2.2.6/trueseeing/libs/android/store.1.sql +2 -0
  47. trueseeing-2.2.6/trueseeing/libs/ios/store.0.sql +1 -0
  48. trueseeing-2.2.6/trueseeing/libs/ios/store.1.sql +2 -0
  49. trueseeing-2.2.6/trueseeing/py.typed +0 -0
  50. trueseeing-2.2.6/trueseeing/sig/android/__init__.py +0 -0
  51. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/sig/android/crypto.py +1 -1
  52. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/sig/android/fingerprint.py +1 -1
  53. trueseeing-2.2.6/trueseeing/sig/android/nat.py +93 -0
  54. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/sig/android/privacy.py +1 -1
  55. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/sig/android/security.py +1 -1
  56. trueseeing-2.2.6/trueseeing/sig/ios/__init__.py +0 -0
  57. trueseeing-2.2.6/trueseeing/sig/ios/base.py +880 -0
  58. trueseeing-2.2.4/Dockerfile +0 -26
  59. trueseeing-2.2.4/trueseeing/__init__.py +0 -2
  60. trueseeing-2.2.4/trueseeing/core/z.py +0 -8
  61. {trueseeing-2.2.4 → trueseeing-2.2.6}/.dockerignore +0 -0
  62. {trueseeing-2.2.4 → trueseeing-2.2.6}/.github/workflows/stale.yaml +0 -0
  63. {trueseeing-2.2.4 → trueseeing-2.2.6}/.gitignore +0 -0
  64. {trueseeing-2.2.4 → trueseeing-2.2.6}/COPYING +0 -0
  65. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/__init__.py +0 -0
  66. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/alias.py +0 -0
  67. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/analyze.py +0 -0
  68. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/android/__init__.py +0 -0
  69. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/config.py +0 -0
  70. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/info.py +0 -0
  71. {trueseeing-2.2.4/trueseeing/core → trueseeing-2.2.6/trueseeing/app/cmd/ios}/__init__.py +0 -0
  72. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/report.py +0 -0
  73. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/scan.py +0 -0
  74. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/search.py +0 -0
  75. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/cmd/show.py +0 -0
  76. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/app/scan.py +0 -0
  77. {trueseeing-2.2.4/trueseeing/core/android/analysis → trueseeing-2.2.6/trueseeing/core}/__init__.py +0 -0
  78. {trueseeing-2.2.4/trueseeing/core/model → trueseeing-2.2.6/trueseeing/core/android/analyze}/__init__.py +0 -0
  79. {trueseeing-2.2.4/trueseeing/core/android/analysis → trueseeing-2.2.6/trueseeing/core/android/analyze}/op.py +0 -0
  80. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/android/store.py +0 -0
  81. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/android/tools.py +0 -0
  82. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/config.py +0 -0
  83. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/cvss.py +0 -0
  84. {trueseeing-2.2.4/trueseeing/sig/android → trueseeing-2.2.6/trueseeing/core/ios}/__init__.py +0 -0
  85. /trueseeing-2.2.4/trueseeing/py.typed → /trueseeing-2.2.6/trueseeing/core/model/__init__.py +0 -0
  86. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/model/cmd.py +0 -0
  87. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/model/issue.py +0 -0
  88. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/model/sig.py +0 -0
  89. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/report.py +0 -0
  90. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/core/store.py +0 -0
  91. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/LICENSE.md +0 -0
  92. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/android/abe.jar +0 -0
  93. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/android/apkeditor.jar +0 -0
  94. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/android/apksigner.jar +0 -0
  95. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/android/frida-app.smali +0 -0
  96. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/android/frida-scriptdir.config +0 -0
  97. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/android/nsc.xml +0 -0
  98. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/files.0.sql +0 -0
  99. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/public_suffix_list.dat +0 -0
  100. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/store.0.sql +0 -0
  101. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/store.s.sql +0 -0
  102. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/template/report.html +0 -0
  103. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/libs/tlds.txt +0 -0
  104. {trueseeing-2.2.4 → trueseeing-2.2.6}/trueseeing/sig/__init__.py +0 -0
  105. {trueseeing-2.2.4 → trueseeing-2.2.6}/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']
@@ -16,7 +16,7 @@ jobs:
16
16
  - name: Setup environment
17
17
  uses: actions/setup-python@v3
18
18
  with:
19
- python-version: 3.11
19
+ python-version: 3.13
20
20
 
21
21
  - name: Set up Docker Buildx
22
22
  uses: docker/setup-buildx-action@v3
@@ -12,7 +12,7 @@ jobs:
12
12
  - name: Setup environment
13
13
  uses: actions/setup-python@v3
14
14
  with:
15
- python-version: 3.11
15
+ python-version: 3.13
16
16
 
17
17
  - name: Install dependencies
18
18
  run: |
@@ -17,7 +17,7 @@ jobs:
17
17
  - name: Setup environment
18
18
  uses: actions/setup-python@v3
19
19
  with:
20
- python-version: 3.11
20
+ python-version: 3.13
21
21
 
22
22
  - name: Set up Docker Buildx
23
23
  uses: docker/setup-buildx-action@v3
@@ -0,0 +1,18 @@
1
+ from python:3.13-slim
2
+ run pip install flit
3
+ copy . /tmp/build/
4
+ run (cd /tmp/build && flit build)
5
+
6
+ from python:3.13-slim
7
+ run apt-get update -y && apt-get install -y openjdk-17-jre-headless zip adb
8
+ run install -d -m 777 /data /ext /cache /out && ln -sfn /cache /root/.local
9
+ copy --from=0 /tmp/build/dist/*.whl /tmp/dist/
10
+ run pip install /tmp/dist/*.whl && rm -rf /tmp/dist /tmp/ext
11
+ env PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
12
+ env TS2_IN_DOCKER=1
13
+ env TS2_CACHEDIR=/cache
14
+ env TS2_HOME=/data
15
+ env TS2_EXTDIR=/ext
16
+ env TS2_SWIFT_DEMANGLER_URL=http://ts2-swift-demangle
17
+ workdir /out
18
+ entrypoint ["trueseeing"]
@@ -1,8 +1,8 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: trueseeing
3
- Version: 2.2.4
4
- Summary: Trueseeing is a non-decompiling Android application vulnerability scanner.
5
- Keywords: android,security,pentest,hacking
3
+ Version: 2.2.6
4
+ Summary: Trueseeing is a non-decompiling iOS/Android application vulnerability scanner.
5
+ Keywords: ios,android,security,pentest,hacking
6
6
  Author-email: Takahiro Yoshimura <alterakey@protonmail.com>
7
7
  Requires-Python: >=3.9
8
8
  Description-Content-Type: text/markdown
@@ -21,14 +21,15 @@ Requires-Dist: termcolor~=2.4
21
21
  Requires-Dist: progressbar2~=4.3
22
22
  Requires-Dist: importlib_metadata~=7.0
23
23
  Requires-Dist: asn1crypto~=1.5
24
- Requires-Dist: zstandard~=0.22
24
+ Requires-Dist: pyzstd~=0.16
25
25
  Requires-Dist: aiohttp~=3.9
26
26
  Requires-Dist: lief~=0.14
27
27
  Requires-Dist: pyaxmlparser~=0.3
28
28
  Requires-Dist: prompt-toolkit~=3.0
29
- Requires-Dist: mypy~=1.7 ; extra == "dev"
30
- Requires-Dist: pyproject-flake8~=6.1 ; extra == "dev"
31
- Requires-Dist: typing_extensions~=4.1 ; extra == "dev"
29
+ Requires-Dist: frida-tools~=13.6
30
+ Requires-Dist: mypy~=1.13 ; extra == "dev"
31
+ Requires-Dist: pyproject-flake8~=7.0 ; extra == "dev"
32
+ Requires-Dist: typing_extensions~=4.12 ; extra == "dev"
32
33
  Project-URL: Source, https://github.com/alterakey/trueseeing
33
34
  Provides-Extra: dev
34
35
 
@@ -39,7 +40,7 @@ Provides-Extra: dev
39
40
  ![Main branch deploy status](https://github.com/alterakey/trueseeing/workflows/deploy/badge.svg)
40
41
  ![Main branch last commit](https://img.shields.io/github/last-commit/alterakey/trueseeing/main)
41
42
 
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.
43
+ 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
44
 
44
45
  ## Capability
45
46
 
@@ -51,6 +52,11 @@ Currently we can:
51
52
  * Copy in/out app data through debug interface
52
53
  * Search for certain calls/consts/sput/iput
53
54
  * Deduce constants/typesets for args of op
55
+ * Scan API/private calls for native codes (NB: you need [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
56
+ * Scan iOS apps for basic vulnerabilities (NB: you need [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
57
+ * Attach frida scripts
58
+ * Provide frida interative session
59
+ * Tracing calls
54
60
  * etc.
55
61
 
56
62
  ## Installation
@@ -84,7 +90,7 @@ Alternatively, you can install our package with pip as follows. This form of ins
84
90
  You can interactively scan/analyze/patch/etc. apps -- making it the ideal choice for manual analysis:
85
91
 
86
92
  $ trueseeing target.apk
87
- [+] trueseeing 2.2.4
93
+ [+] trueseeing 2.2.6
88
94
  ts[target.apk]> ?
89
95
  ...
90
96
  ts[target.apk]> i # show generic information
@@ -5,7 +5,7 @@
5
5
  ![Main branch deploy status](https://github.com/alterakey/trueseeing/workflows/deploy/badge.svg)
6
6
  ![Main branch last commit](https://img.shields.io/github/last-commit/alterakey/trueseeing/main)
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,11 @@ 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))
22
+ * Attach frida scripts
23
+ * Provide frida interative session
24
+ * Tracing calls
20
25
  * etc.
21
26
 
22
27
  ## Installation
@@ -50,7 +55,7 @@ Alternatively, you can install our package with pip as follows. This form of ins
50
55
  You can interactively scan/analyze/patch/etc. apps -- making it the ideal choice for manual analysis:
51
56
 
52
57
  $ trueseeing target.apk
53
- [+] trueseeing 2.2.4
58
+ [+] trueseeing 2.2.6
54
59
  ts[target.apk]> ?
55
60
  ...
56
61
  ts[target.apk]> i # show generic information
@@ -17,7 +17,7 @@ classifiers = [
17
17
  "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
18
18
  ]
19
19
  readme = "README.md"
20
- keywords = ['android', 'security', 'pentest', 'hacking']
20
+ keywords = ['ios', 'android', 'security', 'pentest', 'hacking']
21
21
  dependencies = [
22
22
  "lxml~=5.0",
23
23
  "pyyaml~=6.0",
@@ -27,20 +27,21 @@ dependencies = [
27
27
  "progressbar2~=4.3",
28
28
  "importlib_metadata~=7.0",
29
29
  "asn1crypto~=1.5",
30
- "zstandard~=0.22",
30
+ "pyzstd~=0.16",
31
31
  "aiohttp~=3.9",
32
32
  "lief~=0.14",
33
33
  "pyaxmlparser~=0.3",
34
34
  "prompt-toolkit~=3.0",
35
+ 'frida-tools~=13.6',
35
36
  ]
36
37
  requires-python = ">=3.9"
37
38
  dynamic = ['version', 'description']
38
39
 
39
40
  [project.optional-dependencies]
40
41
  dev = [
41
- "mypy~=1.7",
42
- "pyproject-flake8~=6.1",
43
- "typing_extensions~=4.1",
42
+ "mypy~=1.13",
43
+ "pyproject-flake8~=7.0",
44
+ "typing_extensions~=4.12",
44
45
  ]
45
46
 
46
47
  [project.urls]
@@ -0,0 +1,2 @@
1
+ """Trueseeing is a non-decompiling iOS/Android application vulnerability scanner."""
2
+ __version__ = '2.2.6'
@@ -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
- 'co':dict(e=self._export_context, n='co[!] /path [pat]', d='export codebase'),
33
- 'co!':dict(e=self._export_context),
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:
@@ -58,7 +60,6 @@ class AssembleCommand(CommandMixin):
58
60
 
59
61
  stem = re.sub(r'\.x?apk$', '', apk)
60
62
  for typ in ['apk', 'xapk']:
61
- print(origapk, f'{stem}.{typ}.orig')
62
63
  if os.path.exists(f'{stem}.{typ}.orig') and not cmd.endswith('!'):
63
64
  ui.fatal('backup file exists; force (!) to overwrite')
64
65
 
@@ -214,7 +215,7 @@ class AssembleCommand(CommandMixin):
214
215
  if subformat in ['gz']:
215
216
  kwargs.update(dict(compresslevel=3))
216
217
 
217
- with tarfile.open(root, 'w:{}'.format(subformat), **kwargs) as tf: # type: ignore[arg-type]
218
+ with tarfile.open(root, 'w:{}'.format(subformat), **kwargs) as tf: # type: ignore[call-overload]
218
219
  now = int(time.time())
219
220
  for path,blob in q.file_enum(pat=pat, regex=True):
220
221
  target = os.path.join('files', *path.split('/'))
@@ -223,6 +224,7 @@ class AssembleCommand(CommandMixin):
223
224
 
224
225
  bf = BytesIO(blob)
225
226
  ti = tarfile.TarInfo(name=target)
227
+ ti.size = len(blob)
226
228
  ti.uname = 'root'
227
229
  ti.gname = 'root'
228
230
  ti.mode = 0o600
@@ -239,3 +241,38 @@ class AssembleCommand(CommandMixin):
239
241
  return 'tar:gz'
240
242
  else:
241
243
  return None
244
+
245
+ async def _merge(self, args: deque[str]) -> None:
246
+ target = self._helper.require_target('need target')
247
+
248
+ cmd = args.popleft()
249
+
250
+ import os
251
+ import time
252
+ from tempfile import TemporaryDirectory
253
+ from trueseeing.core.android.asm import APKAssembler
254
+ from trueseeing.core.android.tools import move_apk
255
+
256
+ if args:
257
+ outfn = args.popleft()
258
+ else:
259
+ outfn = target.replace('.xapk', '.apk')
260
+
261
+ origfn = outfn.replace('.apk', '.apk.orig')
262
+
263
+ if os.path.exists(origfn) and not cmd.endswith('!'):
264
+ ui.fatal('backup file exists; force (!) to overwrite')
265
+
266
+ ui.info('merging slices {target} -> {outfn}'.format(target=target, outfn=outfn))
267
+
268
+ at = time.time()
269
+
270
+ with TemporaryDirectory() as td:
271
+ apk, sig = await APKAssembler.merge_slices(target, td)
272
+
273
+ if os.path.exists(outfn):
274
+ move_apk(outfn, origfn)
275
+
276
+ move_apk(apk, outfn)
277
+
278
+ ui.success('done ({t:.02f} sec.)'.format(t=(time.time() - at)))