Skip to content

Commit 5e136f8

Browse files
authored
Merge pull request #198 from SYANiDE-/main
Add shell command history feature (readline)
2 parents 28fbdb8 + 2331184 commit 5e136f8

File tree

4 files changed

+41
-3
lines changed

4 files changed

+41
-3
lines changed

powerview/__init__.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from powerview.utils.parsers import powerview_arg_parse, arg_parse
1010
from powerview.utils.shell import get_prompt
1111
from powerview.utils.colors import bcolors, Gradient
12+
from powerview.utils.history import *
1213

1314
import ldap3
1415
import random
@@ -758,13 +759,21 @@ def main():
758759
powerview.remove_gplink(guid=pv_args.guid, targetidentity=pv_args.targetidentity, args=pv_args)
759760
else:
760761
logging.error("-GUID and -TargetIdentity flags are required")
762+
elif pv_args.module.casefold() == 'history':
763+
hist = get_shell_history(pv_args.last, pv_args.unique)
764+
for index, item in list(enumerate(hist,1))[::-1]:
765+
if pv_args.noNumber:
766+
bol = f""
767+
else:
768+
bol = f"[{index}] "
769+
print(f"{bol}{item}")
770+
elif pv_args.module.casefold() == 'clear':
771+
clear_screen()
761772
elif pv_args.module.casefold() == 'exit':
762773
if mcp_running:
763774
powerview.mcp_server.stop()
764775
log_handler.save_history()
765776
sys.exit(0)
766-
elif pv_args.module.casefold() == 'clear':
767-
clear_screen()
768777

769778
if entries:
770779
if pv_args.outfile:

powerview/utils/completer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
'Stop-NetService':['-Computer','-Name'],
130130
'Add-GPLink':['-GUID','-TargetIdentity','-LinkEnabled','-Enforced','-SearchBase','-Server','-OutFile'],
131131
'Remove-GPLink':['-GUID','-TargetIdentity','-SearchBase','-Server','-OutFile'],
132+
'history':['-Last','-Unique','-NoNumber'],
132133
'clear':'',
133134
'exit':'',
134135
}

powerview/utils/history.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from sys import platform
2+
if platform == "linux" or platform == "linux2":
3+
import gnureadline as readline
4+
else:
5+
import readline
6+
7+
def get_shell_history(last,unique):
8+
'''return the last x number of {,unique} shell history'''
9+
hist_len = readline.get_current_history_length()-1
10+
if last > hist_len:
11+
last = hist_len
12+
returnable_hist_items = []
13+
cursor = hist_len
14+
while (not len(returnable_hist_items) == last) and (not cursor == 1):
15+
analyze_this = readline.get_history_item(cursor)
16+
if unique == True:
17+
if not analyze_this in returnable_hist_items:
18+
returnable_hist_items.append(analyze_this)
19+
else:
20+
returnable_hist_items.append(analyze_this)
21+
cursor = cursor - 1
22+
return returnable_hist_items

powerview/utils/parsers.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,8 +1101,14 @@ def powerview_arg_parse(cmd):
11011101
remove_gplink_parser.add_argument('-Server', action='store', dest='server')
11021102
remove_gplink_parser.add_argument('-OutFile', action='store', dest='outfile')
11031103

1104-
subparsers.add_parser('exit', exit_on_error=False)
1104+
# shell history
1105+
history_parser = subparsers.add_parser('history', exit_on_error=False)
1106+
history_parser.add_argument('-Last',action='store',type=int, default=10, dest='last')
1107+
history_parser.add_argument('-Unique',action='store_true', dest='unique')
1108+
history_parser.add_argument('-NoNumber',action='store_true', dest='noNumber')
1109+
11051110
subparsers.add_parser('clear', exit_on_error=False)
1111+
subparsers.add_parser('exit', exit_on_error=False)
11061112

11071113
try:
11081114
args, unknown = parser.parse_known_args(cmd)

0 commit comments

Comments
 (0)