From 6828dd7baee20f17923305adff851be6f734be9e Mon Sep 17 00:00:00 2001 From: zawz Date: Fri, 26 Mar 2021 14:58:17 +0100 Subject: [PATCH] restructure internal shellcode structure --- include/debashify.hpp | 15 ++++-------- include/processing.hpp | 4 ++-- include/shellcode.hpp | 13 +++++++++-- src/debashify.cpp | 53 ++++++++++++++++-------------------------- src/exec.cpp | 13 ++++------- src/main.cpp | 24 ++++++++++++------- src/options.cpp | 11 ++++++++- src/processing.cpp | 12 ++++------ src/shellcode.cpp | 45 ++++++++++++++++++++++++++++++++--- 9 files changed, 116 insertions(+), 74 deletions(-) diff --git a/include/debashify.hpp b/include/debashify.hpp index 1e9a7ba..8c56b16 100644 --- a/include/debashify.hpp +++ b/include/debashify.hpp @@ -4,16 +4,11 @@ #include "struc.hpp" #include +#include typedef struct debashify_params { - bool need_random_string=false; - bool need_random_tmpfile=false; - bool need_array_create=false; - bool need_array_set=false; - bool need_array_get=false; - bool need_map_create=false; - bool need_map_set=false; - bool need_map_get=false; + std::set required_fcts; + void require_fct(std::string const& in) { required_fcts.insert(in); } // map of detected arrays // bool value: is associative std::map arrays; @@ -21,7 +16,7 @@ typedef struct debashify_params { bool r_debashify(_obj* o, debashify_params* params); -void debashify(_obj* o, debashify_params* params); -void debashify(shmain* sh); +std::set debashify(_obj* o, debashify_params* params); +std::set debashify(shmain* sh); #endif //DEBASHIFY_HPP diff --git a/include/processing.hpp b/include/processing.hpp index 9e668a2..d3f54a1 100644 --- a/include/processing.hpp +++ b/include/processing.hpp @@ -9,7 +9,7 @@ #include "struc.hpp" // constants -#define RESERVED_VARIABLES "HOME", "PATH", "SHELL", "PWD", "OPTIND", "OPTARG", "LC_.*", "LANG", "TERM", "RANDOM" +#define RESERVED_VARIABLES "HOME", "PATH", "SHELL", "PWD", "OPTIND", "OPTARG", "LC_.*", "LANG", "TERM", "RANDOM", "TMPDIR" // types typedef std::map countmap_t; @@ -73,7 +73,7 @@ bool r_delete_var(_obj* in, set_t* vars); /** Processing **/ -void insert_lxsh_commands(shmain* sh); +std::set find_lxsh_commands(shmain* sh); void add_unset_variables(shmain* sh, std::regex const& exclude); #endif //PROCESSING_HPP diff --git a/include/shellcode.hpp b/include/shellcode.hpp index 4302863..aec424f 100644 --- a/include/shellcode.hpp +++ b/include/shellcode.hpp @@ -1,15 +1,24 @@ #ifndef SHELLCODE_HPP #define SHELLCODE_HPP -#include #include +#include +#include +#include + +#include "struc.hpp" struct lxsh_fct { std::string arguments; std::string description; const char* code; + std::vector depends_on=std::vector(); }; -extern const std::map lxsh_shellcode_fcts; +extern const std::map lxsh_extend_fcts; +extern const std::map lxsh_array_fcts; +extern const std::map lxsh_allfcts; + +void add_lxsh_fcts(shmain* sh, std::set fcts); #endif //SHELLCODE_HPP diff --git a/src/debashify.cpp b/src/debashify.cpp index bc77601..d892dab 100644 --- a/src/debashify.cpp +++ b/src/debashify.cpp @@ -341,12 +341,12 @@ subshell_arithmetic* do_debashify_arithmetic(arithmetic* in, debashify_params* p if(params->arrays[varname]) { c = make_cmd_varindex("_lxsh_map_get", varname, index); - params->need_map_get=true; + params->require_fct("_lxsh_map_get"); } else { c = make_cmd_varindex("_lxsh_array_get", varname, index); - params->need_array_get=true; + params->require_fct("_lxsh_array_get"); } ret = new subshell_arithmetic(new subshell(c)); @@ -430,12 +430,12 @@ bool debashify_array_get(arg* in, debashify_params* params) if(params->arrays[varname]) { c = make_cmd_varindex("_lxsh_map_get", varname, index); - params->need_map_get=true; + params->require_fct("_lxsh_map_get"); } else { c = make_cmd_varindex("_lxsh_array_get", varname, index); - params->need_array_get=true; + params->require_fct("_lxsh_array_get"); } subshell_subarg* sb = new subshell_subarg(new subshell(c)); @@ -469,12 +469,12 @@ bool debashify_array_set(cmd* in, debashify_params* params) if(params->arrays[varname]) { c->args->insert(0, new arg("_lxsh_map_create") ); - params->need_map_create=true; + params->require_fct("_lxsh_map_create"); } else { c->args->insert(0, new arg("_lxsh_array_create") ); - params->need_array_create=true; + params->require_fct("_lxsh_array_create"); } subshell_subarg* sb = new subshell_subarg(new subshell(c)); // insert new value @@ -486,7 +486,6 @@ bool debashify_array_set(cmd* in, debashify_params* params) else if(it->first != nullptr && it->first->index != nullptr) { // array value set: VAR[]= - params->need_array_set=true; force_quotes(it->second); force_quotes(it->first->index); string_subarg* tt=dynamic_cast(it->second->sa[0]); @@ -507,12 +506,12 @@ bool debashify_array_set(cmd* in, debashify_params* params) if(params->arrays[varname]) { c = make_cmd_varindex("_lxsh_map_get", varname, copy(index)); - params->need_map_get=true; + params->require_fct("_lxsh_map_get"); } else { c = make_cmd_varindex("_lxsh_array_get", varname, copy(index)); - params->need_array_get=true; + params->require_fct("_lxsh_array_get"); } subshell_subarg* sb = new subshell_subarg(new subshell(c)); sb->quoted=true; @@ -528,12 +527,12 @@ bool debashify_array_set(cmd* in, debashify_params* params) if(params->arrays[varname]) { c->args->add(new arg("_lxsh_map_set") ); - params->need_map_set=true; + params->require_fct("_lxsh_map_set"); } else { c->args->add(new arg("_lxsh_array_set") ); - params->need_array_set=true; + params->require_fct("_lxsh_array_set"); } // _lxsh_array_set "$VAR" c->args->add( make_arg("\"$"+varname+"\"") ); @@ -552,7 +551,6 @@ bool debashify_array_set(cmd* in, debashify_params* params) { // array add: VAR+=() // can be done by creating a new array with old array + new - params->need_array_create=true; std::string varname = it->first->varname; @@ -571,7 +569,7 @@ bool debashify_array_set(cmd* in, debashify_params* params) else { c->args->insert(0, new arg("_lxsh_array_create") ); - params->need_array_create=true; + params->require_fct("_lxsh_array_create"); } // second arg is varname c->args->insert(1, make_arg("\"$"+varname+"\"") ); @@ -703,7 +701,7 @@ bool debashify_procsub(list* lst, debashify_params* params) // perform the replace if(affected_args.size()>0) { - params->need_random_tmpfile = true; + params->require_fct("_lxsh_random_tmpfile"); has_replaced=true; list* lst_insert = new list; std::string mkfifocmd="mkfifo"; @@ -755,6 +753,8 @@ bool debashify_var(variable* in, debashify_params* params) { if(in->is_manip && in->precedence && in->manip->string() == "!") throw std::runtime_error("Cannot debashify ${!VAR}"); + if(in->varname == "RANDOM") + throw std::runtime_error("Cannot debashify $RANDOM"); return false; } @@ -827,31 +827,18 @@ bool r_debashify(_obj* o, debashify_params* params) return true; } -void debashify(_obj* o, debashify_params* params) +// return value: dependencies +std::set debashify(_obj* o, debashify_params* params) { recurse(r_debashify, o, params); + return params->required_fcts; } -// -void debashify(shmain* sh) +// return value: dependencies +std::set debashify(shmain* sh) { debashify_params params; sh->shebang = "#!/bin/sh"; recurse(r_debashify, sh, ¶ms); - if(params.need_random_string || params.need_random_tmpfile) - sh->lst->insert(0, new condlist(make_block(RANDOM_TMPFILE_SH))); - if(params.need_random_tmpfile) - sh->lst->insert(0, new condlist(make_block(RANDOM_STRING_SH))); - if(params.need_array_create) - sh->lst->insert(0, new condlist(make_block(ARRAY_CREATE_SH))); - if(params.need_array_set) - sh->lst->insert(0, new condlist(make_block(ARRAY_SET_SH))); - if(params.need_array_get) - sh->lst->insert(0, new condlist(make_block(ARRAY_GET_SH))); - if(params.need_map_create) - sh->lst->insert(0, new condlist(make_block(MAP_CREATE_SH))); - if(params.need_map_set) - sh->lst->insert(0, new condlist(make_block(MAP_SET_SH))); - if(params.need_map_get) - sh->lst->insert(0, new condlist(make_block(MAP_GET_SH))); + return params.required_fcts; } diff --git a/src/exec.cpp b/src/exec.cpp index 83b31f0..100dc2b 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -13,6 +13,7 @@ #include "debashify.hpp" #include "resolve.hpp" #include "recursive.hpp" +#include "shellcode.hpp" #define PIPE_READ 0 #define PIPE_WRITE 1 @@ -262,15 +263,11 @@ int exec_process(std::string const& runtime, std::vector const& arg ffd = fopen(fifopath.c_str(), "w"); if(options["debashify"]) { - fprintf(ffd, "%s\n", ARRAY_CREATE_SH); - fprintf(ffd, "%s\n", ARRAY_GET_SH); - fprintf(ffd, "%s\n", ARRAY_SET_SH); - fprintf(ffd, "%s\n", MAP_CREATE_SH); - fprintf(ffd, "%s\n", MAP_GET_SH); - fprintf(ffd, "%s\n", MAP_SET_SH); - fprintf(ffd, "%s\n", RANDOM_STRING_SH); - fprintf(ffd, "%s\n", RANDOM_TMPFILE_SH); + for(auto it: lxsh_array_fcts) + fprintf(ffd, "%s\n", it.second.code); } + for(auto it: lxsh_extend_fcts) + fprintf(ffd, "%s\n", it.second.code); parse_exec(ffd, filecontents, file); } catch(std::runtime_error& e) diff --git a/src/main.cpp b/src/main.cpp index 9fc3783..63085ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ #include "processing.hpp" #include "debashify.hpp" #include "exec.hpp" +#include "shellcode.hpp" #include "version.h" #include "g_version.h" @@ -115,9 +116,9 @@ int main(int argc, char* argv[]) bool first_run = true; // do parsing + bool shebang_is_bin=false; for(uint32_t i=0 ; ishebang="#!/bin/sh"; + tsh->shebang="#!/bin/sh"; /* mid processing */ // resolve/include if(g_include || g_resolve) - resolve(tsh); + resolve(tsh); // concatenate to main sh->concat(tsh); @@ -187,6 +188,10 @@ int main(int argc, char* argv[]) } } // end of argument parse + // pre-listing modifiers + if(options["remove-unused"]) + delete_unused( sh, re_var_exclude, re_fct_exclude ); + // list outputs if(options["list-var"]) list_vars(sh, re_var_exclude); @@ -205,17 +210,20 @@ int main(int argc, char* argv[]) } else { - // modifiers - insert_lxsh_commands(sh); + // post-listing modifiers + // implement commands + std::set req_fcts; + if(shebang_is_bin) + req_fcts = find_lxsh_commands(sh); if(options["debashify"]) - debashify(sh); + concat_sets(req_fcts, debashify(sh) ); + + add_lxsh_fcts(sh, req_fcts); // processing before output // minify if(options['m']) opt_minify=true; - if(options["remove-unused"]) - delete_unused( sh, re_var_exclude, re_fct_exclude ); if(options["minify-quotes"]) minify_quotes(sh); if(options["minify-var"]) diff --git a/src/options.cpp b/src/options.cpp index 5ecf536..aa6a423 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -28,6 +28,7 @@ ztd::option_set gen_options() ztd::option('J', "json", false, "Output the json structure"), ztd::option("\r [Processing]"), ztd::option('m', "minify", false, "Minify code without changing functionality"), + ztd::option('M', "minify-full", false, "Enable all minifying features: -m --minify-quotes --minify-var --minify-fct --remove-unused"), ztd::option("minify-quotes", false, "Remove unnecessary quotes"), ztd::option('C', "no-cd", false, "Don't cd when doing %include and %resolve"), ztd::option('I', "no-include", false, "Don't resolve %include commands"), @@ -62,6 +63,14 @@ void get_opts() re_var_exclude=var_exclude_regex("", !options["no-exclude-reserved"]); if(options["exclude-fct"]) re_fct_exclude=fct_exclude_regex(options["exclude-fct"]); + if(options['M']) + { + options['m'].activated=true; + options["minify-var"].activated=true; + options["minify-fct"].activated=true; + options["minify-quotes"].activated=true; + options["remove-unused"].activated=true; + } } ztd::option_set create_include_opts() @@ -126,7 +135,7 @@ void print_resolve_help() void print_lxsh_cmd_help() { - for(auto it: lxsh_shellcode_fcts) + for(auto it: lxsh_extend_fcts) { printf("%s %s\n%s\n\n", it.first.c_str(), it.second.arguments.c_str(), it.second.description.c_str()); } diff --git a/src/processing.cpp b/src/processing.cpp index c9bb979..2707653 100644 --- a/src/processing.cpp +++ b/src/processing.cpp @@ -401,20 +401,18 @@ bool r_delete_var(_obj* in, set_t* vars) return true; } -void insert_lxsh_commands(shmain* sh) +std::set find_lxsh_commands(shmain* sh) { + std::set ret; cmdmap_get(sh, regex_null); - bool req_rescan=false; - for(auto it: lxsh_shellcode_fcts) + for(auto it: lxsh_extend_fcts) { if(m_cmds.find(it.first) != m_cmds.end()) { - sh->lst->insert(0, make_condlist(it.second.code)); - req_rescan=true; + ret.insert(it.first); } } - if(req_rescan) - require_rescan_all(); + return ret; } /** JSON **/ diff --git a/src/shellcode.cpp b/src/shellcode.cpp index 45a5078..a71bce7 100644 --- a/src/shellcode.cpp +++ b/src/shellcode.cpp @@ -1,8 +1,47 @@ #include "shellcode.hpp" #include "g_shellcode.h" +#include "processing.hpp" +#include "struc_helper.hpp" -const std::map lxsh_shellcode_fcts = { - { "_lxsh_random_string", { "N", "Generate a random alphanumeric string of length N. Default 20", RANDOM_STRING_SH} }, - { "_lxsh_random_tmpfile", { "N", "Get a random TMP filepath, with N random chars. Default 20", RANDOM_TMPFILE_SH} } +const std::map lxsh_extend_fcts = { + { "_lxsh_random_string", { "[N]", "Generate a random alphanumeric string of length N. Default 20", RANDOM_STRING_SH} }, + { "_lxsh_random_tmpfile", { "[N]", "Get a random TMP filepath, with N random chars. Default 20", RANDOM_TMPFILE_SH, {"_lxsh_random_string"} } } }; + +const std::map lxsh_array_fcts = { + { "_lxsh_array_create", { "", "Create an array out of input arguments", ARRAY_CREATE_SH} }, + { "_lxsh_array_get", { " ", "Get value from array", ARRAY_GET_SH} }, + { "_lxsh_array_set", { " ", "Set value of array", ARRAY_SET_SH} }, + { "_lxsh_map_create", { "", "Create a map (associative array) out of input arguments", MAP_CREATE_SH} }, + { "_lxsh_map_get", { " ", "Get value from map", MAP_GET_SH} }, + { "_lxsh_map_set", { " ", "Set value of map", MAP_SET_SH} } +}; + +std::map create_allfcts() +{ + auto r = lxsh_array_fcts; + for(auto it: lxsh_extend_fcts) + r.insert(it); + return r; +} + +const std::map lxsh_allfcts = create_allfcts(); + +void add_lxsh_fcts(shmain* sh, std::set fcts) +{ + // resolve dependencies + for(auto fctname: fcts) + { + auto ti=lxsh_allfcts.find(fctname); + if(ti != lxsh_allfcts.end()) + for(auto dep: ti->second.depends_on) + fcts.insert(dep); + } + // insert functions + for(auto it: fcts) + { + sh->lst->insert(0, make_condlist(lxsh_allfcts.find(it)->second.code) ); + } + require_rescan_all(); +}