frida-fusion 0.1.0__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.

@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.1
2
+ Name: frida-fusion
3
+ Version: 0.1.0
4
+ Summary: Hook your mobile tests with Frida
5
+ Author-email: "Helvio Junior (M4v3r1ck)" <helvio_junior@hotmail.com>
6
+ Maintainer-email: "Helvio Junior (M4v3r1ck)" <helvio_junior@hotmail.com>
7
+ Project-URL: Documentation, https://github.com/helviojunior/frida-fusion
8
+ Project-URL: Source, https://github.com/helviojunior/frida-fusion
9
+ Project-URL: Tracker, https://github.com/helviojunior/frida-fusion
10
+ Project-URL: Author, https://github.com/helviojunior
11
+ Keywords: Frida Fusion,Frida,Frida Scripts,development,red team
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
16
+ Classifier: Natural Language :: English
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3 :: Only
25
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
26
+ Classifier: Topic :: Security
27
+ Classifier: Topic :: Utilities
28
+ Requires-Python: <4,>=3.9
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Frida Fusion
32
+
33
+ Hook your mobile tests with Frida.
34
+
35
+ ```bash
36
+ [ FRIDA ]—o—( FUSION )—o—[ MOBILE TESTS ] // v0.1.0
37
+ > hook your mobile tests with Frida
38
+
39
+
40
+ optional arguments:
41
+ -h, --help show this help message and exit
42
+
43
+ Device selector:
44
+ -D [ID], --device [ID] Connect to device with the given ID
45
+ -U, --usb Connect to USB device
46
+ -R, --remote Connect to remote frida-server
47
+ -H [HOST], --host [HOST] Connect to remote frida-server on HOS
48
+
49
+ Application selector:
50
+ -f [APP ID], --package [APP ID] Spawn application ID
51
+ -p [PID], --attach-pid [PID] Spawn application ID
52
+
53
+ General Setting:
54
+ -s [path], --script-path [path] JS File path or directory with Frida script
55
+ --delay-injection Delay script injection
56
+ --show-time Display time
57
+ -o [output file] Save output to disk (default: none)
58
+ -l [level], --min-level [level] Minimum log level to be displayed (V,D,I,W,E,F) (default: I)
59
+
60
+ Modules:
61
+ --list-modules List available modules
62
+ -m ENABLED_MODULES, --module ENABLED_MODULES Enabled module by name. You can specify multiple values repeating the flag.
63
+ ```
64
+
65
+ ## Install
66
+
67
+ > :information_source: We recommend using `pipx` rather than `pip` for system-wide installation.
68
+
69
+ ```
70
+ python3 -m pipx install frida-fusion
71
+ ```
72
+
73
+ > :information_source: Check whether you also need to run the `python3 -m pipx ensurepath` command.
74
+
@@ -0,0 +1,44 @@
1
+ # Frida Fusion
2
+
3
+ Hook your mobile tests with Frida.
4
+
5
+ ```bash
6
+ [ FRIDA ]—o—( FUSION )—o—[ MOBILE TESTS ] // v0.1.0
7
+ > hook your mobile tests with Frida
8
+
9
+
10
+ optional arguments:
11
+ -h, --help show this help message and exit
12
+
13
+ Device selector:
14
+ -D [ID], --device [ID] Connect to device with the given ID
15
+ -U, --usb Connect to USB device
16
+ -R, --remote Connect to remote frida-server
17
+ -H [HOST], --host [HOST] Connect to remote frida-server on HOS
18
+
19
+ Application selector:
20
+ -f [APP ID], --package [APP ID] Spawn application ID
21
+ -p [PID], --attach-pid [PID] Spawn application ID
22
+
23
+ General Setting:
24
+ -s [path], --script-path [path] JS File path or directory with Frida script
25
+ --delay-injection Delay script injection
26
+ --show-time Display time
27
+ -o [output file] Save output to disk (default: none)
28
+ -l [level], --min-level [level] Minimum log level to be displayed (V,D,I,W,E,F) (default: I)
29
+
30
+ Modules:
31
+ --list-modules List available modules
32
+ -m ENABLED_MODULES, --module ENABLED_MODULES Enabled module by name. You can specify multiple values repeating the flag.
33
+ ```
34
+
35
+ ## Install
36
+
37
+ > :information_source: We recommend using `pipx` rather than `pip` for system-wide installation.
38
+
39
+ ```
40
+ python3 -m pipx install frida-fusion
41
+ ```
42
+
43
+ > :information_source: Check whether you also need to run the `python3 -m pipx ensurepath` command.
44
+
File without changes
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/python3
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ from . import fusion
5
+
6
+ if __name__ == "__main__":
7
+ fusion.run()
@@ -0,0 +1,9 @@
1
+ __version__ = '0.1.0'
2
+ __title__ = "Frida Fusion"
3
+ __description__ = "📱 frida-fusion - runtime mobile exploration"
4
+ __url__ = "https://github.com/helviojunior/frida-fusion"
5
+ __build__ = 0x63c974a8
6
+ __author__ = "Helvio Junior (M4v3r1ck)"
7
+ __author_email__ = "helvio_junior@hotmail.com"
8
+ __license__ = "GPL-3.0"
9
+ __copyright__ = "Copyright Helvio Junior"
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/python3
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ import argparse
5
+ import sys
6
+
7
+ from .libs.color import Color
8
+ from .__meta__ import __description__
9
+
10
+ class Arguments(object):
11
+ ''' Holds arguments used by the Frida Fusion '''
12
+ restore = False
13
+
14
+ def __init__(self, custom_args=''):
15
+ self.verbose = any(['-v' in word for word in sys.argv])
16
+ self.restore = any(['-R' in word for word in sys.argv])
17
+ self.args = self.get_arguments(custom_args)
18
+
19
+ def _verbose(self, msg):
20
+ if self.verbose:
21
+ return Color.s(msg)
22
+ else:
23
+ return argparse.SUPPRESS
24
+
25
+ def get_arguments(self, custom_args=''):
26
+ ''' Returns parser.args() containing all program arguments '''
27
+
28
+ parser = argparse.ArgumentParser(
29
+ usage=argparse.SUPPRESS,
30
+ formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=80,
31
+ width=130)
32
+ )
33
+
34
+ device_group = parser.add_argument_group('Device selector')
35
+ self._add_device_args(device_group)
36
+
37
+ app_group = parser.add_argument_group('Application selector')
38
+ self._add_app_args(app_group)
39
+
40
+ glob = parser.add_argument_group('General Setting')
41
+ self._add_global_args(glob)
42
+
43
+ modules_group = parser.add_argument_group('Modules')
44
+ self._add_modules_args(modules_group)
45
+
46
+ return parser.parse_args()
47
+
48
+ def _add_app_args(self, app):
49
+ app.add_argument('-f',
50
+ '--package',
51
+ dest='app_id',
52
+ metavar='[APP ID]',
53
+ required=False,
54
+ default=None,
55
+ help='Spawn application ID')
56
+
57
+ app.add_argument('-p',
58
+ '--attach-pid',
59
+ dest='pid',
60
+ metavar='[PID]',
61
+ default=0,
62
+ required=False,
63
+ type=int,
64
+ help='Spawn application ID')
65
+
66
+ def _add_device_args(self, device):
67
+ device.add_argument('-D',
68
+ '--device',
69
+ dest='device_id',
70
+ metavar='[ID]',
71
+ type=str,
72
+ required=False,
73
+ default=None,
74
+ help='Connect to device with the given ID')
75
+
76
+ device.add_argument('-U',
77
+ '--usb',
78
+ action='store_true',
79
+ dest='use_usb',
80
+ default=False,
81
+ required=False,
82
+ help='Connect to USB device')
83
+
84
+ device.add_argument('-R',
85
+ '--remote',
86
+ action='store_true',
87
+ dest='use_remote',
88
+ default=False,
89
+ required=False,
90
+ help='Connect to remote frida-server')
91
+
92
+ device.add_argument('-H',
93
+ '--host',
94
+ dest='remote_host',
95
+ metavar='[HOST]',
96
+ type=str,
97
+ required=False,
98
+ default=None,
99
+ help='Connect to remote frida-server on HOS')
100
+
101
+ def _add_global_args(self, glob):
102
+ glob.add_argument('-s',
103
+ '--script-path',
104
+ dest='frida_scripts',
105
+ default=None,
106
+ metavar='[path]',
107
+ type=str,
108
+ help='JS File path or directory with Frida script')
109
+
110
+ glob.add_argument('--delay-injection',
111
+ action='store_true',
112
+ dest='delay',
113
+ default=False,
114
+ help='Delay script injection')
115
+
116
+ glob.add_argument('--show-time',
117
+ action='store_true',
118
+ dest='show_time',
119
+ default=False,
120
+ help='Display time')
121
+
122
+ glob.add_argument('-o',
123
+ action='store',
124
+ dest='out_file',
125
+ metavar='[output file]',
126
+ type=str,
127
+ help=Color.s('Save output to disk (default: {G}none{W})'))
128
+
129
+ glob.add_argument('-l',
130
+ '--min-level',
131
+ action='store',
132
+ dest='debug_level',
133
+ metavar='[level]',
134
+ type=str,
135
+ default='I',
136
+ help=Color.s('Minimum log level to be displayed (V,D,I,W,E,F) (default: {G}I{W})'))
137
+
138
+ def _add_modules_args(self, modules):
139
+ modules.add_argument('--list-modules',
140
+ action='store_true',
141
+ default=False,
142
+ dest='list_modules',
143
+ help=Color.s('List available modules'))
144
+
145
+ modules.add_argument('-m',
146
+ '--module',
147
+ action='append',
148
+ dest='enabled_modules',
149
+ help='Enabled module by name. You can specify multiple values repeating the flag.')
150
+
151
+
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/python3
2
+ # -*- coding: UTF-8 -*-
3
+ import os
4
+ import errno
5
+ import sys
6
+ import signal
7
+ from pathlib import Path
8
+
9
+ from .module import Module
10
+ from .libs.color import Color
11
+ from .libs.logger import Logger
12
+ from .__meta__ import __version__
13
+
14
+
15
+ class Configuration(object):
16
+ ''' Stores configuration variables and functions for Frida Fusion. '''
17
+ version = '0.0.0'
18
+
19
+ initialized = False # Flag indicating config has been initialized
20
+ debug_level = 0
21
+ cmd_line = ''
22
+ base_path = str(Path(__file__).resolve().parent)
23
+ db_path = os.path.join(str(Path(".").resolve()), "fusion.db")
24
+ enabled_modules = {}
25
+
26
+ # Device vars
27
+ device_id = None
28
+ use_usb = False
29
+ remote_host = None
30
+
31
+ # App vars
32
+ package = ''
33
+ pid = 0
34
+
35
+ # Scripts
36
+ frida_scripts = None
37
+
38
+ # General
39
+ out_file = None
40
+ print_timestamp = False
41
+ use_delay = False
42
+
43
+ @staticmethod
44
+ def initialize():
45
+ '''
46
+ Sets up default initial configuration values.
47
+ Also sets config values based on command-line arguments.
48
+ '''
49
+
50
+ # Only initialize this class once
51
+ if Configuration.initialized:
52
+ return
53
+
54
+ Configuration.debug_level = 0 # Verbosity level.
55
+
56
+ # Overwrite config values with arguments (if defined)
57
+ Configuration.load_from_arguments()
58
+
59
+ Configuration.initialized = True
60
+
61
+ @staticmethod
62
+ def load_from_arguments():
63
+ ''' Sets configuration values based on Argument.args object '''
64
+ from .args import Arguments
65
+
66
+ config_check = 0
67
+
68
+ sys.argv[0] = 'frida-fusion'
69
+
70
+ list_modules = any(['--list-modules' == word for word in sys.argv])
71
+ #show_help = any(['-h' == word for word in sys.argv])
72
+
73
+ if list_modules:
74
+ mods = Module.list_modules()
75
+ max_name = max(iter([
76
+ len(m.name) + 3
77
+ for _, m in mods.items()
78
+ ] + [15]))
79
+ Color.pl(f"Available modules")
80
+ Color.pl(f" {'Module Name'.ljust(max_name)} : Description")
81
+ for _, m in mods.items():
82
+ Color.pl(f" {m.name.ljust(max_name)} : {m.description}")
83
+
84
+ print("")
85
+ sys.exit(0)
86
+
87
+ args = Arguments().args
88
+
89
+ Color.pl('{+} {W}Startup parameters')
90
+
91
+ if args.out_file is not None and args.out_file != '':
92
+ Configuration.out_file = args.out_file
93
+ try:
94
+ with open(Configuration.out_file, 'a') as f:
95
+ # file opened for writing. write to it here
96
+ Logger.out_file = Configuration.out_file
97
+ f.write(Color.sc(Configuration.get_banner()) + '\n')
98
+ f.write(Color.sc('{+} {W}Startup parameters') + '\n')
99
+ pass
100
+ except IOError as x:
101
+ if x.errno == errno.EACCES:
102
+ Color.pl('{!} {R}error: could not open output file to write {O}permission denied{R}{W}\r\n')
103
+ sys.exit(1)
104
+ elif x.errno == errno.EISDIR:
105
+ Color.pl('{!} {R}error: could not open output file to write {O}it is an directory{R}{W}\r\n')
106
+ sys.exit(1)
107
+ else:
108
+ Color.pl('{!} {R}error: could not open output file to write{W}\r\n')
109
+ sys.exit(1)
110
+
111
+ if args.app_id is None and args.pid == 0:
112
+ Color.pl('{!} {R}error: you must specify either {O}--package{R} or {O}--attach-pid{R}{W}\r\n')
113
+ Configuration.mandatory()
114
+
115
+ if args.app_id is not None and args.pid > 0:
116
+ Color.pl('{!} {R}error: you must specify just one parameter {O}--package{R} or {O}--attach-pid{R}{W}\r\n')
117
+ Configuration.mandatory()
118
+
119
+ if args.app_id is not None:
120
+ Configuration.package = args.app_id
121
+ Logger.pl(' {C}package:{O} %s{W}' % Configuration.package)
122
+ elif args.pid > 0:
123
+ Configuration.pid = args.pid
124
+ Logger.pl(' {C}process id:{O} %s{W}' % Configuration.pid)
125
+
126
+ if args.use_usb is True:
127
+ Configuration.use_usb = True
128
+ Logger.pl(' {C}device:{O} USB{W}')
129
+ elif args.device_id is not None:
130
+ Configuration.device_id = args.device_id
131
+ Logger.pl(' {C}device:{O} %s{W}' % Configuration.device_id)
132
+ elif args.use_remote and args.remote_host is not None:
133
+ Configuration.remote_host = args.remote_host
134
+ Logger.pl(' {C}device:{O} remote %s{W}' % Configuration.remote_host)
135
+
136
+ if Configuration.use_usb is False and Configuration.device_id is None and Configuration.remote_host is None:
137
+ Color.pl('{!} {R}error: you must specify just one parameter {O}--usb{R}, {O}--device{R} or {O}--remote{R}{W}\r\n')
138
+ Configuration.mandatory()
139
+
140
+ if args.frida_scripts is not None and args.frida_scripts.strip() != "":
141
+ if not os.path.exists(args.frida_scripts):
142
+ Color.pl(
143
+ '{!} {R}error: scripts path not found{R}{W}\r\n')
144
+ Configuration.mandatory()
145
+ Configuration.frida_scripts = args.frida_scripts
146
+
147
+ if Configuration.frida_scripts is None:
148
+ Color.pl(
149
+ '{!} {R}error: you must specify scripts path {O}--script-path{R}{W}\r\n')
150
+ Configuration.mandatory()
151
+
152
+ Logger.pl(' {C}scripts path:{O} %s{W}' % Configuration.frida_scripts)
153
+
154
+ if args.delay:
155
+ Configuration.use_delay = True
156
+
157
+ if args.show_time:
158
+ Configuration.print_timestamp = True
159
+
160
+ if str(args.debug_level).upper() not in Color.level_map.keys():
161
+ Color.pl(
162
+ '{!} {R}error: invalid debug level{R}{W}\r\n')
163
+ Configuration.mandatory()
164
+
165
+ Configuration.debug_level = Color.level_map.get(str(args.debug_level).upper(), 0)
166
+
167
+ Logger.pl(' {C}min debug level:{O} %s{W}' % str(args.debug_level).upper())
168
+
169
+ if args.enabled_modules is not None and isinstance(args.enabled_modules, list):
170
+ mods = Module.list_modules()
171
+ for mod in args.enabled_modules:
172
+ fm = next(iter([
173
+ m
174
+ for _, m in mods.items()
175
+ if m.name.lower() == mod.lower()
176
+ ]), None)
177
+ if fm is None:
178
+ Color.pl(
179
+ '{!} {R}error: module {O}%s{R} not found{W}\r\n' % mod)
180
+ sys.exit(1)
181
+
182
+ name = fm.name.lower()
183
+ if name not in Configuration.enabled_modules.keys():
184
+ Configuration.enabled_modules[name] = fm
185
+
186
+ if len(Configuration.enabled_modules) > 0:
187
+ Logger.pl(' {C}modules:{O} %s{W}' % ', '.join([
188
+ m.name
189
+ for _, m in Configuration.enabled_modules.items()
190
+ ]))
191
+
192
+ Logger.pl("")
193
+
194
+ @staticmethod
195
+ def get_banner():
196
+ Configuration.version = str(__version__)
197
+
198
+ return '''
199
+ {P}[ {R}FRIDA {P}]{G}—o—( {O}FUSION {G})—o—{P}[ {C}MOBILE TESTS {P}] {W}{D}// v%s{W}
200
+ {O}> {W}{D}{O}hook your mobile tests with Frida{W}
201
+
202
+ ''' % Configuration.version
203
+
204
+ @staticmethod
205
+ def mandatory():
206
+ Color.pl(
207
+ '{!} {R}error: missing a mandatory option, use {O}-h{R} help{W}\r\n')
208
+ sys.exit(1)
209
+
210
+ @staticmethod
211
+ def exit_gracefully(code=0):
212
+ ''' Deletes temp and exist with the given code '''
213
+ exit(code)
214
+
215
+ @staticmethod
216
+ def kill(code=0):
217
+ ''' Deletes temp and exist with the given code '''
218
+ os.kill(os.getpid(), signal.SIGTERM)