Showing posts with label Scripting. Show all posts
Showing posts with label Scripting. Show all posts

Monday, July 6, 2009

Microsoft Technet Summer Scripting Games : Javelin Throw

I was invited to be a guest commentator for the Javelin Throw event during the recently concluded Microsoft Technet's Summer Scripting Games. For this scenario, I had to write a time logger with time-stamped text entries that describe a particular activity. I created a VB script that accepts user inputs as arguments, stores these together with the date and time of the activity, amount of time spent on the activity, the status of the activity and some remarks onto a CSV file.



You can find my write-up and solution at this link:

Thursday, June 25, 2009

Checking for Remote Desktop Status of a Remote Server

Here's a script that checks for the Remote Desktop feature status of a remote server. The server hostnames are read off a servers.ini file. The server's registry is then queried for the DWORD value of fDenyTSConnections under the server's HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server registry key.




Wednesday, June 24, 2009

List Local Users of Remote Systems (Powershell)

Here's a Powershell script that reads the hostnames off a text file (hosts.ini) and lists all the local users of the remote host:

Tuesday, March 31, 2009

Rebooting a computer (VBS)

The script shown in this post pops up a message to the current logged-in user informing him that a reboot is required.




The user has the option to proceed with the reboot or he can choose to click the "No" button and abort the reboot. Clicking "Yes" will invoke the ShutMeDown procedure which uses the .Reboot method to reboot the computer. Clicking "No" will display the following pop-up:



Not clicking on either the "Yes" or "No" after 60 seconds will abort the script from continuing.



For what possible situations can this script be used? Follow the discussing from the following thread in The Official Scripting Guys Forum on Technet:

http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/65e8699f-fca4-4e08-a181-8b621acbf963

Monday, March 30, 2009

Enumerating Members of a Group (including Nested Groups)

Here's another simple and straightforward script that queries and enumerates the members of an active directory group. If there are nested groups within the groups being queried, these will also be subsequently checked and their members listed.

This is the main body of the script. I have, for this example, three sites where two groups are being queried (one group, for example, is EU-ServerAdmins-G). There is a call in the main body to the EnumGroups function where three parameters are passed - strSite, strDN and strGroupName).



The EnumGroups function queries the strDN parameter where its members are checked. In the Select-Case loop, the object class is further checked; if the object is a group by itself, the function executes again with this group as part of the parameters passed (hence, nested groups will also be queried).



The output of this script is written onto a file (groups.csv). An example output file would look like this:


Monday, March 23, 2009

Stopping and Restarting Multiple Services using VBS

Here's a script that will stop and then restart multiple services using VB script. It stores the services under an array (in this example, I was working on the BITS, Browser, and wuauserv services). Do note that the Win32_Service.Name property should be used and not the Win32_Service.DisplayName; if you want to make use of the more user-friendly or readable .DisplayName property, you have to modify the query for the variable colListOfServices. This script can also be enhanced to accept arguments from the CLI or read off an input file for a list of services to stop.



This script was created for the following thread from the Microsoft Technet's The Official Scripting Guys Forum:

http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/3db5d54d-1d7f-46c5-9129-2130a7bdfaa8/

Friday, February 27, 2009

Moderating the "The Official Scripting Guys" Forum in Technet

Yep, I am now one of the moderators of "The Official Scripting Guys Forum" in Technet. I feel humbled to be in the company of the other moderators, the best of the best, whom I have looked up to in the past. This is my own little way of "paying it forward"...

Thursday, February 12, 2009

Checking for the Uptime of a Remote Computer

I've created this script to query for the uptime of a remote computer. It takes, for an argument, the hostname or IP address of the remote machine. Here's the main body of the script:



The main body checks for 1 argument passed when the script is ran; if the number of arguments is not equal to 1, then the script exits. It then calls for the GetUptime procedure:



The GetUptime procedure queries WMI for the Win32_PerfRawData_PerfOS_System class, in particular the Timestamp_Object, Frequency_Object, and the SystemUpTime properties. To calculate for the system uptime in seconds (in my example, I used the iUptimeInSec variable), the following formula was used:

iUptimeInSec = (intPerfTimeStamp - intCounter)/intPerfTimeFreq

This value is then passed to the ConvertTime(seconds) function.



The iUptimeInSec variable was converted to an easier-t0-read format, eg. days, hours, minutes and seconds.

Monday, January 19, 2009

Identifying the current logged in user of a remote host

Here's a short and simple script to check for the currently logged-in user of a remote computer. This script has been tested on Windows XP and Vista; it may or may not work for older Windows OSes. Save the script as check-user.vbs and pass the remote host (or IP address) as an argument when launching the script (ie, check-user.vbs remote_host). You have to be an administrator of the remote machine being queried in order for the script to run properly.

Thursday, January 8, 2009

Conficker.vbs - Conficker (Worm_DownAD) Detector

Heard from the grapevine that the Conficker (Worm_DownAD) worm is still in the wild (http://msforums.ph/forums/t/50980.aspx). This worm generates randomly named services which makes it a tad difficult to detect and contain. Here's a short script I created to detect for possible rogue services triggered by this worm. The usual disclaimer applies:



The code should be self-explanatory. =)



Tuesday, November 18, 2008

Deleting *.bak Files When the Computer Turns Idle (VBS)

A similar thread from the Technet Forums:
http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/2991aa59-07c6-413e-8bf0-9ffa2bd8f0d3

Here is a script that deletes all *.bak files on a computer's D: drive when the computer becomes idle after 10 minutes.



There is actually a trick behind this script. Using a script to check whether a computer is idle is not really straightforward, but rather relatively complicated (read my lips, I don't know how to do it). I made use of the Screen Saver timeout property via a registry hack, setting it to trigger after 10 minutes (600 seconds) via the sub procedure SetScrSvrTime():



The script checks if the screen saver process is running (it is implied that in this example, the computer is configured with the "Mystify.scr" screen saver). A connection to the WMI service on the local computer is made and an event notification query which fetches within 20 seconds a list of running processes:



The Do-While loop processes the information gathered from this query and checks for the screen saver "Mystify.scr" process. If found, it goes to another loop where a call to the DelFiles(strDrv) sub procedure is launched (strDrv is the parameter passed to the sub procedure which is actually the drive where the *.bak files are going to be deleted). This sub procedure then recursively checks and deletes all *.bak files found:



This script can be further customize to accomplish other things when the computer goes idle. For example, you may want to send out notification, defrag the hard disk, run a back-up and so on. The possibilities are endless, let your imagination loose!

For those interested to have a copy of this script, please drop this post a comment.

Friday, November 14, 2008

VBS Logoff Script to Log User Information


Part 1:
http://badzmanaois.blogspot.com/2008/11/script-to-track-local-logins-vbs.html

Here's a follow-up of the posted earlier. This is executed when the user logs off. It will log the following information to the output log file:

Event Type (Login/Logoff)
User (Full User Name)
Computer
Date & Time of the Event

The output log file looks like this:



The script defines the location and name of the output log file (C:\LogFile\Login.csv) and calls the Main:



The sub procedure Main checks for the current logged in such as .UserName, .DomainName, and .ComputerName. The user's full name is then extracted and is passed to the log file (together with the other earlier-mentioned variables):


The user must have modify permission on the output log file.

Wednesday, November 5, 2008

Script to Track Local Logins (VBS)

Event 528 is logged whenever an account logs on to the local computer whereas Event ID 540 is generated in the event of network logons. It is oftentimes tedious and a tad straining to the eyes to go through the tons of events stored in the event viewer even if you filter out those events you are not interested with.

I would suggest saving the login/logoff events on a log file in a more user-friendly format for easier analysis. For example, one may want to keep track of login time for monitoring purposes while another may do this to ensure optimal usage, for example, on a shared PC where users are allocated certain hours of access.

Heres a script that saves the login information (event ID 528) on a CSV file; the user name, hostname, and the time of login are captured.

The script opens a file (or creates one if the file does not exist) for appending wherein the captured data are stored. It then calls a sub procedure called Main to extract these information. Note that users must have modify rights on the C:\LogFile\Login.csv file.



The Main sub procedure captures the current logged in user's name, domain and the hostname of the computer and then writes these information, together with the type of action (Login) and time, to the log file:



Simple. Next, we will look at this scripts partner, the logoff script to capture the logoff time of the user (logoff time - login time = total usage time).

Saturday, November 1, 2008

Remotely Removing Users from the Local Administrators Group (VBS)

Scenario: You are an administrator of a domain. You are given a task to remove "rogue" administrators of the computers in your domain. On a few machines, this task would be very trivial; you can just remotely connect to each machine and remove the user from the local administrators group. Complexity comes in when you have to remove different users for each machine. Here is a rundown of what I would do if I were given this task. The usual disclaimer applies.

Step 1: Generate a list of computers accounts of the domain (programatically or by exporting the list from the Active Directory Users and Computers snap-in) and save the output to a text file (computers.ini, in this example). Add the login account of the user you are going to remove for each machine as shown (contents of computers.ini):



Step 2: The main script reads off computers.ini the list to be used as parameters (computer name and user name). Notice that the file is read in one go and the data stored in the array arrComputers. Each object in the array is checked and passed to the RemoveAdmin sub procedure.


Step 3: Script the procedures. Three procedures are used in the script; RemoveAdmin which is a sub procedure, and the sConvert and ping  functions. The RemoveAdmin sub procedure queries the remote machine's local administrators group and if the user account (as defined in computers.ini) is found, it is removed from the group.


The sConvert function will return a string depending on the code parameter passed. If code is set to "1," the value returned is the computer account whereas if it is set to "2," the value returned is the user account (note the Select Case section).

The ping function is self-explanatory. It checks if the machine is online and returns a Boolean value (true if online, false if otherwise).


This script must be ran with an account with administrative rights on the computers listed in computers.ini. If this script is ran from a Windows Vista computer, ensure that elevated privileges are invoked (for example, right-clicking on the command-prompt shortcut and choosing "Run As Administrator").

Tuesday, October 28, 2008

So I got PW3ND, now what? (MS08-067)

So the day went past with nary a trace of an outbreak. Good, no need to work long hours this round. Bad, no free pizza. Nonetheless, I came prepared. To wage battle. My weapon of choice? The usual arsenal -- my scripts, Sysinternals' tools, and a few resource kit tools comprising my rootkit toolkit.

The scenario played out here does not, in any way, mirror an actual incident. This is just a simulation and the actual malware may behave differently than what is described here.

First, I would look into the autostarting programs using Sysinternals autoruns. Notice the presence of N2.exe and winbaseInst.exe from the image shown:



This confirms that the computer is infected. Next, I fire up pslist to view a list of running processes (alternatively, I could use Process Monitor (procmon) in lieu of pslist). 



Here's a script which was done in a matter of minutes (scripting cosmetics will be applied later, time permitting). The main body of the script calls three procedures StopProcess(), CleanRegistry(), and DeletePayload(). The malware processes have to be stopped before the payloads and malware executables can be deleted.



The StopProcess() procedure will terminate the process passed as parameter. An array (arrstrproc) contains a list of the malware processes to be terminated.



The CleanRegistry() procedure will, in turn, remove the autostarting entries from the RUN key in the registry. Note that the parameter passed is trimmed of its file extension (".exe") before it is checked. If the string is found in the RUN key, the entry is deleted.


The DeletePayload() procedure will then delete all the malware payload and executables. Malicious DLLs, executables or batch files which are stored in the arrpayload array are passed as parameters to the procedure and are deleted.


A reboot is required; the script doesn't take care of this part. Leave something for the support guys like me to do.

Monday, October 27, 2008

How to Retrieve CPU and Memory Utilization using a script (VBS)

Here's a simple vbs script that displays the CPU and memory utilization of a computer (works on Windows XP and above):

' Salvador Manaois III
' http://badzmanaois.blogspot.com
' =========================================================================
' You have a royalty-free right to use, modify, reproduce and distribute
' this script (and/or any modified version) in any way you find useful,
' provided that you agree that the author has no
' warranty, obligations or liability for the script. If you modify
' or quote the script, you must retain this copyright notice.
' -------------------------------------------------------------------------
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
'Get CPU Usage
myQuery = "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name = '_Total'"
For Each objItem in objWMIService.ExecQuery(myQuery)
   ProcTime = "Processor time " & objItem.PercentProcessorTime & "  %"
next
'Get Memory Information
myQuery = "select FreeVirtualMemory,FreePhysicalMemory from Win32_OperatingSystem"
for each objItem in objWMIService.ExecQuery(myQuery)
for each oProperty in objItem.Properties_
if oProperty.Name = "VirtualMemFreeMemory" then
VirtualMemFree = oProperty.Value
elseif oProperty.Name = "PhMemFreeMemory" then
PhMemFree = oProperty.Value
end if
next
next
myQuery = "select TotalVirtualMemory,TotalPhysicalMemory from Win32_LogicalMemoryConfiguration"
for each objItem in objWMIService.ExecQuery(myQuery)
for each oProperty in objItem.Properties_
if oProperty.Name = "TotalVirtualMemory" then
VirtualTotal = oProperty.Value
elseif oProperty.Name = "TotalPhysicalMemory" then
PhysicalTotal = oProperty.Value
end if
next
next
VirtualUsed = 100 - (100 * (VirtualMemFree / VirtualTotal))
PhysicalUsed = 100 - (100 * (PhMemFree / PhysicalTotal))
wscript.echo Date() & " " & Time()
wscript.echo "Processor Time : " & ProcTime
wscript.echo "Percent Used Virutal Memory" & VirtualUsed
wscript.echo "Percent Used Physical Memory" & PhysicalUsed

Sunday, October 19, 2008

How to disable User Account Control in Windows Vista (vbs)

The introduction of User Account Control (UAC) on Windows Vista (and, subsequently, on Windows Server 2008) demonstrated a complete turnaround as far as Microsoft's strategy on handling administrative privileges is concerned. In contrast, during the initial installation of Microsoft Windows® XP, the Windows XP Setup Wizard creates all user accounts as local administrators. This meant that these users and ensuing users who are added to the local administrators group, having system-level privileges, are able to install, update, and run software. 

UAC on Vista and Windows Server 2008 forces users who are members of the local administrators group to run like they were regular users with no administrative privileges.  This feature automatically reduces the potential of security breeches in the system. For example, if a user runs an application which in turn tries to modify, say, the firewall settings, the system will trigger an UAC prompt (either a confirmation dialog or a UAC credentials dialog) and the user can choose to proceed with the action or not.

I have written a script that turns on or off the UAC on a Vista machine:



The script checks for the value (DWORD) of EnableLUA on the HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System key in the registry. It displays the setting to the user (enabled or disabled) and prompts him to change or ignore this setting.


  
If the user chooses to modify the setting (for example, disabling it), the script will modify the registry value and pops-up a MsgBox informing the user that the change requires a reboot. The script will not trigger a reboot although this functionality should be very easy to incorporate within the script itself.



A function (Getanswer) and a sub procedure (SwitchValue) are called within the script. Two parameters are passed to the function Getanswer,  the string strstatus and strset, and it returns the user's response to the MsgBox invoked (6 = OK, 7 = No, 2 = Cancel).



The SwitchValue sub procedure switches the value of the strValue variable (which stores the EnableLUA value extracted from the registry). If the value of strValue is 1, it is changed to 0, and vice versa.




Friday, October 3, 2008

Checking for Password Complexity Using Regular Expressions

There is this very interesting thread on the Microsoft Technet Forums (Scripting) wherein one poster was inquiring about ways of checking for password complexity using visual basic scripting. One very effective and, in my book, very efficient way to accomplish this task is using Regular Expressions.

What are Regular Expressions?

Regular expressions, commonly known as regex or regexp, are a set of key combinations that are meant to allow people to have a large variety of control over what they are searching for. A regular expression, often called a pattern, is an expression that describes a set of strings. They are usually used to give a concise description of a set, without having to list all elements. (Source: wikipedia.org)


The power of Regular Expressions

Regular Expressions are a neat way to perform powerful, fast and effective string pattern matching and replacing. Starting with VBScript Version 5.0, the RegExp object is made available for developers. 

The most commonly used types of regular expressions matching include character matching, repetition matching, and position matching.

Character matching is, as the term suggests, searching for a match within a string literal. In the example I have posted on the Technet, I used the RegExp Test method to validate the password given. This  method takes a string as its argument and returns True if the regular expression can successfully be matched against the string, otherwise False is returned.

Repetition matching, through the use of repetition operators or quantifiers, details how many times to search for a specified string. The operators are used in conjunction with character-matching syntax to search for multiple characters. By using repetition matching, we can specify the number of times an element may be repeated in a regular expression.

Symbol

Function

{x}

Match exactly x occurrences of a regular expression.
   "\d{5}" matches 5 digits.

{x,}

Match x or more occurrences of a regular expression.
   "\s{2,}" matches at least 2 space characters.

{x,y}

Matches x to y number of occurrences of a regular expression.
   "\d{2,3}" matches at least 2 but no more than 3 digits.

?

Match zero or one occurrences. Equivalent to {0,1}.
   "a\s?b" matches "ab" or "a b".

*

Match zero or more occurrences. Equivalent to {0,}.

+

Match one or more occurrences. Equivalent to {1,}.


Position matching involves the use of the ^ and $ to search for beginning or ending of strings. Setting the pattern property to "^Microsoft" will only successfully match "Microsoft makes cool products." But it will fail to match "I hate Microsoft."

Symbol

Function

^

Only match the beginning of a string.
"^A" matches first "A" in "An A+ for Anita."

$

Only match the ending of a string.
"t$" matches the last "t" in "A cat in the hat"

\b

Matches any word boundary
"ly\b" matches "ly" in "possibly tomorrow."

\B

Matches any non-word boundary


Going back to the Technet forum post, I have posted a script which utilizes the RegExp object and a pattern matching loop to verify the complexity of the password inputted.

Saturday, September 20, 2008

Adding Pictures to an Active Directory Account

I was hoping someone could explain the use of User Account pictures in 2008, is this feature expected to be integrated into AD at some point?
We are setting up 2008 Terminal Services and what I would like to do is automate the user account pictures for my users and link them to a central store of pictures. So if User "Alan Other" logs in he gets "AlanOther.bmp" pulled into his profile and set as his Picture.
I can script the fie moves etc, but what I can't seem to find is where to set the picture in the Reigistry.
The only thing currently open to us is to standarise the picture using Group Policy. 
Anyone any ideas?
This question was posted on Technet and had piqued my interest. The ability to add a picture to an Active Directory account is a stroke of genius, if only this doesn't bloat the AD database. I copied this code from Arricc. Included in the page is a snippet of a Sharepoint webpart. Another possible way of implementing this was described in Oddvar HÃ¥land Moe’s Blog. A third-party tool, Exclaimer's AD Pictures, is able to add pictures in AD with  an intuitive GUI.  

The problem with integrating this feature with an enterprise's Active Directory lies not just in a rather inflated AD database but in the aspect of replication as well. Replication becomes an concern once the AD database grows tremendously. It is going to be a tossup for AD administrators to pick  between this nifty feature versus AD size and replication concerns.

Thursday, September 11, 2008

Changing a User's Profile Path (VBS)

Automation is a key element in the success of day-to-day routines of a systems administrator. Be it using special tools to query a few thousand computers in the domain, checking the health of hundreds of servers, or even crafting your own script to check the status of OS updates on your computing endpoints, automation ensures that a sysadmin is able to generate these types of report in a timely, efficient and accurate manner. I have been involved in so many tasks wherein I had to dig deep in my scripting cheatsheet to come up with scripts to check and manage the six-thousand-over computers that I administer. Fact is, I also contribute my fair share of scripts in the Technet's IT Pro Code Gallery in my own little way.

One such script delves on changing the "profilePath" property of thousands of users (this one is from the Technet forum). Being the KISS (that is "Keep It Simple and Straightforward" for you) advocate that is me, I went to create a simple, short, quick and dirty script.


First, I had to generate a list of all the users in my domain. I can, in fact, accomplish this using adsi within the main script itself. However, the fastest way to do it is actually running the net users /domain command from the CLI and piping the output to users.ini.

The main body of the script shown is as simple as it can get. The domain is defined (strDomain), so is the source file containing the list of all the users in the domain (users.ini). The script reads each line of the users.ini file and passes this to the ChangeUserProfilePath sub-routine (together with strDomain).


The ChangeUserProfilePath sub-routine has the old and the new profile paths defined (oldProfile and newProfile). The Replace string function is used to substitute oldProfile with newProfile. The resulting string, strNewProfilePath, is then set to the "profilePath" property of the user account being processed. An initial check is made to verify if the oldProfile string is located in the user's profile property (sUser.Profile). If and only if this condition is met is the profilePath updated.