| /* ********************************************************** |
| * Copyright (c) 2003-2010 VMware, Inc. All rights reserved. |
| * **********************************************************/ |
| |
| /* |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * * Neither the name of VMware, Inc. nor the names of its contributors may be |
| * used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| */ |
| |
| /* |
| * DRcontrol.c |
| * |
| * command-line tool for changing registry options |
| * |
| * |
| * (c) araksha, inc. all rights reserved |
| */ |
| #include <wchar.h> |
| |
| #include "share.h" |
| #include "config.h" |
| #include "processes.h" |
| |
| #include <stdio.h> |
| |
| /* convenience macros for secure string buffer operations */ |
| #define BUFFER_SIZE_BYTES(buf) sizeof(buf) |
| #define BUFFER_SIZE_ELEMENTS(buf) (BUFFER_SIZE_BYTES(buf) / sizeof(buf[0])) |
| #define BUFFER_LAST_ELEMENT(buf) buf[BUFFER_SIZE_ELEMENTS(buf) - 1] |
| #define NULL_TERMINATE_BUFFER(buf) BUFFER_LAST_ELEMENT(buf) = 0 |
| #define BUFFER_ROOM_LEFT_W(wbuf) (BUFFER_SIZE_ELEMENTS(wbuf) - wcslen(wbuf) - 1) |
| #define BUFFER_ROOM_LEFT(abuf) (BUFFER_SIZE_ELEMENTS(abuf) - strlen(abuf) - 1) |
| |
| typedef unsigned char byte; |
| |
| //helper from config.c, not defined in confg.h |
| void dump_config_group(char *, char *, ConfigGroup *, BOOL); |
| |
| void |
| usage() |
| { |
| fprintf(stderr, |
| "Usage:\nDRControl [-help] [-create path] [-destroy] [-exists] [-reset] \n" |
| "\t[-app name] [-add name] [-remove name] [-run N] [-options string] \n" |
| "\t[-detach pid] [-detachexe name] [-detachall] [-drlib dll]\n" |
| "\t[-preinject {ON|OFF|CLEAR|LIST|REPORT|LOAD_ON|LOAD_OFF|dll}]\n" |
| "\t[-create_eventlog path] [-destroy_eventlog] [-logdir path]\n" |
| "\t[-sharedcache path]\n" |
| "\t[-dump] [-fulldump] [-appdump name] [-load file] [-save file]\n" |
| "\t[-drhome path] [-modes path] [-defs path] \n" |
| "\t[-v] [-hot_patch_nudge pid] [-hot_patch_modes_nudge pid]\n" |
| "\t[-hot_patch_nudge_all] [-hot_patch_modes_nudge_all]\n" |
| "\t[-pid pid] [-all] [-timeout ms] [-delay ms]\n" |
| "\t[-drpop] [-nudge type] [-client_nudge arg] [-verbose] [-canary_default]\n" |
| "\t[-canary <full path of canary.exe> <path to a scratch folder]\n" |
| "\t[-canary_run <run_flags>] [-canary_fault <run_flag> <ops>]\n" |
| "\t[-32] [-64]\n"); |
| exit(1); |
| } |
| |
| void |
| help() |
| { |
| fprintf(stderr, "Configuration Options:\n"); |
| fprintf(stderr, " -create path\t\tcreate a registry and log dir setup, using 'path' as\n\t\t\tDYNAMORIO_HOME (does not change an existing setup)\n"); |
| fprintf(stderr, " -destroy\t\tdelete entire product registry key\n"); |
| fprintf(stderr, " -exists\t\tdisplays whether or not product reg key exists\n\t\t\t(returns 0 if exists, not 0 otherwises)\n"); |
| fprintf(stderr, " -reset\t\t\tremove all app-specific keys\n"); |
| |
| fprintf(stderr, " -app name\t\tset app-specific options\n"); |
| fprintf(stderr, " -add name\t\tadd a new application to the configuration (if not there already)\n"); |
| fprintf(stderr, " -remove name\t\tremove the apps from the configuration\n"); |
| fprintf(stderr, " -run N\t\t\tset global or app-specific RUNUNDER=N\n"); |
| fprintf(stderr, " -options string\tsets the options string to 'string'\n"); |
| fprintf(stderr, " -drlib dll\t\tsets the SC library to use; must be a fully\n"); |
| fprintf(stderr, "\t\t\tqualified pathname\n"); |
| |
| fprintf(stderr, " -preinject {ON|OFF|CLEAR|LIST|REPORT|dll}\n\t\t\tON=set to default, OFF=remove, CLEAR=wipe out list,\n\t\t\tLIST=display current AppInit_DLLs setting;,\n\t\t\tREPORT=display current preinject setting, if any;\n\t\t\tLOAD_OFF=(vista only) turns off loading preinject library;\n\t\t\tLOAD_ON=(vista ionly) turns on loading preinject library;\n\t\t\tdll sets the preinject library to use, must be a\n\t\t\tfully qualified pathname\n"); |
| fprintf(stderr, " -create_eventlog path\t\tinitializes eventlog for "PRODUCT_NAME" library at path\n"); |
| fprintf(stderr, " -destroy_eventlog\t\tfrees our eventlog\n"); |
| fprintf(stderr, " -drhome path\t\tsets DYNAMORIO_HOME to path\n"); |
| fprintf(stderr, " -modes path\t\tsets the modes file directory to path\n"); |
| fprintf(stderr, " -defs path\t\tsets the defs file directory to path\n"); |
| fprintf(stderr, " -logdir path\t\tsets the logging directory\n"); |
| fprintf(stderr, " -sharedcache path\t\tsets the shared DLL cache directory\n"); |
| fprintf(stderr, " -dump\t\t\tdisplays the current configuration\n"); |
| fprintf(stderr, " -fulldump\t\tsame as -dump (deprecated)\n"); |
| fprintf(stderr, " -appdump\t\tdisplays the current app configuration\n"); |
| |
| fprintf(stderr, " -load file\t\tloads configuration from the specified file\n"); |
| fprintf(stderr, " -save file\t\tsaves current configuration to the specified file\n"); |
| fprintf(stderr, " -v\t\t\tdisplay version information\n\n"); |
| fprintf(stderr, "all options/lists/strings should be enclosed in \"'s\n"); |
| fprintf(stderr, "by 'app', we mean the name of an executable (eg notepad.exe), \n"); |
| fprintf(stderr, "\tor the name of a svchost group (eg svchost.exe-netsvcs).\n"); |
| fprintf(stderr, "when not using -app, all settings apply to the globals\n\n"); |
| fprintf(stderr, " -32\t\tconfigure for 32-bit (WOW64) applications\n"); |
| fprintf(stderr, " -64\t\tconfigure for 64-bit (non-WOW64) applications\n"); |
| |
| fprintf(stderr, "Control Options:\n"); |
| fprintf(stderr, " -detach pid\t\tdetaches from indicated pid\n"); |
| fprintf(stderr, " -detachexe name\tdetaches from all processes with given .exe name\n"); |
| fprintf(stderr, " -detachall\t\tdetaches from all processes\n"); |
| fprintf(stderr, " -hot_patch_nudge\tforces hot patch defs and modes information to be re-read for pid\n"); |
| fprintf(stderr, " -hot_patch_modes_nudge\tforces hot patch modes information to be re-read for pid\n"); |
| fprintf(stderr, " -hot_patch_nudge_all\tforces hot patch defs and modes information to be re-read for all processes\n"); |
| fprintf(stderr, " -hot_patch_modes_nudge_all\tforces hot patch modes information to be re-read for all processes\n"); |
| fprintf(stderr, " -pid pid\t\tpid to be nudged\n"); |
| fprintf(stderr, " -all or -pid -1\t\tnudge all DR processes\n"); |
| fprintf(stderr, " -delay ms\t\tdelay between nudges\n"); |
| fprintf(stderr, " -timeout ms\t\texpected time for nudge completion\n"); |
| fprintf(stderr, " -nudge type\t\tnudge action, can be repeated\n"); |
| fprintf(stderr, " -client_nudge arg\t\tsend client nudge with specified hex arg\n"); |
| /* same as -nudge reset -nudge opt, but NOT the same as -reset which wipes out the registry! */ |
| fprintf(stderr, " -drpop\t\t\tcache reset\n"); |
| fprintf(stderr, " -canary_default\trun canary test as PE would using registry implict setup, returns canary code\n"); |
| fprintf(stderr, " -canary path_canary path_scratch_folder\trun customized canary test, returns canary code\n"); |
| fprintf(stderr, " -canary_run run_flags\toverride the runs flags for the canary run\n"); |
| fprintf(stderr, " -canary_fault run_flag ops\tinject a fault at canary run run_flag by setting canry options to ops\n"); |
| |
| exit(1); |
| } |
| |
| void |
| checked_operation(char *label, DWORD res) |
| { |
| if (res != ERROR_SUCCESS) { |
| fprintf(stderr, "Error %d on operation: %s\n", res, label); |
| exit(-1); |
| } |
| } |
| |
| |
| int |
| main(int argc, char **argv) |
| { |
| int res=0, |
| run=0, |
| dump=0, |
| reset=0, |
| detachall=0, |
| detachpid=0, |
| all=0, /* applies to all running processes */ |
| pid=-1, /* applies to pid, -1 means -all */ |
| hotp_nudge_pid=0, |
| hotp_modes_nudge_pid=0, |
| hotp_nudge_all=0, |
| hotp_modes_nudge_all=0, |
| nudge=0, /* generic nudge with argument */ |
| nudge_action_mask=0, /* generic nudge action mask */ |
| delay_ms_all= /* delay between acting on processes */ |
| NUDGE_NO_DELAY, |
| timeout_ms= /* timeout for finishing a nudge on a single process */ |
| DETACH_RECOMMENDED_TIMEOUT, |
| runval=0, |
| canary_default=0, |
| canary_run = CANARY_RUN_FLAGS_DEFAULT, |
| canary_fault_run = 0, |
| exists = 0, |
| destroy = 0, |
| free_eventlog = 0; |
| |
| uint64 nudge_client_arg=0; /* client nudge argument */ |
| |
| int verbose = 0; |
| |
| char *create=NULL, |
| *addapp=NULL, |
| *appdump=NULL, |
| *removeapp=NULL, |
| *opstring=NULL, |
| *drdll=NULL, |
| *preinject=NULL, |
| *logdir=NULL, |
| *sharedcache=NULL, |
| *appname=NULL, |
| *drhome=NULL, |
| *modes=NULL, |
| *defs=NULL, |
| *detach_exename=NULL, |
| *load=NULL, |
| *save=NULL, |
| *eventlog=NULL, |
| *canary_process=NULL, |
| *scratch_folder=NULL, |
| *canary_fault_ops=NULL; |
| |
| dr_platform_t dr_platform = DR_PLATFORM_DEFAULT; |
| |
| int argidx=1; |
| |
| WCHAR wbuf[MAX_PATH]; |
| ConfigGroup *policy = NULL, *working_group; |
| |
| if (argc < 2) |
| usage(); |
| |
| while (argidx < argc) { |
| |
| if (!strcmp(argv[argidx], "-help")) { |
| help(); |
| } |
| /* ******************** actions on active processes ******************** */ |
| else if (!strcmp(argv[argidx], "-detachall")) { |
| detachall=1; |
| } |
| else if (!strcmp(argv[argidx], "-detach")) { |
| if (++argidx >= argc) |
| usage(); |
| detachpid=atoi(argv[argidx]); |
| } |
| else if (!strcmp(argv[argidx], "-detachexe")) { |
| if (++argidx >= argc) |
| usage(); |
| detach_exename=argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-pid") || !strcmp(argv[argidx], "-p")) { |
| if (++argidx >= argc) |
| usage(); |
| pid=atoi(argv[argidx]); |
| } |
| else if (!strcmp(argv[argidx], "-all")) { |
| all=1; |
| } |
| else if (!strcmp(argv[argidx], "-delay")) { |
| /* in milliseconds */ |
| if (++argidx >= argc) |
| usage(); |
| delay_ms_all=atoi(argv[argidx]); |
| } |
| else if (!strcmp(argv[argidx], "-timeout")) { |
| /* in milliseconds */ |
| if (++argidx >= argc) |
| usage(); |
| timeout_ms=atoi(argv[argidx]); |
| } |
| else if (!strcmp(argv[argidx], "-hot_patch_nudge")) { |
| if (++argidx >= argc) |
| usage(); |
| hotp_nudge_pid=atoi(argv[argidx]); |
| } |
| else if (!strcmp(argv[argidx], "-hot_patch_modes_nudge")) { |
| if (++argidx >= argc) |
| usage(); |
| hotp_modes_nudge_pid=atoi(argv[argidx]); |
| } |
| else if (!strcmp(argv[argidx], "-hot_patch_nudge_all")) { |
| hotp_nudge_all = 1; |
| } |
| else if (!strcmp(argv[argidx], "-verbose")) { |
| verbose = 1; |
| } |
| else if (!strcmp(argv[argidx], "-hot_patch_modes_nudge_all")) { |
| hotp_modes_nudge_all = 1; |
| } |
| else if (!strcmp(argv[argidx], "-drpop")) { |
| nudge = 1; |
| /* allow composition */ |
| nudge_action_mask |= NUDGE_GENERIC(opt) | NUDGE_GENERIC(reset); |
| } |
| else if (!strcmp(argv[argidx], "-nudge")) { |
| int nudge_numeric; |
| if (++argidx >= argc) |
| usage(); |
| nudge_numeric = atoi(argv[argidx]); /* 0 if fails */ |
| nudge_action_mask |= nudge_numeric; |
| |
| /* compare against numeric new code, or against symbolic names */ |
| /* -nudge opt -nudge reset -nudge stats -nudge 30000 */ |
| { |
| int found = 0; |
| #define NUDGE_DEF(name, comment) if (strcmp(#name, argv[argidx]) == 0) { found = 1; nudge_action_mask |= NUDGE_GENERIC(name);} |
| NUDGE_DEFINITIONS(); |
| #undef NUDGE_DEF |
| if (!found && nudge_numeric == 0) { |
| printf("unknown -nudge %s\n", argv[argidx]); |
| usage(); |
| } |
| } |
| |
| nudge=1; |
| } |
| else if (!strcmp(argv[argidx], "-client_nudge")) { |
| if (++argidx >= argc) |
| usage(); |
| nudge_client_arg = _strtoui64(argv[argidx], NULL, 16); |
| nudge_action_mask |= NUDGE_GENERIC(client); |
| nudge = 1; |
| } |
| /* ******************** configuration actions ******************** */ |
| else if (!strcmp(argv[argidx], "-reset")) { |
| reset=1; |
| } |
| else if (!strcmp(argv[argidx], "-create")) { |
| if (++argidx >= argc) |
| usage(); |
| create = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-destroy")) { |
| destroy = 1; |
| } |
| else if (!strcmp(argv[argidx], "-exists")) { |
| exists = 1; |
| } |
| else if (!strcmp(argv[argidx], "-run")) { |
| run = 1; |
| if (++argidx >= argc) |
| usage(); |
| runval = atoi(argv[argidx]); |
| } |
| else if (!strcmp(argv[argidx], "-app")) { |
| if (++argidx >= argc) |
| usage(); |
| appname = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-add")) { |
| if (++argidx >= argc) |
| usage(); |
| addapp = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-remove")) { |
| if (++argidx >= argc) |
| usage(); |
| removeapp = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-options")) { |
| if (++argidx >= argc) |
| usage(); |
| opstring = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-drlib")) { |
| if (++argidx >= argc) |
| usage(); |
| drdll = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-preinject")) { |
| if (++argidx >= argc) |
| usage(); |
| preinject = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-create_eventlog")) { |
| if (++argidx >= argc) |
| usage(); |
| eventlog = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-destroy_eventlog")) { |
| free_eventlog = 1; |
| } |
| else if (!strcmp(argv[argidx], "-drhome")) { |
| if (++argidx >= argc) |
| usage(); |
| drhome = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-modes")) { |
| if (++argidx >= argc) |
| usage(); |
| modes = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-defs")) { |
| if (++argidx >= argc) |
| usage(); |
| defs = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-logdir")) { |
| if (++argidx >= argc) |
| usage(); |
| logdir = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-sharedcache")) { |
| if (++argidx >= argc) |
| usage(); |
| sharedcache = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-load")) { |
| if (++argidx >= argc) |
| usage(); |
| load = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-save")) { |
| if (++argidx >= argc) |
| usage(); |
| save = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-dump")) { |
| dump = 1; |
| } |
| else if (!strcmp(argv[argidx], "-appdump")) { |
| if (++argidx >= argc) |
| usage(); |
| appdump = argv[argidx]; |
| } |
| else if (!strcmp(argv[argidx], "-fulldump")) { |
| dump = 1; |
| } |
| else if (!strcmp(argv[argidx], "-v")) { |
| #ifdef BUILD_NUMBER |
| printf("DRcontrol.exe build %d -- %s", BUILD_NUMBER, __DATE__); |
| #else |
| printf("DRcontrol.exe custom build -- %s, %s", __DATE__, __TIME__); |
| #endif |
| } else if (!strcmp(argv[argidx], "-canary_default")) { |
| canary_default = 1; |
| } else if (!strcmp(argv[argidx], "-canary")) { |
| if (++argidx >= argc) |
| usage(); |
| canary_process=argv[argidx]; |
| if (++argidx >= argc) |
| usage(); |
| scratch_folder=argv[argidx]; |
| } else if (!strcmp(argv[argidx], "-canary_run")) { |
| if (++argidx >= argc) |
| usage(); |
| canary_run = strtol(argv[argidx], NULL, 0); |
| } else if (!strcmp(argv[argidx], "-canary_fault")) { |
| char *dummy; |
| if (++argidx >= argc) |
| usage(); |
| canary_fault_run = strtol(argv[argidx], &dummy, 0); |
| if (++argidx >= argc) |
| usage(); |
| canary_fault_ops = argv[argidx]; |
| } else if (!strcmp(argv[argidx], "-32")) { |
| dr_platform = DR_PLATFORM_32BIT; |
| } else if (!strcmp(argv[argidx], "-64")) { |
| dr_platform = DR_PLATFORM_64BIT; |
| } else { |
| fprintf(stderr, "Unknown option: %s\n", argv[argidx]); |
| usage(); |
| } |
| argidx++; |
| } |
| |
| /* PR 244206: set the registry view before any registry access */ |
| set_dr_platform(dr_platform); |
| |
| if (canary_process != NULL || canary_default != 0) { |
| BOOL result = TRUE; |
| WCHAR canary_fault_args[MAX_PATH]; |
| CANARY_INFO info = {0}; |
| |
| info.run_flags = canary_run; |
| info.info_flags = CANARY_INFO_FLAGS_DEFAULT; |
| info.fault_run = canary_fault_run; |
| _snwprintf(canary_fault_args, BUFFER_SIZE_ELEMENTS(canary_fault_args), |
| L"%S", canary_fault_ops); |
| NULL_TERMINATE_BUFFER(canary_fault_args); |
| info.canary_fault_args = canary_fault_args; |
| |
| if (canary_process != NULL && *canary_process != '\0' && |
| scratch_folder != NULL && *scratch_folder != '\0') { |
| wchar_t canary[MAX_PATH], scratch[MAX_PATH], out[MAX_PATH]; |
| FILE *out_file; |
| _snwprintf(canary, BUFFER_SIZE_ELEMENTS(canary), L"%S", canary_process); |
| NULL_TERMINATE_BUFFER(canary); |
| _snwprintf(scratch, BUFFER_SIZE_ELEMENTS(scratch), L"%S\\canary_test", |
| scratch_folder); |
| NULL_TERMINATE_BUFFER(scratch); |
| CreateDirectory(scratch, NULL); |
| _snwprintf(out, BUFFER_SIZE_ELEMENTS(out), L"%S\\canary_report.crep", |
| scratch_folder); |
| out_file = _wfopen(out, L"wb"); |
| /* FIXME - check directory, out_file, and canary proc exist */ |
| result = run_canary_test_ex(out_file, &info, scratch, canary); |
| } else if (canary_default != 0) { |
| result = run_canary_test(&info, L_EXPAND_LEVEL(STRINGIFY(BUILD_NUMBER))); |
| printf("See report file \"%S\"\n", info.report); |
| } |
| printf("Canary test - %s enable protection - code 0x%08x\n" |
| " msg=\"%S\"\n url=\"%S\"\n", result ? "do" : "don\'t", |
| info.canary_code, info.msg, info.url); |
| return info.canary_code; |
| } |
| |
| if (exists) { |
| if (get_dynamorio_home() != NULL) { |
| printf("Registry setup exists\n"); |
| return 0; |
| } |
| printf("Registry setup doesn't exist\n"); |
| return 1; |
| } |
| |
| if (save) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", save); |
| NULL_TERMINATE_BUFFER(wbuf); |
| checked_operation("save policy", save_policy(wbuf)); |
| } |
| |
| if (destroy) { |
| checked_operation("delete product key", destroy_root_key()); |
| if (!load && create == NULL) |
| return 0; |
| } |
| |
| if (load) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", load); |
| NULL_TERMINATE_BUFFER(wbuf); |
| checked_operation("load policy", load_policy(wbuf, FALSE, NULL)); |
| } |
| |
| if (create != NULL) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", create); |
| NULL_TERMINATE_BUFFER(wbuf); |
| /* FALSE: do not overwrite (preserves old behavior) */ |
| checked_operation("create registry", setup_installation(wbuf, FALSE)); |
| } |
| |
| /* ensure we init dynamorio_home, case 4009 */ |
| get_dynamorio_home(); /* ignore return value */ |
| |
| if (nudge) { |
| if (verbose) |
| printf("-nudge %d -pid %d %s\n", nudge_action_mask, pid, all ? "all" : ""); |
| if (pid == -1) /* explicitly set */ |
| all = 1; |
| |
| if (all) |
| checked_operation("nudge all", |
| generic_nudge_all(nudge_action_mask, nudge_client_arg, |
| timeout_ms, delay_ms_all)); |
| else |
| checked_operation("nudge", |
| generic_nudge(pid, TRUE, |
| nudge_action_mask, |
| 0, /* client ID (ignored here) */ |
| nudge_client_arg, |
| timeout_ms)); |
| goto finished; |
| } |
| |
| if (detachall) { |
| checked_operation("detach all", |
| detach_all(timeout_ms)); |
| goto finished; |
| } |
| if (detachpid) { |
| checked_operation("detach", |
| detach(detachpid, TRUE, timeout_ms)); |
| goto finished; |
| } |
| |
| if (detach_exename) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", detach_exename); |
| NULL_TERMINATE_BUFFER(wbuf); |
| checked_operation("detach-exe", |
| detach_exe(wbuf, timeout_ms)); |
| goto finished; |
| } |
| |
| |
| if (hotp_nudge_pid) { |
| checked_operation("hot patch update", |
| hotp_notify_defs_update(hotp_nudge_pid, TRUE, |
| timeout_ms)); |
| goto finished; |
| } |
| |
| if (hotp_modes_nudge_pid) { |
| checked_operation("hot patch modes update", |
| hotp_notify_modes_update(hotp_modes_nudge_pid, TRUE, |
| timeout_ms)); |
| goto finished; |
| } |
| |
| if (hotp_nudge_all) { |
| checked_operation("hot patch nudge all", |
| hotp_notify_all_defs_update(timeout_ms)); |
| goto finished; |
| } |
| |
| if (hotp_modes_nudge_all) { |
| checked_operation("hot patch modes nudge all", |
| hotp_notify_all_modes_update(timeout_ms)); |
| goto finished; |
| } |
| |
| checked_operation("read config", |
| read_config_group(&policy, L_PRODUCT_NAME, TRUE)); |
| |
| if (reset) { |
| remove_children(policy); |
| policy->should_clear = TRUE; |
| checked_operation("write registry", write_config_group(policy)); |
| } |
| |
| working_group = policy; |
| |
| if (dump || appdump) |
| goto dumponly; |
| |
| if (preinject) { |
| if (0 == strcmp(preinject, "OFF")) { |
| checked_operation("unset autoinject", unset_autoinjection()); |
| } |
| else if (0 == strcmp(preinject, "ON")) { |
| checked_operation("set autoinject", set_autoinjection()); |
| } |
| else if (0 == strcmp(preinject, "CLEAR")) { |
| checked_operation("clear autoinject", |
| set_autoinjection_ex(FALSE, |
| APPINIT_USE_WHITELIST, |
| NULL, |
| L"", |
| NULL, |
| NULL, |
| NULL, |
| 0)); |
| } |
| else if (0 == strcmp(preinject, "LIST")) { |
| WCHAR list[MAX_PARAM_LEN]; |
| checked_operation("read appinit", |
| get_config_parameter(INJECT_ALL_KEY_L, |
| TRUE, |
| INJECT_ALL_SUBKEY_L, |
| list, |
| MAX_PARAM_LEN)); |
| printf("%S\n", list); |
| if (is_vista()) { |
| printf("LoadAppInit is %s\n", |
| is_loadappinit_set() ? "on" : "off"); |
| } |
| } |
| else if (0 == strcmp(preinject, "REPORT")) { |
| WCHAR list[MAX_PARAM_LEN], *entry, *sep; |
| checked_operation("read appinit", |
| get_config_parameter(INJECT_ALL_KEY_L, |
| TRUE, |
| INJECT_ALL_SUBKEY_L, |
| list, |
| MAX_PARAM_LEN)); |
| entry = get_entry_location(list, L_EXPAND_LEVEL(INJECT_DLL_8_3_NAME), |
| APPINIT_SEPARATOR_CHAR); |
| if (NULL != entry) { |
| sep = wcschr(entry, APPINIT_SEPARATOR_CHAR); |
| if (NULL != sep) |
| *sep = L'\0'; |
| printf("%S\n", entry); |
| if (is_vista()) { |
| printf("LoadAppInit is %s\n", |
| is_loadappinit_set() ? "on" : "off"); |
| } |
| } |
| } |
| else if (0 == strcmp(preinject, "LOAD_OFF")) { |
| checked_operation("unset load autoinject", unset_loadappinit()); |
| } |
| else if (0 == strcmp(preinject, "LOAD_ON")) { |
| checked_operation("set load autoinject", set_loadappinit()); |
| } |
| else { |
| _snwprintf(wbuf, MAX_PATH, L"%S", preinject); |
| NULL_TERMINATE_BUFFER(wbuf); |
| checked_operation("set custom autoinject", |
| set_autoinjection_ex(TRUE, APPINIT_OVERWRITE, |
| NULL, NULL, NULL, wbuf, |
| NULL, 0)); |
| } |
| |
| if (0 != strcmp(preinject, "LIST") && |
| 0 != strcmp(preinject, "REPORT") && |
| using_system32_for_preinject(NULL)) { |
| DWORD platform; |
| if (get_platform(&platform) == ERROR_SUCCESS && |
| platform == PLATFORM_WIN_NT_4) { |
| fprintf(stderr, "Warning! On NT4, new AppInit_DLLs setting will not take effect until reboot!\n"); |
| } |
| } |
| |
| } |
| |
| if (free_eventlog) { |
| checked_operation("free eventlog", destroy_eventlog()); |
| } |
| |
| if (eventlog) { |
| _snwprintf(wbuf, BUFFER_SIZE_ELEMENTS(wbuf), L"%S", eventlog); |
| NULL_TERMINATE_BUFFER(wbuf); |
| checked_operation("create eventlog", create_eventlog(wbuf)); |
| } |
| |
| /* configuration */ |
| |
| |
| if (addapp) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", addapp); |
| NULL_TERMINATE_BUFFER(wbuf); |
| if (NULL == get_child(wbuf, policy)) { |
| add_config_group(policy, new_config_group(wbuf)); |
| } |
| } |
| |
| if (removeapp) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", removeapp); |
| NULL_TERMINATE_BUFFER(wbuf); |
| remove_child(wbuf, policy); |
| policy->should_clear = TRUE; |
| } |
| |
| if (appname) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", appname); |
| NULL_TERMINATE_BUFFER(wbuf); |
| working_group = get_child(wbuf, policy); |
| |
| if (NULL == working_group) { |
| working_group = new_config_group(wbuf); |
| add_config_group(policy, working_group); |
| } |
| } |
| |
| if (run) { |
| _snwprintf(wbuf, MAX_PATH, L"%d", runval); |
| NULL_TERMINATE_BUFFER(wbuf); |
| set_config_group_parameter(working_group, |
| L_DYNAMORIO_VAR_RUNUNDER, wbuf); |
| } |
| |
| if (opstring) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", opstring); |
| NULL_TERMINATE_BUFFER(wbuf); |
| set_config_group_parameter(working_group, |
| L_DYNAMORIO_VAR_OPTIONS, wbuf); |
| } |
| |
| if (drdll) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", drdll); |
| NULL_TERMINATE_BUFFER(wbuf); |
| set_config_group_parameter(working_group, |
| L_DYNAMORIO_VAR_AUTOINJECT, wbuf); |
| } |
| |
| if (drhome) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", drhome); |
| NULL_TERMINATE_BUFFER(wbuf); |
| set_config_group_parameter(working_group, |
| L_DYNAMORIO_VAR_HOME, wbuf); |
| } |
| |
| if (modes) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", modes); |
| NULL_TERMINATE_BUFFER(wbuf); |
| set_config_group_parameter(working_group, |
| L_DYNAMORIO_VAR_HOT_PATCH_MODES, wbuf); |
| } |
| |
| if (defs) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", defs); |
| NULL_TERMINATE_BUFFER(wbuf); |
| set_config_group_parameter(working_group, |
| L_DYNAMORIO_VAR_HOT_PATCH_POLICIES, wbuf); |
| } |
| |
| if (logdir) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", logdir); |
| NULL_TERMINATE_BUFFER(wbuf); |
| set_config_group_parameter(working_group, |
| L_DYNAMORIO_VAR_LOGDIR, wbuf); |
| } |
| |
| if (sharedcache) { |
| /* note if the sharedcache root directory doesn't exist it should be |
| * created before calling this function */ |
| _snwprintf(wbuf, MAX_PATH, L"%S", sharedcache); |
| NULL_TERMINATE_BUFFER(wbuf); |
| |
| res = setup_cache_shared_directories(wbuf); |
| if (res != ERROR_SUCCESS) { |
| fprintf(stderr, "error %d creating directories!\n", res); |
| } |
| setup_cache_shared_registry(wbuf, working_group); |
| } |
| |
| checked_operation("write policy", write_config_group(policy)); |
| |
| dumponly: |
| |
| if (appdump) { |
| _snwprintf(wbuf, MAX_PATH, L"%S", appdump); |
| NULL_TERMINATE_BUFFER(wbuf); |
| working_group = get_child(wbuf, policy); |
| } |
| else { |
| working_group = policy; |
| } |
| |
| if (dump || appdump) { |
| if (NULL == working_group) |
| fprintf(stderr, "No Configuration Exists!\n"); |
| else |
| dump_config_group(""," ",working_group,FALSE); |
| } |
| |
| finished: |
| if (policy != NULL) |
| free_config_group(policy); |
| |
| return 0; |
| |
| } |