#include #include #include #include #include #include "inject/options.h" void options_help(FILE *f) { assert(f != NULL); fputs( "Usage: inject [options] program args...\n" "All options must precede the program name.\n" "\n" "The following options are understood:\n" "\n" "-h\tPrint this message.\n" "\n" "-d\tAttach to target as a debugger and print debug messages.\n" "\n" "-p\tPause the target until a debugger attaches to it.\n" " \tCannot be used with -d.\n" "\n" "-w\tWait for target to terminate.\n" " \tCannot be used with -d.\n" "\n" "-k dll\tInject the named DLL into the target process.\n" " \tCan be specified more than once.\n" "\n", f); } HRESULT options_init(struct options *opt, int argc, char **argv) { int nconsumed; const char *arg; int i; assert(opt != NULL); memset(opt, 0, sizeof(*opt)); nconsumed = 1; for (i = 1 ; i < argc && argv[i][0] == '-' ; i++) { arg = argv[i]; nconsumed++; switch (arg[1]) { case 'h': opt->help = true; break; case 'd': if (opt->debug_pause || opt->wait) { return E_FAIL; } opt->debug = true; break; case 'p': if (opt->debug) { return E_FAIL; } opt->debug_pause = true; break; case 'w': if (opt->debug) { return E_FAIL; } opt->wait = true; break; case 'k': if (i + 1 >= argc) { return E_FAIL; } /* These get pulled by options_next_dll. Consume its argument as well though. */ nconsumed++; i++; break; default: return E_FAIL; } } if (nconsumed == argc) { return E_FAIL; } opt->orig_argc = argc; opt->orig_argv = argv; opt->target_argc = argc - nconsumed; opt->target_argv = argv + nconsumed; opt->dll_pos = 1; return S_OK; } HRESULT options_target_cmdline(const struct options *opt, char **out) { char *str; char *pos; size_t nchars; size_t len; int i; assert(opt != NULL); assert(out != NULL); *out = NULL; /* Measure string. Each element requires an opening quote, a closing quote and either a trailing space or a trailing NUL. */ nchars = 3 * opt->target_argc; for (i = 0 ; i < opt->target_argc ; i++) { nchars += strlen(opt->target_argv[i]); } str = malloc(nchars); if (str == NULL) { return E_OUTOFMEMORY; } /* Construct string. This doesn't escape quotes within individual args yet but ugh I'll fix that later if it really becomes necessary, it's a pain to deal with. */ for (i = 0, pos = str ; i < opt->target_argc ; i++) { len = strlen(opt->target_argv[i]); *pos++ = '"'; memcpy(pos, opt->target_argv[i], len); pos += len; *pos++ = '"'; if (i + 1 < opt->target_argc) { *pos++ = ' '; } else { *pos++ = '\0'; } } *out = str; return S_OK; } HRESULT options_next_dll(struct options *opt, const char **out) { const char *arg; assert(opt != NULL); assert(opt->orig_argv != NULL); assert(out != NULL); *out = NULL; while (opt->dll_pos < opt->orig_argc) { arg = opt->orig_argv[opt->dll_pos]; if (arg[0] != '-') { break; } opt->dll_pos++; if (arg[1] == 'k' && opt->dll_pos < opt->orig_argc) { *out = opt->orig_argv[opt->dll_pos++]; return S_OK; } } return S_FALSE; }