frida-fusion 0.1.3__tar.gz → 0.1.4__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 (26) hide show
  1. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/PKG-INFO +2 -5
  2. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/README.md +1 -4
  3. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/__meta__.py +1 -1
  4. frida-fusion-0.1.4/frida_fusion/libs/helpers.js +305 -0
  5. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion.egg-info/PKG-INFO +2 -5
  6. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion.egg-info/SOURCES.txt +1 -0
  7. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/pyproject.toml +2 -0
  8. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/__init__.py +0 -0
  9. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/__main__.py +0 -0
  10. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/args.py +0 -0
  11. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/config.py +0 -0
  12. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/fusion.py +0 -0
  13. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/libs/__init__.py +0 -0
  14. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/libs/color.py +0 -0
  15. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/libs/database.py +0 -0
  16. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/libs/logger.py +0 -0
  17. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/module.py +0 -0
  18. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/modules/__init__.py +0 -0
  19. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/modules/crypto.js +0 -0
  20. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion/modules/crypto.py +0 -0
  21. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion.egg-info/dependency_links.txt +0 -0
  22. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion.egg-info/entry_points.txt +0 -0
  23. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion.egg-info/requires.txt +0 -0
  24. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/frida_fusion.egg-info/top_level.txt +0 -0
  25. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/setup.cfg +0 -0
  26. {frida-fusion-0.1.3 → frida-fusion-0.1.4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: frida-fusion
3
- Version: 0.1.3
3
+ Version: 0.1.4
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>
@@ -64,11 +64,8 @@ Modules:
64
64
 
65
65
  ## Install
66
66
 
67
- > :information_source: We recommend using `pipx` rather than `pip` for system-wide installation.
68
-
69
67
  ```
70
- python3 -m pipx install frida-fusion
68
+ pip3 install frida-fusion
71
69
  ```
72
70
 
73
- > :information_source: Check whether you also need to run the `python3 -m pipx ensurepath` command.
74
71
 
@@ -34,11 +34,8 @@ Modules:
34
34
 
35
35
  ## Install
36
36
 
37
- > :information_source: We recommend using `pipx` rather than `pip` for system-wide installation.
38
-
39
37
  ```
40
- python3 -m pipx install frida-fusion
38
+ pip3 install frida-fusion
41
39
  ```
42
40
 
43
- > :information_source: Check whether you also need to run the `python3 -m pipx ensurepath` command.
44
41
 
@@ -1,4 +1,4 @@
1
- __version__ = '0.1.3'
1
+ __version__ = '0.1.4'
2
2
  __title__ = "Frida Fusion"
3
3
  __description__ = "📱 frida-fusion - runtime mobile exploration"
4
4
  __url__ = "https://github.com/helviojunior/frida-fusion"
@@ -0,0 +1,305 @@
1
+ /* Android Scripts
2
+ Author: Hélvio - M4v3r1ck
3
+ */
4
+
5
+
6
+ function waitForClass(name, onReady) {
7
+ var intv = setInterval(function () {
8
+ try {
9
+ var C = Java.use(name);
10
+ clearInterval(intv);
11
+ onReady(C);
12
+ } catch (e) { /* ainda não carregou */ }
13
+ }, 100);
14
+ }
15
+
16
+ function printStackTrace(){
17
+ var trace = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
18
+ trace = trace.replace("java.lang.Exception\n", "Stack trace:\n");
19
+ sendMessage("*", trace);
20
+ }
21
+
22
+ function toBytes(message){
23
+ try{
24
+ const StringClass = Java.use('java.lang.String');
25
+ var bTxt = StringClass.$new(message).getBytes('utf-8');
26
+
27
+ return bTxt;
28
+ } catch (err) {
29
+ sendMessage("*", err)
30
+ }
31
+ }
32
+
33
+ function toBase64(message){
34
+ try{
35
+ const StringClass = Java.use('java.lang.String');
36
+ const Base64Class = Java.use('android.util.Base64');
37
+ var bTxt = StringClass.$new(message).getBytes('utf-8');
38
+ var b64Msg = Base64Class.encodeToString(bTxt, 0x00000002); //Base64Class.NO_WRAP = 0x00000002
39
+
40
+ return b64Msg;
41
+ } catch (err) {
42
+ sendMessage("*", err)
43
+ }
44
+ }
45
+
46
+ function bytesToBase64(message){
47
+
48
+ if (message === null || message === undefined) return "IA==";
49
+ try {
50
+ // 1) Confirma tipo byte[], se não tenta converter em string
51
+ message = Java.array('byte', message);
52
+
53
+ // 2) Tem 'length' numérico
54
+ const len = message.length;
55
+ if (typeof len !== "number") return "IA==";
56
+
57
+ // 3) (opcional) Exigir conteúdo
58
+ if (len === 0) return "IA==";
59
+
60
+ } catch (e) {
61
+ return "IA==";
62
+ }
63
+
64
+ try{
65
+
66
+ const Base64Class = Java.use('android.util.Base64');
67
+ var b64Msg = Base64Class.encodeToString(message, 0x00000002); //Base64Class.NO_WRAP = 0x00000002
68
+
69
+ return b64Msg;
70
+ } catch (err) {
71
+ sendMessage("*", err)
72
+ return "IA==";
73
+ }
74
+ }
75
+
76
+ function getCallerInfo() {
77
+ try{
78
+ const stack = new Error().stack.split("\n");
79
+
80
+ //Skip Error and getCallerInfo from stack trace
81
+ for (let i = 2; i < stack.length; i++) {
82
+ const line = stack[i].trim();
83
+
84
+ // Extrai: functionName (file:line:col)
85
+ // ou apenas (file:line:col) se não tiver nome
86
+ const m = line.match(/at\s+(?:(\S+)\s+)?[\( ]?(\S+):(\d+)\)?$/);
87
+ if (m) {
88
+ const func = m[1] || "";
89
+ const file = m[2];
90
+ const ln = parseInt(m[3], 10);
91
+
92
+ // Ignora funções cujo nome comece com "send" (qualquer case)
93
+ if (/^send/i.test(func)) continue;
94
+ if (/^isend/i.test(func)) continue;
95
+
96
+ return { file_name: file, function_name: func, line: ln };
97
+ }
98
+ }
99
+ } catch (err) {
100
+ console.log(`Error: ${err}`)
101
+ }
102
+ return null;
103
+ }
104
+
105
+ function iSend(payload1, payload2){
106
+ try{
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();
128
+
129
+ var data = [];
130
+
131
+ // Force as String
132
+ for (let i = 0; i < items.length; i++) {
133
+ data = data.concat([{key: `${items[i].key}`, value:`${items[i].value}`}]);
134
+ }
135
+
136
+ iSend({
137
+ type: "key_value_data",
138
+ module: module,
139
+ data: data,
140
+ stack_trace: st
141
+ }, null);
142
+
143
+
144
+ /*
145
+ var jData = `{"type" : "key_value_data", "module": "${module}", "data": [`;
146
+ for (let i = 0; i < items.length; i++) {
147
+ if (i > 0) {
148
+ jData += `, `
149
+ }
150
+ jData += `{"key": "${items[i].key}", "value": "${items[i].value}"}`
151
+ }
152
+ jData += `], "stack_trace": "${st}"}`;
153
+ iSend(jData, "");
154
+ */
155
+ }
156
+
157
+ function sendMessage(level, message){
158
+ try{
159
+ const StringClass = Java.use('java.lang.String');
160
+ const Base64Class = Java.use('android.util.Base64');
161
+ var bTxt = StringClass.$new(message).getBytes('utf-8');
162
+ var b64Msg = Base64Class.encodeToString(bTxt, 0x00000002); //Base64Class.NO_WRAP = 0x00000002
163
+
164
+ //send('{"type" : "message", "level" : "'+ level +'", "message" : "'+ b64Msg +'"}');
165
+ iSend({
166
+ type: "message",
167
+ level: level,
168
+ message: b64Msg
169
+ }, null)
170
+ } catch (err) {
171
+ sendMessage("*", err)
172
+ //sendMessage('-', 'secret_key_spec.$init.overload error: ' + err + '\n' + err.stack);
173
+ }
174
+ }
175
+
176
+ function sendError(error) {
177
+ try{
178
+ sendMessage("-", error + '\n' + error.stack);
179
+ } catch (err) {
180
+ sendMessage("*", err)
181
+ }
182
+ }
183
+
184
+ function encodeHex(byteArray) {
185
+
186
+ const HexClass = Java.use('org.apache.commons.codec.binary.Hex');
187
+ const StringClass = Java.use('java.lang.String');
188
+ const hexChars = HexClass.encodeHex(byteArray);
189
+ //sendMessage("*", StringClass.$new(hexChars).toString());
190
+ //Buffer.from(bufStr, 'utf8');
191
+ //sendMessage("*", new Uint8Array(byteArray));
192
+ return StringClass.$new(hexChars).toString();
193
+
194
+ }
195
+
196
+ function getB64StackTrace(){
197
+
198
+ try{
199
+ const StringClass = Java.use('java.lang.String');
200
+ const Base64Class = Java.use('android.util.Base64');
201
+ var trace = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
202
+ trace = trace.replace("java.lang.Exception\n", "Stack trace:\n");
203
+ var bTrace = StringClass.$new(trace).getBytes('utf-8');
204
+ var b64Msg = Base64Class.encodeToString(bTrace, 0x00000002); //Base64Class.NO_WRAP = 0x00000002
205
+
206
+ return b64Msg
207
+
208
+ } catch (err) {
209
+ sendMessage("*", err);
210
+ return '';
211
+ }
212
+ }
213
+
214
+ function enumMethods(targetClass)
215
+ {
216
+ var hook = Java.use(targetClass);
217
+ var ownMethods = hook.class.getDeclaredMethods();
218
+ hook.$dispose;
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);
229
+ });
230
+
231
+ }
232
+
233
+ function intToHex(intVal)
234
+ {
235
+ return intVal.toString(16);
236
+ }
237
+
238
+
239
+ Java.perform(function () {
240
+ const Thread = Java.use('java.lang.Thread');
241
+ const UEH = Java.registerClass({
242
+ name: 'br.com.sec4us.UehProxy',
243
+ implements: [Java.use('java.lang.Thread$UncaughtExceptionHandler')],
244
+ methods: {
245
+ uncaughtException: [{
246
+ returnType: 'void',
247
+ argumentTypes: ['java.lang.Thread', 'java.lang.Throwable'],
248
+ implementation: function (t, e) {
249
+ try {
250
+ const Throwable = Java.use('java.lang.Throwable');
251
+ const sw = Java.use('java.io.StringWriter').$new();
252
+ const pw = Java.use('java.io.PrintWriter').$new(sw);
253
+ Throwable.$new(e).printStackTrace(pw);
254
+ send({ type: 'java-uncaught', thread: t.getName(), stack: sw.toString() });
255
+ } catch (err) { send({ type: 'java-uncaught-error', err: err+'' }); }
256
+ // Opcional: impedir que o app morra? Não é garantido; normalmente o processo cai.
257
+ }
258
+ }]
259
+ }
260
+ });
261
+
262
+ // Define globalmente
263
+ Thread.setDefaultUncaughtExceptionHandler(UEH.$new());
264
+ });
265
+
266
+ function formatBacktrace(frames) {
267
+ return frames.map((addr, i) => {
268
+ const sym = DebugSymbol.fromAddress(addr);
269
+ const mod = Process.findModuleByAddress(addr);
270
+ const off = (mod && addr.sub(mod.base)) ? "0x" + addr.sub(mod.base).toString(16) : String(addr);
271
+ const name = (sym && sym.name) ? sym.name : "<unknown>";
272
+ const modname = mod ? mod.name : "<unknown>";
273
+ return `${i.toString().padStart(2)} ${name} (${modname}+${off})`;
274
+ });
275
+ }
276
+
277
+ Process.setExceptionHandler(function (details) {
278
+ let frames;
279
+ try {
280
+ frames = Thread.backtrace(details.context, Backtracer.ACCURATE);
281
+ } catch (e) {
282
+ frames = Thread.backtrace(details.context, Backtracer.FUZZY);
283
+ }
284
+
285
+ const pretty = formatBacktrace(frames);
286
+
287
+ send({
288
+ type: "native-exception",
289
+ details: {
290
+ message: details.message,
291
+ type: details.type,
292
+ address: String(details.address),
293
+ memory: details.memory,
294
+ context: details.context,
295
+ nativeContext: String(details.nativeContext),
296
+ backtrace: pretty, // <— pilha simbólica
297
+ backtrace_raw: frames.map(String) // <— opcional: endereços puros
298
+ }
299
+ });
300
+
301
+ // true = tenta engolir a exceção; se quiser ver o processo cair, retorne false
302
+ return false;
303
+ });
304
+
305
+ sendMessage("W", "Helper functions have been successfully initialized.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: frida-fusion
3
- Version: 0.1.3
3
+ Version: 0.1.4
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>
@@ -64,11 +64,8 @@ Modules:
64
64
 
65
65
  ## Install
66
66
 
67
- > :information_source: We recommend using `pipx` rather than `pip` for system-wide installation.
68
-
69
67
  ```
70
- python3 -m pipx install frida-fusion
68
+ pip3 install frida-fusion
71
69
  ```
72
70
 
73
- > :information_source: Check whether you also need to run the `python3 -m pipx ensurepath` command.
74
71
 
@@ -17,6 +17,7 @@ frida_fusion.egg-info/top_level.txt
17
17
  frida_fusion/libs/__init__.py
18
18
  frida_fusion/libs/color.py
19
19
  frida_fusion/libs/database.py
20
+ frida_fusion/libs/helpers.js
20
21
  frida_fusion/libs/logger.py
21
22
  frida_fusion/modules/__init__.py
22
23
  frida_fusion/modules/crypto.js
@@ -60,6 +60,8 @@ exclude = ["frida_fusion*tests", "frida_fusion*images", "frida_fusion*docs"]
60
60
  'resources/**/*',
61
61
  'modules/*',
62
62
  'modules/**/*',
63
+ 'libs/*',
64
+ 'libs/**/*',
63
65
  ]
64
66
 
65
67
  [project.urls]
File without changes
File without changes