restructure internal shellcode structure

This commit is contained in:
zawz 2021-03-26 14:58:17 +01:00
parent 588aae09e9
commit 6828dd7bae
9 changed files with 116 additions and 74 deletions

View file

@ -4,16 +4,11 @@
#include "struc.hpp"
#include <map>
#include <set>
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<std::string> required_fcts;
void require_fct(std::string const& in) { required_fcts.insert(in); }
// map of detected arrays
// bool value: is associative
std::map<std::string,bool> 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<std::string> debashify(_obj* o, debashify_params* params);
std::set<std::string> debashify(shmain* sh);
#endif //DEBASHIFY_HPP

View file

@ -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<std::string,uint32_t> countmap_t;
@ -73,7 +73,7 @@ bool r_delete_var(_obj* in, set_t* vars);
/** Processing **/
void insert_lxsh_commands(shmain* sh);
std::set<std::string> find_lxsh_commands(shmain* sh);
void add_unset_variables(shmain* sh, std::regex const& exclude);
#endif //PROCESSING_HPP

View file

@ -1,15 +1,24 @@
#ifndef SHELLCODE_HPP
#define SHELLCODE_HPP
#include <map>
#include <string>
#include <set>
#include <vector>
#include <map>
#include "struc.hpp"
struct lxsh_fct {
std::string arguments;
std::string description;
const char* code;
std::vector<std::string> depends_on=std::vector<std::string>();
};
extern const std::map<const std::string, const struct lxsh_fct> lxsh_shellcode_fcts;
extern const std::map<const std::string, const struct lxsh_fct> lxsh_extend_fcts;
extern const std::map<const std::string, const struct lxsh_fct> lxsh_array_fcts;
extern const std::map<const std::string, const struct lxsh_fct> lxsh_allfcts;
void add_lxsh_fcts(shmain* sh, std::set<std::string> fcts);
#endif //SHELLCODE_HPP

View file

@ -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<string_subarg*>(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<std::string> debashify(_obj* o, debashify_params* params)
{
recurse(r_debashify, o, params);
return params->required_fcts;
}
//
void debashify(shmain* sh)
// return value: dependencies
std::set<std::string> debashify(shmain* sh)
{
debashify_params params;
sh->shebang = "#!/bin/sh";
recurse(r_debashify, sh, &params);
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;
}

View file

@ -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<std::string> 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)

View file

@ -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 ; i<args.size() ; i++)
{
bool shebang_is_bin=false;
std::string file = args[i];
std::string filecontents=import_file(file);
std::string shebang=filecontents.substr(0,filecontents.find('\n'));
@ -173,12 +174,12 @@ int main(int argc, char* argv[])
{
tsh = parse_text(filecontents, file);
if(shebang_is_bin) // resolve lxsh shebang to sh
tsh->shebang="#!/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<std::string> 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"])

View file

@ -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());
}

View file

@ -401,20 +401,18 @@ bool r_delete_var(_obj* in, set_t* vars)
return true;
}
void insert_lxsh_commands(shmain* sh)
std::set<std::string> find_lxsh_commands(shmain* sh)
{
std::set<std::string> 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 **/

View file

@ -1,8 +1,47 @@
#include "shellcode.hpp"
#include "g_shellcode.h"
#include "processing.hpp"
#include "struc_helper.hpp"
const std::map<const std::string, const struct lxsh_fct> 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<const std::string, const struct lxsh_fct> 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<const std::string, const struct lxsh_fct> lxsh_array_fcts = {
{ "_lxsh_array_create", { "<VAL...>", "Create an array out of input arguments", ARRAY_CREATE_SH} },
{ "_lxsh_array_get", { "<ARRAY> <I>", "Get value from array", ARRAY_GET_SH} },
{ "_lxsh_array_set", { "<ARRAY> <I> <VAL>", "Set value of array", ARRAY_SET_SH} },
{ "_lxsh_map_create", { "<VAL...>", "Create a map (associative array) out of input arguments", MAP_CREATE_SH} },
{ "_lxsh_map_get", { "<MAP> <KEY>", "Get value from map", MAP_GET_SH} },
{ "_lxsh_map_set", { "<MAP> <KEY> <VAL>", "Set value of map", MAP_SET_SH} }
};
std::map<const std::string, const struct lxsh_fct> create_allfcts()
{
auto r = lxsh_array_fcts;
for(auto it: lxsh_extend_fcts)
r.insert(it);
return r;
}
const std::map<const std::string, const struct lxsh_fct> lxsh_allfcts = create_allfcts();
void add_lxsh_fcts(shmain* sh, std::set<std::string> 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();
}