frida-fusion 0.1.8__tar.gz → 0.1.9__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.
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/PKG-INFO +41 -3
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/README.md +40 -2
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/__meta__.py +2 -2
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/fusion.py +11 -7
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/libs/helpers.js +65 -86
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/modules/crypto/crypto.js +99 -100
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion.egg-info/PKG-INFO +41 -3
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/LICENSE +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/__init__.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/__main__.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/args.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/config.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/libs/__init__.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/libs/color.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/libs/database.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/libs/logger.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/libs/scriptlocation.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/module.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/modules/__init__.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/modules/crypto/__init__.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/modules/crypto/crypto.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/modules/tls_unpinning/__init__.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion/modules/tls_unpinning/frida_multiple_unpinning.py +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion.egg-info/SOURCES.txt +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion.egg-info/dependency_links.txt +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion.egg-info/entry_points.txt +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion.egg-info/requires.txt +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/frida_fusion.egg-info/top_level.txt +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/pyproject.toml +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/setup.cfg +0 -0
- {frida_fusion-0.1.8 → frida_fusion-0.1.9}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frida-fusion
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
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>
|
|
@@ -73,6 +73,43 @@ Modules:
|
|
|
73
73
|
pip3 install frida-fusion
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
## Custom Frida script
|
|
77
|
+
|
|
78
|
+
You must provide a custom Frida script as usual. To do this you must provide `-s/--script-path` parameter.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Just one file
|
|
82
|
+
frida-fusion -f [app_id] -U --script-path mytest.js
|
|
83
|
+
|
|
84
|
+
# A entire directory
|
|
85
|
+
frida-fusion -f [app_id] -U --script-path /tmp/scripts
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Exposed JavaScript (frida) functions
|
|
89
|
+
|
|
90
|
+
The Frida Fusion define/expose several functions to be used at frida scripts. Follows the typedef of these functions.
|
|
91
|
+
|
|
92
|
+
```java
|
|
93
|
+
# Send message/data to Frida-Fusion
|
|
94
|
+
void fusion_sendMessage(String level, String message);
|
|
95
|
+
void fusion_sendMessageWithTrace(String level, String message);
|
|
96
|
+
void fusion_sendKeyValueData(String module, Object items);
|
|
97
|
+
|
|
98
|
+
# Print StackTrace
|
|
99
|
+
void fusion_printStackTrace();
|
|
100
|
+
|
|
101
|
+
# Print all methods of class 'name'
|
|
102
|
+
void fusion_printMethods(String name);
|
|
103
|
+
|
|
104
|
+
# Wait until the class 'name' exists in memory to execute the callback function
|
|
105
|
+
void fusion_waitForClass(String name, CallbackFunction onReady)
|
|
106
|
+
|
|
107
|
+
# Conversions
|
|
108
|
+
byte[] fusion_stringToBase64(String message);
|
|
109
|
+
String fusion_bytesToBase64(byte[] byteArray);
|
|
110
|
+
String fusion_encodeHex(byte[] byteArray);
|
|
111
|
+
```
|
|
112
|
+
|
|
76
113
|
## Module engine
|
|
77
114
|
|
|
78
115
|
You can check available modules with `frida-fusion --list-modules` command.
|
|
@@ -104,7 +141,7 @@ export FUSION_MODULES=/tmp/modules
|
|
|
104
141
|
frida-fusion --list-modules
|
|
105
142
|
|
|
106
143
|
# Using available module
|
|
107
|
-
frida-fusion -f [app_id] -U --script-path . -m [module_name]
|
|
144
|
+
frida-fusion -f [app_id] -U --script-path mytest.js -m [module_name]
|
|
108
145
|
```
|
|
109
146
|
|
|
110
147
|
At windows:
|
|
@@ -116,7 +153,7 @@ $env:FUSION_MODULES = "C:\extra_mods"
|
|
|
116
153
|
frida-fusion --list-modules
|
|
117
154
|
|
|
118
155
|
# Using available module
|
|
119
|
-
frida-fusion -f [app_id] -U --script-path . -m [module_name]
|
|
156
|
+
frida-fusion -f [app_id] -U --script-path mytest.js -m [module_name]
|
|
120
157
|
```
|
|
121
158
|
|
|
122
159
|
### Community modules
|
|
@@ -131,3 +168,4 @@ export FUSION_MODULES=/tmp/frida-fusion-community-modules
|
|
|
131
168
|
# List all modules
|
|
132
169
|
frida-fusion --list-modules
|
|
133
170
|
```
|
|
171
|
+
|
|
@@ -38,6 +38,43 @@ Modules:
|
|
|
38
38
|
pip3 install frida-fusion
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
## Custom Frida script
|
|
42
|
+
|
|
43
|
+
You must provide a custom Frida script as usual. To do this you must provide `-s/--script-path` parameter.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Just one file
|
|
47
|
+
frida-fusion -f [app_id] -U --script-path mytest.js
|
|
48
|
+
|
|
49
|
+
# A entire directory
|
|
50
|
+
frida-fusion -f [app_id] -U --script-path /tmp/scripts
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Exposed JavaScript (frida) functions
|
|
54
|
+
|
|
55
|
+
The Frida Fusion define/expose several functions to be used at frida scripts. Follows the typedef of these functions.
|
|
56
|
+
|
|
57
|
+
```java
|
|
58
|
+
# Send message/data to Frida-Fusion
|
|
59
|
+
void fusion_sendMessage(String level, String message);
|
|
60
|
+
void fusion_sendMessageWithTrace(String level, String message);
|
|
61
|
+
void fusion_sendKeyValueData(String module, Object items);
|
|
62
|
+
|
|
63
|
+
# Print StackTrace
|
|
64
|
+
void fusion_printStackTrace();
|
|
65
|
+
|
|
66
|
+
# Print all methods of class 'name'
|
|
67
|
+
void fusion_printMethods(String name);
|
|
68
|
+
|
|
69
|
+
# Wait until the class 'name' exists in memory to execute the callback function
|
|
70
|
+
void fusion_waitForClass(String name, CallbackFunction onReady)
|
|
71
|
+
|
|
72
|
+
# Conversions
|
|
73
|
+
byte[] fusion_stringToBase64(String message);
|
|
74
|
+
String fusion_bytesToBase64(byte[] byteArray);
|
|
75
|
+
String fusion_encodeHex(byte[] byteArray);
|
|
76
|
+
```
|
|
77
|
+
|
|
41
78
|
## Module engine
|
|
42
79
|
|
|
43
80
|
You can check available modules with `frida-fusion --list-modules` command.
|
|
@@ -69,7 +106,7 @@ export FUSION_MODULES=/tmp/modules
|
|
|
69
106
|
frida-fusion --list-modules
|
|
70
107
|
|
|
71
108
|
# Using available module
|
|
72
|
-
frida-fusion -f [app_id] -U --script-path . -m [module_name]
|
|
109
|
+
frida-fusion -f [app_id] -U --script-path mytest.js -m [module_name]
|
|
73
110
|
```
|
|
74
111
|
|
|
75
112
|
At windows:
|
|
@@ -81,7 +118,7 @@ $env:FUSION_MODULES = "C:\extra_mods"
|
|
|
81
118
|
frida-fusion --list-modules
|
|
82
119
|
|
|
83
120
|
# Using available module
|
|
84
|
-
frida-fusion -f [app_id] -U --script-path . -m [module_name]
|
|
121
|
+
frida-fusion -f [app_id] -U --script-path mytest.js -m [module_name]
|
|
85
122
|
```
|
|
86
123
|
|
|
87
124
|
### Community modules
|
|
@@ -96,3 +133,4 @@ export FUSION_MODULES=/tmp/frida-fusion-community-modules
|
|
|
96
133
|
# List all modules
|
|
97
134
|
frida-fusion --list-modules
|
|
98
135
|
```
|
|
136
|
+
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
__version__ = '0.1.
|
|
1
|
+
__version__ = '0.1.9'
|
|
2
2
|
__title__ = "Frida Fusion"
|
|
3
3
|
__description__ = "📱 frida-fusion - runtime mobile exploration"
|
|
4
4
|
__url__ = "https://github.com/helviojunior/frida-fusion"
|
|
5
|
-
__build__ =
|
|
5
|
+
__build__ = 0x2c0d061
|
|
6
6
|
__author__ = "Helvio Junior (M4v3r1ck)"
|
|
7
7
|
__author_email__ = "helvio_junior@hotmail.com"
|
|
8
8
|
__license__ = "GPL-3.0"
|
|
@@ -167,14 +167,14 @@ class Fusion(object):
|
|
|
167
167
|
else:
|
|
168
168
|
Logger.pl("{*} Loading script file " + file_name)
|
|
169
169
|
for r in ["*", "-", "+", "!"]:
|
|
170
|
-
file_data = file_data.replace(f"console.log('[{r}] ", f"
|
|
171
|
-
file_data = file_data.replace(f'console.log("[{r}] ', f'
|
|
172
|
-
file_data = file_data.replace(f"console.log('[{r}]", f"
|
|
173
|
-
file_data = file_data.replace(f'console.log("[{r}]', f'
|
|
170
|
+
file_data = file_data.replace(f"console.log('[{r}] ", f"fusion_sendMessage('{r}', '")
|
|
171
|
+
file_data = file_data.replace(f'console.log("[{r}] ', f'fusion_sendMessage("{r}", "')
|
|
172
|
+
file_data = file_data.replace(f"console.log('[{r}]", f"fusion_sendMessage('{r}', '")
|
|
173
|
+
file_data = file_data.replace(f'console.log("[{r}]', f'fusion_sendMessage("{r}", "')
|
|
174
174
|
|
|
175
|
-
file_data = re.sub(r'(?<!\w)send\(', '
|
|
175
|
+
file_data = re.sub(r'(?<!\w)send\(', 'fusion_Send(', file_data)
|
|
176
176
|
|
|
177
|
-
file_data = file_data.replace(f'console.log(', f'
|
|
177
|
+
file_data = file_data.replace(f'console.log(', f'fusion_sendMessage("I", ')
|
|
178
178
|
file_data += "\n\n"
|
|
179
179
|
|
|
180
180
|
line_cnt = len(file_data.split("\n")) - 1
|
|
@@ -371,7 +371,11 @@ class Fusion(object):
|
|
|
371
371
|
for m in matches:
|
|
372
372
|
stack = stack.replace(m[0], f"{m[1].file_name}:{m[1].line}")
|
|
373
373
|
|
|
374
|
-
if script_location.file_name == "
|
|
374
|
+
if script_location.file_name == "fusion_bundle.js" and len(matches) >= 1:
|
|
375
|
+
script_location.file_name = matches[0][1].file_name
|
|
376
|
+
script_location.line = matches[0][1].line
|
|
377
|
+
|
|
378
|
+
elif script_location.file_name == "class-factory.js" and len(matches) == 1:
|
|
375
379
|
script_location.file_name = matches[0][1].file_name
|
|
376
380
|
script_location.line = matches[0][1].line
|
|
377
381
|
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Author:
|
|
1
|
+
/* Frida Fusion helper functions
|
|
2
|
+
Author: Helvio Junior - M4v3r1ck
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
function fusion_Send(payload1, payload2){
|
|
6
|
+
const info = fusion_getCallerInfo();
|
|
7
|
+
send({
|
|
8
|
+
payload: payload1,
|
|
9
|
+
location: info
|
|
10
|
+
}, payload2);
|
|
11
|
+
}
|
|
5
12
|
|
|
6
|
-
function
|
|
13
|
+
function fusion_waitForClass(name, onReady) {
|
|
7
14
|
var intv = setInterval(function () {
|
|
8
15
|
try {
|
|
9
16
|
var C = Java.use(name);
|
|
@@ -13,24 +20,24 @@ function waitForClass(name, onReady) {
|
|
|
13
20
|
}, 100);
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
function
|
|
23
|
+
function fusion_printStackTrace(){
|
|
17
24
|
var trace = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
|
|
18
25
|
trace = trace.replace("java.lang.Exception\n", "Stack trace:\n");
|
|
19
|
-
|
|
26
|
+
fusion_sendMessage("I", trace);
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
function
|
|
29
|
+
function fusion_toBytes(message){
|
|
23
30
|
try{
|
|
24
31
|
const StringClass = Java.use('java.lang.String');
|
|
25
32
|
var bTxt = StringClass.$new(message).getBytes('utf-8');
|
|
26
33
|
|
|
27
34
|
return bTxt;
|
|
28
35
|
} catch (err) {
|
|
29
|
-
|
|
36
|
+
fusion_sendMessage("W", err)
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
function
|
|
40
|
+
function fusion_stringToBase64(message){
|
|
34
41
|
try{
|
|
35
42
|
const StringClass = Java.use('java.lang.String');
|
|
36
43
|
const Base64Class = Java.use('android.util.Base64');
|
|
@@ -39,19 +46,19 @@ function toBase64(message){
|
|
|
39
46
|
|
|
40
47
|
return b64Msg;
|
|
41
48
|
} catch (err) {
|
|
42
|
-
|
|
49
|
+
fusion_sendMessage("W", err)
|
|
43
50
|
}
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
function
|
|
53
|
+
function fusion_bytesToBase64(byteArray){
|
|
47
54
|
|
|
48
|
-
if (
|
|
55
|
+
if (byteArray === null || byteArray === undefined) return "IA==";
|
|
49
56
|
try {
|
|
50
57
|
// 1) Confirma tipo byte[], se não tenta converter em string
|
|
51
|
-
|
|
58
|
+
byteArray = Java.array('byte', byteArray);
|
|
52
59
|
|
|
53
60
|
// 2) Tem 'length' numérico
|
|
54
|
-
const len =
|
|
61
|
+
const len = byteArray.length;
|
|
55
62
|
if (typeof len !== "number") return "IA==";
|
|
56
63
|
|
|
57
64
|
// 3) (opcional) Exigir conteúdo
|
|
@@ -64,16 +71,16 @@ function bytesToBase64(message){
|
|
|
64
71
|
try{
|
|
65
72
|
|
|
66
73
|
const Base64Class = Java.use('android.util.Base64');
|
|
67
|
-
var b64Msg = Base64Class.encodeToString(
|
|
74
|
+
var b64Msg = Base64Class.encodeToString(byteArray, 0x00000002); //Base64Class.NO_WRAP = 0x00000002
|
|
68
75
|
|
|
69
76
|
return b64Msg;
|
|
70
77
|
} catch (err) {
|
|
71
|
-
|
|
78
|
+
fusion_sendMessage("W", err)
|
|
72
79
|
return "IA==";
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
function
|
|
83
|
+
function fusion_getCallerInfo() {
|
|
77
84
|
try{
|
|
78
85
|
const stack = new Error().stack.split("\n");
|
|
79
86
|
|
|
@@ -89,9 +96,9 @@ function getCallerInfo() {
|
|
|
89
96
|
const file = m[2];
|
|
90
97
|
const ln = parseInt(m[3], 10);
|
|
91
98
|
|
|
92
|
-
//
|
|
99
|
+
// Ignore helper functions (with name "send")
|
|
93
100
|
if (/^send/i.test(func)) continue;
|
|
94
|
-
if (/^
|
|
101
|
+
if (/^fusion_Send/i.test(func)) continue;
|
|
95
102
|
|
|
96
103
|
return { file_name: file, function_name: func, line: ln };
|
|
97
104
|
}
|
|
@@ -102,29 +109,8 @@ function getCallerInfo() {
|
|
|
102
109
|
return null;
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
function
|
|
106
|
-
|
|
107
|
-
const info = getCallerInfo();
|
|
108
|
-
send({
|
|
109
|
-
payload: payload1,
|
|
110
|
-
location: info
|
|
111
|
-
}, payload2);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
//sendMessage("*", err)
|
|
114
|
-
console.log(`Error: ${err}`)
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function sendData(mType, jData, bData){
|
|
119
|
-
//iSend('{"type" : "'+ mType +'", "jdata" : "'+ jData +'"}', bData);
|
|
120
|
-
iSend({
|
|
121
|
-
type: mType,
|
|
122
|
-
jdata: jData
|
|
123
|
-
}, bData)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function sendKeyValueData(module, items) {
|
|
127
|
-
var st = getB64StackTrace();
|
|
112
|
+
function fusion_sendKeyValueData(module, items) {
|
|
113
|
+
var st = fusion_getB64StackTrace();
|
|
128
114
|
|
|
129
115
|
var data = [];
|
|
130
116
|
|
|
@@ -133,67 +119,75 @@ function sendKeyValueData(module, items) {
|
|
|
133
119
|
data = data.concat([{key: `${items[i].key}`, value:`${items[i].value}`}]);
|
|
134
120
|
}
|
|
135
121
|
|
|
136
|
-
|
|
122
|
+
fusion_Send({
|
|
137
123
|
type: "key_value_data",
|
|
138
124
|
module: module,
|
|
139
125
|
data: data,
|
|
140
126
|
stack_trace: st
|
|
141
127
|
}, null);
|
|
142
128
|
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function fusion_sendMessage(level, message){
|
|
132
|
+
try{
|
|
133
|
+
const StringClass = Java.use('java.lang.String');
|
|
134
|
+
const Base64Class = Java.use('android.util.Base64');
|
|
135
|
+
var bTxt = StringClass.$new(message).getBytes('utf-8');
|
|
136
|
+
var b64Msg = Base64Class.encodeToString(bTxt, 0x00000002); //Base64Class.NO_WRAP = 0x00000002
|
|
143
137
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
138
|
+
//send('{"type" : "message", "level" : "'+ level +'", "message" : "'+ b64Msg +'"}');
|
|
139
|
+
fusion_Send({
|
|
140
|
+
type: "message",
|
|
141
|
+
level: level,
|
|
142
|
+
message: b64Msg
|
|
143
|
+
}, null)
|
|
144
|
+
} catch (err) {
|
|
145
|
+
fusion_sendMessage("W", err)
|
|
151
146
|
}
|
|
152
|
-
jData += `], "stack_trace": "${st}"}`;
|
|
153
|
-
iSend(jData, "");
|
|
154
|
-
*/
|
|
155
147
|
}
|
|
156
148
|
|
|
157
|
-
function
|
|
149
|
+
function fusion_sendMessageWithTrace(level, message){
|
|
158
150
|
try{
|
|
159
151
|
const StringClass = Java.use('java.lang.String');
|
|
160
152
|
const Base64Class = Java.use('android.util.Base64');
|
|
153
|
+
|
|
154
|
+
var trace = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
|
|
155
|
+
trace = trace.replace("java.lang.Exception\n", "Stack trace:\n");
|
|
156
|
+
message += "\n"
|
|
157
|
+
message += trace
|
|
158
|
+
|
|
161
159
|
var bTxt = StringClass.$new(message).getBytes('utf-8');
|
|
162
160
|
var b64Msg = Base64Class.encodeToString(bTxt, 0x00000002); //Base64Class.NO_WRAP = 0x00000002
|
|
163
161
|
|
|
164
162
|
//send('{"type" : "message", "level" : "'+ level +'", "message" : "'+ b64Msg +'"}');
|
|
165
|
-
|
|
163
|
+
fusion_Send({
|
|
166
164
|
type: "message",
|
|
167
165
|
level: level,
|
|
168
166
|
message: b64Msg
|
|
169
167
|
}, null)
|
|
170
168
|
} catch (err) {
|
|
171
|
-
|
|
172
|
-
//sendMessage('-', 'secret_key_spec.$init.overload error: ' + err + '\n' + err.stack);
|
|
169
|
+
fusion_sendMessage("W", err)
|
|
173
170
|
}
|
|
174
171
|
}
|
|
175
172
|
|
|
176
|
-
function
|
|
173
|
+
function fusion_sendError(error) {
|
|
177
174
|
try{
|
|
178
|
-
|
|
175
|
+
fusion_sendMessage("E", error + '\n' + error.stack);
|
|
179
176
|
} catch (err) {
|
|
180
|
-
|
|
177
|
+
fusion_sendMessage("W", err)
|
|
181
178
|
}
|
|
182
179
|
}
|
|
183
180
|
|
|
184
|
-
function
|
|
181
|
+
function fusion_encodeHex(byteArray) {
|
|
185
182
|
|
|
186
183
|
const HexClass = Java.use('org.apache.commons.codec.binary.Hex');
|
|
187
184
|
const StringClass = Java.use('java.lang.String');
|
|
188
185
|
const hexChars = HexClass.encodeHex(byteArray);
|
|
189
|
-
//sendMessage("*", StringClass.$new(hexChars).toString());
|
|
190
|
-
//Buffer.from(bufStr, 'utf8');
|
|
191
|
-
//sendMessage("*", new Uint8Array(byteArray));
|
|
192
186
|
return StringClass.$new(hexChars).toString();
|
|
193
187
|
|
|
194
188
|
}
|
|
195
189
|
|
|
196
|
-
function
|
|
190
|
+
function fusion_getB64StackTrace(){
|
|
197
191
|
|
|
198
192
|
try{
|
|
199
193
|
const StringClass = Java.use('java.lang.String');
|
|
@@ -206,33 +200,18 @@ function getB64StackTrace(){
|
|
|
206
200
|
return b64Msg
|
|
207
201
|
|
|
208
202
|
} catch (err) {
|
|
209
|
-
|
|
203
|
+
fusion_sendMessage("W", err);
|
|
210
204
|
return '';
|
|
211
205
|
}
|
|
212
206
|
}
|
|
213
207
|
|
|
214
|
-
function
|
|
208
|
+
function fusion_printMethods(targetClass)
|
|
215
209
|
{
|
|
216
210
|
var hook = Java.use(targetClass);
|
|
217
211
|
var ownMethods = hook.class.getDeclaredMethods();
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return ownMethods;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function printMethods(hook)
|
|
224
|
-
{
|
|
225
|
-
var ownMethods = hook.class.getDeclaredMethods();
|
|
226
|
-
ownMethods.forEach(function(s) {
|
|
227
|
-
//sendMessage(s);
|
|
228
|
-
sendMessage('*', s);
|
|
212
|
+
ownMethods.forEach(function(s) {
|
|
213
|
+
fusion_sendMessage('I', s);
|
|
229
214
|
});
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function intToHex(intVal)
|
|
234
|
-
{
|
|
235
|
-
return intVal.toString(16);
|
|
236
215
|
}
|
|
237
216
|
|
|
238
217
|
|
|
@@ -263,7 +242,7 @@ Java.perform(function () {
|
|
|
263
242
|
Thread.setDefaultUncaughtExceptionHandler(UEH.$new());
|
|
264
243
|
});
|
|
265
244
|
|
|
266
|
-
function
|
|
245
|
+
function fusion_formatBacktrace(frames) {
|
|
267
246
|
return frames.map((addr, i) => {
|
|
268
247
|
const sym = DebugSymbol.fromAddress(addr);
|
|
269
248
|
const mod = Process.findModuleByAddress(addr);
|
|
@@ -282,7 +261,7 @@ Process.setExceptionHandler(function (details) {
|
|
|
282
261
|
frames = Thread.backtrace(details.context, Backtracer.FUZZY);
|
|
283
262
|
}
|
|
284
263
|
|
|
285
|
-
const pretty =
|
|
264
|
+
const pretty = fusion_formatBacktrace(frames);
|
|
286
265
|
|
|
287
266
|
send({
|
|
288
267
|
type: "native-exception",
|
|
@@ -302,4 +281,4 @@ Process.setExceptionHandler(function (details) {
|
|
|
302
281
|
return false;
|
|
303
282
|
});
|
|
304
283
|
|
|
305
|
-
|
|
284
|
+
fusion_sendMessage("W", "Helper functions have been successfully initialized.")
|
|
@@ -21,23 +21,23 @@ setTimeout(function() {
|
|
|
21
21
|
const System = Java.use("java.lang.System");
|
|
22
22
|
|
|
23
23
|
if (MODULES.KeyGenerator) {
|
|
24
|
-
|
|
24
|
+
fusion_sendMessage('*', "Module attached: javax.crypto.KeyGenerator");
|
|
25
25
|
const keyGenerator = Java.use("javax.crypto.KeyGenerator");
|
|
26
26
|
|
|
27
27
|
keyGenerator.generateKey.implementation = function () {
|
|
28
|
-
|
|
28
|
+
fusion_sendMessage('*', "keyGenerator.generateKey");
|
|
29
29
|
return this.generateKey();
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
keyGenerator.getInstance.overload("java.lang.String").implementation = function (arg0) {
|
|
33
|
-
|
|
33
|
+
fusion_sendKeyValueData("keyGenerator.getInstance", [
|
|
34
34
|
{key: "Algorithm", value: arg0}
|
|
35
35
|
]);
|
|
36
36
|
return this.getInstance(arg0);
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
keyGenerator.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
|
|
40
|
-
|
|
40
|
+
fusion_sendKeyValueData("keyGenerator.getInstance", [
|
|
41
41
|
{key: "Algorithm", value: arg0},
|
|
42
42
|
{key: "Provider", value: arg1}
|
|
43
43
|
]);
|
|
@@ -45,7 +45,7 @@ setTimeout(function() {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
keyGenerator.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
|
|
48
|
-
|
|
48
|
+
fusion_sendKeyValueData("keyGenerator.getInstance", [
|
|
49
49
|
{key: "Algorithm", value: arg0},
|
|
50
50
|
{key: "Provider", value: arg1}
|
|
51
51
|
]);
|
|
@@ -55,17 +55,17 @@ setTimeout(function() {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (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) {
|
|
61
|
-
|
|
61
|
+
fusion_sendKeyValueData("keyPairGenerator.getInstance", [
|
|
62
62
|
{key: "Algorithm", value: arg0}
|
|
63
63
|
]);
|
|
64
64
|
return this.getInstance(arg0);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
keyPairGenerator.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
|
|
68
|
-
|
|
68
|
+
fusion_sendKeyValueData("keyPairGenerator.getInstance", [
|
|
69
69
|
{key: "Algorithm", value: arg0},
|
|
70
70
|
{key: "Provider", value: arg1}
|
|
71
71
|
]);
|
|
@@ -73,7 +73,7 @@ setTimeout(function() {
|
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
keyPairGenerator.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
|
|
76
|
-
|
|
76
|
+
fusion_sendKeyValueData("keyPairGenerator.getInstance", [
|
|
77
77
|
{key: "Algorithm", value: arg0},
|
|
78
78
|
{key: "Provider", value: arg1}
|
|
79
79
|
]);
|
|
@@ -82,11 +82,11 @@ setTimeout(function() {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
if (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
|
-
const keyBase64 =
|
|
89
|
-
|
|
88
|
+
const keyBase64 = fusion_bytesToBase64(key);
|
|
89
|
+
fusion_sendKeyValueData("secretKeySpec.init", [
|
|
90
90
|
{key: "Key", value: keyBase64},
|
|
91
91
|
{key: "Algorithm", value: cipher}
|
|
92
92
|
]);
|
|
@@ -95,17 +95,17 @@ setTimeout(function() {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
if (MODULES.MessageDigest) {
|
|
98
|
-
|
|
98
|
+
fusion_sendMessage('*', "Module attached: java.security.MessageDigest");
|
|
99
99
|
const messageDigest = Java.use("java.security.MessageDigest");
|
|
100
100
|
messageDigest.getInstance.overload("java.lang.String").implementation = function (arg0) {
|
|
101
|
-
|
|
101
|
+
fusion_sendKeyValueData("messageDigest.getInstance", [
|
|
102
102
|
{key: "Algorithm", value: arg0}
|
|
103
103
|
]);
|
|
104
104
|
return this.getInstance(arg0);
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
messageDigest.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
|
|
108
|
-
|
|
108
|
+
fusion_sendKeyValueData("messageDigest.getInstance", [
|
|
109
109
|
{key: "Algorithm", value: arg0},
|
|
110
110
|
{key: "Provider", value: arg1}
|
|
111
111
|
]);
|
|
@@ -113,7 +113,7 @@ setTimeout(function() {
|
|
|
113
113
|
};
|
|
114
114
|
|
|
115
115
|
messageDigest.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
|
|
116
|
-
|
|
116
|
+
fusion_sendKeyValueData("messageDigest.getInstance", [
|
|
117
117
|
{key: "Algorithm", value: arg0},
|
|
118
118
|
{key: "Provider", value: arg1}
|
|
119
119
|
]);
|
|
@@ -121,8 +121,8 @@ setTimeout(function() {
|
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
messageDigest.update.overload("[B").implementation = function (input) {
|
|
124
|
-
const inputBase64 =
|
|
125
|
-
|
|
124
|
+
const inputBase64 = fusion_bytesToBase64(input);
|
|
125
|
+
fusion_sendKeyValueData("messageDigest.update", [
|
|
126
126
|
{key: "HashCode", value: System.identityHashCode(this)},
|
|
127
127
|
{key: "Input", value: inputBase64},
|
|
128
128
|
{key: "Algorithm", value: this.getAlgorithm()}
|
|
@@ -132,8 +132,8 @@ setTimeout(function() {
|
|
|
132
132
|
|
|
133
133
|
messageDigest.digest.overload().implementation = function () {
|
|
134
134
|
const output = messageDigest.digest.overload().call(this);
|
|
135
|
-
const outputBase64 =
|
|
136
|
-
|
|
135
|
+
const outputBase64 = fusion_bytesToBase64(output);
|
|
136
|
+
fusion_sendKeyValueData("messageDigest.digest", [
|
|
137
137
|
{key: "HashCode", value: System.identityHashCode(this)},
|
|
138
138
|
{key: "Output", value: outputBase64},
|
|
139
139
|
{key: "Algorithm", value: this.getAlgorithm()}
|
|
@@ -143,8 +143,8 @@ setTimeout(function() {
|
|
|
143
143
|
|
|
144
144
|
/*
|
|
145
145
|
messageDigest.digest.overload("[B").implementation = function (input) {
|
|
146
|
-
const inputBase64 =
|
|
147
|
-
|
|
146
|
+
const inputBase64 = fusion_bytesToBase64(input);
|
|
147
|
+
fusion_sendKeyValueData("messageDigest.digest", [
|
|
148
148
|
{key: "Input", value: inputBase64},
|
|
149
149
|
{key: "Algorithm", value: this.getAlgorithm()}
|
|
150
150
|
]);
|
|
@@ -152,8 +152,8 @@ setTimeout(function() {
|
|
|
152
152
|
};
|
|
153
153
|
|
|
154
154
|
messageDigest.digest.overload("[B", "int", "int").implementation = function (input, offset, len) {
|
|
155
|
-
const inputBase64 =
|
|
156
|
-
|
|
155
|
+
const inputBase64 = fusion_bytesToBase64(input);
|
|
156
|
+
fusion_sendKeyValueData("messageDigest.digest", [
|
|
157
157
|
{key: "Input", value: inputBase64},
|
|
158
158
|
{key: "Algorithm", value: this.getAlgorithm()},
|
|
159
159
|
{key: "Offset", value: offset},
|
|
@@ -166,17 +166,17 @@ setTimeout(function() {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
if (MODULES.SecretKeyFactory) {
|
|
169
|
-
|
|
169
|
+
fusion_sendMessage('*', "Module attached: javax.crypto.SecretKeyFactory");
|
|
170
170
|
const secretKeyFactory = Java.use("javax.crypto.SecretKeyFactory");
|
|
171
171
|
secretKeyFactory.getInstance.overload("java.lang.String").implementation = function (arg0) {
|
|
172
|
-
|
|
172
|
+
fusion_sendKeyValueData("secretKeyFactory.getInstance", [
|
|
173
173
|
{key: "Algorithm", value: arg0}
|
|
174
174
|
]);
|
|
175
175
|
return this.getInstance(arg0);
|
|
176
176
|
};
|
|
177
177
|
|
|
178
178
|
secretKeyFactory.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
|
|
179
|
-
|
|
179
|
+
fusion_sendKeyValueData("secretKeyFactory.getInstance", [
|
|
180
180
|
{key: "Algorithm", value: arg0},
|
|
181
181
|
{key: "Provider", value: arg1}
|
|
182
182
|
]);
|
|
@@ -184,7 +184,7 @@ setTimeout(function() {
|
|
|
184
184
|
};
|
|
185
185
|
|
|
186
186
|
secretKeyFactory.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
|
|
187
|
-
|
|
187
|
+
fusion_sendKeyValueData("secretKeyFactory.getInstance", [
|
|
188
188
|
{key: "Algorithm", value: arg0},
|
|
189
189
|
{key: "Provider", value: arg1}
|
|
190
190
|
]);
|
|
@@ -193,17 +193,17 @@ setTimeout(function() {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
if (MODULES.Signature) {
|
|
196
|
-
|
|
196
|
+
fusion_sendMessage('*', "Module attached: java.security.Signature");
|
|
197
197
|
const signature = Java.use("java.security.Signature");
|
|
198
198
|
signature.getInstance.overload("java.lang.String").implementation = function (arg0) {
|
|
199
|
-
|
|
199
|
+
fusion_sendKeyValueData("signature.getInstance", [
|
|
200
200
|
{key: "Algorithm", value: arg0}
|
|
201
201
|
]);
|
|
202
202
|
return this.getInstance(arg0);
|
|
203
203
|
};
|
|
204
204
|
|
|
205
205
|
signature.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
|
|
206
|
-
|
|
206
|
+
fusion_sendKeyValueData("signature.getInstance", [
|
|
207
207
|
{key: "Algorithm", value: arg0},
|
|
208
208
|
{key: "Provider", value: arg1}
|
|
209
209
|
]);
|
|
@@ -211,7 +211,7 @@ setTimeout(function() {
|
|
|
211
211
|
};
|
|
212
212
|
|
|
213
213
|
signature.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
|
|
214
|
-
|
|
214
|
+
fusion_sendKeyValueData("signature.getInstance", [
|
|
215
215
|
{key: "Algorithm", value: arg0},
|
|
216
216
|
{key: "Provider", value: arg1}
|
|
217
217
|
]);
|
|
@@ -220,15 +220,15 @@ setTimeout(function() {
|
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
if (MODULES.Cipher) {
|
|
223
|
-
|
|
223
|
+
fusion_sendMessage('*', "Module attached: javax.crypto.Cipher");
|
|
224
224
|
var iv_parameter_spec = Java.use("javax.crypto.spec.IvParameterSpec");
|
|
225
225
|
var pbe_parameter_spec = Java.use("javax.crypto.spec.PBEParameterSpec");
|
|
226
226
|
var gcm_parameter_spec = Java.use("javax.crypto.spec.GCMParameterSpec");
|
|
227
227
|
const cipher = Java.use("javax.crypto.Cipher");
|
|
228
228
|
cipher.init.overload("int", "java.security.Key").implementation = function (opmode, key) {
|
|
229
|
-
|
|
229
|
+
fusion_sendKeyValueData("cipher.init", [
|
|
230
230
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
231
|
-
{key: "Key", value:
|
|
231
|
+
{key: "Key", value: fusion_keyToBase64(key)},
|
|
232
232
|
{key: "Opmode", value: this.getOpmodeString(opmode)},
|
|
233
233
|
{key: "Algorithm", value: this.getAlgorithm()}
|
|
234
234
|
]);
|
|
@@ -236,9 +236,9 @@ setTimeout(function() {
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
cipher.init.overload("int", "java.security.cert.Certificate").implementation = function (opmode, certificate) {
|
|
239
|
-
|
|
239
|
+
fusion_sendKeyValueData("cipher.init", [
|
|
240
240
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
241
|
-
{key: "Certificate", value:
|
|
241
|
+
{key: "Certificate", value: fusion_keyToBase64(certificate)},
|
|
242
242
|
{key: "Opmode", value: this.getOpmodeString(opmode)},
|
|
243
243
|
{key: "Algorithm", value: this.getAlgorithm()}
|
|
244
244
|
]);
|
|
@@ -246,9 +246,9 @@ setTimeout(function() {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
cipher.init.overload("int", "java.security.Key", "java.security.AlgorithmParameters").implementation = function (opmode, key, algorithmParameter) {
|
|
249
|
-
|
|
249
|
+
fusion_sendKeyValueData("cipher.init", [
|
|
250
250
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
251
|
-
{key: "Key", value:
|
|
251
|
+
{key: "Key", value: fusion_keyToBase64(key)},
|
|
252
252
|
{key: "Opmode", value: this.getOpmodeString(opmode)},
|
|
253
253
|
{key: "Algorithm", value: this.getAlgorithm()}
|
|
254
254
|
]);
|
|
@@ -260,7 +260,7 @@ setTimeout(function() {
|
|
|
260
260
|
try{
|
|
261
261
|
var data = [
|
|
262
262
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
263
|
-
{key: "Key", value:
|
|
263
|
+
{key: "Key", value: fusion_keyToBase64(key)},
|
|
264
264
|
{key: "Opmode", value: this.getOpmodeString(opmode)},
|
|
265
265
|
{key: "Algorithm", value: this.getAlgorithm()}
|
|
266
266
|
];
|
|
@@ -270,41 +270,41 @@ setTimeout(function() {
|
|
|
270
270
|
//Cast from javax.crypto.spec.PBEParameterSpec to javax.crypto.spec.IvParameterSpec
|
|
271
271
|
try{
|
|
272
272
|
data = data.concat([
|
|
273
|
-
{key: "IV_Key", value:
|
|
273
|
+
{key: "IV_Key", value: fusion_bytesToBase64(Java.cast(z, iv_parameter_spec).getIV())}
|
|
274
274
|
]);
|
|
275
275
|
|
|
276
276
|
} catch (err) {
|
|
277
277
|
try{
|
|
278
278
|
data = data.concat([
|
|
279
|
-
{key: "PBE_Salt", value:
|
|
279
|
+
{key: "PBE_Salt", value: fusion_bytesToBase64(Java.cast(z, pbe_parameter_spec).getSalt())}
|
|
280
280
|
]);
|
|
281
281
|
} catch (err) {
|
|
282
282
|
try{
|
|
283
283
|
gcm = Java.cast(z, gcm_parameter_spec)
|
|
284
284
|
data = data.concat([
|
|
285
|
-
{key: "IV_Key", value:
|
|
285
|
+
{key: "IV_Key", value: fusion_bytesToBase64(gcm.getIV())},
|
|
286
286
|
{key: "Auth_Tag_Length", value: gcm.getTLen().toString()},
|
|
287
287
|
]);
|
|
288
288
|
} catch (err) { }
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
|
|
292
|
+
fusion_sendKeyValueData("cipher.init", data);
|
|
293
293
|
} catch (err1) {
|
|
294
|
-
|
|
294
|
+
fusion_sendError(err1)
|
|
295
295
|
}
|
|
296
296
|
this.init.overload("int", "java.security.Key", "java.security.spec.AlgorithmParameterSpec").call(this, opmode, key, algorithmParameter);
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
cipher.getInstance.overload("java.lang.String").implementation = function (arg0) {
|
|
300
|
-
|
|
300
|
+
fusion_sendKeyValueData("cipher.getInstance", [
|
|
301
301
|
{key: "Algorithm", value: arg0}
|
|
302
302
|
]);
|
|
303
303
|
return this.getInstance(arg0);
|
|
304
304
|
};
|
|
305
305
|
|
|
306
306
|
cipher.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
|
|
307
|
-
|
|
307
|
+
fusion_sendKeyValueData("cipher.getInstance", [
|
|
308
308
|
{key: "Algorithm", value: arg0},
|
|
309
309
|
{key: "Provider", value: arg1}
|
|
310
310
|
]);
|
|
@@ -312,7 +312,7 @@ setTimeout(function() {
|
|
|
312
312
|
};
|
|
313
313
|
|
|
314
314
|
cipher.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
|
|
315
|
-
|
|
315
|
+
fusion_sendKeyValueData("cipher.getInstance", [
|
|
316
316
|
{key: "Algorithm", value: arg0},
|
|
317
317
|
{key: "Provider", value: arg1}
|
|
318
318
|
]);
|
|
@@ -320,10 +320,10 @@ setTimeout(function() {
|
|
|
320
320
|
};
|
|
321
321
|
|
|
322
322
|
cipher.doFinal.overload("[B").implementation = function (arg0) {
|
|
323
|
-
const inputBase64 =
|
|
323
|
+
const inputBase64 = fusion_bytesToBase64(arg0);
|
|
324
324
|
const output = this.doFinal.overload("[B").call(this, arg0);
|
|
325
|
-
const outputBase64 =
|
|
326
|
-
|
|
325
|
+
const outputBase64 = fusion_bytesToBase64(output);
|
|
326
|
+
fusion_sendKeyValueData("cipher.doFinal", [
|
|
327
327
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
328
328
|
{key: "Input", value: inputBase64},
|
|
329
329
|
{key: "Output", value: outputBase64}
|
|
@@ -332,10 +332,10 @@ setTimeout(function() {
|
|
|
332
332
|
};
|
|
333
333
|
|
|
334
334
|
cipher.doFinal.overload("[B", "int").implementation = function (arg0, arg1) {
|
|
335
|
-
const inputBase64 =
|
|
335
|
+
const inputBase64 = fusion_bytesToBase64(arg0);
|
|
336
336
|
const output = this.doFinal.overload("[B", "int").call(this, arg0, arg1);
|
|
337
|
-
const outputBase64 =
|
|
338
|
-
|
|
337
|
+
const outputBase64 = fusion_bytesToBase64(output);
|
|
338
|
+
fusion_sendKeyValueData("cipher.doFinal", [
|
|
339
339
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
340
340
|
{key: "Input", value: inputBase64},
|
|
341
341
|
{key: "Output", value: outputBase64}
|
|
@@ -344,10 +344,10 @@ setTimeout(function() {
|
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
cipher.doFinal.overload("[B", "int", "int").implementation = function (arg0, arg1, arg2) {
|
|
347
|
-
const inputBase64 =
|
|
347
|
+
const inputBase64 = fusion_bytesToBase64(arg0);
|
|
348
348
|
const output = this.doFinal.overload("[B", "int", "int").call(this, arg0, arg1, arg2);
|
|
349
|
-
const outputBase64 =
|
|
350
|
-
|
|
349
|
+
const outputBase64 = fusion_bytesToBase64(output);
|
|
350
|
+
fusion_sendKeyValueData("cipher.doFinal", [
|
|
351
351
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
352
352
|
{key: "Input", value: inputBase64},
|
|
353
353
|
{key: "Output", value: outputBase64}
|
|
@@ -356,10 +356,10 @@ setTimeout(function() {
|
|
|
356
356
|
}
|
|
357
357
|
|
|
358
358
|
cipher.doFinal.overload("[B", "int", "int", "[B").implementation = function (arg0, arg1, arg2, arg3) {
|
|
359
|
-
const inputBase64 =
|
|
359
|
+
const inputBase64 = fusion_bytesToBase64(arg0);
|
|
360
360
|
const output = this.doFinal.overload("[B", "int", "int", "[B").call(this, arg0, arg1, arg2, arg3);
|
|
361
|
-
const outputBase64 =
|
|
362
|
-
|
|
361
|
+
const outputBase64 = fusion_bytesToBase64(output);
|
|
362
|
+
fusion_sendKeyValueData("cipher.doFinal", [
|
|
363
363
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
364
364
|
{key: "Input", value: inputBase64},
|
|
365
365
|
{key: "Output", value: outputBase64}
|
|
@@ -368,10 +368,10 @@ setTimeout(function() {
|
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
cipher.doFinal.overload("[B", "int", "int", "[B", "int").implementation = function (arg0, arg1, arg2, arg3, arg4) {
|
|
371
|
-
const inputBase64 =
|
|
371
|
+
const inputBase64 = fusion_bytesToBase64(arg0);
|
|
372
372
|
const output = this.doFinal.overload("[B", "int", "int", "[B", "int").call(this, arg0, arg1, arg2, arg3, arg4);
|
|
373
|
-
const outputBase64 =
|
|
374
|
-
|
|
373
|
+
const outputBase64 = fusion_bytesToBase64(output);
|
|
374
|
+
fusion_sendKeyValueData("cipher.doFinal", [
|
|
375
375
|
{key: "HashCode", value: this.hashCode().toString()},
|
|
376
376
|
{key: "Input", value: inputBase64},
|
|
377
377
|
{key: "Output", value: outputBase64}
|
|
@@ -382,17 +382,17 @@ setTimeout(function() {
|
|
|
382
382
|
|
|
383
383
|
|
|
384
384
|
if (MODULES.Mac) {
|
|
385
|
-
|
|
385
|
+
fusion_sendMessage('*', "Module attached: javax.crypto.Mac");
|
|
386
386
|
const mac = Java.use("javax.crypto.Mac");
|
|
387
387
|
mac.getInstance.overload("java.lang.String").implementation = function (arg0) {
|
|
388
|
-
|
|
388
|
+
fusion_sendKeyValueData("mac.getInstance", [
|
|
389
389
|
{key: "Algorithm", value: arg0}
|
|
390
390
|
]);
|
|
391
391
|
return this.getInstance(arg0);
|
|
392
392
|
};
|
|
393
393
|
|
|
394
394
|
mac.getInstance.overload("java.lang.String", "java.lang.String").implementation = function (arg0, arg1) {
|
|
395
|
-
|
|
395
|
+
fusion_sendKeyValueData("mac.getInstance", [
|
|
396
396
|
{key: "Algorithm", value: arg0},
|
|
397
397
|
{key: "Provider", value: arg1}
|
|
398
398
|
]);
|
|
@@ -400,7 +400,7 @@ setTimeout(function() {
|
|
|
400
400
|
};
|
|
401
401
|
|
|
402
402
|
mac.getInstance.overload("java.lang.String", "java.security.Provider").implementation = function (arg0, arg1) {
|
|
403
|
-
|
|
403
|
+
fusion_sendKeyValueData("mac.getInstance", [
|
|
404
404
|
{key: "Algorithm", value: arg0},
|
|
405
405
|
{key: "Provider", value: arg1}
|
|
406
406
|
]);
|
|
@@ -409,7 +409,7 @@ setTimeout(function() {
|
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
if (MODULES.KeyGenParameterSpec) {
|
|
412
|
-
|
|
412
|
+
fusion_sendMessage('*', "Module attached: android.security.keystore.KeyGenParameterSpec$Builder");
|
|
413
413
|
const useKeyGen = Java.use("android.security.keystore.KeyGenParameterSpec$Builder");
|
|
414
414
|
useKeyGen.$init.overload("java.lang.String", "int").implementation = function (keyStoreAlias, purpose) {
|
|
415
415
|
let purposeStr = "";
|
|
@@ -427,7 +427,7 @@ setTimeout(function() {
|
|
|
427
427
|
purposeStr = purpose;
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
-
|
|
430
|
+
fusion_sendKeyValueData("KeyGenParameterSpec.init", [
|
|
431
431
|
{key: "KeyStoreAlias", value: keyStoreAlias},
|
|
432
432
|
{key: "Purpose", value: purposeStr}
|
|
433
433
|
]);
|
|
@@ -435,66 +435,66 @@ setTimeout(function() {
|
|
|
435
435
|
}
|
|
436
436
|
|
|
437
437
|
useKeyGen.setBlockModes.implementation = function (modes) {
|
|
438
|
-
|
|
438
|
+
fusion_sendKeyValueData("KeyGenParameterSpec.setBlockModes", [
|
|
439
439
|
{key: "BlockMode", value: modes.toString()}
|
|
440
440
|
]);
|
|
441
441
|
return useKeyGen.setBlockModes.call(this, modes);
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
useKeyGen.setDigests.implementation = function (digests) {
|
|
445
|
-
|
|
445
|
+
fusion_sendKeyValueData("KeyGenParameterSpec.setDigests", [
|
|
446
446
|
{key: "Digests", value: digests.toString()}
|
|
447
447
|
]);
|
|
448
448
|
return useKeyGen.setDigests.call(this, digests);
|
|
449
449
|
}
|
|
450
450
|
|
|
451
451
|
useKeyGen.setKeySize.implementation = function (keySize) {
|
|
452
|
-
|
|
452
|
+
fusion_sendKeyValueData("KeyGenParameterSpec.setKeySize", [
|
|
453
453
|
{key: "KeySize", value: keySize}
|
|
454
454
|
]);
|
|
455
455
|
return useKeyGen.setKeySize.call(this, keySize);
|
|
456
456
|
}
|
|
457
457
|
|
|
458
458
|
useKeyGen.setEncryptionPaddings.implementation = function (paddings) {
|
|
459
|
-
|
|
459
|
+
fusion_sendKeyValueData("KeyGenParameterSpec.setEncryptionPaddings", [
|
|
460
460
|
{key: "Paddings", value: paddings.toString()}
|
|
461
461
|
]);
|
|
462
462
|
return useKeyGen.setEncryptionPaddings.call(this, paddings);
|
|
463
463
|
}
|
|
464
464
|
|
|
465
465
|
useKeyGen.setSignaturePaddings.implementation = function (paddings) {
|
|
466
|
-
|
|
466
|
+
fusion_sendKeyValueData("KeyGenParameterSpec.setSignaturePaddings", [
|
|
467
467
|
{key: "Paddings", value: paddings.toString()}
|
|
468
468
|
]);
|
|
469
469
|
return useKeyGen.setSignaturePaddings.call(this, paddings);
|
|
470
470
|
}
|
|
471
471
|
|
|
472
472
|
useKeyGen.setAlgorithmParameterSpec.implementation = function (spec) {
|
|
473
|
-
|
|
473
|
+
fusion_sendKeyValueData("KeyGenParameterSpec.setAlgorithmParameterSpec", [
|
|
474
474
|
{key: "ParameterSpec", value: spec.toString()}
|
|
475
475
|
]);
|
|
476
476
|
return useKeyGen.setAlgorithmParameterSpec.call(this, spec);
|
|
477
477
|
}
|
|
478
478
|
|
|
479
479
|
useKeyGen.build.implementation = function () {
|
|
480
|
-
|
|
480
|
+
fusion_sendMessage('*', "KeyGenParameterSpec.build");
|
|
481
481
|
return useKeyGen.build.call(this);
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
484
|
|
|
485
485
|
if (MODULES.IvParameterSpec) {
|
|
486
|
-
|
|
486
|
+
fusion_sendMessage('*', "Module attached: javax.crypto.spec.IvParameterSpec");
|
|
487
487
|
const ivParameter = Java.use("javax.crypto.spec.IvParameterSpec");
|
|
488
488
|
ivParameter.$init.overload("[B").implementation = function (ivKey) {
|
|
489
|
-
|
|
490
|
-
{key: "IV_Key", value:
|
|
489
|
+
fusion_sendKeyValueData("IvParameterSpec.init", [
|
|
490
|
+
{key: "IV_Key", value: fusion_bytesToBase64(ivKey)}
|
|
491
491
|
]);
|
|
492
492
|
return this.$init.overload("[B").call(this, ivKey);
|
|
493
493
|
}
|
|
494
494
|
|
|
495
495
|
ivParameter.$init.overload("[B", "int", "int").implementation = function (ivKey, offset, len) {
|
|
496
|
-
|
|
497
|
-
{key: "IV Key", value:
|
|
496
|
+
fusion_sendKeyValueData("IvParameterSpec.init", [
|
|
497
|
+
{key: "IV Key", value: fusion_bytesToBase64(ivKey)},
|
|
498
498
|
{key: "Offset", value: offset},
|
|
499
499
|
{key: "Length", value: len}
|
|
500
500
|
]);
|
|
@@ -503,19 +503,19 @@ setTimeout(function() {
|
|
|
503
503
|
}
|
|
504
504
|
|
|
505
505
|
if (MODULES.GCMParameterSpec) {
|
|
506
|
-
|
|
506
|
+
fusion_sendMessage('*', "Module attached: javax.crypto.spec.GCMParameterSpec");
|
|
507
507
|
const gcmParameter = Java.use("javax.crypto.spec.GCMParameterSpec");
|
|
508
508
|
gcmParameter.$init.overload("int", "[B").implementation = function (tLen, ivKey) {
|
|
509
|
-
|
|
510
|
-
{key: "IV_Key", value:
|
|
509
|
+
fusion_sendKeyValueData("GCMParameterSpec.init", [
|
|
510
|
+
{key: "IV_Key", value: fusion_bytesToBase64(ivKey)},
|
|
511
511
|
{key: "Auth_Tag_Length", value: tLen.toString()}
|
|
512
512
|
]);
|
|
513
513
|
return this.$init.overload("int", "[B").call(this, tLen, ivKey);
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
gcmParameter.$init.overload("int", "[B", "int", "int").implementation = function (tLen, ivKey, offset, len) {
|
|
517
|
-
|
|
518
|
-
{key: "IV_Key", value:
|
|
517
|
+
fusion_sendKeyValueData("GCMParameterSpec.init", [
|
|
518
|
+
{key: "IV_Key", value: fusion_bytesToBase64(ivKey)},
|
|
519
519
|
{key: "Auth_Tag_Length", value: tLen.toString()},
|
|
520
520
|
{key: "Offset", value: offset},
|
|
521
521
|
{key: "Length", value: len}
|
|
@@ -525,11 +525,11 @@ setTimeout(function() {
|
|
|
525
525
|
}
|
|
526
526
|
|
|
527
527
|
if (MODULES.PBEParameterSpec) {
|
|
528
|
-
|
|
528
|
+
fusion_sendMessage('*', "Module attached: javax.crypto.spec.PBEParameterSpec");
|
|
529
529
|
const pbeParameter = Java.use("javax.crypto.spec.PBEParameterSpec");
|
|
530
530
|
pbeParameter.$init.overload("[B", "int").implementation = function (salt, iterationCount) {
|
|
531
|
-
|
|
532
|
-
{key: "PBE_Salt", value:
|
|
531
|
+
fusion_sendKeyValueData("PBEParameterSpec.init", [
|
|
532
|
+
{key: "PBE_Salt", value: fusion_bytesToBase64(salt)},
|
|
533
533
|
{key: "Iteration_Count", value: iterationCount.toString()}
|
|
534
534
|
]);
|
|
535
535
|
return this.$init.overload("[B", "int").call(this, salt, iterationCount);
|
|
@@ -538,7 +538,7 @@ setTimeout(function() {
|
|
|
538
538
|
pbeParameter.$init.overload("[B", "int", "java.security.spec.AlgorithmParameterSpec").implementation = function (salt, iterationCount, paramSpec) {
|
|
539
539
|
|
|
540
540
|
var data = [
|
|
541
|
-
{key: "PBE_Salt", value:
|
|
541
|
+
{key: "PBE_Salt", value: fusion_bytesToBase64(salt)},
|
|
542
542
|
{key: "Iteration_Count", value: iterationCount.toString()}
|
|
543
543
|
|
|
544
544
|
]
|
|
@@ -546,42 +546,41 @@ setTimeout(function() {
|
|
|
546
546
|
try{
|
|
547
547
|
data = data.concat([
|
|
548
548
|
{key: "Algorithm", value: paramSpec.getAlgorithm()},
|
|
549
|
-
{key: "ParamSpec", value:
|
|
549
|
+
{key: "ParamSpec", value: fusion_keyToBase64(paramSpec)},
|
|
550
550
|
{key: "Provider", value: paramSpec.getProvider()}
|
|
551
551
|
]);
|
|
552
552
|
} catch (err) { }
|
|
553
553
|
|
|
554
|
-
|
|
554
|
+
fusion_sendKeyValueData("PBEParameterSpec.init", data);
|
|
555
555
|
return this.$init.overload("[B", "int", "java.security.spec.AlgorithmParameterSpec").call(this, salt, iterationCount, paramSpec);
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
558
|
|
|
559
559
|
if (MODULES.X509EncodedKeySpec) {
|
|
560
|
-
|
|
560
|
+
fusion_sendMessage('*', "Module attached: java.security.spec.X509EncodedKeySpec");
|
|
561
561
|
const x509EncodedKeySpec = Java.use("java.security.spec.X509EncodedKeySpec");
|
|
562
562
|
x509EncodedKeySpec.$init.overload("[B").implementation = function (encodedKey) {
|
|
563
|
-
|
|
564
|
-
{key: "Key", value:
|
|
563
|
+
fusion_sendKeyValueData("X509EncodedKeySpec.init", [
|
|
564
|
+
{key: "Key", value: fusion_bytesToBase64(encodedKey)}
|
|
565
565
|
]);
|
|
566
566
|
return this.$init.overload("[B").call(this, encodedKey);
|
|
567
567
|
}
|
|
568
568
|
|
|
569
569
|
}
|
|
570
570
|
|
|
571
|
-
|
|
571
|
+
fusion_sendMessage("W", "Crypto functions have been successfully initialized.")
|
|
572
572
|
});
|
|
573
573
|
|
|
574
574
|
}, 0);
|
|
575
575
|
|
|
576
|
-
|
|
577
|
-
function keyToBase64(key){
|
|
576
|
+
function fusion_keyToBase64(key){
|
|
578
577
|
if (key === null || key === undefined) return "IA==";
|
|
579
578
|
try{
|
|
580
579
|
|
|
581
|
-
return
|
|
580
|
+
return fusion_bytesToBase64(key.getEncoded())
|
|
582
581
|
|
|
583
582
|
} catch (err) {
|
|
584
|
-
|
|
583
|
+
fusion_sendMessage("W", err);
|
|
585
584
|
return "IA==";
|
|
586
585
|
}
|
|
587
586
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frida-fusion
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
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>
|
|
@@ -73,6 +73,43 @@ Modules:
|
|
|
73
73
|
pip3 install frida-fusion
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
## Custom Frida script
|
|
77
|
+
|
|
78
|
+
You must provide a custom Frida script as usual. To do this you must provide `-s/--script-path` parameter.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Just one file
|
|
82
|
+
frida-fusion -f [app_id] -U --script-path mytest.js
|
|
83
|
+
|
|
84
|
+
# A entire directory
|
|
85
|
+
frida-fusion -f [app_id] -U --script-path /tmp/scripts
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Exposed JavaScript (frida) functions
|
|
89
|
+
|
|
90
|
+
The Frida Fusion define/expose several functions to be used at frida scripts. Follows the typedef of these functions.
|
|
91
|
+
|
|
92
|
+
```java
|
|
93
|
+
# Send message/data to Frida-Fusion
|
|
94
|
+
void fusion_sendMessage(String level, String message);
|
|
95
|
+
void fusion_sendMessageWithTrace(String level, String message);
|
|
96
|
+
void fusion_sendKeyValueData(String module, Object items);
|
|
97
|
+
|
|
98
|
+
# Print StackTrace
|
|
99
|
+
void fusion_printStackTrace();
|
|
100
|
+
|
|
101
|
+
# Print all methods of class 'name'
|
|
102
|
+
void fusion_printMethods(String name);
|
|
103
|
+
|
|
104
|
+
# Wait until the class 'name' exists in memory to execute the callback function
|
|
105
|
+
void fusion_waitForClass(String name, CallbackFunction onReady)
|
|
106
|
+
|
|
107
|
+
# Conversions
|
|
108
|
+
byte[] fusion_stringToBase64(String message);
|
|
109
|
+
String fusion_bytesToBase64(byte[] byteArray);
|
|
110
|
+
String fusion_encodeHex(byte[] byteArray);
|
|
111
|
+
```
|
|
112
|
+
|
|
76
113
|
## Module engine
|
|
77
114
|
|
|
78
115
|
You can check available modules with `frida-fusion --list-modules` command.
|
|
@@ -104,7 +141,7 @@ export FUSION_MODULES=/tmp/modules
|
|
|
104
141
|
frida-fusion --list-modules
|
|
105
142
|
|
|
106
143
|
# Using available module
|
|
107
|
-
frida-fusion -f [app_id] -U --script-path . -m [module_name]
|
|
144
|
+
frida-fusion -f [app_id] -U --script-path mytest.js -m [module_name]
|
|
108
145
|
```
|
|
109
146
|
|
|
110
147
|
At windows:
|
|
@@ -116,7 +153,7 @@ $env:FUSION_MODULES = "C:\extra_mods"
|
|
|
116
153
|
frida-fusion --list-modules
|
|
117
154
|
|
|
118
155
|
# Using available module
|
|
119
|
-
frida-fusion -f [app_id] -U --script-path . -m [module_name]
|
|
156
|
+
frida-fusion -f [app_id] -U --script-path mytest.js -m [module_name]
|
|
120
157
|
```
|
|
121
158
|
|
|
122
159
|
### Community modules
|
|
@@ -131,3 +168,4 @@ export FUSION_MODULES=/tmp/frida-fusion-community-modules
|
|
|
131
168
|
# List all modules
|
|
132
169
|
frida-fusion --list-modules
|
|
133
170
|
```
|
|
171
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|