frida-fusion 0.1.10__tar.gz → 0.1.12__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.

Potentially problematic release.


This version of frida-fusion might be problematic. Click here for more details.

Files changed (34) hide show
  1. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/PKG-INFO +1 -1
  2. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/__meta__.py +2 -2
  3. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/args.py +4 -0
  4. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/config.py +35 -2
  5. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/fusion.py +45 -4
  6. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/module.py +6 -7
  7. frida_fusion-0.1.12/frida_fusion/modules/android_setings/settings.js +172 -0
  8. frida_fusion-0.1.12/frida_fusion/modules/android_setings/settings.py +110 -0
  9. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/modules/crypto/crypto.js +14 -14
  10. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/modules/crypto/crypto.py +71 -27
  11. frida_fusion-0.1.12/frida_fusion/modules/tls_unpinning/__init__.py +0 -0
  12. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion.egg-info/PKG-INFO +1 -1
  13. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion.egg-info/SOURCES.txt +3 -0
  14. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/LICENSE +0 -0
  15. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/README.md +0 -0
  16. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/__init__.py +0 -0
  17. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/__main__.py +0 -0
  18. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/libs/__init__.py +0 -0
  19. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/libs/color.py +0 -0
  20. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/libs/database.py +0 -0
  21. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/libs/helpers.js +0 -0
  22. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/libs/logger.py +0 -0
  23. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/libs/scriptlocation.py +0 -0
  24. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/modules/__init__.py +0 -0
  25. {frida_fusion-0.1.10/frida_fusion/modules/crypto → frida_fusion-0.1.12/frida_fusion/modules/android_setings}/__init__.py +0 -0
  26. {frida_fusion-0.1.10/frida_fusion/modules/tls_unpinning → frida_fusion-0.1.12/frida_fusion/modules/crypto}/__init__.py +0 -0
  27. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion/modules/tls_unpinning/frida_multiple_unpinning.py +0 -0
  28. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion.egg-info/dependency_links.txt +0 -0
  29. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion.egg-info/entry_points.txt +0 -0
  30. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion.egg-info/requires.txt +0 -0
  31. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/frida_fusion.egg-info/top_level.txt +0 -0
  32. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/pyproject.toml +0 -0
  33. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/setup.cfg +0 -0
  34. {frida_fusion-0.1.10 → frida_fusion-0.1.12}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frida-fusion
3
- Version: 0.1.10
3
+ Version: 0.1.12
4
4
  Summary: Hook your mobile tests with Frida
5
5
  Author-email: "Helvio Junior (M4v3r1ck)" <helvio_junior@hotmail.com>
6
6
  Maintainer-email: "Helvio Junior (M4v3r1ck)" <helvio_junior@hotmail.com>
@@ -1,8 +1,8 @@
1
- __version__ = '0.1.10'
1
+ __version__ = '0.1.12'
2
2
  __title__ = "Frida Fusion"
3
3
  __description__ = "📱 frida-fusion - runtime mobile exploration"
4
4
  __url__ = "https://github.com/helviojunior/frida-fusion"
5
- __build__ = 0x3c147be
5
+ __build__ = 0x6c949ce
6
6
  __author__ = "Helvio Junior (M4v3r1ck)"
7
7
  __author_email__ = "helvio_junior@hotmail.com"
8
8
  __license__ = "GPL-3.0"
@@ -148,4 +148,8 @@ class Arguments(object):
148
148
  dest='enabled_modules',
149
149
  help='Enabled module by name. You can specify multiple values repeating the flag.')
150
150
 
151
+ modules.add_argument('--silence-module-messages',
152
+ action='append',
153
+ dest='ignore_messages_modules',
154
+ help='Silence messages becaming from module by name. You can specify multiple values repeating the flag.')
151
155
 
@@ -22,6 +22,7 @@ class Configuration(object):
22
22
  base_path = str(Path(__file__).resolve().parent)
23
23
  db_path = os.path.join(str(Path(".").resolve()), "fusion.db")
24
24
  enabled_modules = {}
25
+ ignore_messages_modules = {}
25
26
 
26
27
  # Device vars
27
28
  device_id = None
@@ -180,9 +181,15 @@ class Configuration(object):
180
181
 
181
182
  Logger.pl(' {C}min debug level:{O} %s{W}' % str(args.debug_level).upper())
182
183
 
183
- if args.enabled_modules is not None and isinstance(args.enabled_modules, list):
184
+ if (args.enabled_modules is not None and isinstance(args.enabled_modules, list)) or \
185
+ (args.ignore_messages_modules is not None and isinstance(args.ignore_messages_modules, list)):
184
186
  mods = ModuleManager.list_modules()
185
- for mod in args.enabled_modules:
187
+ for mod in [
188
+ m.strip()
189
+ for md in args.enabled_modules
190
+ for m in md.split(",")
191
+ if m.strip() != ""
192
+ ]:
186
193
  fm = next(iter([
187
194
  m
188
195
  for _, m in mods.items()
@@ -197,12 +204,38 @@ class Configuration(object):
197
204
  if name not in Configuration.enabled_modules.keys():
198
205
  Configuration.enabled_modules[name] = fm
199
206
 
207
+ for mod in [
208
+ m.strip()
209
+ for md in args.ignore_messages_modules
210
+ for m in md.split(",")
211
+ if m.strip() != ""
212
+ ]:
213
+ fm = next(iter([
214
+ m
215
+ for _, m in mods.items()
216
+ if m.safe_name() == mod.lower()
217
+ ]), None)
218
+ if fm is None:
219
+ Color.pl(
220
+ '{!} {R}error: module {O}%s{R} not found{W}\r\n' % mod)
221
+ sys.exit(1)
222
+
223
+ name = fm.safe_name()
224
+ if name not in Configuration.ignore_messages_modules.keys():
225
+ Configuration.ignore_messages_modules[name] = fm
226
+
200
227
  if len(Configuration.enabled_modules) > 0:
201
228
  Logger.pl(' {C}modules:{O} %s{W}' % ', '.join([
202
229
  m.name
203
230
  for _, m in Configuration.enabled_modules.items()
204
231
  ]))
205
232
 
233
+ if len(Configuration.ignore_messages_modules) > 0:
234
+ Logger.pl(' {C}ignored messages from modules:{O} %s{W}' % ', '.join([
235
+ m.name
236
+ for _, m in Configuration.ignore_messages_modules.items()
237
+ ]))
238
+
206
239
  Logger.pl("")
207
240
 
208
241
  @staticmethod
@@ -44,6 +44,7 @@ class Fusion(object):
44
44
  self.pid = 0
45
45
  self.script_trace = {}
46
46
  self._modules = []
47
+ self._ignore_messages = []
47
48
  signal.signal(signal.SIGINT, self.signal_handler)
48
49
 
49
50
  t = threading.Thread(target=Fusion._db_worker, daemon=True)
@@ -194,9 +195,29 @@ class Fusion(object):
194
195
  s.on("message", self.make_handler("fusion_bundle.js")) # register the message handler
195
196
  s.load()
196
197
  except Exception as e:
197
- Logger.pl('{!} {R}Error:{O} %s{W}' % str(e))
198
- print("")
199
- sys.exit(1)
198
+
199
+ try:
200
+ err = str(e)
201
+ pattern = re.compile(r'script\(line (\d+)\):')
202
+ matches = [
203
+ (
204
+ m.group(0),
205
+ self.translate_location(dict(
206
+ file_name="fusion_bundle.js",
207
+ line=m.group(1),
208
+ ))
209
+ )
210
+ for m in pattern.finditer(err)
211
+ ]
212
+ for m in matches:
213
+ err = err.replace(m[0], f"{m[1].file_name}(line {m[1].line})")
214
+ Logger.pl('{!} {R}Error:{O} %s{W}' % err)
215
+ print("")
216
+ sys.exit(1)
217
+ except Exception:
218
+ Logger.pl('{!} {R}Error:{O} %s{W}' % str(e))
219
+ print("")
220
+ sys.exit(1)
200
221
 
201
222
  def attach(self, pid: int):
202
223
  self.running = True
@@ -273,6 +294,10 @@ class Fusion(object):
273
294
  mType = jData.get('type', '').lower()
274
295
  mLevel = jData.get('level', None)
275
296
  if mType == "message":
297
+
298
+ if script_location.file_name in self._ignore_messages:
299
+ return
300
+
276
301
  msg = jData.get('message', '')
277
302
  try:
278
303
  msg = base64.b64decode(msg).decode("UTF-8")
@@ -601,7 +626,23 @@ class Fusion(object):
601
626
  if len(self._modules) > 0:
602
627
  Logger.pl("{+} Starting selected modules")
603
628
  for m in self._modules:
604
- m.start_module(db_path=Configuration.db_path)
629
+ m.start_module(
630
+ package=Configuration.package,
631
+ db_path=Configuration.db_path
632
+ )
633
+ if m.safe_name() in Configuration.ignore_messages_modules.keys():
634
+ m.suppress_messages()
635
+
636
+ self._ignore_messages = [
637
+ Path(f).name
638
+ for _, md in Configuration.ignore_messages_modules.items()
639
+ if (m := next(iter([
640
+ mi
641
+ for mi in self._modules
642
+ if mi.name == md.name
643
+ ]), None)) is not None
644
+ for f in m.js_files()
645
+ ]
605
646
 
606
647
  self.get_device()
607
648
  if self.device is not None:
@@ -8,13 +8,9 @@ import requests
8
8
  import importlib.util
9
9
  from pathlib import Path
10
10
 
11
- from typing import TYPE_CHECKING
12
-
13
11
  from .__meta__ import __version__
14
12
  from .libs.logger import Logger
15
-
16
- if TYPE_CHECKING:
17
- from .fusion import Fusion # só no type checker
13
+ from .libs.scriptlocation import ScriptLocation
18
14
 
19
15
 
20
16
  class ModuleLoaderError(Exception):
@@ -42,8 +38,11 @@ class ModuleBase(object):
42
38
  def js_files(self) -> list:
43
39
  return []
44
40
 
41
+ def suppress_messages(self):
42
+ pass
43
+
45
44
  def key_value_event(self,
46
- script_location: "Fusion.ScriptLocation" = None,
45
+ script_location: ScriptLocation = None,
47
46
  stack_trace: str = None,
48
47
  module: str = None,
49
48
  received_data: dict = None
@@ -51,7 +50,7 @@ class ModuleBase(object):
51
50
  raise Exception('Method "key_value_event" is not yet implemented.')
52
51
 
53
52
  def data_event(self,
54
- script_location: "Fusion.ScriptLocation" = None,
53
+ script_location: ScriptLocation = None,
55
54
  stack_trace: str = None,
56
55
  received_data: str = None
57
56
  ) -> bool:
@@ -0,0 +1,172 @@
1
+ /*
2
+ Documentation
3
+ https://developer.android.com/reference/android/provider/Settings
4
+
5
+ */
6
+
7
+ const SET_MODULES = {
8
+ Global: true,
9
+ Secure: true,
10
+ System: true,
11
+ };
12
+
13
+ setTimeout(function() {
14
+ Java.perform(function() {
15
+
16
+ // Bypass Settings
17
+ var androidSettings = [
18
+ ['adb_enabled', 0],
19
+ ['development_settings_enabled', 0],
20
+ ['play_protect_enabled', 1],
21
+ ['adb_enabled', 0]
22
+ ];
23
+
24
+ function settings_bypassValue(name, originalValue) {
25
+ androidSettings.forEach(function(item) {
26
+ let name = item[0];
27
+ let value = item[1];
28
+
29
+ if (name === name) {
30
+ fusion_sendMessage('D', `Bypassing android settings checking: ${name}`)
31
+ return value;
32
+ }
33
+ });
34
+ return originalValue;
35
+ }
36
+
37
+ if (SET_MODULES.System) {
38
+
39
+ fusion_sendMessage('D', "Module attached: android.provider.Settings.System");
40
+ const settingsSystem = Java.use("android.provider.Settings$System");
41
+
42
+ settingsSystem.getString.overload('android.content.ContentResolver', 'java.lang.String').implementation = function (cr, name) {
43
+ var data = this.getString.overload('android.content.ContentResolver', 'java.lang.String').call(this, cr, name);
44
+ fusion_sendKeyValueData("Settings$System.getString", [
45
+ {key: "Name", value: name},
46
+ {key: "Result", value: data}
47
+ ]);
48
+ return data
49
+ };
50
+
51
+ settingsSystem.putString.overload('android.content.ContentResolver', 'java.lang.String', 'java.lang.String').implementation = function (cr, name, value) {
52
+ fusion_sendKeyValueData("Settings$System.putString", [
53
+ {key: "Name", value: name},
54
+ {key: "Value", value: value}
55
+ ]);
56
+ return this.putString.overload('android.content.ContentResolver', 'java.lang.String', 'java.lang.String').call(this, cr, name, value);
57
+ };
58
+
59
+ settingsSystem.getUriFor.overload('java.lang.String').implementation = function (name) {
60
+ var data = this.getUriFor.overload('java.lang.String').call(this, name);
61
+ fusion_sendKeyValueData("Settings$System.getUriFor", [
62
+ {key: "Name", value: name},
63
+ {key: "Result", value: data}
64
+ ]);
65
+ return data
66
+ };
67
+
68
+ settingsSystem.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').implementation = function(cr, name, flag) {
69
+ var data = this.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').call(this, cr, name, flag);
70
+ fusion_sendKeyValueData("Settings$System.getInt", [
71
+ {key: "Name", value: name},
72
+ {key: "Flag", value: flag},
73
+ {key: "Result", value: data}
74
+ ]);
75
+
76
+ return settings_bypassValue(name, data);
77
+ }
78
+
79
+ settingsSystem.getInt.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) {
80
+ var data = this.getInt.overload('android.content.ContentResolver', 'java.lang.String').call(this, cr, name);
81
+ fusion_sendKeyValueData("Settings$System.getInt", [
82
+ {key: "Name", value: name},
83
+ {key: "Result", value: data}
84
+ ]);
85
+ return settings_bypassValue(name, data);
86
+ }
87
+
88
+ }
89
+
90
+ if (SET_MODULES.Secure) {
91
+
92
+ fusion_sendMessage('D', "Module attached: android.provider.Settings.Secure");
93
+ const settingsSecure = Java.use("android.provider.Settings$Secure");
94
+
95
+ settingsSecure.getString.overload('android.content.ContentResolver', 'java.lang.String').implementation = function (cr, name) {
96
+ var data = this.getString.overload('android.content.ContentResolver', 'java.lang.String').call(this, cr, name);
97
+ fusion_sendKeyValueData("Settings$Secure.getString", [
98
+ {key: "Name", value: name},
99
+ {key: "Result", value: data}
100
+ ]);
101
+ return data
102
+ };
103
+
104
+ settingsSecure.putString.overload('android.content.ContentResolver', 'java.lang.String', 'java.lang.String').implementation = function (cr, name, value) {
105
+ fusion_sendKeyValueData("Settings$Secure.putString", [
106
+ {key: "Name", value: name},
107
+ {key: "Value", value: value}
108
+ ]);
109
+ return this.putString.overload('android.content.ContentResolver', 'java.lang.String', 'java.lang.String').call(this, cr, name, value);
110
+ };
111
+
112
+ settingsSecure.getUriFor.overload('java.lang.String').implementation = function (name) {
113
+ var data = this.getUriFor.overload('java.lang.String').call(this, name);
114
+ fusion_sendKeyValueData("Settings$Secure.getUriFor", [
115
+ {key: "Name", value: name},
116
+ {key: "Result", value: data}
117
+ ]);
118
+ return data
119
+ };
120
+
121
+ settingsSecure.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').implementation = function(cr, name, flag) {
122
+ var data = this.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').call(this, cr, name, flag);
123
+ fusion_sendKeyValueData("Settings$Secure.getInt", [
124
+ {key: "Name", value: name},
125
+ {key: "Flag", value: flag},
126
+ {key: "Result", value: data}
127
+ ]);
128
+
129
+ return settings_bypassValue(name, data);
130
+ }
131
+
132
+ settingsSecure.getInt.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) {
133
+ var data = this.getInt.overload('android.content.ContentResolver', 'java.lang.String').call(this, cr, name);
134
+ fusion_sendKeyValueData("Settings$Secure.getInt", [
135
+ {key: "Name", value: name},
136
+ {key: "Result", value: data}
137
+ ]);
138
+ return settings_bypassValue(name, data);
139
+ }
140
+
141
+ }
142
+
143
+ if (SET_MODULES.Global) {
144
+
145
+ fusion_sendMessage('D', "Module attached: android.provider.Settings.Global");
146
+ const settingGlobal = Java.use('android.provider.Settings$Global');
147
+
148
+ settingGlobal.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').implementation = function(cr, name, flag) {
149
+ var data = this.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').call(this, cr, name, flag);
150
+ fusion_sendKeyValueData("Settings$Global.getInt", [
151
+ {key: "Name", value: name},
152
+ {key: "Flag", value: flag},
153
+ {key: "Result", value: data}
154
+ ]);
155
+ return settings_bypassValue(name, data);
156
+ }
157
+
158
+ settingGlobal.getInt.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) {
159
+ var data = this.getInt.overload('android.content.ContentResolver', 'java.lang.String').call(this, cr, name);
160
+ fusion_sendKeyValueData("Settings$Global.getInt", [
161
+ {key: "Name", value: name},
162
+ {key: "Result", value: data}
163
+ ]);
164
+ return settings_bypassValue(name, data);
165
+ }
166
+
167
+ }
168
+
169
+ fusion_sendMessage("W", "Android Settings hook module have been successfully initialized.")
170
+ });
171
+
172
+ }, 0);
@@ -0,0 +1,110 @@
1
+ import json
2
+ import os.path
3
+ from pathlib import Path
4
+ import base64
5
+ import string
6
+
7
+ from frida_fusion.libs.logger import Logger
8
+ from frida_fusion.libs.database import Database
9
+ from frida_fusion.libs.scriptlocation import ScriptLocation
10
+ from frida_fusion.module import ModuleBase
11
+
12
+
13
+ class Settings(ModuleBase):
14
+ class SettingsDB(Database):
15
+ dbName = ""
16
+
17
+ def __init__(self, db_name: str):
18
+ super().__init__(
19
+ auto_create=True,
20
+ db_name=db_name
21
+ )
22
+ self.create_db()
23
+
24
+ def create_db(self):
25
+ super().create_db()
26
+ conn = self.connect_to_db(check=False)
27
+
28
+ # definindo um cursor
29
+ cursor = conn.cursor()
30
+
31
+ # criando a tabela (schema)
32
+ cursor.execute("""
33
+ CREATE TABLE IF NOT EXISTS [android_settings] (
34
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
35
+ package TEXT NOT NULL,
36
+ module TEXT NULL,
37
+ name TEXT NULL,
38
+ flag INTEGER NULL DEFAULT (0),
39
+ data TEXT NULL,
40
+ created_date datetime not null DEFAULT (datetime('now','localtime')),
41
+ UNIQUE (module, name, flag, data)
42
+ );
43
+ """)
44
+
45
+ conn.commit()
46
+
47
+ # Must get the constraints
48
+ self.get_constraints(conn)
49
+
50
+ def __init__(self):
51
+ super().__init__('Settings', 'Hook Android Settings functions')
52
+ self._settings_db = None
53
+ self._package = None
54
+ self.mod_path = str(Path(__file__).resolve().parent)
55
+
56
+ def start_module(self, **kwargs) -> bool:
57
+ if 'db_path' not in kwargs:
58
+ raise Exception("parameter db_path not found")
59
+
60
+ self._package = kwargs['package']
61
+ self._settings_db = Settings.SettingsDB(db_name=kwargs['db_path'])
62
+ return True
63
+
64
+ def js_files(self) -> list:
65
+ return [
66
+ os.path.join(self.mod_path, "settings.js")
67
+ ]
68
+
69
+ def key_value_event(self,
70
+ script_location: ScriptLocation = None,
71
+ stack_trace: str = None,
72
+ module: str = None,
73
+ received_data: dict = None
74
+ ) -> bool:
75
+
76
+ if module in ["Settings$Secure.getString",
77
+ "Settings$Secure.putString",
78
+ "Settings$Secure.getUriFor",
79
+ "Settings$Secure.getInt",
80
+ "Settings$System.getString",
81
+ "Settings$System.putString",
82
+ "Settings$System.getUriFor",
83
+ "Settings$System.getInt",
84
+ "Settings$Global.getInt"
85
+ ]:
86
+ name = received_data.get('name', None)
87
+ flag = received_data.get('flag', 0)
88
+ value = received_data.get('value', None)
89
+ result = received_data.get('result', value)
90
+
91
+ self._settings_db.insert_ignore_one(
92
+ table_name='android_settings',
93
+ package=self._package,
94
+ module=module,
95
+ name=name,
96
+ flag=flag,
97
+ data=result
98
+ )
99
+
100
+ return True
101
+
102
+ def data_event(self,
103
+ script_location: ScriptLocation = None,
104
+ stack_trace: str = None,
105
+ received_data: str = None
106
+ ) -> bool:
107
+ #Nothing by now
108
+ return True
109
+
110
+
@@ -1,5 +1,5 @@
1
1
 
2
- const MODULES = {
2
+ const CRYPTO_MODULES = {
3
3
  KeyGenerator: true,
4
4
  KeyPairGenerator: true,
5
5
  SecretKeySpec: true,
@@ -20,7 +20,7 @@ setTimeout(function() {
20
20
 
21
21
  const System = Java.use("java.lang.System");
22
22
 
23
- if (MODULES.KeyGenerator) {
23
+ if (CRYPTO_MODULES.KeyGenerator) {
24
24
  fusion_sendMessage('*', "Module attached: javax.crypto.KeyGenerator");
25
25
  const keyGenerator = Java.use("javax.crypto.KeyGenerator");
26
26
 
@@ -54,7 +54,7 @@ setTimeout(function() {
54
54
 
55
55
  }
56
56
 
57
- if (MODULES.KeyPairGenerator) {
57
+ if (CRYPTO_MODULES.KeyPairGenerator) {
58
58
  fusion_sendMessage('*', "Module attached: java.security.KeyPairGenerator");
59
59
  const keyPairGenerator = Java.use("java.security.KeyPairGenerator");
60
60
  keyPairGenerator.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -81,7 +81,7 @@ setTimeout(function() {
81
81
  };
82
82
  }
83
83
 
84
- if (MODULES.SecretKeySpec) {
84
+ if (CRYPTO_MODULES.SecretKeySpec) {
85
85
  fusion_sendMessage('*', "Module attached: javax.crypto.spec.SecretKeySpec");
86
86
  const secretKeySpec = Java.use("javax.crypto.spec.SecretKeySpec");
87
87
  secretKeySpec.$init.overload("[B", "java.lang.String").implementation = function (key, cipher) {
@@ -95,7 +95,7 @@ setTimeout(function() {
95
95
  }
96
96
  }
97
97
 
98
- if (MODULES.MessageDigest) {
98
+ if (CRYPTO_MODULES.MessageDigest) {
99
99
  fusion_sendMessage('*', "Module attached: java.security.MessageDigest");
100
100
  const messageDigest = Java.use("java.security.MessageDigest");
101
101
  messageDigest.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -144,7 +144,7 @@ setTimeout(function() {
144
144
 
145
145
  }
146
146
 
147
- if (MODULES.SecretKeyFactory) {
147
+ if (CRYPTO_MODULES.SecretKeyFactory) {
148
148
  fusion_sendMessage('*', "Module attached: javax.crypto.SecretKeyFactory");
149
149
  const secretKeyFactory = Java.use("javax.crypto.SecretKeyFactory");
150
150
  secretKeyFactory.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -171,7 +171,7 @@ setTimeout(function() {
171
171
  };
172
172
  }
173
173
 
174
- if (MODULES.Signature) {
174
+ if (CRYPTO_MODULES.Signature) {
175
175
  fusion_sendMessage('*', "Module attached: java.security.Signature");
176
176
  const signature = Java.use("java.security.Signature");
177
177
  signature.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -198,7 +198,7 @@ setTimeout(function() {
198
198
  };
199
199
  }
200
200
 
201
- if (MODULES.Cipher) {
201
+ if (CRYPTO_MODULES.Cipher) {
202
202
  fusion_sendMessage('*', "Module attached: javax.crypto.Cipher");
203
203
  var iv_parameter_spec = Java.use("javax.crypto.spec.IvParameterSpec");
204
204
  var pbe_parameter_spec = Java.use("javax.crypto.spec.PBEParameterSpec");
@@ -365,7 +365,7 @@ setTimeout(function() {
365
365
  }
366
366
 
367
367
 
368
- if (MODULES.Mac) {
368
+ if (CRYPTO_MODULES.Mac) {
369
369
  fusion_sendMessage('*', "Module attached: javax.crypto.Mac");
370
370
  const mac = Java.use("javax.crypto.Mac");
371
371
  mac.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -392,7 +392,7 @@ setTimeout(function() {
392
392
  };
393
393
  }
394
394
 
395
- if (MODULES.KeyGenParameterSpec) {
395
+ if (CRYPTO_MODULES.KeyGenParameterSpec) {
396
396
  fusion_sendMessage('*', "Module attached: android.security.keystore.KeyGenParameterSpec$Builder");
397
397
  const useKeyGen = Java.use("android.security.keystore.KeyGenParameterSpec$Builder");
398
398
  useKeyGen.$init.overload("java.lang.String", "int").implementation = function (keyStoreAlias, purpose) {
@@ -466,7 +466,7 @@ setTimeout(function() {
466
466
  }
467
467
  }
468
468
 
469
- if (MODULES.IvParameterSpec) {
469
+ if (CRYPTO_MODULES.IvParameterSpec) {
470
470
  fusion_sendMessage('*', "Module attached: javax.crypto.spec.IvParameterSpec");
471
471
  const ivParameter = Java.use("javax.crypto.spec.IvParameterSpec");
472
472
  ivParameter.$init.overload("[B").implementation = function (ivKey) {
@@ -488,7 +488,7 @@ setTimeout(function() {
488
488
  }
489
489
  }
490
490
 
491
- if (MODULES.GCMParameterSpec) {
491
+ if (CRYPTO_MODULES.GCMParameterSpec) {
492
492
  fusion_sendMessage('*', "Module attached: javax.crypto.spec.GCMParameterSpec");
493
493
  const gcmParameter = Java.use("javax.crypto.spec.GCMParameterSpec");
494
494
  gcmParameter.$init.overload("int", "[B").implementation = function (tLen, ivKey) {
@@ -512,7 +512,7 @@ setTimeout(function() {
512
512
  }
513
513
  }
514
514
 
515
- if (MODULES.PBEParameterSpec) {
515
+ if (CRYPTO_MODULES.PBEParameterSpec) {
516
516
  fusion_sendMessage('*', "Module attached: javax.crypto.spec.PBEParameterSpec");
517
517
  const pbeParameter = Java.use("javax.crypto.spec.PBEParameterSpec");
518
518
  pbeParameter.$init.overload("[B", "int").implementation = function (salt, iterationCount) {
@@ -547,7 +547,7 @@ setTimeout(function() {
547
547
  }
548
548
  }
549
549
 
550
- if (MODULES.X509EncodedKeySpec) {
550
+ if (CRYPTO_MODULES.X509EncodedKeySpec) {
551
551
  fusion_sendMessage('*', "Module attached: java.security.spec.X509EncodedKeySpec");
552
552
  const x509EncodedKeySpec = Java.use("java.security.spec.X509EncodedKeySpec");
553
553
  x509EncodedKeySpec.$init.overload("[B").implementation = function (encodedKey) {
@@ -32,6 +32,7 @@ class Crypto(ModuleBase):
32
32
  cursor.execute("""
33
33
  CREATE TABLE IF NOT EXISTS [crypto] (
34
34
  id INTEGER PRIMARY KEY AUTOINCREMENT,
35
+ package TEXT NOT NULL,
35
36
  hashcode TEXT NOT NULL,
36
37
  algorithm TEXT NULL,
37
38
  init_key TEXT NULL,
@@ -52,6 +53,7 @@ class Crypto(ModuleBase):
52
53
  cursor.execute("""
53
54
  CREATE TABLE IF NOT EXISTS [crypto_key] (
54
55
  id INTEGER PRIMARY KEY AUTOINCREMENT,
56
+ package TEXT NOT NULL,
55
57
  key TEXT NULL,
56
58
  printable_key TEXT NULL,
57
59
  salt TEXT NULL,
@@ -59,7 +61,7 @@ class Crypto(ModuleBase):
59
61
  key_class TEXT NULL DEFAULT ('<unknown>'),
60
62
  additional_data TEXT NULL,
61
63
  created_date datetime not null DEFAULT (datetime('now','localtime')),
62
- UNIQUE (key, key_class)
64
+ UNIQUE (package, key, key_class)
63
65
  );
64
66
  """)
65
67
 
@@ -68,6 +70,7 @@ class Crypto(ModuleBase):
68
70
  cursor.execute("""
69
71
  CREATE TABLE IF NOT EXISTS [digest] (
70
72
  id INTEGER PRIMARY KEY AUTOINCREMENT,
73
+ package TEXT NOT NULL,
71
74
  algorithm TEXT NOT NULL,
72
75
  hashcode TEXT NULL,
73
76
  clear_text TEXT NULL,
@@ -98,7 +101,7 @@ class Crypto(ModuleBase):
98
101
 
99
102
  def update_crypto(self, iv=None, hashcode=None, flow=None, key=None, before_final=None,
100
103
  after_final=None, stack_trace=None, id=None, algorithm=None,
101
- status=None):
104
+ status=None, package=None):
102
105
 
103
106
  conn = self.connect_to_db(check=False)
104
107
  cursor = conn.cursor()
@@ -124,6 +127,12 @@ class Crypto(ModuleBase):
124
127
 
125
128
  data = []
126
129
  update = "update [crypto] set "
130
+
131
+ if package is not None:
132
+ integrity = True
133
+ update += " package = ?,"
134
+ data.append(package)
135
+
127
136
  if iv is not None:
128
137
  integrity = True
129
138
  update += " iv = ?,"
@@ -213,7 +222,7 @@ class Crypto(ModuleBase):
213
222
 
214
223
  conn.close()
215
224
 
216
- def insert_digest(self, hashcode, algorithm, data_input, data_output, stack_trace):
225
+ def insert_digest(self, package, hashcode, algorithm, data_input, data_output, stack_trace):
217
226
 
218
227
  conn = self.connect_to_db(check=False)
219
228
 
@@ -243,9 +252,9 @@ class Crypto(ModuleBase):
243
252
 
244
253
  cursor = conn.cursor()
245
254
  cursor.execute("""
246
- insert into [digest] ([hashcode], [algorithm], [clear_text], [clear_text_b64], [hash_b64], [hash_hex], [stack_trace])
247
- VALUES (?,?,?,?,?,?,?);
248
- """, (hashcode, algorithm, clear_text, clear_text_b64, hash_b64, hash_hex, stack_trace,))
255
+ insert into [digest] ([package], [hashcode], [algorithm], [clear_text], [clear_text_b64], [hash_b64], [hash_hex], [stack_trace])
256
+ VALUES (?,?,?,?,?,?,?,?);
257
+ """, (package, hashcode, algorithm, clear_text, clear_text_b64, hash_b64, hash_hex, stack_trace,))
249
258
 
250
259
  conn.commit()
251
260
 
@@ -253,13 +262,14 @@ class Crypto(ModuleBase):
253
262
 
254
263
  # Color.pl('{+} {W}Inserindo crypto. {C}Algorithm: {O}%s{W}' % algorithm)
255
264
 
256
- def insert_crypto(self, hashcode, algorithm, init_key):
265
+ def insert_crypto(self, package, hashcode, algorithm, init_key):
257
266
 
258
267
  if hashcode is None:
259
268
  return
260
269
 
261
270
  rows = self.select(
262
271
  table_name='crypto',
272
+ package=package,
263
273
  hashcode=hashcode,
264
274
  status='open'
265
275
  )
@@ -280,6 +290,7 @@ class Crypto(ModuleBase):
280
290
  if init_key is not None and init_key != '' and init_key != 'IA==':
281
291
  self.insert_one(
282
292
  table_name='crypto',
293
+ package=package,
283
294
  hashcode=hashcode,
284
295
  algorithm=algorithm,
285
296
  init_key=init_key,
@@ -287,15 +298,17 @@ class Crypto(ModuleBase):
287
298
  else:
288
299
  self.insert_one(
289
300
  table_name='crypto',
301
+ package=package,
290
302
  hashcode=hashcode,
291
303
  algorithm=algorithm,
292
304
  status='open')
293
305
 
294
- def insert_crypto_key(self, key, key_class, salt=None,
306
+ def insert_crypto_key(self, package, key, key_class, salt=None,
295
307
  iteration_count=0, module="<unknown>", additional_data=dict):
296
308
  if key is not None and key != '' and key != 'IA==':
297
309
  self.insert_ignore_one(
298
310
  table_name='crypto_key',
311
+ package=package,
299
312
  key=key,
300
313
  printable_key=self.get_printable(key),
301
314
  key_class=key_class,
@@ -309,13 +322,16 @@ class Crypto(ModuleBase):
309
322
 
310
323
  def __init__(self):
311
324
  super().__init__('Crypto', 'Hook cryptography/hashing functions')
325
+ self._package = None
312
326
  self._crypto_db = None
327
+ self._suppress_messages = False
313
328
  self.mod_path = str(Path(__file__).resolve().parent)
314
329
 
315
330
  def start_module(self, **kwargs) -> bool:
316
331
  if 'db_path' not in kwargs:
317
332
  raise Exception("parameter db_path not found")
318
333
 
334
+ self._package = kwargs['package']
319
335
  self._crypto_db = Crypto.CryptoDB(db_name=kwargs['db_path'])
320
336
  return True
321
337
 
@@ -324,6 +340,9 @@ class Crypto(ModuleBase):
324
340
  os.path.join(self.mod_path, "crypto.js")
325
341
  ]
326
342
 
343
+ def suppress_messages(self):
344
+ self._suppress_messages = True
345
+
327
346
  def key_value_event(self,
328
347
  script_location: ScriptLocation = None,
329
348
  stack_trace: str = None,
@@ -347,6 +366,7 @@ class Crypto(ModuleBase):
347
366
  iteration_count = received_data.get('iteration_count', None)
348
367
 
349
368
  self._crypto_db.insert_crypto_key(
369
+ package=self._package,
350
370
  key=key,
351
371
  key_class=key_class,
352
372
  salt=salt,
@@ -361,11 +381,13 @@ class Crypto(ModuleBase):
361
381
  hashcode = received_data.get('hashcode', None)
362
382
  key_class = received_data.get('classtype', "SecretKeySpec")
363
383
  self._crypto_db.insert_crypto(
384
+ package=self._package,
364
385
  hashcode=hashcode,
365
386
  algorithm=algorithm,
366
387
  init_key=key)
367
388
 
368
389
  self._crypto_db.insert_crypto_key(
390
+ package=self._package,
369
391
  key=key,
370
392
  key_class=key_class,
371
393
  module=module,
@@ -375,10 +397,24 @@ class Crypto(ModuleBase):
375
397
  elif module == "IvParameterSpec.init":
376
398
  bData = received_data.get('iv_key', None)
377
399
  key_class = received_data.get('classtype', "IvParameterSpec")
378
- # print("IV: %s" % bData)
400
+
401
+ offset = received_data.get('offset', None)
402
+ length = received_data.get('length', None)
403
+ if offset is not None and length is not None:
404
+ try:
405
+ offset = int(offset)
406
+ length = int(length)
407
+ if isinstance(bData, str):
408
+ bData = base64.b64decode(bData)
409
+ if offset + length <= len(bData):
410
+ bData = base64.b64encode(bData[offset:offset+length]).decode("UTF-8")
411
+ except:
412
+ pass
413
+
379
414
  self._crypto_db.update_crypto(iv=bData)
380
415
 
381
416
  self._crypto_db.insert_crypto_key(
417
+ package=self._package,
382
418
  key=bData,
383
419
  key_class=key_class,
384
420
  module=module,
@@ -393,12 +429,14 @@ class Crypto(ModuleBase):
393
429
  algorithm = received_data.get('algorithm', None)
394
430
 
395
431
  self._crypto_db.insert_crypto(
432
+ package=self._package,
396
433
  hashcode=hashcode,
397
434
  algorithm=algorithm,
398
435
  init_key=key
399
436
  )
400
437
 
401
438
  self._crypto_db.update_crypto(
439
+ package=self._package,
402
440
  hashcode=hashcode,
403
441
  flow='enc' if 'encrypt' in opmode else ('dec' if 'decrypt' in opmode else str(opmode)),
404
442
  key=key,
@@ -406,28 +444,32 @@ class Crypto(ModuleBase):
406
444
  )
407
445
 
408
446
  self._crypto_db.insert_crypto_key(
447
+ package=self._package,
409
448
  key=key,
410
449
  key_class=key_class,
411
450
  module=module,
412
451
  additional_data=received_data
413
452
  )
414
453
 
415
- Logger.print_message(
416
- level="W",
417
- message=f"Cipher init received\nHashcode: {hashcode}\nOpmode: {opmode}\nKeytype: {key_class}",
418
- script_location=script_location
419
- )
454
+ if not self._suppress_messages:
455
+ Logger.print_message(
456
+ level="W",
457
+ message=f"Cipher init received\nHashcode: {hashcode}\nOpmode: {opmode}\nKeytype: {key_class}",
458
+ script_location=script_location
459
+ )
420
460
 
421
461
  elif module == "cipher.doFinal":
422
462
  hashcode = received_data.get('hashcode', None)
423
463
 
424
464
  self._crypto_db.insert_crypto(
465
+ package=self._package,
425
466
  hashcode=hashcode,
426
467
  algorithm=None,
427
468
  init_key=None
428
469
  )
429
470
 
430
471
  self._crypto_db.update_crypto(
472
+ package=self._package,
431
473
  hashcode=hashcode,
432
474
  before_final=received_data.get('input', ''),
433
475
  after_final=received_data.get('output', ''),
@@ -435,24 +477,25 @@ class Crypto(ModuleBase):
435
477
  status="complete"
436
478
  )
437
479
 
438
- Logger.print_message(
439
- level="D",
440
- message=f"Cipher doFinal received\n{stack_trace}",
441
- script_location=script_location
442
- )
480
+ if not self._suppress_messages:
481
+ Logger.print_message(
482
+ level="D",
483
+ message=f"Cipher doFinal received\n{stack_trace}",
484
+ script_location=script_location
485
+ )
443
486
 
444
487
  elif module == "messageDigest.update":
445
488
  hashcode = received_data.get('hashcode', None)
446
489
  algorithm = received_data.get('algorithm', None)
447
490
  bInput = received_data.get('input', None)
448
- self._crypto_db.insert_digest(hashcode, algorithm, bInput, None, stack_trace=stack_trace)
491
+ self._crypto_db.insert_digest(self._package, hashcode, algorithm, bInput, None, stack_trace=stack_trace)
449
492
 
450
493
  elif module == "messageDigest.digest":
451
494
  hashcode = received_data.get('hashcode', None)
452
495
  algorithm = received_data.get('algorithm', None)
453
496
  bInput = received_data.get('input', None) # Se não existir teve um messageDigest.update antes
454
497
  bOutput = received_data.get('output', None)
455
- self._crypto_db.insert_digest(hashcode, algorithm, bInput, bOutput, stack_trace=stack_trace)
498
+ self._crypto_db.insert_digest(self._package, hashcode, algorithm, bInput, bOutput, stack_trace=stack_trace)
456
499
 
457
500
  hash_hex = ""
458
501
  if bOutput is not None:
@@ -465,12 +508,13 @@ class Crypto(ModuleBase):
465
508
  pass
466
509
 
467
510
  # Do not print TLS certificate verification hash
468
- if 'com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain' not in stack_trace:
469
- Logger.print_message(
470
- level="D",
471
- message=f"Message digest\nAlgorithm: {algorithm}\nHash: {hash_hex}\n{stack_trace}",
472
- script_location=script_location
473
- )
511
+ if not self._suppress_messages:
512
+ if 'com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain' not in stack_trace:
513
+ Logger.print_message(
514
+ level="D",
515
+ message=f"Message digest\nAlgorithm: {algorithm}\nHash: {hash_hex}\n{stack_trace}",
516
+ script_location=script_location
517
+ )
474
518
 
475
519
  return True
476
520
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frida-fusion
3
- Version: 0.1.10
3
+ Version: 0.1.12
4
4
  Summary: Hook your mobile tests with Frida
5
5
  Author-email: "Helvio Junior (M4v3r1ck)" <helvio_junior@hotmail.com>
6
6
  Maintainer-email: "Helvio Junior (M4v3r1ck)" <helvio_junior@hotmail.com>
@@ -22,6 +22,9 @@ frida_fusion/libs/helpers.js
22
22
  frida_fusion/libs/logger.py
23
23
  frida_fusion/libs/scriptlocation.py
24
24
  frida_fusion/modules/__init__.py
25
+ frida_fusion/modules/android_setings/__init__.py
26
+ frida_fusion/modules/android_setings/settings.js
27
+ frida_fusion/modules/android_setings/settings.py
25
28
  frida_fusion/modules/crypto/__init__.py
26
29
  frida_fusion/modules/crypto/crypto.js
27
30
  frida_fusion/modules/crypto/crypto.py
File without changes
File without changes
File without changes
File without changes