From b3323da564c3e2b9425cf627e7fc3605be28eeae Mon Sep 17 00:00:00 2001 From: Marc Date: Sat, 14 Apr 2018 22:00:10 +0200 Subject: [PATCH] Added ArgParse and x64 compatibility --- ShellcodeLoader/ShellcodeLoader.cpp | Bin 8262 -> 9020 bytes ShellcodeLoader/argparse.hpp | 443 ++++++++++++++++++++++++++++ ShellcodeLoader/example.exe | Bin 997 -> 0 bytes ShellcodeLoader/shellcode64.bin | Bin 0 -> 426 bytes ShellcodeLoader/shellcodex86.bin | Bin 0 -> 290 bytes ShellcodeLoader/stdafx.h | Bin 988 -> 1506 bytes 6 files changed, 443 insertions(+) create mode 100644 ShellcodeLoader/argparse.hpp delete mode 100644 ShellcodeLoader/example.exe create mode 100644 ShellcodeLoader/shellcode64.bin create mode 100644 ShellcodeLoader/shellcodex86.bin diff --git a/ShellcodeLoader/ShellcodeLoader.cpp b/ShellcodeLoader/ShellcodeLoader.cpp index ab242e17a7aad0933a3d01b885185b65220c27ac..a4852caf92e2241b2ec85a89fb7b2275c6872dc7 100644 GIT binary patch delta 2330 zcmbtWOKTHR6h2AQHj}h9R@*W3k((fz7Ta1Mh_tpoYE=Zaf{21jnoMJ9o0dFkOO=2N zcOrNM!G#EJ1%-l(;zk4)uKWRt8{N5a=SK89cP5QV$6A!jOy=Hu9^X0lJLl%@;a8(C znmqOMG)t3|;)r*c?|4JJV(csCC{J0eW++XH3X~%Y^HZ45VV0)>tTs|WKL+(-D4L-J zO+ilKS3%OE8~8l}y)<-YFwa2q9CovgJ+WZ8Ner!uC^#%D3^)#dU+cyG9L5>^ijz3S z_+Bs)j!_q2R)b6+&>voNukE_pPKr`%;J_aBz;29x_@c*lA*6n?-zED-1xCU1XFCbl z`BvXn{9ij+pb{H`tq0jEAi3p;|B9$dpM@RTI3RthYbpLseN^)yLDQ}&n!xU~q{%hy z%G*TJ`ITMx`4`fBsQTmgAdyDF9Nkgf_?F~q6x zW;eg~Z{cSVf6=alje!Px*8yFD*{K4-mBSD{33tg!lHr_2j{AJIJm>Eolc@eFE*DSb z2;Vg}@YfpuSeXY|k_1;`m1_F)VN}cNTGOZTpnf|$9xkl!0Y$c9596Sog{Y=bn5M7L zWjHyr+pH8?2D{V9W)&UzX-%|PiDLu2Kn<-|x=CHGNuZG$luERVK`h&?K83Gwbf7eb z)eP_ok0dFhp{Dsu&Hnw0c3>!qI-qlCTSF+}lB(-IzX|tG4bv6qjjT$-iS{A7c|1w| zPQkLGi)aT0q()l9qW)HxO*;2d9xDnVh@K7oDDEQ#@Rr?3_)w?WIEr+IgqpFam5ZR$lLuEB=1$~bi`-)i{iF-C9(XX!kREL%+nz1$rN zb>!e#y7)M}2|7iC7&e{-_B3qaubY%-fTN)>uLPTxLz~ak@t#0Czcf$sRr4};Zu`#f zf}!K<8d^0Q*CE>fTqIcelH!*82Atv7L2(mWz8$__%f9wzZjanF#Iyy)X?_@a{tKJM Bsm%ZY delta 1666 zcmb_cO-oc^6h60{soQ+`akFu*2{RMcj5>}A1*SzUv;r9yDM=;ad^Tt^b~RH>hM-mS z0Un6_18sr`23oZVqD^3%meC?wwd)52J?FjirGhBM<>lV@zUSk4o^#Ioe)Q9Yw_dHd zNGmi?X-Z*bC_oFeNEY3rB;Em9B@Z1TopO{{`vPn-ut{S#R6a{k0nZ$)^LWqG47|l+ z=egua;51u3%Q@}996K89tT-g;HiB5xg^(Gfo~s61qX5S=pQ8sST^!Z?hV3IDt1$SF z$H%?e$rDMy$tywu(5c0g*jZYl8#K-1TB{=>MEQA3tDeNyFxCKnF#XXCg((E9C{5$v zgrX^k(sUnt3-7xilT%+QE;jgFLViJ!Pw|H5RIC?varo7Eh`=Iu5`Mx>gb&h9;0#fO ze>eM$3}Vcw7!^I%*slkJ;W`cxrH{>_ALx`Nf7Va)N2kdz4^Q#D&soeMvxVGYn?s!RG-J*$7uzB!6`*sETXc>&ApneZOHKJOC$BlOW)$A?(Fyc;r(bB@N%*z}% yM@yS#n>M(MKhy}TNm+o7S#XwHO=eA6Gr|u|gO|Nch}~359bb2>haT~>(3`(?A1Q7C diff --git a/ShellcodeLoader/argparse.hpp b/ShellcodeLoader/argparse.hpp new file mode 100644 index 0000000..1fd027b --- /dev/null +++ b/ShellcodeLoader/argparse.hpp @@ -0,0 +1,443 @@ +#ifndef ARGPARSE_HPP_ +#define ARGPARSE_HPP_ + +#if __cplusplus >= 201103L +#include +typedef std::unordered_map IndexMap; +#else +#include +typedef std::map IndexMap; +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/*! @class ArgumentParser + * @brief A simple command-line argument parser based on the design of + * python's parser of the same name. + * + * ArgumentParser is a simple C++ class that can parse arguments from + * the command-line or any array of strings. The syntax is familiar to + * anyone who has used python's ArgumentParser: + * \code + * // create a parser and add the options + * ArgumentParser parser; + * parser.addArgument("-n", "--name"); + * parser.addArgument("--inputs", '+'); + * + * // parse the command-line arguments + * parser.parse(argc, argv); + * + * // get the inputs and iterate over them + * string name = parser.retrieve("name"); + * vector inputs = parser.retrieve>("inputs"); + * \endcode + * + */ +class ArgumentParser { +private: + class Any; + class Argument; + class PlaceHolder; + class Holder; + typedef std::string String; + typedef std::vector AnyVector; + typedef std::vector StringVector; + typedef std::vector ArgumentVector; + + // -------------------------------------------------------------------------- + // Type-erasure internal storage + // -------------------------------------------------------------------------- + class Any { + public: + // constructor + Any() : content(0) {} + // destructor + ~Any() { delete content; } + // INWARD CONVERSIONS + Any(const Any& other) : content(other.content ? other.content->clone() : 0) {} + template + Any(const ValueType& other) + : content(new Holder(other)) {} + Any& swap(Any& other) { + std::swap(content, other.content); + return *this; + } + Any& operator=(const Any& rhs) { + Any tmp(rhs); + return swap(tmp); + } + template + Any& operator=(const ValueType& rhs) { + Any tmp(rhs); + return swap(tmp); + } + // OUTWARD CONVERSIONS + template + ValueType* toPtr() const { + return content->type_info() == typeid(ValueType) + ? &static_cast*>(content)->held_ + : 0; + } + template + ValueType& castTo() { + if (!toPtr()) throw std::bad_cast(); + return *toPtr(); + } + template + const ValueType& castTo() const { + if (!toPtr()) throw std::bad_cast(); + return *toPtr(); + } + + private: + // Inner placeholder interface + class PlaceHolder { + public: + virtual ~PlaceHolder() {} + virtual const std::type_info& type_info() const = 0; + virtual PlaceHolder* clone() const = 0; + }; + // Inner template concrete instantiation of PlaceHolder + template + class Holder : public PlaceHolder { + public: + ValueType held_; + Holder(const ValueType& value) : held_(value) {} + virtual const std::type_info& type_info() const { return typeid(ValueType); } + virtual PlaceHolder* clone() const { return new Holder(held_); } + }; + PlaceHolder* content; + }; + + // -------------------------------------------------------------------------- + // Argument + // -------------------------------------------------------------------------- + static String delimit(const String& name) { + return String(std::min(name.size(), (size_t)2), '-').append(name); + } + static String strip(const String& name) { + size_t begin = 0; + begin += name.size() > 0 ? name[0] == '-' : 0; + begin += name.size() > 3 ? name[1] == '-' : 0; + return name.substr(begin); + } + static String upper(const String& in) { + String out(in); + std::transform(out.begin(), out.end(), out.begin(), ::toupper); + return out; + } + static String escape(const String& in) { + String out(in); + if (in.find(' ') != std::string::npos) out = String("\"").append(out).append("\""); + return out; + } + + struct Argument { + Argument() : short_name(""), name(""), optional(true), fixed_nargs(0), fixed(true) {} + Argument(const String& _short_name, const String& _name, bool _optional, char nargs) + : short_name(_short_name), name(_name), optional(_optional) { + if (nargs == '+' || nargs == '*') { + variable_nargs = nargs; + fixed = false; + } else { + fixed_nargs = nargs; + fixed = true; + } + } + String short_name; + String name; + bool optional; + union { + size_t fixed_nargs; + char variable_nargs; + }; + bool fixed; + String canonicalName() const { return (name.empty()) ? short_name : name; } + String toString(bool named = true) const { + std::ostringstream s; + String uname = name.empty() ? upper(strip(short_name)) : upper(strip(name)); + if (named && optional) s << "["; + if (named) s << canonicalName(); + if (fixed) { + size_t N = std::min((size_t)3, fixed_nargs); + for (size_t n = 0; n < N; ++n) s << " " << uname; + if (N < fixed_nargs) s << " ..."; + } + if (!fixed) { + s << " "; + if (variable_nargs == '*') s << "["; + s << uname << " "; + if (variable_nargs == '+') s << "["; + s << uname << "...]"; + } + if (named && optional) s << "]"; + return s.str(); + } + }; + + void insertArgument(const Argument& arg) { + size_t N = arguments_.size(); + arguments_.push_back(arg); + if (arg.fixed && arg.fixed_nargs <= 1) { + variables_.push_back(String()); + } else { + variables_.push_back(StringVector()); + } + if (!arg.short_name.empty()) index_[arg.short_name] = N; + if (!arg.name.empty()) index_[arg.name] = N; + if (!arg.optional) required_++; + } + + // -------------------------------------------------------------------------- + // Error handling + // -------------------------------------------------------------------------- + void argumentError(const std::string& msg, bool show_usage = false) { + if (use_exceptions_) throw std::invalid_argument(msg); + std::cerr << "ArgumentParser error: " << msg << std::endl; + if (show_usage) std::cerr << usage() << std::endl; + exit(-5); + } + + // -------------------------------------------------------------------------- + // Member variables + // -------------------------------------------------------------------------- + IndexMap index_; + bool ignore_first_; + bool use_exceptions_; + size_t required_; + String app_name_; + String final_name_; + ArgumentVector arguments_; + AnyVector variables_; + std::vector all_args; + +public: + ArgumentParser() : ignore_first_(true), use_exceptions_(false), required_(0) {} + // -------------------------------------------------------------------------- + // addArgument + // -------------------------------------------------------------------------- + void appName(const String& name) { app_name_ = name; } + void addArgument(const String& name, char nargs = 0, bool optional = true) { + if (name.size() > 2) { + Argument arg("", verify(name), optional, nargs); + insertArgument(arg); + } else { + Argument arg(verify(name), "", optional, nargs); + insertArgument(arg); + } + } + void addArgument(const String& short_name, const String& name, char nargs = 0, + bool optional = true) { + Argument arg(verify(short_name), verify(name), optional, nargs); + insertArgument(arg); + } + void addFinalArgument(const String& name, char nargs = 1, bool optional = false) { + final_name_ = delimit(name); + Argument arg("", final_name_, optional, nargs); + insertArgument(arg); + } + void ignoreFirstArgument(bool ignore_first) { ignore_first_ = ignore_first; } + String verify(const String& name) { + if (name.empty()) argumentError("argument names must be non-empty"); + if ((name.size() == 2 && name[0] != '-') || name.size() == 3) + argumentError(String("invalid argument '") + .append(name) + .append("'. Short names must begin with '-'")); + if (name.size() > 3 && (name[0] != '-' || name[1] != '-')) + argumentError(String("invalid argument '") + .append(name) + .append("'. Multi-character names must begin with '--'")); + return name; + } + + // -------------------------------------------------------------------------- + // Parse + // -------------------------------------------------------------------------- + void parse(size_t argc, const char** argv) { parse(StringVector(argv, argv + argc)); } + + void parse(const StringVector& argv) { + // check if the app is named + if (app_name_.empty() && ignore_first_ && !argv.empty()) app_name_ = argv[0]; + + // set up the working set + Argument active; + Argument final = final_name_.empty() ? Argument() : arguments_[index_[final_name_]]; + size_t consumed = 0; + size_t nrequired = final.optional ? required_ : required_ - 1; + size_t nfinal = final.optional ? 0 : (final.fixed ? final.fixed_nargs + : (final.variable_nargs == '+' ? 1 : 0)); + + // iterate over each element of the array + for (StringVector::const_iterator in = argv.begin() + ignore_first_; + in < argv.end() - nfinal; ++in) { + String active_name = active.canonicalName(); + String el = *in; + + // add arguments to vector + all_args.push_back(el); + + // check if the element is a key + if (index_.count(el) == 0) { + // input + // is the current active argument expecting more inputs? + if (active.fixed && active.fixed_nargs <= consumed) + argumentError(String("attempt to pass too many inputs to ").append(active_name), + true); + if (active.fixed && active.fixed_nargs == 1) { + variables_[index_[active_name]].castTo() = el; + } else { + variables_[index_[active_name]].castTo().push_back(el); + } + consumed++; + } else { + // new key! + // has the active argument consumed enough elements? + if ((active.fixed && active.fixed_nargs != consumed) || + (!active.fixed && active.variable_nargs == '+' && consumed < 1)) + argumentError(String("encountered argument ") + .append(el) + .append(" when expecting more inputs to ") + .append(active_name), + true); + active = arguments_[index_[el]]; + // check if we've satisfied the required arguments + if (active.optional && nrequired > 0) + argumentError(String("encountered optional argument ") + .append(el) + .append(" when expecting more required arguments"), + true); + // are there enough arguments for the new argument to consume? + if ((active.fixed && active.fixed_nargs > (argv.end() - in - nfinal - 1)) || + (!active.fixed && active.variable_nargs == '+' && + !(argv.end() - in - nfinal - 1))) + argumentError(String("too few inputs passed to argument ").append(el), true); + if (!active.optional) nrequired--; + consumed = 0; + } + } + + for (StringVector::const_iterator in = + std::max(argv.begin() + ignore_first_, argv.end() - nfinal); + in != argv.end(); ++in) { + String el = *in; + // check if we accidentally find an argument specifier + if (index_.count(el)) + argumentError(String("encountered argument specifier ") + .append(el) + .append(" while parsing final required inputs"), + true); + if (final.fixed && final.fixed_nargs == 1) { + variables_[index_[final_name_]].castTo() = el; + } else { + variables_[index_[final_name_]].castTo().push_back(el); + } + nfinal--; + } + + // check that all of the required arguments have been encountered + if (nrequired > 0 || nfinal > 0) + argumentError(String("too few required arguments passed to ").append(app_name_), true); + + //all_args.assign(argv, argv + argc); + } + + // -------------------------------------------------------------------------- + // Retrieve + // -------------------------------------------------------------------------- + template + T& retrieve(const String& name) { + if (index_.count(delimit(name)) == 0) throw std::out_of_range("Key not found"); + size_t N = index_[delimit(name)]; + return variables_[N].castTo(); + } + + // -------------------------------------------------------------------------- + // Properties + // -------------------------------------------------------------------------- + String usage() { + // premable app name + std::ostringstream help; + help << "Usage: " << escape(app_name_); + size_t indent = help.str().size(); + size_t linelength = 0; + + // get the required arguments + for (ArgumentVector::const_iterator it = arguments_.begin(); it != arguments_.end(); ++it) { + Argument arg = *it; + if (arg.optional) continue; + if (arg.name.compare(final_name_) == 0) continue; + help << " "; + String argstr = arg.toString(); + if (argstr.size() + linelength > 80) { + help << "\n" << String(indent, ' '); + linelength = 0; + } else { + linelength += argstr.size(); + } + help << argstr; + } + + // get the optional arguments + for (ArgumentVector::const_iterator it = arguments_.begin(); it != arguments_.end(); ++it) { + Argument arg = *it; + if (!arg.optional) continue; + if (arg.name.compare(final_name_) == 0) continue; + help << " "; + String argstr = arg.toString(); + if (argstr.size() + linelength > 80) { + help << "\n" << String(indent, ' '); + linelength = 0; + } else { + linelength += argstr.size(); + } + help << argstr; + } + + // get the final argument + if (!final_name_.empty()) { + Argument arg = arguments_[index_[final_name_]]; + String argstr = arg.toString(false); + if (argstr.size() + linelength > 80) { + help << "\n" << String(indent, ' '); + linelength = 0; + } else { + linelength += argstr.size(); + } + help << argstr; + } + + return help.str(); + } + void useExceptions(bool state) { use_exceptions_ = state; } + bool empty() const { return index_.empty(); } + void clear() { + ignore_first_ = true; + required_ = 0; + index_.clear(); + arguments_.clear(); + variables_.clear(); + } + bool exists(const String& name) const { + return find(all_args.begin(), all_args.end(), delimit(name)) != all_args.end(); + } + size_t count(const String& name) { + // check if the name is an argument + if (index_.count(delimit(name)) == 0) return 0; + size_t N = index_[delimit(name)]; + Argument arg = arguments_[N]; + Any var = variables_[N]; + // check if the argument is a vector + if (arg.fixed) { + return !var.castTo().empty(); + } else { + return var.castTo().size(); + } + } +}; +#endif diff --git a/ShellcodeLoader/example.exe b/ShellcodeLoader/example.exe deleted file mode 100644 index 80112721e6fa3b0721790238078be43d2f223948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 997 zcmeZ`n!v!!z`(!)#Q*;@Fzf)*Am9Kd@e?4meDb^a7`AYpRoubob5=1VBePhcpeR4R zC^1(dIWaFUzeFJ^RiUUfPa!i;!NosVAvZrIRgagKO9g6lVD-`)qEe^3VK^gMq+0~Y z&qx*p(?OZZ86Y`ymjt*nF!(SsGOT}pG888FfPsmTn~{fsfe9u8qy?Z@0VL)C;REH_ zKwKbz(F_Ve4pbi#gF_=&AxJOC05A=wK!O7X^h#1IN`ST>2e|;`E|8m{?gj~gfC2+U z0*EFC7@th(_B81B5k;+c2wx*Y^dNdF8$Q~nmN~|JGX-Qb+@Ym^I_vl-6j*5 zKRY$rxu=!{lzwWgV=2l{b}W6_U8=(TIjvhHth-c(`Ez&4v_H(BjsJ&dBon>%$o~uB8Tl2CjQ@O8m@^X7Q=Kw=Q;Um30{&kM k&nU`CQOw9!2+z;(NX^OVJ`)}u82L`+T0~`JUqo`>hC9aW(>~U+S6$s>h-0rBD0U zdmakkxl1&#UyWQssg?DRTqPj4*f_`ni-63rSuWQZaANbE$|R>oI>RwAm?kTMDZfyu zULhL-2YxNwO@q8SKd9t}%EQIqwL)956^v9JAGkF-&1aet(I2M{;mYd;8CaMakE0#4 z^hc{yJtAV_7!!wYv_c~%1QIGRYGRJH3;o@|IlqaEK}&yduZ3b|17i&I2FUuE<12U2 z!(GjQ{1~ugeRbbiE;!Mc-KCN}eIoE`| z0>xR@aBqeD_?I9*Uwy9Yf_`sF4bV#oy_C>PiT*ar(MyTgJf||rsgZ_K)eH4<&Rj^C Yd~zb>xvy+)oB52b*=t*ND3i}UWOL}K&dQ--ewV?V8H*$ASH)GJD&!Ig?Ib% zbe9Tr*NXf%`(MiOLKvv9lfC&kOYd&_hOD|APz zFdk$)1mqe41&?Jh{x9VTd!Y=`$I*O&Fp>m(se04?bdIyvWQL86Ou7asUU& z0fE6mh9?bg8(!*m<>(SR4- literal 0 HcmV?d00001 diff --git a/ShellcodeLoader/stdafx.h b/ShellcodeLoader/stdafx.h index 97094e0a101bdfd1d10e3c5071d216761648c648..f89a965d3a0d67ebbdf9230046761cfeaf33cd92 100644 GIT binary patch delta 513 zcmZ`$J8l9o5PeGuL{OS26j2(B3J{`5n~EFc1`*ly0utbr4MOV5)IJ(!tr#$Dx z$3#Z#dm7d1kIz;w$^+lg(&&oQJAIL1CBEl<$&69^UhO|s{}3=ZD{dN&n2>*wS1tc9 XR%6m>Lp|p2*mj}dh<