frida-fusion 0.1.9__tar.gz → 0.1.11__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.9 → frida_fusion-0.1.11}/PKG-INFO +1 -1
  2. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/__meta__.py +2 -2
  3. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/fusion.py +23 -3
  4. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/libs/database.py +11 -0
  5. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/libs/helpers.js +29 -0
  6. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/libs/logger.py +1 -1
  7. frida_fusion-0.1.11/frida_fusion/modules/android_setings/settings.js +172 -0
  8. frida_fusion-0.1.11/frida_fusion/modules/android_setings/settings.py +106 -0
  9. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/modules/crypto/crypto.js +41 -48
  10. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/modules/crypto/crypto.py +185 -66
  11. frida_fusion-0.1.11/frida_fusion/modules/tls_unpinning/__init__.py +0 -0
  12. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion.egg-info/PKG-INFO +1 -1
  13. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion.egg-info/SOURCES.txt +3 -0
  14. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/LICENSE +0 -0
  15. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/README.md +0 -0
  16. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/__init__.py +0 -0
  17. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/__main__.py +0 -0
  18. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/args.py +0 -0
  19. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/config.py +0 -0
  20. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/libs/__init__.py +0 -0
  21. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/libs/color.py +0 -0
  22. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/libs/scriptlocation.py +0 -0
  23. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/module.py +0 -0
  24. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/modules/__init__.py +0 -0
  25. {frida_fusion-0.1.9/frida_fusion/modules/crypto → frida_fusion-0.1.11/frida_fusion/modules/android_setings}/__init__.py +0 -0
  26. {frida_fusion-0.1.9/frida_fusion/modules/tls_unpinning → frida_fusion-0.1.11/frida_fusion/modules/crypto}/__init__.py +0 -0
  27. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion/modules/tls_unpinning/frida_multiple_unpinning.py +0 -0
  28. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion.egg-info/dependency_links.txt +0 -0
  29. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion.egg-info/entry_points.txt +0 -0
  30. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion.egg-info/requires.txt +0 -0
  31. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/frida_fusion.egg-info/top_level.txt +0 -0
  32. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/pyproject.toml +0 -0
  33. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/setup.cfg +0 -0
  34. {frida_fusion-0.1.9 → frida_fusion-0.1.11}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frida-fusion
3
- Version: 0.1.9
3
+ Version: 0.1.11
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.9'
1
+ __version__ = '0.1.11'
2
2
  __title__ = "Frida Fusion"
3
3
  __description__ = "📱 frida-fusion - runtime mobile exploration"
4
4
  __url__ = "https://github.com/helviojunior/frida-fusion"
5
- __build__ = 0x2c0d061
5
+ __build__ = 0xc8879a3
6
6
  __author__ = "Helvio Junior (M4v3r1ck)"
7
7
  __author_email__ = "helvio_junior@hotmail.com"
8
8
  __license__ = "GPL-3.0"
@@ -194,9 +194,29 @@ class Fusion(object):
194
194
  s.on("message", self.make_handler("fusion_bundle.js")) # register the message handler
195
195
  s.load()
196
196
  except Exception as e:
197
- Logger.pl('{!} {R}Error:{O} %s{W}' % str(e))
198
- print("")
199
- sys.exit(1)
197
+
198
+ try:
199
+ err = str(e)
200
+ pattern = re.compile(r'script\(line (\d+)\):')
201
+ matches = [
202
+ (
203
+ m.group(0),
204
+ self.translate_location(dict(
205
+ file_name="fusion_bundle.js",
206
+ line=m.group(1),
207
+ ))
208
+ )
209
+ for m in pattern.finditer(err)
210
+ ]
211
+ for m in matches:
212
+ err = err.replace(m[0], f"{m[1].file_name}(line {m[1].line})")
213
+ Logger.pl('{!} {R}Error:{O} %s{W}' % err)
214
+ print("")
215
+ sys.exit(1)
216
+ except Exception:
217
+ Logger.pl('{!} {R}Error:{O} %s{W}' % str(e))
218
+ print("")
219
+ sys.exit(1)
200
220
 
201
221
  def attach(self, pid: int):
202
222
  self.running = True
@@ -81,6 +81,17 @@ class Database(object):
81
81
  conn.execute(sql, values)
82
82
  conn.commit()
83
83
 
84
+ @connect
85
+ def insert_if_not_exists(self, conn: Connection, table_name, **kwargs):
86
+ table_name = self.scrub(table_name)
87
+
88
+ if self.select_count(table_name=table_name, **kwargs) == 0:
89
+ (columns, values) = self.parse_args(kwargs)
90
+ sql = "INSERT INTO {} ({}) VALUES ({})" \
91
+ .format(table_name, ','.join(columns), ', '.join(['?'] * len(columns)))
92
+ conn.execute(sql, values)
93
+ conn.commit()
94
+
84
95
  @connect
85
96
  def insert_ignore_one(self, conn: Connection, table_name, **kwargs):
86
97
  table_name = self.scrub(table_name)
@@ -214,6 +214,35 @@ function fusion_printMethods(targetClass)
214
214
  });
215
215
  }
216
216
 
217
+ function fusion_getClassName(obj)
218
+ {
219
+ if (obj === null || obj === undefined) return "";
220
+
221
+ try {
222
+ // Caso seja um objeto Java real
223
+ if (obj.$className !== undefined) {
224
+ // Objetos instanciados via Java.use
225
+ return obj.$className;
226
+ }
227
+
228
+ // Caso seja uma instância Java (não necessariamente via Java.use)
229
+ if (Java.isJavaObject(obj)) {
230
+ return obj.getClass().getName();
231
+ }
232
+
233
+ // Caso seja uma classe Java carregada (Java.use)
234
+ if (Java.isJavaClass(obj)) {
235
+ return obj.class.getName();
236
+ }
237
+
238
+ // Se for algo não Java, apenas retorna tipo do JS
239
+ return typeof obj;
240
+ } catch (err) {
241
+ fusion_sendMessage("W", err);
242
+ return '';
243
+ }
244
+
245
+ }
217
246
 
218
247
  Java.perform(function () {
219
248
  const Thread = Java.use('java.lang.Thread');
@@ -41,7 +41,7 @@ class Logger(object):
41
41
  if Logger.out_file != '':
42
42
  try:
43
43
  with open(Logger.out_file, "a") as text_file:
44
- text_file.write(Color.sc(text) + '\n')
44
+ text_file.write(Color.escape_ansi(Color.sc(text)) + '\n')
45
45
  except:
46
46
  pass
47
47
 
@@ -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 ${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,106 @@
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
+ module TEXT NULL,
36
+ name TEXT NULL,
37
+ flag INTEGER NULL DEFAULT (0),
38
+ data TEXT NULL,
39
+ created_date datetime not null DEFAULT (datetime('now','localtime')),
40
+ UNIQUE (module, name, flag, data)
41
+ );
42
+ """)
43
+
44
+ conn.commit()
45
+
46
+ # Must get the constraints
47
+ self.get_constraints(conn)
48
+
49
+ def __init__(self):
50
+ super().__init__('Settings', 'Hook Android Settings functions')
51
+ self._settings_db = None
52
+ self.mod_path = str(Path(__file__).resolve().parent)
53
+
54
+ def start_module(self, **kwargs) -> bool:
55
+ if 'db_path' not in kwargs:
56
+ raise Exception("parameter db_path not found")
57
+
58
+ self._settings_db = Settings.SettingsDB(db_name=kwargs['db_path'])
59
+ return True
60
+
61
+ def js_files(self) -> list:
62
+ return [
63
+ os.path.join(self.mod_path, "settings.js")
64
+ ]
65
+
66
+ def key_value_event(self,
67
+ script_location: ScriptLocation = None,
68
+ stack_trace: str = None,
69
+ module: str = None,
70
+ received_data: dict = None
71
+ ) -> bool:
72
+
73
+ if module in ["Settings$Secure.getString",
74
+ "Settings$Secure.putString",
75
+ "Settings$Secure.getUriFor",
76
+ "Settings$Secure.getInt",
77
+ "Settings$System.getString",
78
+ "Settings$System.putString",
79
+ "Settings$System.getUriFor",
80
+ "Settings$System.getInt",
81
+ "Settings$Global.getInt"
82
+ ]:
83
+ name = received_data.get('name', None)
84
+ flag = received_data.get('flag', 0)
85
+ value = received_data.get('value', None)
86
+ result = received_data.get('result', value)
87
+
88
+ self._settings_db.insert_ignore_one(
89
+ table_name='android_settings',
90
+ module=module,
91
+ name=name,
92
+ flag=flag,
93
+ data=result
94
+ )
95
+
96
+ return True
97
+
98
+ def data_event(self,
99
+ script_location: ScriptLocation = None,
100
+ stack_trace: str = None,
101
+ received_data: str = None
102
+ ) -> bool:
103
+ #Nothing by now
104
+ return True
105
+
106
+
@@ -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,20 +81,21 @@ 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) {
88
88
  const keyBase64 = fusion_bytesToBase64(key);
89
- fusion_sendKeyValueData("secretKeySpec.init", [
89
+ fusion_sendKeyValueData("SecretKeySpec.init", [
90
90
  {key: "Key", value: keyBase64},
91
- {key: "Algorithm", value: cipher}
91
+ {key: "Algorithm", value: cipher},
92
+ {key: "ClassType", value: fusion_getClassName(this)}
92
93
  ]);
93
94
  return secretKeySpec.$init.overload("[B", "java.lang.String").call(this, key, cipher);
94
95
  }
95
96
  }
96
97
 
97
- if (MODULES.MessageDigest) {
98
+ if (CRYPTO_MODULES.MessageDigest) {
98
99
  fusion_sendMessage('*', "Module attached: java.security.MessageDigest");
99
100
  const messageDigest = Java.use("java.security.MessageDigest");
100
101
  messageDigest.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -141,42 +142,20 @@ setTimeout(function() {
141
142
  return output;
142
143
  };
143
144
 
144
- /*
145
- messageDigest.digest.overload("[B").implementation = function (input) {
146
- const inputBase64 = fusion_bytesToBase64(input);
147
- fusion_sendKeyValueData("messageDigest.digest", [
148
- {key: "Input", value: inputBase64},
149
- {key: "Algorithm", value: this.getAlgorithm()}
150
- ]);
151
- return this.digest.overload("[B").call(this, input);
152
- };
153
-
154
- messageDigest.digest.overload("[B", "int", "int").implementation = function (input, offset, len) {
155
- const inputBase64 = fusion_bytesToBase64(input);
156
- fusion_sendKeyValueData("messageDigest.digest", [
157
- {key: "Input", value: inputBase64},
158
- {key: "Algorithm", value: this.getAlgorithm()},
159
- {key: "Offset", value: offset},
160
- {key: "Length", value: len}
161
- ]);
162
- return this.digest.overload("[B", "int", "int").call(this, input, offset, len);
163
- };*/
164
-
165
-
166
145
  }
167
146
 
168
- if (MODULES.SecretKeyFactory) {
147
+ if (CRYPTO_MODULES.SecretKeyFactory) {
169
148
  fusion_sendMessage('*', "Module attached: javax.crypto.SecretKeyFactory");
170
149
  const secretKeyFactory = Java.use("javax.crypto.SecretKeyFactory");
171
150
  secretKeyFactory.getInstance.overload("java.lang.String").implementation = function (arg0) {
172
- fusion_sendKeyValueData("secretKeyFactory.getInstance", [
151
+ fusion_sendKeyValueData("SecretKeyFactory.getInstance", [
173
152
  {key: "Algorithm", value: arg0}
174
153
  ]);
175
154
  return this.getInstance(arg0);
176
155
  };
177
156
 
178
157
  secretKeyFactory.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
179
- fusion_sendKeyValueData("secretKeyFactory.getInstance", [
158
+ fusion_sendKeyValueData("SecretKeyFactory.getInstance", [
180
159
  {key: "Algorithm", value: arg0},
181
160
  {key: "Provider", value: arg1}
182
161
  ]);
@@ -184,7 +163,7 @@ setTimeout(function() {
184
163
  };
185
164
 
186
165
  secretKeyFactory.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
187
- fusion_sendKeyValueData("secretKeyFactory.getInstance", [
166
+ fusion_sendKeyValueData("SecretKeyFactory.getInstance", [
188
167
  {key: "Algorithm", value: arg0},
189
168
  {key: "Provider", value: arg1}
190
169
  ]);
@@ -192,7 +171,7 @@ setTimeout(function() {
192
171
  };
193
172
  }
194
173
 
195
- if (MODULES.Signature) {
174
+ if (CRYPTO_MODULES.Signature) {
196
175
  fusion_sendMessage('*', "Module attached: java.security.Signature");
197
176
  const signature = Java.use("java.security.Signature");
198
177
  signature.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -219,7 +198,7 @@ setTimeout(function() {
219
198
  };
220
199
  }
221
200
 
222
- if (MODULES.Cipher) {
201
+ if (CRYPTO_MODULES.Cipher) {
223
202
  fusion_sendMessage('*', "Module attached: javax.crypto.Cipher");
224
203
  var iv_parameter_spec = Java.use("javax.crypto.spec.IvParameterSpec");
225
204
  var pbe_parameter_spec = Java.use("javax.crypto.spec.PBEParameterSpec");
@@ -229,6 +208,7 @@ setTimeout(function() {
229
208
  fusion_sendKeyValueData("cipher.init", [
230
209
  {key: "HashCode", value: this.hashCode().toString()},
231
210
  {key: "Key", value: fusion_keyToBase64(key)},
211
+ {key: "KeyType", value: fusion_getClassName(key)},
232
212
  {key: "Opmode", value: this.getOpmodeString(opmode)},
233
213
  {key: "Algorithm", value: this.getAlgorithm()}
234
214
  ]);
@@ -238,7 +218,9 @@ setTimeout(function() {
238
218
  cipher.init.overload("int", "java.security.cert.Certificate").implementation = function (opmode, certificate) {
239
219
  fusion_sendKeyValueData("cipher.init", [
240
220
  {key: "HashCode", value: this.hashCode().toString()},
221
+ {key: "Key", value: fusion_keyToBase64(certificate)},
241
222
  {key: "Certificate", value: fusion_keyToBase64(certificate)},
223
+ {key: "KeyType", value: fusion_getClassName(certificate)},
242
224
  {key: "Opmode", value: this.getOpmodeString(opmode)},
243
225
  {key: "Algorithm", value: this.getAlgorithm()}
244
226
  ]);
@@ -249,6 +231,7 @@ setTimeout(function() {
249
231
  fusion_sendKeyValueData("cipher.init", [
250
232
  {key: "HashCode", value: this.hashCode().toString()},
251
233
  {key: "Key", value: fusion_keyToBase64(key)},
234
+ {key: "KeyType", value: fusion_getClassName(key)},
252
235
  {key: "Opmode", value: this.getOpmodeString(opmode)},
253
236
  {key: "Algorithm", value: this.getAlgorithm()}
254
237
  ]);
@@ -261,6 +244,7 @@ setTimeout(function() {
261
244
  var data = [
262
245
  {key: "HashCode", value: this.hashCode().toString()},
263
246
  {key: "Key", value: fusion_keyToBase64(key)},
247
+ {key: "KeyType", value: fusion_getClassName(key)},
264
248
  {key: "Opmode", value: this.getOpmodeString(opmode)},
265
249
  {key: "Algorithm", value: this.getAlgorithm()}
266
250
  ];
@@ -381,7 +365,7 @@ setTimeout(function() {
381
365
  }
382
366
 
383
367
 
384
- if (MODULES.Mac) {
368
+ if (CRYPTO_MODULES.Mac) {
385
369
  fusion_sendMessage('*', "Module attached: javax.crypto.Mac");
386
370
  const mac = Java.use("javax.crypto.Mac");
387
371
  mac.getInstance.overload("java.lang.String").implementation = function (arg0) {
@@ -408,7 +392,7 @@ setTimeout(function() {
408
392
  };
409
393
  }
410
394
 
411
- if (MODULES.KeyGenParameterSpec) {
395
+ if (CRYPTO_MODULES.KeyGenParameterSpec) {
412
396
  fusion_sendMessage('*', "Module attached: android.security.keystore.KeyGenParameterSpec$Builder");
413
397
  const useKeyGen = Java.use("android.security.keystore.KeyGenParameterSpec$Builder");
414
398
  useKeyGen.$init.overload("java.lang.String", "int").implementation = function (keyStoreAlias, purpose) {
@@ -482,12 +466,13 @@ setTimeout(function() {
482
466
  }
483
467
  }
484
468
 
485
- if (MODULES.IvParameterSpec) {
469
+ if (CRYPTO_MODULES.IvParameterSpec) {
486
470
  fusion_sendMessage('*', "Module attached: javax.crypto.spec.IvParameterSpec");
487
471
  const ivParameter = Java.use("javax.crypto.spec.IvParameterSpec");
488
472
  ivParameter.$init.overload("[B").implementation = function (ivKey) {
489
473
  fusion_sendKeyValueData("IvParameterSpec.init", [
490
- {key: "IV_Key", value: fusion_bytesToBase64(ivKey)}
474
+ {key: "IV_Key", value: fusion_bytesToBase64(ivKey)},
475
+ {key: "ClassType", value: fusion_getClassName(this)}
491
476
  ]);
492
477
  return this.$init.overload("[B").call(this, ivKey);
493
478
  }
@@ -496,19 +481,21 @@ setTimeout(function() {
496
481
  fusion_sendKeyValueData("IvParameterSpec.init", [
497
482
  {key: "IV Key", value: fusion_bytesToBase64(ivKey)},
498
483
  {key: "Offset", value: offset},
499
- {key: "Length", value: len}
484
+ {key: "Length", value: len},
485
+ {key: "ClassType", value: fusion_getClassName(this)}
500
486
  ]);
501
487
  return this.$init.overload("[B", "int", "int").call(this, ivKey, offset, len);
502
488
  }
503
489
  }
504
490
 
505
- if (MODULES.GCMParameterSpec) {
491
+ if (CRYPTO_MODULES.GCMParameterSpec) {
506
492
  fusion_sendMessage('*', "Module attached: javax.crypto.spec.GCMParameterSpec");
507
493
  const gcmParameter = Java.use("javax.crypto.spec.GCMParameterSpec");
508
494
  gcmParameter.$init.overload("int", "[B").implementation = function (tLen, ivKey) {
509
495
  fusion_sendKeyValueData("GCMParameterSpec.init", [
510
496
  {key: "IV_Key", value: fusion_bytesToBase64(ivKey)},
511
- {key: "Auth_Tag_Length", value: tLen.toString()}
497
+ {key: "Auth_Tag_Length", value: tLen.toString()},
498
+ {key: "ClassType", value: fusion_getClassName(this)}
512
499
  ]);
513
500
  return this.$init.overload("int", "[B").call(this, tLen, ivKey);
514
501
  }
@@ -518,19 +505,21 @@ setTimeout(function() {
518
505
  {key: "IV_Key", value: fusion_bytesToBase64(ivKey)},
519
506
  {key: "Auth_Tag_Length", value: tLen.toString()},
520
507
  {key: "Offset", value: offset},
521
- {key: "Length", value: len}
508
+ {key: "Length", value: len},
509
+ {key: "ClassType", value: fusion_getClassName(this)}
522
510
  ]);
523
511
  return this.$init.overload("int", "[B", "int", "int").call(this, tLen, ivKey, offset, len);
524
512
  }
525
513
  }
526
514
 
527
- if (MODULES.PBEParameterSpec) {
515
+ if (CRYPTO_MODULES.PBEParameterSpec) {
528
516
  fusion_sendMessage('*', "Module attached: javax.crypto.spec.PBEParameterSpec");
529
517
  const pbeParameter = Java.use("javax.crypto.spec.PBEParameterSpec");
530
518
  pbeParameter.$init.overload("[B", "int").implementation = function (salt, iterationCount) {
531
519
  fusion_sendKeyValueData("PBEParameterSpec.init", [
532
520
  {key: "PBE_Salt", value: fusion_bytesToBase64(salt)},
533
- {key: "Iteration_Count", value: iterationCount.toString()}
521
+ {key: "Iteration_Count", value: iterationCount.toString()},
522
+ {key: "ClassType", value: fusion_getClassName(this)},
534
523
  ]);
535
524
  return this.$init.overload("[B", "int").call(this, salt, iterationCount);
536
525
  }
@@ -539,7 +528,8 @@ setTimeout(function() {
539
528
 
540
529
  var data = [
541
530
  {key: "PBE_Salt", value: fusion_bytesToBase64(salt)},
542
- {key: "Iteration_Count", value: iterationCount.toString()}
531
+ {key: "Iteration_Count", value: iterationCount.toString()},
532
+ {key: "ClassType", value: fusion_getClassName(this)}
543
533
 
544
534
  ]
545
535
 
@@ -547,6 +537,7 @@ setTimeout(function() {
547
537
  data = data.concat([
548
538
  {key: "Algorithm", value: paramSpec.getAlgorithm()},
549
539
  {key: "ParamSpec", value: fusion_keyToBase64(paramSpec)},
540
+ {key: "ParamSpecType", value: fusion_getClassName(paramSpec)},
550
541
  {key: "Provider", value: paramSpec.getProvider()}
551
542
  ]);
552
543
  } catch (err) { }
@@ -556,12 +547,14 @@ setTimeout(function() {
556
547
  }
557
548
  }
558
549
 
559
- if (MODULES.X509EncodedKeySpec) {
550
+ if (CRYPTO_MODULES.X509EncodedKeySpec) {
560
551
  fusion_sendMessage('*', "Module attached: java.security.spec.X509EncodedKeySpec");
561
552
  const x509EncodedKeySpec = Java.use("java.security.spec.X509EncodedKeySpec");
562
553
  x509EncodedKeySpec.$init.overload("[B").implementation = function (encodedKey) {
563
554
  fusion_sendKeyValueData("X509EncodedKeySpec.init", [
564
- {key: "Key", value: fusion_bytesToBase64(encodedKey)}
555
+ {key: "Key", value: fusion_bytesToBase64(encodedKey)},
556
+ {key: "ClassType", value: fusion_getClassName(this)}
557
+
565
558
  ]);
566
559
  return this.$init.overload("[B").call(this, encodedKey);
567
560
  }
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import os.path
2
3
  from pathlib import Path
3
4
  import base64
@@ -31,10 +32,10 @@ class Crypto(ModuleBase):
31
32
  cursor.execute("""
32
33
  CREATE TABLE IF NOT EXISTS [crypto] (
33
34
  id INTEGER PRIMARY KEY AUTOINCREMENT,
34
- algorithm TEXT NOT NULL,
35
- init_key TEXT NOT NULL,
35
+ hashcode TEXT NOT NULL,
36
+ algorithm TEXT NULL,
37
+ init_key TEXT NULL,
36
38
  iv TEXT NULL,
37
- hashcode TEXT NULL,
38
39
  flow TEXT NULL,
39
40
  key TEXT NULL,
40
41
  clear_text TEXT NULL,
@@ -48,6 +49,22 @@ class Crypto(ModuleBase):
48
49
 
49
50
  conn.commit()
50
51
 
52
+ cursor.execute("""
53
+ CREATE TABLE IF NOT EXISTS [crypto_key] (
54
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
55
+ key TEXT NULL,
56
+ printable_key TEXT NULL,
57
+ salt TEXT NULL,
58
+ iteration_count INTEGER NULL DEFAULT (0),
59
+ key_class TEXT NULL DEFAULT ('<unknown>'),
60
+ additional_data TEXT NULL,
61
+ created_date datetime not null DEFAULT (datetime('now','localtime')),
62
+ UNIQUE (key, key_class)
63
+ );
64
+ """)
65
+
66
+ conn.commit()
67
+
51
68
  cursor.execute("""
52
69
  CREATE TABLE IF NOT EXISTS [digest] (
53
70
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -80,7 +97,8 @@ class Crypto(ModuleBase):
80
97
  return ''
81
98
 
82
99
  def update_crypto(self, iv=None, hashcode=None, flow=None, key=None, before_final=None,
83
- after_final=None, stack_trace=None, id=None):
100
+ after_final=None, stack_trace=None, id=None, algorithm=None,
101
+ status=None):
84
102
 
85
103
  conn = self.connect_to_db(check=False)
86
104
  cursor = conn.cursor()
@@ -116,6 +134,11 @@ class Crypto(ModuleBase):
116
134
  update += " hashcode = ?,"
117
135
  data.append(hashcode)
118
136
 
137
+ if flow is not None:
138
+ integrity = True
139
+ update += " algorithm = ?,"
140
+ data.append(algorithm)
141
+
119
142
  if flow is not None:
120
143
  integrity = True
121
144
  update += " flow = ?,"
@@ -136,6 +159,11 @@ class Crypto(ModuleBase):
136
159
  update += " stack_trace = ?,"
137
160
  data.append(stack_trace)
138
161
 
162
+ if status is not None:
163
+ integrity = True
164
+ update += " status = ?,"
165
+ data.append(status)
166
+
139
167
  if before_final is not None:
140
168
  integrity = True
141
169
  if dbflow == "enc":
@@ -169,6 +197,16 @@ class Crypto(ModuleBase):
169
197
 
170
198
  cursor.execute(update, data)
171
199
 
200
+ cursor = conn.cursor()
201
+ cursor.execute("""
202
+ delete from [crypto]
203
+ where algorithm is null and init_key is null and key is null and clear_text is null
204
+ and hashcode in (
205
+ select hashcode from [crypto]
206
+ where id = ?
207
+ )
208
+ """, (id,))
209
+
172
210
  conn.commit()
173
211
 
174
212
  # Color.pl('{+} {W}Crypto atualizada. {C}ID: {O}%s{W}' % id)
@@ -215,56 +253,59 @@ class Crypto(ModuleBase):
215
253
 
216
254
  # Color.pl('{+} {W}Inserindo crypto. {C}Algorithm: {O}%s{W}' % algorithm)
217
255
 
218
- def insert_crypto(self, algorithm, init_key):
219
-
220
- conn = self.connect_to_db(check=False)
221
-
222
- cursor = conn.cursor()
223
- cursor.execute("""
224
- update [crypto] set status = 'incomplete' where status = 'open';
225
- """)
226
-
227
- cursor = conn.cursor()
228
- cursor.execute("""
229
- insert into [crypto] ([algorithm], [init_key])
230
- VALUES (?,?);
231
- """, (algorithm, init_key,))
232
-
233
- conn.commit()
234
-
235
- conn.close()
236
-
237
- # Color.pl('{+} {W}Inserindo crypto. {C}Algorithm: {O}%s{W}' % algorithm)
238
-
239
- def insert_crypto2(self, algorithm, key, iv, clear_text, cipher_data, flow='enc'):
240
-
241
- conn = self.connect_to_db(check=False)
242
-
243
- if isinstance(clear_text, bytes):
244
- clear_text = clear_text.decode("UTF-8")
245
-
246
- if isinstance(cipher_data, bytes):
247
- cipher_data = cipher_data.decode("UTF-8")
248
-
249
- if isinstance(key, bytes):
250
- key = base64.b64encode(key).decode("UTF-8")
251
-
252
- if isinstance(iv, bytes):
253
- iv = base64.b64encode(iv).decode("UTF-8")
256
+ def insert_crypto(self, hashcode, algorithm, init_key):
254
257
 
255
- clear_text_b64 = base64.b64encode(clear_text.encode("UTF-8")).decode("UTF-8")
258
+ if hashcode is None:
259
+ return
256
260
 
257
- cursor = conn.cursor()
258
- cursor.execute("""
259
- insert into [crypto] ([flow], [algorithm], [init_key], [key], [iv], [clear_text], [clear_text_b64], [cipher_data], [status])
260
- VALUES (?,?,?,?,?,?,?,?,?);
261
- """, (flow, algorithm, key, key, iv, clear_text, clear_text_b64, cipher_data, 'complete',))
262
-
263
- conn.commit()
264
-
265
- conn.close()
266
-
267
- # Color.pl('{+} {W}Inserindo crypto. {C}Algorithm: {O}%s{W}' % algorithm)
261
+ rows = self.select(
262
+ table_name='crypto',
263
+ hashcode=hashcode,
264
+ status='open'
265
+ )
266
+ if len(rows) == 0 or not any(iter([
267
+ True
268
+ for r in rows
269
+ if (
270
+ (algorithm is not None and algorithm == r['algorithm'])
271
+ or (r['algorithm'] is None or r['algorithm'].strip() == "")
272
+ ) and (
273
+ (
274
+ (init_key is not None and init_key != '' and init_key != 'IA==')
275
+ and (init_key == r['init_key'] or init_key == r['key'])
276
+ )
277
+ or (r['init_key'] is None or r['init_key'].strip() == "")
278
+ )
279
+ ])):
280
+ if init_key is not None and init_key != '' and init_key != 'IA==':
281
+ self.insert_one(
282
+ table_name='crypto',
283
+ hashcode=hashcode,
284
+ algorithm=algorithm,
285
+ init_key=init_key,
286
+ status='open')
287
+ else:
288
+ self.insert_one(
289
+ table_name='crypto',
290
+ hashcode=hashcode,
291
+ algorithm=algorithm,
292
+ status='open')
293
+
294
+ def insert_crypto_key(self, key, key_class, salt=None,
295
+ iteration_count=0, module="<unknown>", additional_data=dict):
296
+ if key is not None and key != '' and key != 'IA==':
297
+ self.insert_ignore_one(
298
+ table_name='crypto_key',
299
+ key=key,
300
+ printable_key=self.get_printable(key),
301
+ key_class=key_class,
302
+ salt=salt,
303
+ iteration_count=iteration_count,
304
+ additional_data=json.dumps({
305
+ **{"module": module},
306
+ **(additional_data if additional_data is not None and isinstance(additional_data, dict) else {})
307
+ }, default=Logger.json_serial)
308
+ )
268
309
 
269
310
  def __init__(self):
270
311
  super().__init__('Crypto', 'Hook cryptography/hashing functions')
@@ -290,31 +331,109 @@ class Crypto(ModuleBase):
290
331
  received_data: dict = None
291
332
  ) -> bool:
292
333
 
293
- if module == "secretKeySpec.init":
334
+ if module in ["X509EncodedKeySpec.init", "GCMParameterSpec.init", "PBEParameterSpec.init"]:
335
+
336
+ key_class = received_data.get('classtype', module)
337
+ salt = None
338
+ iteration_count = 0
339
+
340
+ key = received_data.get('key', None)
341
+ if module == "GCMParameterSpec.init":
342
+ key = received_data.get('iv_key', None)
343
+
344
+ if module == "PBEParameterSpec.init":
345
+ key = "None"
346
+ salt = received_data.get('pbe_salt', None)
347
+ iteration_count = received_data.get('iteration_count', None)
348
+
349
+ self._crypto_db.insert_crypto_key(
350
+ key=key,
351
+ key_class=key_class,
352
+ salt=salt,
353
+ iteration_count=iteration_count,
354
+ module=module,
355
+ additional_data=received_data
356
+ )
357
+
358
+ if module == "SecretKeySpec.init":
294
359
  algorithm = received_data.get('algorithm', None)
295
- bData = received_data.get('key', None)
296
- self._crypto_db.insert_crypto(algorithm, bData)
360
+ key = received_data.get('key', None)
361
+ hashcode = received_data.get('hashcode', None)
362
+ key_class = received_data.get('classtype', "SecretKeySpec")
363
+ self._crypto_db.insert_crypto(
364
+ hashcode=hashcode,
365
+ algorithm=algorithm,
366
+ init_key=key)
367
+
368
+ self._crypto_db.insert_crypto_key(
369
+ key=key,
370
+ key_class=key_class,
371
+ module=module,
372
+ additional_data=received_data
373
+ )
297
374
 
298
375
  elif module == "IvParameterSpec.init":
299
376
  bData = received_data.get('iv_key', None)
377
+ key_class = received_data.get('classtype', "IvParameterSpec")
300
378
  # print("IV: %s" % bData)
301
- self._crypto_db.update_crypto(bData)
379
+ self._crypto_db.update_crypto(iv=bData)
380
+
381
+ self._crypto_db.insert_crypto_key(
382
+ key=bData,
383
+ key_class=key_class,
384
+ module=module,
385
+ additional_data=received_data
386
+ )
302
387
 
303
388
  elif module == "cipher.init":
304
389
  hashcode = received_data.get('hashcode', None)
305
390
  opmode = received_data.get('opmode', "")
306
- if 'encrypt' in opmode:
307
- self._crypto_db.update_crypto(None, hashcode, 'enc')
308
- elif 'decrypt' in opmode:
309
- self._crypto_db.update_crypto(None, hashcode, 'dec')
391
+ key_class = received_data.get('keytype', "")
392
+ key = received_data.get('key', None)
393
+ algorithm = received_data.get('algorithm', None)
394
+
395
+ self._crypto_db.insert_crypto(
396
+ hashcode=hashcode,
397
+ algorithm=algorithm,
398
+ init_key=key
399
+ )
400
+
401
+ self._crypto_db.update_crypto(
402
+ hashcode=hashcode,
403
+ flow='enc' if 'encrypt' in opmode else ('dec' if 'decrypt' in opmode else str(opmode)),
404
+ key=key,
405
+ algorithm=algorithm
406
+ )
407
+
408
+ self._crypto_db.insert_crypto_key(
409
+ key=key,
410
+ key_class=key_class,
411
+ module=module,
412
+ additional_data=received_data
413
+ )
414
+
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
+ )
310
420
 
311
421
  elif module == "cipher.doFinal":
312
- self._crypto_db.update_crypto(None, None, None, None,
313
- received_data.get('input', ''),
314
- stack_trace=stack_trace)
315
- self._crypto_db.update_crypto(None, None, None, None, None,
316
- received_data.get('output', ''),
317
- stack_trace=stack_trace)
422
+ hashcode = received_data.get('hashcode', None)
423
+
424
+ self._crypto_db.insert_crypto(
425
+ hashcode=hashcode,
426
+ algorithm=None,
427
+ init_key=None
428
+ )
429
+
430
+ self._crypto_db.update_crypto(
431
+ hashcode=hashcode,
432
+ before_final=received_data.get('input', ''),
433
+ after_final=received_data.get('output', ''),
434
+ stack_trace=stack_trace,
435
+ status="complete"
436
+ )
318
437
 
319
438
  Logger.print_message(
320
439
  level="D",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frida-fusion
3
- Version: 0.1.9
3
+ Version: 0.1.11
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