# chSvcRunner.pl changes account an NT service runs as on remote machines via the registry. # Written 8-mar-2000 by fgb. # usage: chSvcRunner /service=svcname /runas=acctname [machinelist.fil] # # Notes: # ----- # Add code to check existing account and only change if it's not localSystem # (or user-supplied account name)? # # Nothin' but perl, baby! require "ctime.pl"; use Net::Ping; use Win32::Registry; # evil globals: $bDebug = 0; $sAppName = "chSvcRunner"; $sDate = &ctime(time); chop $sDate; $sLocalMachine = Win32::NodeName; $sMachine = ""; $sMachineList = ""; $sNow = time(); $sRunAs = ""; $sService = ""; $nTotalMachines = 0; $bVerbose = 0; $sVersion = "1.0"; MAIN: ParseCmdArgs(); if (($sRunAs eq "") || ($sService eq "")) { print "Missing or invalid syntax\n"; Help(); exit; } print "$sAppName $sVersion starting at $sDate...\n"; if ($sMachineList eq "") { if (! $bSingleMachine) { $sMachine = $sLocalMachine; print "No list supplied; trashing local machine.\n"; # arf exit; } if (-1 != &ChRunner()) { ++$nTotalMachines; } } else { open(FPCLIST,$sMachineList) || die "Can't open file $sMachineList: $!\n"; while () { if (!/^\!/) { # skip comments chop $_; s/\s(.*)//; # remove whitespace s/^\\\\//; # remove leading '\\' $sMachine = $_; if (&IsVisibleOnNet()) { if (-1 != &ChRunner()) { ++$nTotalMachines; } } } } close(FPCLIST); } print "\n$sAppName: updated $sService service on $nTotalMachines machine"; if ($nTotalMachines != 1) { print "s."; } exit; # subroutines: sub ChRunner { ### incomplete *** local $sKey = ""; local $sBaseKey = "SYSTEM\\CurrentControlSet\\Services"; local $sValName = "ObjectName"; local $hk; local $hkr; local @subkeys = (); local $pSubkeys = \@subkeys; # reference (ptr) to subkeys list $sServer = "\\\\" . $sMachine; # used by Connect() print "Updating $sMachine..."; $HKR = $main::HKEY_LOCAL_MACHINE; unless ($HKR->Connect($sServer,$hkr)) { print "Can't connect to $sServer; Win95?\n"; return -1; } $sKey = $sBaseKey . '\\' . $sService; if (!$hkr->Open($sKey,$hk)) { print "error opening key $sKey\n"; return; } if ($bDebug) { print "dbg: SetValueEx($sValName,0,REG_SZ,$sRunAs)\n"; } else { if (!$hk->SetValueEx($sValName,0,REG_SZ,$sRunAs)) { if ($bVerbose) { print "error setting value for $sValName\n"; } } else { print "Set $sValName for $sKey\n"; } } $hk->Close(); $hkr->Close(); } sub Help { printf("%s version %s\n",$sAppName,$sVersion); printf("\nusage: %s /service= /runas= [machinelist.fil]\n\n",$sAppName); print "service= value must be name as it appears in NET START listing\n"; print "runas= value is account name; if domain account, format is DOMAIN\Username\n"; } sub IsVisibleOnNet { $p = Net::Ping->new("icmp"); return ($p->ping($sMachine,1)); } sub ParseCmdArgs { unless ($#ARGV + 1) { Help(); exit; } while (@ARGV) { $_ = shift @ARGV; if ($bDebug) { print "dbg: parsing $_\n"; } if (/^[\/\-]/) { # is arg a switch? $arg = substr($_,1,3); # parse 1st 3 chars: if (($arg eq "hel") || (substr($arg,0,1) eq "?")) { &Help(); exit; } if ($arg eq "ser") { $i = index($_,"="); $i++; $sService = sprintf("%s",substr($_,$i)); } if ($arg eq "run") { $i = index($_,"="); $i++; $sRunAs = sprintf("%s",substr($_,$i)); } } else { # not a switch if (/^[\\]/) { # single machine (UNC) s/\s(.*)//; # remove whitespace s/^\\\\//; # remove leading \\ $sMachine = $_; $bSingleMachine = 1; } else { $sMachineList = $_; } } } }