5
5
import click
6
6
import delegator
7
7
import frida
8
- import pygments . styles
9
- from prompt_toolkit import AbortAction , prompt
8
+ from prompt_toolkit import PromptSession
9
+ from prompt_toolkit . application import run_in_terminal
10
10
from prompt_toolkit .auto_suggest import AutoSuggestFromHistory
11
11
from prompt_toolkit .history import FileHistory
12
- from prompt_toolkit .styles import default_style_extensions , style_from_dict
13
- from pygments .style import Style
14
- from pygments .token import Token
12
+ from prompt_toolkit .key_binding import KeyBindings
13
+ from prompt_toolkit .styles import Style
15
14
16
15
from objection .utils .agent import Agent
17
16
from .commands import COMMANDS
22
21
from ..state .connection import state_connection
23
22
from ..utils .helpers import get_tokens
24
23
24
+ bindings = KeyBindings ()
25
25
26
- class PromptStyle (Style ):
27
- """
28
- Class used to define some visual attributes for the
29
- REPL prompt.
30
- """
31
-
32
- def __init__ (self ) -> None :
33
- self .style = self ._init_style ()
34
-
35
- @staticmethod
36
- def _init_style () -> dict :
37
- """
38
- Grab the values for the prompt styling.
39
-
40
- :return:
41
- """
42
-
43
- style = pygments .styles .get_style_by_name ('vim' )
44
-
45
- styles = {}
46
- styles .update (style .styles )
47
- styles .update (default_style_extensions )
48
-
49
- styles .update ({
50
- # completions
51
- Token .Menu .Completions .Completion .Current : 'bg:#00aaaa #000000' ,
52
- Token .Menu .Completions .Completion : 'bg:#008888 #ffffff' ,
53
- Token .Menu .Completions .ProgressButton : 'bg:#003333' ,
54
- Token .Menu .Completions .ProgressBar : 'bg:#00aaaa' ,
55
-
56
- # User input.
57
- Token : '#ff0066' ,
58
26
59
- # Prompt.
60
- Token .Applicationname : '#007cff' ,
61
- Token .On : '#00aa00' ,
62
- Token .Devicetype : '#00ff48' ,
63
- Token .Version : '#00ff48' ,
64
- Token .Connection : '#717171'
65
- })
66
-
67
- return style_from_dict (styles )
27
+ @bindings .add ('c-c' )
28
+ def _ (_ ):
29
+ """
30
+ Warn about exiting when Ctrl+C is pressed
68
31
69
- def get_style ( self ) -> dict :
70
- """
71
- Return the style for this Class.
32
+ :param _ :
33
+ :return:
34
+ """
72
35
73
- :return :
74
- """
36
+ def print_warn () :
37
+ click . secho ( '[warning] To exit, press ctrl+d or issue the exit command.' , dim = True )
75
38
76
- return self . style
39
+ run_in_terminal ( print_warn )
77
40
78
41
79
42
class Repl (object ):
@@ -88,6 +51,31 @@ def __init__(self) -> None:
88
51
self .completer = CommandCompleter ()
89
52
self .commands_repository = COMMANDS
90
53
54
+ self .session = PromptSession (
55
+ history = FileHistory (os .path .expanduser ('~/.objection/objection_history' )),
56
+ )
57
+
58
+ @staticmethod
59
+ def get_prompt_style () -> Style :
60
+ """
61
+ Get the style to use for our prompt
62
+
63
+ :return:
64
+ """
65
+
66
+ return Style .from_dict ({
67
+ # completions menu
68
+ 'completion-menu.completion.current' : 'bg:#00aaaa #000000' ,
69
+ 'completion-menu.completion' : 'bg:#008888 #ffffff' ,
70
+
71
+ # Prompt.
72
+ 'applicationname' : '#007cff' ,
73
+ 'on' : '#00aa00' ,
74
+ 'devicetype' : '#00ff48' ,
75
+ 'version' : '#00ff48' ,
76
+ 'connection' : '#717171'
77
+ })
78
+
91
79
def set_prompt_tokens (self , device_info : tuple ) -> None :
92
80
"""
93
81
Set prompt tokens sourced from a command.device.device_info()
@@ -96,37 +84,35 @@ def set_prompt_tokens(self, device_info: tuple) -> None:
96
84
:param device_info:
97
85
:return:
98
86
"""
99
-
100
87
device_name , system_name , model , system_version = device_info
101
88
102
89
self .prompt_tokens = [
103
- (Token . Applicationname , device_name ),
104
- (Token . On , ' on ' ),
105
- (Token . Devicetype , '(' + model + ': ' ),
106
- (Token . Version , system_version + ') ' ),
107
- (Token . Connection , '[' + state_connection .get_comms_type_string () + '] # ' ),
90
+ ('class:applicationname' , device_name ),
91
+ ('class:on' , ' on ' ),
92
+ ('class:devicetype' , '(' + model + ': ' ),
93
+ ('class:version' , system_version + ') ' ),
94
+ ('class:connection' , '[' + state_connection .get_comms_type_string () + '] # ' ),
108
95
]
109
96
110
- def get_prompt_tokens (self , _ ) -> list :
97
+ def get_prompt_message (self ) -> list :
111
98
"""
112
99
Return prompt tokens to use in the cli app.
113
100
114
101
If none were set during the init of this class, it
115
102
is assumed that the connection failed.
116
103
117
- :param _:
118
104
:return:
119
105
"""
120
106
121
107
if self .prompt_tokens :
122
108
return self .prompt_tokens
123
109
124
110
return [
125
- (Token . Applicationname , 'unknown application' ),
126
- (Token . On , '' ),
127
- (Token . Devicetype , '' ),
128
- (Token . Version , ' ' ),
129
- (Token . Connection , '[' + state_connection .get_comms_type_string () + '] # ' ),
111
+ ('class:applicationname' , 'unknown application' ),
112
+ ('class:on' , '' ),
113
+ ('class:devicetype' , '' ),
114
+ ('class:version' , ' ' ),
115
+ ('class:connection' , '[' + state_connection .get_comms_type_string () + '] # ' ),
130
116
]
131
117
132
118
def run_command (self , document : str ) -> None :
@@ -368,14 +354,14 @@ def start_repl(self, quiet: bool) -> None:
368
354
369
355
try :
370
356
371
- document = prompt (
372
- get_prompt_tokens = self .get_prompt_tokens ,
357
+ document = self . session . prompt (
358
+ self .get_prompt_message (), # prompt message
373
359
completer = self .completer ,
374
- style = PromptStyle (). get_style (),
375
- history = FileHistory ( os . path . expanduser ( '~/.objection/objection_history' )) ,
360
+ style = self . get_prompt_style (),
361
+ key_bindings = bindings ,
376
362
auto_suggest = AutoSuggestFromHistory (),
377
- on_abort = AbortAction . RETRY ,
378
- reserve_space_for_menu = 4
363
+ reserve_space_for_menu = 4 ,
364
+ complete_in_thread = True
379
365
)
380
366
381
367
# check if this is an exit command
@@ -394,6 +380,9 @@ def start_repl(self, quiet: bool) -> None:
394
380
# find something to run
395
381
self .run_command (document )
396
382
383
+ except KeyboardInterrupt :
384
+ pass
385
+
397
386
except frida .core .RPCException as e :
398
387
click .secho ('A Frida agent exception has occured.' , fg = 'red' , bold = True )
399
388
click .secho ('{0}' .format (e ), fg = 'red' )
0 commit comments