Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/config #91

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ This project is inspired by navi (<https://github.com/denisidoro/navi>) because
- Add yml support (thx @0xswitch )
- Add fzf support with ctrl+t (thx @mgp25)
- Add prefix to commands generated (with -f)
- Add user config file (generated at first run in ~/.arsenal.conf)

## Install & Launch
- with pip :
Expand Down Expand Up @@ -81,19 +82,17 @@ yay -S arsenal
./run -t -e # just like the -t mode but with direct execution in the other pane without quitting arsenal
```

## Edit config file

When arsenal is run if `~/.arsenal.comf` does not exist a copy of `<arsenal_home>/data/arsenal.conf` is made.

## Add external cheatsheets

You could add your own cheatsheets insode the my_cheats folder or in the ~/.cheats folder.
You could add your own cheatsheets by referencing them in your `.arsenal.conf`

You could also add additional paths to the file `<arsenal_home>/arsenal/modules/config.py`,
arsenal reads `.md` (MarkDown) and `.rst` (RestructuredText).
If in `.arsenal.conf` you set `use_builtin_cheats` to `yes` your cheats will will be mered with cheats defined in `<arsenal_home>/data/cheats`

```
CHEATS_PATHS = [
join(BASEPATH, "cheats"), # DEFAULT
join(HOMEPATH, "docs/my_cheats")
]
```
arsenal reads `.md` (MarkDown) and `.rst` (RestructuredText).

Cheatsheets examples are in `<arsenal_home>/cheats`: `README.md` and `README.rst`

Expand Down
4 changes: 3 additions & 1 deletion arsenal/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import termios
import re
import time
from shutil import copy
from curses import wrapper

# arsenal
Expand Down Expand Up @@ -59,7 +60,6 @@ def run(self):
# load cheatsheets
cheatsheets = cheat.Cheats().read_files(config.CHEATS_PATHS, config.FORMATS,
config.EXCLUDE_LIST)

if args.check:
check.check(cheatsheets)
else:
Expand Down Expand Up @@ -194,6 +194,8 @@ def prefil_shell_cmd(self, cmd):


def main():
if not os.path.exists(config.CONFIG_PATH):
copy(config.DEFAULT_CONFIG_PATH, config.CONFIG_PATH)
try:
App().run()
except KeyboardInterrupt:
Expand Down
34 changes: 34 additions & 0 deletions arsenal/data/arsenal.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[arsenal]
fuzzing_dirs = ["/usr/local/share/wordlists/**/*.txt"]
use_builtin_cheats = yes
user_cheats_paths = ["~/.cheats"]
formats = ["md", "rst", "yml"]
exclude_list = ["README.md", "README.rst", "index.rst"]
savevarfile = "~/.arsenal.json"
prefix_globalvar_name = "arsenal_prefix_cmd"



[colors]
basic_color = 0
col1_color = 7
; gold
col2_color = 4
; purple light
col3_color = 14
; 26 ; violet clair: 14 ; 4 yellow ; 6 purple ; 7 cyan ; 9 dark grey
col4_color = 5
; blue
col5_color = 5
; output std invert
col1_color_select = 256
col2_color_select = 256
col3_color_select = 256
col4_color_select = 256
; background red
cursor_color_select = 266
prompt_color = 0
info_name_color = 4
info_desc_color = 0
info_cmd_color = 0
arg_name_color = 5
55 changes: 40 additions & 15 deletions arsenal/modules/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ class Command:
cmdline = ""
description = ""
args = [] # [(name, value)]
nb_args = 0
nb_place_holder = 0
nb_lines_cmd = 1
nb_lines_desc = 0

def __init__(self, cheat, gvars):
self.cmdline = cheat.command
self.nb_place_holder = 0

self.cmd_tags = cheat.command_tags
self.description = ''
Expand All @@ -22,8 +23,7 @@ def __init__(self, cheat, gvars):
self.description += '\n-----\n'
self.description += cheat.description

self.get_args(cheat, gvars)
self.nb_args = len(self.args)
self.compute_args(cheat, gvars)
# careful this is not the lines number in GUI
self.nb_lines_cmd = len(cheat.command.split('\n'))
# careful this is not the lines number in GUI
Expand All @@ -39,30 +39,54 @@ def get_description_cut_by_size(self, size):
result.extend(textwrap.wrap(line, size))
return result

def get_args(self, cheat, gvars):
def compute_args(self, cheat, gvars):
"""
Process cmdline from the cheatsheet to get args names
"""
self.args = []
self.args = {}
# Use a list of tuples here instead of dict in case
# the cmd has multiple args with the same name..
position = 0
for arg_name in re.findall(r'<([^ <>]+)>', cheat.command):
if "|" in arg_name: # Format <name|default_value>
name, var = arg_name.split("|")[:2]
self.args.append([name, var])
self._add_arg(name, var, position)
# Variable has been added to cheat variables before, remove it
cheat.command = cheat.command.replace(arg_name, name)
self.cmdline = cheat.command
elif arg_name in gvars:
self.args.append([arg_name, gvars[arg_name]])
self._add_arg(arg_name, gvars[arg_name], position)
elif arg_name in cheat.variables:
self.args.append([arg_name, cheat.variables[arg_name]])
self._add_arg(arg_name, cheat.variables[arg_name], position)
else:
self.args.append([arg_name, ""])
self._add_arg(arg_name, "", position)
position += 1

def _add_arg(self, name=None, value="", position=0):
if name in self.args:
self.args[name]["value"] = value
self.args[name]["positions"].append(position)
else:
v = {}
v["value"] = value
v["positions"] = [position]
self.args[name] = v
self.nb_place_holder += 1

def get_arg(self, position):
for k, v in self.args.items():
if position in v["positions"]:
return k, v["value"]
return f"{position}", f"|{self.nb_place_holder}|"

def set_arg_value(self, position, value):
for k, v in self.args.items():
if position in v["positions"]:
self.args[k]["value"] = value

def get_command_parts(self):
if self.nb_args != 0:
regex = ''.join('<' + arg[0] + '>|' for arg in self.args)[:-1]
if self.nb_place_holder != 0:
regex = '|'.join('<' + arg + '>' for arg in self.args)
cmdparts = re.split(regex, self.cmdline)
else:
cmdparts = [self.cmdline]
Expand All @@ -74,20 +98,21 @@ def build(self):
-> if some args values are still empty do nothing
-> else build the final command string by adding args values
"""
if self.nb_args == 0 :
if self.nb_place_holder == 0 :
return True
argsval = [a[1] for a in self.args]
if "" not in argsval:
# split cmdline at each arg position
regex = ''.join('<' + arg[0] + '>|' for arg in self.args)[:-1]
regex = '|'.join('<' + arg + '>' for arg in self.args)
cmdparts = re.split(regex, self.cmdline)
# concat command parts and arguments values to build the command
self.cmdline = ""
for i in range(len(cmdparts) + len(self.args)):
for i in range(len(cmdparts) + self.nb_place_holder):
if i % 2 == 0:
self.cmdline += cmdparts[i // 2]
else:
self.cmdline += argsval[(i - 1) // 2]
_, value = self.get_arg((i - 1) // 2)
self.cmdline += value
curses.endwin()

# build ok ?
Expand Down
70 changes: 57 additions & 13 deletions arsenal/modules/config.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,71 @@
import configparser
import os
from os.path import dirname, abspath, expanduser, join
from ast import literal_eval

# Base paths
DATAPATH = join(dirname(dirname(abspath(__file__))), 'data')
BASEPATH = dirname(dirname(dirname(abspath(__file__))))
DEFAULT_CONFIG_PATH = join(DATAPATH, "arsenal.conf")
CONFIG_PATH = expanduser("~/.arsenal.conf")
HOMEPATH = expanduser("~")
FORMATS = ["md", "rst", "yml"]
EXCLUDE_LIST = ["README.md", "README.rst", "index.rst"]
FUZZING_DIRS = ["/usr/local/share/wordlists/**/*.txt"]

CHEATS_PATHS = [
join(DATAPATH, "cheats"), # DEFAULT
# Additional paths below, add comma to line above
join(BASEPATH, "my_cheats"),
join(HOMEPATH, ".cheats")
]

DEFAULT_CHEATS_PATHS = [join(DATAPATH, "cheats")]
messages_error_missing_arguments = 'Error missing arguments'

# set lower delay to use ESC key (in ms)
os.environ.setdefault('ESCDELAY', '25')
os.environ['TERM'] = 'xterm-256color'

savevarfile = join(HOMEPATH, ".arsenal.json")
arsenal_default_config = configparser.ConfigParser()
arsenal_default_config.read(DEFAULT_CONFIG_PATH)

arsenal_config = configparser.ConfigParser()
arsenal_config.read(CONFIG_PATH)


# Update config in case default have been extended or use has removed required
config_updated = False
for section in arsenal_default_config.sections():
if not arsenal_config.has_section(section):
arsenal_config.add_section(section)
config_updated = True
for option in arsenal_default_config.options(section):
if not arsenal_config.has_option(section, option):
config_updated = True
arsenal_config.set(section, option, arsenal_default_config.get(section, option))

if config_updated:
with open(CONFIG_PATH, "w") as config_file:
arsenal_config.write(config_file)

CHEATS_PATHS = []
use_builtin_cheats = arsenal_config.getboolean("arsenal", "use_builtin_cheats")
user_cheats_paths = literal_eval(arsenal_config.get("arsenal", "user_cheats_paths"))

for p in user_cheats_paths:
CHEATS_PATHS.append(expanduser(p))
if use_builtin_cheats:
CHEATS_PATHS += DEFAULT_CHEATS_PATHS

savevarfile = expanduser(literal_eval(arsenal_config.get("arsenal", "savevarfile")))
FORMATS = literal_eval(arsenal_config.get("arsenal", "formats"))
EXCLUDE_LIST = literal_eval(arsenal_config.get("arsenal", "exclude_list"))
FUZZING_DIRS = literal_eval(arsenal_config.get("arsenal", "fuzzing_dirs"))
PREFIX_GLOBALVAR_NAME = arsenal_config.get("arsenal", "prefix_globalvar_name")

PREFIX_GLOBALVAR_NAME = "arsenal_prefix_cmd"
BASIC_COLOR = arsenal_config.getint("colors", "basic_color")
COL1_COLOR = arsenal_config.getint("colors", "col1_color")
COL2_COLOR = arsenal_config.getint("colors", "col2_color")
COL3_COLOR = arsenal_config.getint("colors", "col3_color")
COL4_COLOR = arsenal_config.getint("colors", "col4_color")
COL5_COLOR = arsenal_config.getint("colors", "col5_color")
COL1_COLOR_SELECT = arsenal_config.getint("colors", "col1_color_select")
COL2_COLOR_SELECT = arsenal_config.getint("colors", "col2_color_select")
COL3_COLOR_SELECT = arsenal_config.getint("colors", "col3_color_select")
COL4_COLOR_SELECT = arsenal_config.getint("colors", "col4_color_select")
CURSOR_COLOR_SELECT = arsenal_config.getint("colors", "cursor_color_select")
PROMPT_COLOR = arsenal_config.getint("colors", "prompt_color")
INFO_NAME_COLOR = arsenal_config.getint("colors", "info_name_color")
INFO_DESC_COLOR = arsenal_config.getint("colors", "info_desc_color")
INFO_CMD_COLOR = arsenal_config.getint("colors", "info_cmd_color")
ARG_NAME_COLOR = arsenal_config.getint("colors", "arg_name_color")
Loading
Loading