Full Code of ubeeri/Invoke-UserSimulator for AI

master ba8898cca103 cached
3 files
20.1 KB
5.3k tokens
1 requests
Download .txt
Repository: ubeeri/Invoke-UserSimulator
Branch: master
Commit: ba8898cca103
Files: 3
Total size: 20.1 KB

Directory structure:
gitextract_rpgf6rzh/

├── Invoke-UserSimulator.ps1
├── README.md
└── sample.xml

================================================
FILE CONTENTS
================================================

================================================
FILE: Invoke-UserSimulator.ps1
================================================
function Invoke-UserSimulator {
<#
.SYNOPSIS

Simulates common user behaviour on local and remote Windows hosts.
Authors:  Barrett Adams (@peewpw) and Chris Myers (@swizzlez_)

.DESCRIPTION

Performs different actions to simulate real user activity and is intended for use in a lab
environment. It will browse the internet using Internet Explorer, attempt to map non-existant
network shares, and open emails with Outlook, including embeded links and attachments.

.PARAMETER Standalone

Define if the script should run as a standalone script on the localhost or on remote systems.

.PARAMETER ConfigXML

The configuration xml file to use when running on remote hosts.

.PARAMETER IE

Run the Internet Explorer simulation.

.PARAMETER Shares

 Run the mapping shares simulation.
 
.PARAMETER Email

Run the opening email simulation.

.PARAMETER All

Run all script simulation functions (IE, Shares, Email).

.EXAMPLE

Import the script modules:
PS>Import-Module .\Invoke-UserSimulator.ps1

Run only the Internet Explorer function on the local host:
PS>Invoke-UserSimulator -StandAlone -IE

Configure remote hosts prior to running the script remotely:
PS>Invoke-ConfigureHosts -ConfigXML .\config.xml

Run all simulation functionality on remote hosts configured in the config.xml file:
PS>Invoke-UserSimulator -ConfigXML .\config.xml -All

#>
    [CmdletBinding()]
    Param(
		[Parameter(Mandatory=$False)]
		[switch]$StandAlone,

		[Parameter(Mandatory=$False)]
		[switch]$Email,

		[Parameter(Mandatory=$False)]
		[switch]$IE,

		[Parameter(Mandatory=$False)]
		[switch]$Shares,

		[Parameter(Mandatory=$False)]
		[switch]$All,

		[Parameter(Mandatory=$False)]
		[string]$ConfigXML
    )

    $RemoteScriptBlock = {
	# TOOL FUNCTIONS

        [CmdletBinding()]
        Param(
            [Parameter(Position = 0, Mandatory = $false)]
            [Int]$EmailInterval,
			
            [Parameter(Position = 1, Mandatory = $false)]
            [Int]$PageDuration,
			
            [Parameter(Position = 2, Mandatory = $false)]
            [Int]$LinkDepth,
            
            [Parameter(Position = 3, Mandatory = $false)]
            [Int]$MountInterval,
			
            [Parameter(Position = 4, Mandatory=$False)]
            [Int]$Email,
			
            [Parameter(Position = 5, Mandatory=$False)]
            [Int]$IE,
			
            [Parameter(Position = 6, Mandatory=$False)]
            [Int]$Shares,
			
            [Parameter(Position = 7, Mandatory=$False)]
            [Int]$All
        )

        # Creates an Outlook COM Object, then iterates through unread mail. Parses the mail
        # and opens links in IE. Downloads and executes any attachments in a Microsoft trusted
        # folder, resulting in automatic MACRO execution.
        $InvokeOpenEmail = {
            Param(
                [Parameter(Position = 0, Mandatory=$True)]
                [int]$Interval
            )

            While ($True) {

                Add-type -assembly "Microsoft.Office.Interop.Outlook"
                $Outlook = New-Object -comobject Outlook.Application
                $Outlook.visible = $True
                $namespace = $Outlook.GetNameSpace("MAPI")
                $namespace.Logon("","",$false,$true)
                $namespace.SendAndReceive($false)
                Start-Sleep -s 60
                $inbox = $namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)
                $filepath = ("C:\Users\" + $env:username + "\AppData\Roaming\Microsoft\Templates")

                ForEach($mail in $inbox.Items.Restrict("[Unread] = True")) {
                    Write-Host "Found Emails"
                    If ($mail.Attachments) {
                        Write-Host "Found attachments!!"
                        ForEach ($attach in $mail.Attachments) {
                            Write-Host "in attachment loop..."
                            $path = (Join-Path $filepath $attach.filename)
                            $attach.saveasfile($path)
                            Invoke-Item $path
                        }
                    }
					
                    # URL Regex
                    [regex]$regex = "([a-zA-Z]{3,})://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)*?"
                    $URLs = echo $mail.Body | Select-String -Pattern $regex -AllMatches

                    ForEach ($object in $URLs.Matches) {
                        $ie = new-object -COM "InternetExplorer.Application"
                        $ie.visible=$true
                        echo "Parsed link:" $object.Value
                        $ie.navigate2($object.Value)
						$timeout = 0
						While ($ie.busy -And $timeout -lt 10) {
							Start-Sleep -milliseconds 1000
							$timeout += 1
						}
                        Start-Sleep -s 15
                        $ie.Quit()
                    }
					
                    # Set mail object as read
                    $mail.Unread = $false
                }
                Start-Sleep -s $Interval
            }
        }
        $InvokeMapShares = {
            Param(
                [Parameter(Position = 0, Mandatory=$True)]
                [int]$Interval
            )

            While ($True) {
                $randShare = -join ((65..90) + (97..122) | Get-Random -Count 10 | % {[char]$_})
                New-PSDrive -Name "K" -PSProvider FileSystem -Root "\\$randShare\sendCreds"
                Start-Sleep -s $Interval
            }
        }
        
        # Simulates a user browsing the Internet. Will open pseudo-random URLs
        $InvokeIETraffic = {
            Param(
                [Parameter(Position = 0, Mandatory=$True)]
                [int]$Interval,

                [Parameter(Position = 1, Mandatory=$True)]
                [int]$MaxLinkDepth
            )

            $URIs = "https://news.google.com","https://www.reddit.com","https://www.msn.com","http://www.cnn.com","http://www.bbc.com","http://www.uroulette.com"
            $depth = 0

            $ie = New-Object -ComObject "InternetExplorer.Application"
            $ie.visible=$true 
            While ($ie.Application -ne $null) {
                If ($depth -eq 0) {
                    $requestUri = get-random -input $URIs
                }
				
                $depth = $depth + 1

                $ie.navigate2($requestUri)
				$timeout = 0
                While ($ie.busy -And $timeout -lt 10) {
					Start-Sleep -milliseconds 1000
					$timeout += 1
				}

                $linklist = New-Object System.Collections.ArrayList($null)
                ForEach ($link in $ie.document.getElementsByTagName("a")) {
                    If ($link.href.length -gt 1) {
                        $linklist.add($link.href)
                        echo $link.href
                    }
                }

                $requestUri = get-random -input $linklist
                echo $requestUri
                echo $depth
                Start-Sleep -s $Interval
                If ($depth -eq $MaxLinkDepth) {
                    $depth = 0
                }
            }
        }
        
        $emailJob = 0
        $ieJob = 0
        $shareJob = 0
        
        If ($Email -or $All) { $emailJob = Start-Job -ScriptBlock $InvokeOpenEmail -ArgumentList @($EmailInterval) -Name 'usersimemail' }
        If ($IE -or $All) { $ieJob = Start-Job -ScriptBlock $InvokeIETraffic -ArgumentList @($PageDuration, $LinkDepth) -Name 'usersimie' }
        If ($Shares -or $All) { $shareJob = Start-Job -ScriptBlock $InvokeMapShares -ArgumentList @($MountInterval) -Name 'usersimshares' }

        # Start health check loop

        $StartTime = Get-Date
        $TimeOut = New-TimeSpan -Hours 1
        While ($True) {
            Start-Sleep -Seconds 60

            If (($All -or $Email) -and $emailJob.State -ne 'Running') {
                $emailJob = Start-Job -ScriptBlock $InvokeOpenEmail -ArgumentList @($EmailInterval) -Name 'usersimemail'
            }
            If (($All -or $IE) -and $ieJob.State -ne 'Running') {
                $ieJob = Start-Job -ScriptBlock $InvokeIETraffic -ArgumentList @($PageDuration, $LinkDepth) -Name 'usersimie'
            }
            If (($All -or $Shares) -and $shareJob.State -ne 'Running') {
                $shareJob = Start-Job -ScriptBlock $InvokeMapShares -ArgumentList @($MountInterval) -Name 'usersimshares'
            }
            
            If ((New-TimeSpan -Start $StartTime -End (Get-Date)) -gt $TimeOut) {
                    If ($All -or $Email) {
                        Stop-Job -Job $emailJob
                        Stop-Process -Name outlook
                        Stop-Process -Name werfault
                    }
                    If ($All -or $IE) {
                        Stop-Job -Job $ieJob
                        Stop-Process -Name iexplore
                        Stop-Process -Name werfault
                    }
                    If ($All -or $Shares) {
                        Stop-Job -Job $shareJob
                    }
                    $StartTime = Get-Date
            }
        }
    }
	
    If ($StandAlone) {
	# CLIENT BEHAVIOR
        If ($ConfigXML) {
            [xml]$XML = Get-Content $ConfigXML
            $EmailInterval = $XML.usersim.email.checkinInterval
            $PageDuration = $XML.usersim.web.pageDuration
            $LinkDepth = $XML.usersim.web.linkDepth
            $MountInterval = $XML.usersim.shares.mountInterval
        } Else {
            $EmailInterval = 300
            $PageDuration = 20
            $LinkDepth = 10
            $MountInterval = 30
        }

        # Make sure variables have values of the right type
		$myEmailInterval = if ($EmailInterval) {$EmailInterval} else {300}
		$myPageDuration = if ($PageDuration) {$PageDuration} else {20}
		$myLinkDepth = if ($LinkDepth) {$LinkDepth} else {10}
		$myMountInterval = if ($MountInterval) {$MountInterval} else {30}
		$myEmail = if ($Email) {1} else {0}
		$myIE = if ($IE) {1} else {0}
		$myShares = if ($Shares) {1} else {0}
		$myAll = if ($All) {1} else {0}
		
        Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($myEmailInterval, $myPageDuration, $myLinkDepth, $myMountInterval, $myEmail, $myIE, $myShares, $myAll)
    } Else {
	# SERVER BEHAVIOR
        If (!$ConfigXML) {
			Write-Host "Please provide a configuration file with '-ConfigXML' flag."
			Break
		}
		
		$ShareName = 'UserSim'
		
		Create-UserSimShare "C:\UserSim" $ShareName $RemoteScriptBlock
		
		[xml]$XML = Get-Content $ConfigXML
		$EmailInterval = $XML.usersim.email.checkinInterval
		$PageDuration = $XML.usersim.web.pageDuration
		$LinkDepth = $XML.usersim.web.linkDepth
		$MountInterval = $XML.usersim.shares.mountInterval
		$Server = $XML.usersim.serverIP
		
		$myEmailInterval = if ($EmailInterval) {$EmailInterval} else {300}
		$myPageDuration = if ($PageDuration) {$PageDuration} else {20}
		$myLinkDepth = if ($LinkDepth) {$LinkDepth} else {10}
		$myMountInterval = if ($MountInterval) {$MountInterval} else {30}
		$myEmail = if ($Email) {1} else {0}
		$myIE = if ($IE) {1} else {0}
		$myShares = if ($Shares) {1} else {0}
		$myAll = if ($All) {1} else {0}
		
		$TaskArgs = "-exec bypass -w hidden -c ipmo \\$Server\$ShareName\UserSim.ps1;Invoke-UserSim $myEmailInterval $myPageDuration $myLinkDepth $myMountInterval $myEmail $myIE $myShares $myAll"

		$XML.usersim.client | ForEach-Object { 

			$myHost = $_.host
			$username = $_.username
			$password = $_.password
			$domain = $_.domain
			$DomainUser = $domain+'\'+$username
		
			Write-Host "In foreach loop..."
			Write-Host "$myHost"
			cmdkey /delete:"$myHost"
			Start-RemoteUserSimTask $myHost $TaskArgs $DomainUser $password
			start-sleep -s 1
			cmdkey /add:$myHost /user:"$domain\$username" /pass:"$password"
			Start-Sleep -s 1
			mstsc.exe /v "$myHost"
			Start-Sleep -s 5
			cmdkey /delete:"$myHost"

			Write-Host "Starting usersim on '$myHost' with username '$username'"
		}
    }
}

function Create-UserSimShare {
    [CmdletBinding()]
    Param(
		[Parameter(Position = 0, Mandatory=$True)]
		[String]$SharePath,

		[Parameter(Position = 1, Mandatory=$True)]
		[String]$ShareName,

		[Parameter(Position = 2, Mandatory=$True)]
		[Management.Automation.ScriptBlock]$ScriptBlock
    )
	
	If (Test-Path $SharePath) {
		Remove-Item -Path $SharePath -Recurse -Force
        Start-Sleep -Milliseconds 400
	}
	New-Item $SharePath -Type Directory 

	$Shares=[WMICLASS]"Win32_Share"

	$old_shares = Get-WMIObject Win32_Share -Filter "name='$ShareName'"
	If ($old_shares) { 
		ForEach ($share in $old_shares) {
			$delete = $share.Delete()
		}
	}

	$Shares.Create($SharePath,$ShareName,0)
	$functionString = "function Invoke-UserSim {" + $ScriptBlock + "}"
    $functionString | Out-File $SharePath\UserSim.ps1
}

function Start-RemoteUserSimTask {
    [CmdletBinding()]
    Param(
		[Parameter(Position = 0, Mandatory=$True)]
		[String]$RemoteHost,
		
		[Parameter(Position = 1, Mandatory=$True)]
		[String]$TaskArguments,
		
		[Parameter(Position = 2, Mandatory=$True)]
		[String]$TaskUser,

		[Parameter(Position = 3, Mandatory=$True)]
		[String]$TaskPassword
    )
	
	$RemoteStart = {
		Param(
			[Parameter(Position = 0, Mandatory=$True)]
			[String]$TaskArguments,
			
			[Parameter(Position = 1, Mandatory=$True)]
			[String]$TaskUser,
			
			[Parameter(Position = 2, Mandatory=$True)]
			[String]$TaskPassword
		)
	
		$ExpTime = (Get-Date).AddMinutes(10).GetDateTimeFormats('s')[0]
		
		$ShedService = New-Object -comobject 'Schedule.Service'
		$ShedService.Connect('localhost')

		$Task = $ShedService.NewTask(0)
		$Task.RegistrationInfo.Description = 'Temporary User Sim Task'
		$Task.Settings.Enabled = $true
		$Task.Settings.AllowDemandStart = $true
		$Task.Settings.DeleteExpiredTaskAfter = 'PT5M'

		$trigger = $Task.Triggers.Create(11)
		$trigger.Enabled = $true
		$trigger.UserId = $TaskUser
		$trigger.StateChange = 3
		$trigger.EndBoundary = $ExpTime
		
		$trigger2 = $Task.Triggers.Create(9)
		$trigger2.Enabled = $true
		$trigger2.UserId = $TaskUser
		$trigger2.EndBoundary = $ExpTime

		$action = $Task.Actions.Create(0)
		$action.Path = "powershell"
		$action.Arguments = $TaskArguments

		$taskFolder = $ShedService.GetFolder("\")
		$taskFolder.RegisterTaskDefinition("UserSim", $Task , 6, $TaskUser, $TaskPassword, 3)
	}
	
	Invoke-Command -ScriptBlock $RemoteStart -ArgumentList @($TaskArguments, $TaskUser, $TaskPassword) -ComputerName $RemoteHost
}

function Invoke-ConfigureHosts {
<#
.SYNOPSIS

Configure remote hosts in preperation for Invoke-UserSimulator

.DESCRIPTION

Sets some registry keys to allow programatic access to Outlook and prevent the "welcome" window
in Internet Explorer. Also adds the user to run as to the "Remote Desktop Users" group on the
remote computer.

.PARAMETER ConfigXML

The configuration xml file to use for host configuration on remote hosts.

.EXAMPLE

Import the script modules:
PS>Import-Module .\Invoke-UserSimulator.ps1

Configure remote hosts prior to running the script remotely:
PS>Invoke-ConfigureHosts -ConfigXML .\config.xml

#>
    Param(
		[Parameter(Position = 0, Mandatory=$True)]
		[String]$ConfigXML
    )

    If (!$ConfigXML) {
			Write-Host "Please provide a configuration file with '-ConfigXML' flag."
			Break
	} else {
        [xml]$XML = Get-Content $ConfigXML

        $XML.usersim.client | ForEach-Object {

	        $myHost = $_.host
	        $username = $_.username
            $domain = $_.domain
            $domUser = "$domain\$username"

            $configBlock = {
                Param(
		            [Parameter(Position = 0, Mandatory=$True)]
		            [String]$domuser
                )
                net localgroup "Remote Desktop Users" $domuser /add

                $registryPath = "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Wow6432Node\Microsoft\Office\16.0\Outlook\Security"
                New-Item -Path $registryPath -Force
                Set-ItemProperty -Path $registryPath -Name ObjectModelGuard -Value 2 -Type DWord

                $registryPath = "HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Microsoft\Office\16.0\Outlook\Security"
                New-Item -Path $registryPath -Force
                Set-ItemProperty -Path $registryPath -Name ObjectModelGuard -Value 2 -Type DWord

                $registryPath = "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main"
                New-Item -Path $registryPath  -Force
                Set-ItemProperty -Path $registryPath -Name DisableFirstRunCustomize -Value 1
            }
			
            Invoke-Command -ScriptBlock $configBlock -ArgumentList $domuser -ComputerName $myHost
        }
    }
}

================================================
FILE: README.md
================================================
# Invoke-UserSimulator
Simulates common user behaviour on local and remote Windows hosts.

Invoke-UserSimulator is a tool developed with the aim of improving the realism of penetration testing labs (or other lab environments) to more accurately mirror a real network with users that create various types of traffic. Currently supported user behaviours the tool simulates are:

**Internet Explorer Browsing -** Creates an IE process and browses to a psuedo-random URL, then spiders the page for additional links to browse to. Simulates a user browsing the internet and creating web traffic on the network. 

**Mapping Shares -** Generates a random share name, and attempts to map it to the "K" drive. Creates LLMNR traffic on the network, allowing capturing network credentials via MitM attacks (Responder).

**Opening Emails -** Creates and Outlook COM object and iterates through any unread mail of the logged in user. Downloads and executes any attachments, and browses to any embedded links in IE.

The script can be run on a local server, or numerous remote hosts at once. For running on remote hosts, the script includes a configuration function to preconfigure Remote Desktop Users and various 

### Requirements:
**Windows -** The tool should work with any recent versions of Microsoft Windows (tested on Windows 7 through Server 2016). There is heavy use of PowerShell remoting, so when working with Windows 7 machines, some additional configuration will be required. 

**Microsoft Office -** When running the tool with -All or -Email flags, you'll need to have Outlook installed and configured to properly receive mail. Your users will also need to have working email addresses. If you plan on sending Macro phishing payloads, be sure the rest of the Office suite is installed as well.

### Arguments:
-Standalone
Define if the script should run as a standalone script on the localhost or on remote systems.

-ConfigXML [filepath]
The configuration xml file to use for host configuration and when running on remote hosts.

-ALL
Run all script simulation functions (IE, Shares, Email).

-IE
Run the Internet Explorer simulation.

-Shares
Run the mapping shares simulation.

-Email
Run the opening email simulation.

### Examples:
Import the script modules:

`PS>Import-Module .\Invoke-UserSimulator.ps1`

Run only the Internet Explorer function on the local host:

`PS>Invoke-UserSimulator -StandAlone -IE`

Configure remote hosts prior to running the script remotely:

`PS>Invoke-ConfigureHosts -ConfigXML .\config.xml`

Run all simulation functionality on remote hosts configured in the config.xml file:

`PS>Invoke-UserSimulator -ConfigXML .\config.xml -All`

*View the sample.xml file for an example of the file ConfigXML takes.*

### Walkthrough:
You can view a video walkthrough of the tool here: https://www.youtube.com/watch?v=lsC8mBKRZrs


================================================
FILE: sample.xml
================================================
<?xml version="1.0"?>
<usersim>
	<serverIP>10.10.12.105</serverIP>
	<email>
		<checkinInterval>60</checkinInterval>
	</email>
	<web>
		<pageDuration>60</pageDuration>
		<linkDepth>5</linkDepth>
	</web>
	<shares>
		<mountInterval>60</mountInterval>
	</shares>
	<client>
		<host>DESK001.peew.pw</host>
		<domain>peew.pw</domain>
		<username>jsmith</username>
		<password>Passw0rd!</password>
	</client>
	<client>
		<host>DESK002.peew.pw</host>
		<domain>peew.pw</domain>
		<username>awilliams</username>
		<password>Qwerty1234</password>
	</client>
</usersim>
Download .txt
gitextract_rpgf6rzh/

├── Invoke-UserSimulator.ps1
├── README.md
└── sample.xml
Condensed preview — 3 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (22K chars).
[
  {
    "path": "Invoke-UserSimulator.ps1",
    "chars": 17165,
    "preview": "function Invoke-UserSimulator {\r\n<#\r\n.SYNOPSIS\r\n\r\nSimulates common user behaviour on local and remote Windows hosts.\r\nA"
  },
  {
    "path": "README.md",
    "chars": 2855,
    "preview": "# Invoke-UserSimulator\nSimulates common user behaviour on local and remote Windows hosts.\n\nInvoke-UserSimulator is a too"
  },
  {
    "path": "sample.xml",
    "chars": 582,
    "preview": "<?xml version=\"1.0\"?>\r\n<usersim>\r\n\t<serverIP>10.10.12.105</serverIP>\r\n\t<email>\r\n\t\t<checkinInterval>60</checkinInterval>\r"
  }
]

About this extraction

This page contains the full source code of the ubeeri/Invoke-UserSimulator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 3 files (20.1 KB), approximately 5.3k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!