Powershell Shell

In subject area: Computer Science

A PowerShell shell is a command-line interface that provides access to Microsoft's .NET tools, allowing users to execute commands for system administration tasks, such as retrieving information about running processes or performing network activities with ease.

AI generated definition based on: Coding for Penetration Testers, 2012

How useful is this definition?

Add to Mendeley

Chapters and Articles

You might find these chapters and articles relevant to this topic.

2012, Coding for Penetration TestersJason Andress, Ryan Linn

Publisher Summary

PowerShell can be put to a number of penetration testing uses. Since PowerShell has access to Microsoft's .NET set of tools, and many of the existing functionality that ships with it is intended for system administration, this provides a great deal of utility to the penetration tester as well. One can simply issue the commands directly at the prompt in the PowerShell shell and have the data returned to the console such as, if one wants to get a list of all the running processes on a system then Get-Process can be executed. In PowerShell, one can kill a process using the Stop-Process cmdlet. Stop-Process can be run using either the process ID or the process name as an argument. If one uses the process ID, the Stop-Process 13768 run. One can use PowerShell to perform several types of network activity with relative ease. On a Linux system, one of the most useful tools that one has to pull data down from a Web server is wget. Metasploit can be used to interface with PowerShell. There are several great modules such as PowerDump that allow spawning shells, and make use of some of the code through Metasploit.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9781597497299000060

Abstract

In this chapter, we talk about shells, in the sense of the text-based interfaces we use to communicate with operating systems. UNIX, Linux, and OS X, as well as most UNIX-like operating systems, tend to work on the same general principles for purposes of shell scripting, and make use of many common programming concepts such as data structures, variables, control statements, if-then clauses, and while loops. In Microsoft operating systems, we can find many similar shell scripting tools as well. In Windows, we can carry out commands and write scripts using the generic shells command.com and CMD.exe, the PowerShell shell, and add-on tools such as Cygwin to give us access to bash on Windows, just to name a few.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780128054727000012
2012, Coding for Penetration TestersJason Andress, Ryan Linn

Summary

Shells, of the type we commonly refer to in the context of shell scripting, are the text-based interfaces we use to communicate with operating systems. Using various scripting languages, we can develop software to take advantage of the features the various shells provide to us. Shell scripting can be a very useful tool to have in our penetration testing arsenal. Being able to build tools and utilities from the components provided to us by the operating system can mean the difference between success and failure during a penetration test.

UNIX, Linux, and OS X, as well as most UNIX-like operating systems, tend to work on the same general principles for purposes of shell scripting. There are a number of shells we might find available on such systems, generally classified as Bourne-compatible shells and C shell-compatible shells. One of the most common shells at present for UNIX-like systems is the Bourne-again, or bash, shell. Developing scripts in bash will allow us to use them on a wide variety of the systems we might encounter.

The main programming structures of bash can be categorized into data structures, such as variables, and control statements, such as if-then clauses and while loops. With the addition of a few other components, such as functions and the ability to input and output data, we have a sufficient structure on which to develop simple bash scripts. As an example of the tools we can build with bash, we looked at building a port scanner in this scripting environment.

Microsoft operating systems such as the various versions of Windows have their fair share of shell scripting tools as well. In Windows, we can carry out commands and write scripts using the generic shells command.com and CMD.exe, the PowerShell shell, and add-on tools such as Cygwin to give us access to bash on Windows, just to name a few. PowerShell provides one of the most complete facilities for Windows scripting and shell use and was the focus of the Windows scripting efforts in this chapter.

Similar to the discussion on the bash scripting language, in PowerShell we can find comparable data structures and control statements, allowing us to control the flow of our scripts, store data, and take inputs and give outputs. PowerShell also allows us to perform much more complex activities that are in line with what can be done with compiled programming languages, due to its ability to interface with Microsoft's .NET tools. In this way, PowerShell can play a role in everything from the simplest of scripts to critical roles in production software.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9781597497299000011

PowerShell Basics

As an introduction to PowerShell scripting, we will start with the traditional Hello World script. In order to get started, we again need a few components. Depending on the specific Microsoft operating system we are using, we may or may not already have PowerShell installed. In Windows 7 or Windows Server 2008 R2 or later, PowerShell is already installed. For other versions, with a minimum of Windows XP SP2 being required, PowerShell can be downloaded from Microsoft [5]. All the PowerShell examples in this chapter were developed on Windows 8.1.

We also need a text editor of some variety. The simplest to use is Notepad, which ships with Windows. If we are using PowerShell 4.0, as Windows 8.1 ships with, we also have access to the PowerShell Integrated Script Editor (ISE). ISE can be accessed by running powershell_ise.exe, or by right-clicking and choosing Edit on a .ps1 file. We will be using ISE as an editor for the rest of our PowerShell examples.

Next, we will need to wrestle with the system security settings a bit in order to get them to relax enough to allow us to run our own scripts. If we run a PowerShell script before doing this, we will just get an error and it will refuse to run. In order to make this change on Windows 8, we will need to search for PowerShell on the Start menu, then right-click on the Windows PowerShell shortcut and choose Run as Administrator.

Warning

By changing the execution policy for PowerShell scripts to be more permissive than the defaults, we are opening a vulnerability on our systems! Although we are allowing the minimum permissions we can use in order to work with PowerShell scripts, this is still a security hole that the bad guys could potentially use to attack us. This is relatively unlikely to happen with this particular setting, but caveat scriptor. For more details on this setting, Microsoft has additional information on the various options we can use [6].

This will open a PowerShell shell with administrative privileges so that we can make the required changes. In this window, we need to type Set-ExecutionPolicy RemoteSigned. This will set our execution policy for PowerShell to allow us to run any scripts we might create, and any scripts we download signed by a trusted publisher.

We can see what the permission setting exchange should look like in Fig. 1.9. We should now be ready to create our HelloWorld script.

BERJAYA

Figure 1.9. Changing permissions in PowerShell.

Hello World

One of the simplest ways to create our script is to create a file called HelloWorld.PS1, then right-click on it and choose Edit. This will open the PowerShell ISE, as shown in Fig. 1.10.

BERJAYA

Figure 1.10. PowerShell ISE.

In the top window, right next to the 1, we will want to paste the following code:

Write-Output "Hello World"

That’s all there is to it. After saving the file, we can either run our code manually now by opening a PowerShell shell, navigating to it, and then running HelloWorld.PS1, or run it by clicking on the green triangle (10th from the left) in the toolbar of ISE. In ISE, we will see the output from our script execution in the middle window of the interface. Write-Output is one of the PowerShell cmdlets we discussed earlier in this section, and it contains all the necessary functionality to print our statement. Also notice that, unlike our example in bash, we did not need to use anything like a shebang in order to indicate the interpreter we needed to use. In Windows, this function is handled through the use of the file extension .PS1, which indicates that the script should be handled by PowerShell.

Variables

Variables under PowerShell are, again, very similar to what we might find under bash. By default, variables have no type, meaning that a given variable can contain text or numeric data. Variables are always addressed as $<variable name>, whether assigning data to them or extracting data from them. Let’s look at a quick variable example and a new cmdlet:

$processes = Get-Process powershell_ise

$processes

In this case, we are invoking the Get-Process cmdlet in order to get the process information for the ISE application we are using to develop our scripts. Then we are taking the returned data from the cmdlet and storing it in the $processes variable. On the next line, we are echoing out the contents of $processes. If everything was successful, when we press run, we should see output similar to Table 1.3.

Table 1.3. Output from Get-Process powershell_ise

HandlesNPM(K)PM(K)WS(K)VM(M)CPU(s)IdProcessName
-----------------------------------------------
769731382121856849708.732612powershell_ise

The return from the cmdlet we echoed contains the information on the handles, nonpaged memory, paged memory, working set, virtual memory, CPU usage, process ID, and process name of the process on which we had requested information. Also notice that the formatted output of the cmdlet survives being stored in a variable and echoed out again.

We can also do local and global variable scoping in PowerShell. With variable scoping we can limit a variable to a portion of code or function. By using functions we can see a nice demonstration of how to deal with variable scope.

function hello{

$LOCAL:name = "whoever you are"

write-output "hello there "$name

}

$name = $args[0]

Write-output "hello there "$name

hello

write-output "hello there "$name

The first item we find in our script is the function we will use to demonstrate the scope of our variable. Functions in PowerShell are very similar to those we discussed when we went over the same topic in bash. The first line of the function is simply the function tag, the name by which we want to refer to the function, in this case hello, and the opening curly bracket, {, to start the function. On the first line inside the function, we can see the line creating our local variable. This variable, created with the local keyword, will only exist inside the scope of our function, and the function will keep its own copy of the contents, regardless of what we name it. Here, we set the contents of $LOCAL:name to the string whoever you are. On the next line, we echo out a greeting and the contents of the variable, then close up the function with }.

In the main body of the script, we take in an argument from the command line, $args[0], and place the contents of it into $name. Notice that this is the same variable name we used in our function, but without the LOCAL tag to set the variable scope, this implicitly makes the variable global in scope. Next, we echo out our greeting and the contents of $name, run the function, and echo the greeting and variable contents again. We can see from the output in Fig. 1.11 that, even though we changed the contents of our local copy of $name in the function, we did not change the contents of the same variable in the main body of the script, due to the difference in variable scopes. To run our script with command line arguments, we can type our command in the bottom window of the Powershell ISE. In this case, we called our script SayHello.ps1 so we would just type in .\SayHello.PS1.

BERJAYA

Figure 1.11. Differing variable scopes.

Arguments

We can work with arguments in PowerShell in a very simple fashion. To expand on our process script in order to use an argument, we can do the following:

$processes = Get-Process $args

$processes

In order to run this script, we need to supply an argument containing the name of the process for which we will retrieve the information. In this case, we will save this file as arguments.ps1 and use the explorer process as an argument. When we will run ./arguments.ps1 explorer we should see output similar to Fig. 1.12, showing us information for at least a couple of explorer processes.

BERJAYA

Figure 1.12. Output from arguments.ps1.

When we supply a command line argument in PowerShell, it is stored in an array called $args. We can think of an array as a variable with multiple storage compartments called elements, each of them individually addressable. With an array we can use a single data structure to store multiple pieces of information, adding, changing, or deleting them as we need to, without necessarily affecting any of the data we don’t care to change.

The first element in the array holds our first (and only) argument: the name of the process we want information about. In order to reference this, we could either refer directly to the first element in the array $args[0] or simply refer to the entire contents of the array with $args. If we wanted to refer to further arguments, we would just need to add a number, such as $args[1], which would refer to the second argument, $args[2] for the third argument, and so on.

If we wanted to modify our code to pull in information on multiple processes, we would change our script to:

$processes = Get-Process $args[0], $args[1]

$processes

Running the script as .\arguments2.ps1 explorer powershell_ise would then return us information on both processes (likely more than one in the case of explorer).

Control Statements

Powershell and almost all high-level programming languages have control statements. Just as we discussed in the first part of the chapter when we talked about control statements in bash, we will discuss some examples of both conditionals and looping functions in PowerShell in this section.

Conditionals

Conditional statements in PowerShell follow many of the same conventions as any of a number of other languages. We will look at if else statements and switches here.

If else statements are a slight variation on the if statements we can find in most languages. We can add an if statement to our earlier process example to add a little intelligence to it:

$processes = Get-Process

If ($processes –match "winword"){

  write-output "Microsoft Word is running"

}else{

  write-output "Microsoft Word is not running"

}

In this case, we run the same code we did previously to dump the information on all the running processes. We then set up our if statement to match against the output of Get-Process in order to look for the string “winword,” which is the process name for Microsoft Word. The –match operator uses a regular expression (regex), a text string which describe a search pattern, to search for the string we give it. It is a good choice in this particular instance, as it keeps us from having to parse through the entire process listing manually for the string we want.

Based on whether we get a match or not, we can then determine whether the process is running and provide the appropriate output to the user.

Switch statements function along the same general lines as an if statement, but enable us to configure a more complex set of actions based on the conditions we find. We can make our process checker a bit more capable by using a switch:

$processes = Get-Process

switch -regex ($processes){

   "winword" {write-output "Microsoft Word is running"}

   "explorer" {write-output "Explorer is running"}

   "vlc" {write-output "VLC is running"}

}

Now we can look for multiple processes in one go. Here we used the same cmdlet to dump out the process listing, and instead of being limited by the if statement, we built a more complicated set of conditions using the switch statement. We set up the first line of the switch on line 2 of the script, and configure our matching to use a regex and match against the contents of $processes, the variable where we stored the process listing.

In the body of our switch statement, we set up a series of lines, each for a different potential match. On each line, our very simple regex will check the line for the name of our process. Interestingly, since our variable $processes is holding multiple lines of text, the switch will attempt to match each line in the variable against each case in the switch. When we run our script as process2.ps1 we can see if any processes match, as shown in Fig. 1.13. In some cases, there may even be multiple copies of programs running, such as two copies of Explorer, and those will be reflected here as well.

BERJAYA

Figure 1.13. Output from the Process2.ps1 example.

Introducing the Windows Management Interface

While PowerShell has cmdlets built that will get process information, sometimes you want more control of the information you are seeing. The Windows Management Interface (WMI) is a scriptable interface for interacting with Windows. Using WMI, we can query the information that Windows stores about processes, event logs, and just about everything else about the underlying Windows system. It can even be used to query information about remote systems. We will be talking more about WMI in Chapter 6, Manipulating Windows With PowerShell, but for contrast, let’s look at how to use WMI to get information about processes in Windows.

There are WMI Objects for most of the aspects of the operating system. These Objects contain tables with the information describing the data. This includes Processes, Patches, Operating System information, and more. To learn more about the different things that can be queried, there is a reference that Microsoft supplies here: https://msdn.microsoft.com/en-us/library/aa393964(v=vs.85).aspx.

To begin with, we need to understand how to get information from WMI. Using the Get-WMIObject cmdlet inside Powershell, we have the ability to query the different WMI tables. Let’s look at an example that retrieves some relevant process information.

$procs=@("winword.exe","explorer.exe","vlc.exe","powershell_ise.exe")

foreach ($proc in $procs)

{

  $data = Get-WmiObject Win32_Process | Where {$_.Name -like $proc}

  $data | Select-Object ProcessId, Name, ExecutablePath, CommandLine | format-table -wrap

}

Like other scripts, we start out with an array of processes we are interested in searching for. We put those into an array called $procs and then do a foreach loop iterating through the $procs array and each entry will be assigned to the variable called $proc. Next, we query the WMI Win32_Process table, the table that has all of the process information in it. We get all of the elements from that table and then use a pipe to select just the ones where the name is the same as our $proc variable. That gets assigned into a new variable called $data.

Powershell treats data as objects. This means that each entry from the process table has a number of other pieces of data that are related to it, and it is all stored together in an object that can be assigned to a variable. In this case, our $proc variable stores an object for each of the processes that matched our query. We don’t really want to know everything about that object, so by using a pipe to the Select cmdlet we can choose what fields we’d like to display. In our case, what we care about is the ProcessId of the process, the Name of the process, the ExecutablePath so we can tell where the original binary is, the CommandLine of the process so we can see what arguments were passed to the binary. This will give us a huge amount of information about where the binary is, and how it is being called.

When we run our binary as .\WMIProcess.PS1, we should be able to see the output to the screen. By passing the data to another cmdlet called Format-Table, we have the ability to format the data so that it wraps on the screen, allowing us to see all of the text. This should look like Fig. 1.14.

BERJAYA

Figure 1.14. The output of WMIProcess.ps1.

Looping

There are a number of looping structures we can use in PowerShell and we will look at a couple of the more common and useful possibilities here. Looping in PowerShell follows much the same format as looping in most programming languages. One of the simplest looping constructs we can look at is the for loop:

for ($counter=0; $counter -lt 10; $counter++)

{

  $ping = New-Object System.Net.NetworkInformation.Ping

  $ping.Send($args[0])

  Start-Sleep -Second 5

}

We would want to run this script with .\looping.ps1 scanme.nmap.org. Let’s have a look at what we did here. First we set up the beginning of our for loop, for ($counter=0; counter –lt 10; $counter++). So, this line initializes $counter with zero. This will be the variable that keeps track of how many times our for loop has executed. Next, we evaluate $counter to make sure that it is still less than 10 with –lt. If this is true, we will continue; if not, we will stop right here. Lastly, we increment the value in $counter by 1. Next, we can find the body of our loop enclosed in braces, {}.

Inside the loop we are doing a very nice little bit of .NET work to call the ping function provided there. As PowerShell is a native Microsoft tool, it is fully capable of taking advantage of Microsoft’s .NET development framework and all the goodies that come with it. In this particular case, we are instantiating an object, a computer construct that allows us to group data as well as functions related to that data together for easy management, to use for ping. We use that object when running a ping against the host name or IP provided by our first argument, and sleeping for 5 seconds. After we finish sleeping, we will go back to the top of the loop, repeating this for a total of 10 times through. In the output, we will see the results of our pings display each time we execute the loop.

$devices = @("scanme.nmap.org","happypacket.net")

foreach ($device in $devices)

{

  write-output "device is " $device

  $ping = New-Object System.Net.NetworkInformation.Ping

  $result = $ping.Send($device)

  $result

}

Here, we are doing things a bit differently. In this case, we want to ping more than one machine with our pinging routine. We would feed this in from the command line in the form of arguments, or we could pull it in from a file, but in this case we will use an array to hold the names of our hosts.

The first line in our script sets up and populates the array. We can see that this is very similar to setting up and populating a variable, with a little additional information to indicate we want it to be an array, in the form of the @. We also need to put parentheses around our list of elements and separate each of them with a comma.

After constructing the array, we set up the foreach loop. Here, we say foreach ($device in $devices). This means that for each item in our array called $devices, we should be doing something on each individual element, which we refer to as $device. We could have used any variable name to hold the contents of each element as we process through them, such as $i or $monkey; it really makes no difference what we call it.

The only other change from our previous pinging routine is to change the target of our ping.send to $device, in order to match our foreach configuration.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780128054727000012
2012, Coding for Penetration TestersJason Andress, Ryan Linn

Penetration Testing uses for PowerShell

There are a number of uses to which we can put PowerShell in a penetration testing situation. Since PowerShell has access to Microsoft's .NET set of tools, and many of the existing functionality that ships with it is intended for system administration, this provides a great deal of utility to the penetration tester as well. We will go over a few example uses for PowerShell, such as controlling processes and services, interfacing with the event logs, getting and sending files over the network, and interfacing with the Registry.

Controlling processes and services

Since the examples here are very simple, we'll be working with PowerShell in interactive mode to run them, something that we have not covered in great detail either in this chapter or in Chapter 1. We can simply issue the commands directly at the prompt in the PowerShell shell and have the data returned to the console. For example, if we want to get a list of all the running processes on a system, we can execute Get-Process, as we discussed in Chapter 1. This will send quite a bit of data scrolling past on our console, considering the large number of processes generally running on a Windows system.

In order to get back something a bit more specific, we can include the process name. To give us an example process to look at, we can start Notepad by simply entering Notepad at the prompt in PowerShell. We can also specifically use the Start-Process cmdlet to start the process by running StartProcess Notepad. Once Notepad has started, we can get the process information for it by running Get-Process notepad. We should see something similar to that shown in Figure 6.1 returned as output.

BERJAYA

FIGURE 6.1. Get-Process Output

Now that we have a process to work with, we can set about killing it. In PowerShell, we can kill a process using the Stop-Process cmdlet. Stop-Process can be run using either the process ID or the process name as an argument. If we use the process ID, we can simply run Stop-Process 13768. If we use the process name, we need to add an argument, such as Stop-Process –processname notepad.

Working with services is very similar to working with processes. In order to get the list of services, we can run Get-Service. As with processes, Get-Service and the service name will get us the information for a specific service, such as Get-Service Fax. We should see output similar to that shown in Figure 6.2.

BERJAYA

FIGURE 6.2. Get-Service Output

The basic information returned from Get-Service will give us the name of the process and its current state. We can then start, stop, or restart the service with Start-Service, Stop-Service, or Restart-Service, respectively. In general, we will need administrative access to manipulate services.

Interfacing with the event logs

Working with the event logs in PowerShell is a very easy task to carry out. Microsoft has given us a simple interface to work with them, although there are a few limitations. Again, we will look at how to work with the event logs in PowerShell in interactive mode, just as we did earlier in this section with processes.

The first thing we are likely to want to do on our target system with the event logs is to look at what we have on the system. For this, we can use the Get-EventLog cmdlet, with the list argument, as in Get-EventLog –List. When we run this cmdlet, we should see output similar to that shown in Figure 6.3.

BERJAYA

FIGURE 6.3. Listing the Event Logs on Windows

Conveniently, once we have the list of event logs in hand, we can use the same cmdlet with a different argument to list the content of a specific log. When we look at a log on a given system, there will likely be a very large amount of information in it, so we will also want to filter what is returned to us, unless we are just dumping the log contents out to a file. We can get the last few messages from the log that we specify by using the –newest argument with Get-EventLog, as in Get-EventLog –newest 5 Application. This will give us output similar to that shown in Figure 6.4.

BERJAYA

FIGURE 6.4. Get-EventLog Output

We can also clear the event logs quite easily by using the Clear-EventLog cmdlet. To do this, we need to specify the log that we want to clear and the name of the system on which the log resides, as in Clear-Eventlog –log Application –ComputerName . (the space and the period following –ComputerName are necessary; without them, this command will not work). This is one area in which we need to be an administrator to run this particular item of PowerShell code. If we are not an administrator, we will get a “permission denied” error message.

Getting and sending files over the network

When we have accessed a system during a penetration test, we may want to pull files onto the system in order to load additional tools locally, or send information off the system in order to exfiltrate data. We can use PowerShell to perform several types of network activity with relative ease. On a Linux system, one of the most useful tools that we have to pull data down from a Web server is wget. Handily, we can replicate its more basic features with a quick PowerShell script and a little .NET magic. As long as we can write to the download location, we should be able to execute this script with the permissions of a normal user.

$src = "http://nmap.org/dist/nmap-5.51-setup.exe"

$dest = "c:\temp\nmap-5.51-setup.exe"

$web = New-Object System.Net.WebClient

$web.DownloadFile($src, $dest)

Let's take a quick look at what we've done here. We first take in the argument containing the URL that we want to download, which came from the argument that we passed in at the command line. Here we are also using param to handle the arguments, as we looked at earlier in the chapter, a slightly different method from what we looked at in Chapter 1. In the $path variable, we place the location of our current directory, which is where our downloaded file will be saved. In order to make the script more flexible, we might want to take in the path from an argument also, and this would be an easy change to make.

Here we instantiate our object to interface with the Web, System.Net.WebClient, using $web as a handle for it. Lastly, we call the DownloadFile method on the handle for our object, passing the URL that we will be downloading and where we want to store it, as in $web.DownloadFile($url, $path). This is a fairly simple piece of code for handling Web traffic on a Windows machine.

There are a number of very handy objects and methods that we can use to handle other types of transactions and traffic. With System.Net.WebClient, we can also make use of the UploadFile method to send files in the other direction, which may or may not be very handy for us when we look at Web transactions but we can also use System.Net.WebClient to do FTP, with no major changes required.

$src = "ftp://ftp.fr.netbsd.org/pub/pkgsrc/distfiles/netcat-0.7.1.tar.gz"

$dest = "c:\temp\netcat.tar.gz"

$ftp = New-Object System.Net.WebClient

$ftp.DownloadFile($src, $dest)

#$ftp.UploadFile($src, $dest) #a quick change makes this an upload

This is, of course, very similar code to what we just looked at for our Web download, which makes sense as we're using the same object and the same methods. Since we're doing very much the same transaction, the only real difference is in the source and/or destination of the file being on a different protocol. The System.Net.WebClient is handling all the protocol differences internally and transparently for us.

As we discussed in Chapter 1, we have access to a huge number of objects in .NET, many of which are network-related. We can find, in many cases, existing objects and methods for most of the common tasks we might want to carry out for shipping files around on the network. For the oddball situations where we can't make one of these fit, there are large amounts of user-generated code floating around the Internet for us to use and build on. Additionally, we can access most any other functionality available through the operating system or installed applications that have a command-line interface.

TIP

Anyone that has never encountered Netcat3 is missing a major penetration testing tool with an amazing degree of flexibility. Netcat is available for many operating systems, and we may find it on some as part of the default install. Netcat essentially allows us to handle incoming and outgoing network traffic (or both) and move files or data over the network to and from any port that we might care to. For those interested in learning the capabilities of Netcat check out the book Netcat Power Tools (ISBN: 978-1-59749-257-7, Syngress), edited by Jan Kanclirz Jr.

Given tools such as Netcat, which we can download for Windows operating systems and easily control through PowerShell, we can move files over the network, open shells or reverse shells, and perform a broad variety of similar tasks.

Interfacing with the Registry

The Registry in Microsoft operating systems, first brought into existence in Windows 3.1, is a database that holds the configuration settings for Microsoft operating systems and the applications installed on them. We can use the Registry to manipulate how applications function (or keep them from functioning), what happens when the operating system starts, and a variety of other similar tasks.

The Registry is hierarchical in nature, often presented as a series of folders in graphical tools designed for accessing it. Inside each level of the hierarchy, we may find additional levels of the hierarchy, referred to as “keys,” as well as individual entries, referred to as “values.” The values are a pair containing a name and associated data.

In the Registry, we can find five major sections, often referred to as “hives”:

HKEY_LOCAL_MACHINE (HKLM) Holds settings for the local machine

HKEY_CURRENT_CONFIG (HKCC) Holds information generated at boot time

HKEY_CLASSES_ROOT (HKCR) Holds information about applications

HKEY_USERS (HKU) Holds the superset of HKEY_CURRENT_USER entries

HKEY_CURRENT_USER (HKCU) Holds settings that pertain to the currently logged-in user

These hives are present in most Windows operating systems, with some slight variation depending on the specific version in use, and some hives not being accessible outside of application program interfaces (APIs).

PowerShell presents us with a very interesting and convenient interface to the Windows Registry. PowerShell displays the Registry as a file system, and we can use the cd (change directory) command to access it, using the abbreviated names listed earlier, just as we would any other portion of the normal file system: for example, cd HKLM:. Once we are there we can use dir to display the keys under HKLM. We should see output similar to that shown in Figure 6.5.

BERJAYA

FIGURE 6.5. Exploring the Registry in PowerShell

We also see a few errors regarding Registry access being restricted, which is normal for most Windows operating systems starting with Vista. From here, we can browse around in the portion of the Registry that exists under HKLM.

For those of us that jumped ahead and tried to navigate to all the different Registry hives, we might have found that only two of them are immediately accessible: HKLM and HKCU. These are the only hives that PowerShell configures access to by default. Fortunately, we can create the others with no great deal of effort:

New-PSDRIVE -name HKCC -PSProvider Registry -Root HKEY_CURRENT_CONFIG

New-PSDRIVE -name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT

New-PSDRIVE -name HKU -PSProvider Registry -Root HKEY_USERS

To create access for these additional hives, we should not need any privileges beyond being a user on the system. After each entry, we should be able to cd to the new Registry hive and view its contents with dir, similar to what is shown in Figure 6.6.

BERJAYA

FIGURE 6.6. Accessing HKCC in PowerShell

Once we are where we need to be in the Registry structure, we need to use a different command to look at the individual values within the key. Using dir will only show us the subkeys at any particular location in the hierarchy, not the values, which is somewhat counterintuitive.

Let's take a quick look at a few interesting values in the Registry. In most Windows operating systems, if we place a value in HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run, and that value contains a pointer to an executable program, that particular program will be launched whenever the operating system is booted. When we buy a new computer that is chock-full of crapware, all of which loads whenever the system is booted, this is generally the place from which everything is being started. If we run Get-ItemProperty "hklm:\software\microsoft\windows\currentversion\run" we should see output similar to that shown in Figure 6.7, although the individual entries will vary from one machine to another. Each of these values and its associated data points to a particular installed application or executable script which is stored in the file system.

BERJAYA

FIGURE 6.7. Registry Values to Start Applications at Boot

If we want to introduce a new application of our own to run at boot time we just need to make a new entry, so let's take a crack at that. Seeing as this is a very common Registry location that we might want to write to, and the path is a bit long to keep typing repeatedly, we will put together a small script to handle the creation of our value in the appropriate place.

Get-ItemProperty "HKLM:\software\microsoft\windows\currentversion\run"

$regpath = "HKLM:\software\microsoft\windows\currentversion\run"

$apppath = "%windir%\system32\calc.exe"

$name = "Calc"

Get-ItemProperty "HKLM:\software\microsoft\windows\currentversion\run"

Set-ItemProperty -path $regpath -name $name -value $apppath

Get-ItemProperty "HKLM:\software\microsoft\windows\currentversion\run"

This is a very simple script, but we'll take a quick walk through it. First, we should know that this is another place where PowerShell will trip over permissions if we are not an administrator. If we try to run the script as a normal user, we will get an error similar to Set-ItemProperty: Requested registry access is not allowed. So what we're doing here is first taking a quick look at what is already in the HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run key in the way of values, as we discussed earlier in this section. We then set a variable to hold the path to our location in the Registry where we will be making our entry, called $regpath, and populating it with our location.

We also set the $apppath variable with the path to the application that we will be starting at boot, in this case the Windows Calculator application, located at %windir%\system32\calc.exe, and the $name value which holds, in this case, the string "Calc" as the name of our intended value. The meat of our small script is the Set-ItemProperty cmdlet, which does exactly as we would think it might and adds a new value to our specified Registry key. We then call Set-ItemProperty with Set-ItemProperty –path $regpath –name $name –value $apppath to plug in the values from all of our variables, and away we go into the Registry.

After this, we run Get-ItemProperty again so that we can see the fruits of our labor. We should see quite a bit of text scroll past, ending up with a nice view of our newly created value, as shown in Figure 6.8.

BERJAYA

FIGURE 6.8. Adding a Value to the Registry

If we were planning to use this script with any great frequency, we would likely want to make allowances for different target locations in the Registry and different applications to be installed. We could easily modify the script to take these parameters in as arguments, as we discussed in Chapter 1 when we went over the basics of PowerShell.

We can also use the Registry to gather a variety of information on the system and environment that we are examining. Another interesting spot to look at is HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall. This location holds the uninstall information for the system, which can be of interest during a penetration test. Here we can find information such as the application name, when it was installed, the major and minor versions, and quite a bit of other information. Let's put something together to retrieve this information and dump it out to a file that we can review later.

$file = "c:\temp\installed-software.txt"

Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object{

$property = Get-ItemProperty $_.pspath | out-file $file -append

}

This is a very short script, but it does quite a bit of work for us. If we take a look at HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall in Regedit, as shown in Figure 6.9, we can see that this is not the easiest location in the Registry to parse.

BERJAYA

FIGURE 6.9. Regedit

The key names are very cryptic and there are a load of name-value pairs in each of them. It would be much nicer to have a simple list, either for purposes of reading manually or for parsing with another tool, such as grep.

Looking at the script, the first line sets up the location for our output file and stores that in the $file variable, in this case c:\temp\installed-software.txt. Next, we make use of the Get-ChildItem cmdlet to recurse through all the subkeys that are under HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall, passing the results off to the ForEach-Object cmdlet to handle iterating through all of them. The ForEach-Object does exactly as it sounds and performs a for each loop-style iteration through all our results, but without us having to explicitly write out the code to do so. As the ForEach-Object cmdlet is crunching through our subkeys, we have it performing a Get-ItemProperty on each of them in order to dump out the entries. For each set of values that we find, we pass these to Out-File, which will append them to the file location that we have stored in $file.

As a result, we should have a file with contents similar to that shown in Figure 6.10. This file will likely have a very large amount of information in it, as it will include not only software that has been installed by the user, but also additional items that have been installed as part of the OS, entries from patches, and so on. Conveniently, the output is nicely formatted for the use of search utilities such as grep, if we were to want to get a quick list of names, versions, install paths, or other similar information.

BERJAYA

FIGURE 6.10. Installedsoftware.ps1 Output

There are an enormous number of tweaks that we can make to the Registry to produce a variety of different effects on Microsoft operating systems. With a bit of research, we can find locations in the Registry that will allow us to change the way networking functions, accounts are handled, and encryption is dealt with, as well as implement a variety of other changes.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9781597497299000060
2012, Coding for Penetration TestersJason Andress, Ryan Linn

Hello World

One of the simplest ways to create our script is to create a file called HelloWorld.PS1, then right-click on it and choose Edit. This will open the PowerShell ISE, as shown in Figure 1.10.

BERJAYA

FIGURE 1.10. PowerShell ISE

In the top window, right next to the 1, we will want to paste the following code:

Write-Output "Hello World"

That's all there is to it. After saving the file, we can either run our code manually now by opening a PowerShell shell, navigating to it, and then running HelloWorld.PS1, or run it by clicking on the green triangle (10th from the left) in the toolbar of ISE. In ISE, we will see the output from our script execution in the middle window of the interface. Write-Output is one of the PowerShell cmdlets we discussed earlier in this section, and it contains all the necessary functionality to print our statement. Also notice that, unlike our example in bash, we did not need to use anything like a shebang in order to indicate the interpreter we needed to use. In Windows, this function is handled through the use of the file extension .PS1, which indicates that the script should be handled by PowerShell.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9781597497299000011
2012, Coding for Penetration TestersJason Andress, Ryan Linn

Controlling processes and services

Since the examples here are very simple, we'll be working with PowerShell in interactive mode to run them, something that we have not covered in great detail either in this chapter or in Chapter 1. We can simply issue the commands directly at the prompt in the PowerShell shell and have the data returned to the console. For example, if we want to get a list of all the running processes on a system, we can execute Get-Process, as we discussed in Chapter 1. This will send quite a bit of data scrolling past on our console, considering the large number of processes generally running on a Windows system.

In order to get back something a bit more specific, we can include the process name. To give us an example process to look at, we can start Notepad by simply entering Notepad at the prompt in PowerShell. We can also specifically use the Start-Process cmdlet to start the process by running StartProcess Notepad. Once Notepad has started, we can get the process information for it by running Get-Process notepad. We should see something similar to that shown in Figure 6.1 returned as output.

BERJAYA

FIGURE 6.1. Get-Process Output

Now that we have a process to work with, we can set about killing it. In PowerShell, we can kill a process using the Stop-Process cmdlet. Stop-Process can be run using either the process ID or the process name as an argument. If we use the process ID, we can simply run Stop-Process 13768. If we use the process name, we need to add an argument, such as Stop-Process –processname notepad.

Working with services is very similar to working with processes. In order to get the list of services, we can run Get-Service. As with processes, Get-Service and the service name will get us the information for a specific service, such as Get-Service Fax. We should see output similar to that shown in Figure 6.2.

BERJAYA

FIGURE 6.2. Get-Service Output

The basic information returned from Get-Service will give us the name of the process and its current state. We can then start, stop, or restart the service with Start-Service, Stop-Service, or Restart-Service, respectively. In general, we will need administrative access to manipulate services.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9781597497299000060

How this Book is Organized

Due to the content and organization of the topics in this book, it is not necessary to read it from front to back. Chapter 1 through Chapter 6 and the Appendix cover language concepts, while the final chapters cover applications of these languages. When we refer to information in other chapters in the book, we include references to point to the chapter where the information can be found. The following descriptions provide an overview of the contents of each chapter:

Chapter 1: Introduction to command shell scripting

In this chapter, we talk about shells, in the sense of the text-based interfaces we use to communicate with operating systems. UNIX, Linux, and OS X, as well as most UNIX-like operating systems, tend to work on the same general principles for purposes of shell scripting, and make use of many common programming concepts such as data structures, variables, control statements, if-then clauses, and while loops. In Microsoft operating systems, we can find many similar shell scripting tools as well. In Windows, we can carry out commands and write scripts using the generic shells command.com and CMD.exe, the PowerShell shell, and add-on tools such as Cygwin to give us access to bash on Windows, just to name a few.

Chapter 2: Introduction to Python

In this chapter, we dig into the Python language and investigate different types of network scripts, subnetting, and file manipulation. These topics are investigated through practical examples that we will encounter while penetration testing. We look at how to build scripts to communicate with Web servers, determine what Web servers may be hiding, and even investigate how to send our data without it being seen by network tools. These examples and more provide practical, real-world scenarios for when and how to use the Python language. While we're building tools that we can extend for our scripting toolkit, we investigate all the Python basics from data structures, to control statements, to interacting with the shell, and manipulating strings and files.

Chapter 3: Introduction to Perl

In this chapter, we examine the Perl language. We can use Perl to process data and merge data together from disparate sources, a common function in the penetration testing world with its many tools. Scripting in Perl follows most of the standard conventions we can find in other scripting or programming languages and can make use of various data structures, such as variables and arrays to store data in our scripts, arguments, control statements such as loops and conditionals, as well as regular expressions, file I/O, and many of the other standard programming language features.

Chapter 4: Introduction to Ruby

Ruby is a flexible programming language that has taken the better parts of Perl, Python, and many others to create a language that is both powerful and easy to read. In this chapter, we take a look at the powerful object-oriented approach to Ruby. Using Ruby to convert data between hex, binary, and plaintext data, this chapter looks at the details of network and file manipulation, building new classes, manipulating databases, and even building basic network servers. Through these examples, we explore the critical aspects of the Ruby language, and develop the skills to aid in real-world testing scenarios.

Chapter 5: Introduction to Web scripting with PHP

Chapter 5 dives into the world of PHP and Web scripting. Through building basic Web applications with the HyperText Markup Language (HTML) and PHP, we can build dynamic Web pages that take advantage of file manipulation, databases, and even issuing system calls. This chapter focuses on some of the basics and works up to create Web shells that we can use in the field. While working through examples of file manipulation, command execution, loops, and data structures, this chapter walks through the core concepts of PHP that we will need to understand while testing, as well as helps us to create tools that we can use, extend, and incorporate into more sophisticated tools.

Chapter 6: Manipulating windows with PowerShell

This chapter delves deeper into the capabilities of PowerShell, which can be very handy in certain penetration testing situations. PowerShell has access to all the functionality of .NET and can give us capabilities that we might not otherwise have in such an environment without needing to upload tools to the system. We go over execution policies, taking control of the processes on the system, interfacing with the event logs, tweaking the Registry, and more, all through the tools provided by the operating system.

Chapter 7: Scanner scripting

This chapter covers the use of Netcat, Nmap, and Nessus/OpenVAS, and what we can do with them through scripting languages. We talk about automating Netcat through shell scripts, in order to allow us to send files, run simple network services, and forward ports, altering or adding to the behavior of Nmap, customization of Nessus and OpenVAS through the use of the Nessus Attack Scripting Language (NASL), and several other similar tasks.

Chapter 8: Information gathering

In this chapter, we look into information gathering and how it can be of great use to us in the course of a penetration test. We talk about automating searches with Google, parsing text and automating Web interaction with Perl, and finding and working with the metadata stored in documents, files, visual media, and other such structures intended for digital storage of information. We also look at the various tools we might want to use to search for and sift through such data once we have it.

Chapter 9: Exploitation scripting

The ability to use and build exploits is what sets penetration tests apart from vulnerability scans. This chapter works through building a simple exploit from scratch using Python. Once Python has squeezed the application into submission and returned us a shell, we move to Ruby to make it repeatable and more powerful by converting it to a Metasploit module. After exploring the world of binary exploitation, this chapter moves into Web application testing and investigates how to deal with Remote File Inclusion (RFI) vulnerabilities and Cross-Site Scripting (XSS) vulnerabilities. This chapter walks through using the RFI vulnerabilities and leveraging the shells that were created in Chapter 5 to go from Web vulnerability to command line, and ends with building additional scripts to steal data using XSS.

Chapter 10: Post-Exploitation scripting

Once the shells come back, we have a bit more work to do. Chapter 10 discusses what happens after we've gotten in. Working from information gathering under Windows, and moving toward maintaining access through creating users using the Windows command line, this chapter looks at how to query and manipulate Windows systems from the command line. Once we've gotten the hang of it, Chapter 10 works to convert that hard work into a Meterpreter script using Ruby where we can easily run these commands through Metasploit.

After exploiting a Web application, we don't want the database to feel left out, so this chapter ends with manipulating SQL injection vulnerabilities to gain access to applications, dump data, and even get a shell. While looking at capabilities of MySQL and Microsoft SQL Server, this chapter helps develop post-exploitation abilities that will start a basic Web application tester on the road to becoming an advanced one.

Appendix: Subnetting and CIDR addresses

The Appendix fills in information about subnetting for those who want to know more after the subnet calculator example from Chapter 2. The Appendix covers the basics of netmask calculation, Classless Inter-Domain Routing (CIDR) addressing, and the relationship among netmasks, IP addresses, broadcast addresses, and network addresses. Combined with the skills in Chapter 2, this knowledge should make subnetting easy.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9781597497299000175