This commit is contained in:
William Blum 2016-05-22 12:48:41 -07:00
Родитель 858d1ef41f
Коммит bf50230e28
3 изменённых файлов: 127 добавлений и 159 удалений

Просмотреть файл

@ -1,13 +1,22 @@
<#
.SYNOPSIS
This script demonstrate how to use the Springfield service from Powershell
.NOTE
via the Springfield REST API.
.DESCRIPTION
The script performs the following:
- Create a Springfield job
- Wait for preparation machine associated with the job to be ready
- Inject test application to be fuzzed and associated seed files into the virtual machine
- Submit the job
- Monitor the job progress until it starts fuzzing
- Wait until at least one result is reported
- Delete the job
.REMARK
The API token can be generated from the Springfield website on the setting page
#>
param(
# URL to the Springfield service
$springfieldUri = "https://www.alamosand.azurewebsites.net",
$springfieldUri = "https://www.alamohendersonville.com",
# Springfield Account Id
[Parameter(Mandatory=$true)]
@ -17,81 +26,68 @@ param(
[Parameter(Mandatory=$true)]
$apiToken,
# The Azure subscription ID
# Azure subscription ID
[Parameter(Mandatory=$true)]
$subscriptionId,
# Resource group containing the stroage account
[Parameter(Mandatory=$true)]
$resourceGroup,
# The resource group of the storage account
# Name of Azure storage account where to upload the test payload
[Parameter(Mandatory=$true)]
$storageAccountName,
# The key of the storageAccount
# Azure storage account key
[Parameter(Mandatory=$true)]
$storageAccountKey,
# The path to the folder containing the application to fuzz
$testFileFolder="$PSScriptRoot\..\SampleFuzzingJobs\Demofuzz",
$testFileFolder = "$PSScriptRoot\..\SampleFuzzingJobs\Demofuzz",
# Set of job parameters. This correspond to the answer to the wizard's questionnaire
$jobParameters = @{
seedDir = 'c:\DemoFuzz\Data'
seedExtension = '.bin'
testDriverExecutable = 'c:\DemoFuzz\demofuzz.exe'
testDriverExeType = 'x86'
testDriverParameters = '"%testfile%"'
closesItself = $true
maxDurationSeconds = 5
runsInLessThan5 = $true
canRunRepeat = $true
canTestDriverBeRenamed = $true
singleOsProcess = $true
sysprepCompleted = $false
promptValidationSysprep = $false
seedExtension = '.bin'
testDriverExecutable = 'c:\DemoFuzz\demofuzz.exe'
testDriverExeType = 'x86'
testDriverParameters = '"%testfile%"'
closesItself = $true
maxDurationSeconds = 5
runsInLessThan5 = $true
canRunRepeat = $true
canTestDriverBeRenamed = $true
singleOsProcess = $true
sysprepCompleted = $false
promptValidationSysprep = $false
}
)
# Extract name of sample from directory name
$sampleName = $(Split-Path $testFileFolder -Leaf)
<#
.SYNOPSIS
Helper function used to upload files as blob to the azure storage account
#>
function UploadFileToAzure (
# Path to the file to be uploaded to the storageAccount
[Parameter(Mandatory=$true)] $sourceFileName
) {
$targetStorage = Get-AzureRmStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroup
$destContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
$containerName = "sample"
$container = Get-AzureStorageContainer -Context $destContext -Name $containerName -ErrorAction SilentlyContinue
# Path to the file to be uploaded to the storage account
[Parameter(Mandatory=$true)] $sourceFileName,
$containerName = "sample"
) {
$destContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
$container = Get-AzureStorageContainer -Context $destContext -Name $containerName -ErrorAction SilentlyContinue
if(-not $container) {
$container = New-AzureStorageContainer -Name $containerName -Context $destContext
}
$blobName = Split-Path $sourceFileName -Leaf
$blob = Set-AzureStorageBlobContent -Context $destContext -Container $containerName -File $sourceFileName -Blob $blobName -Force
$blobSas = New-AzureStorageBlobSASToken -Context $destContext -Container $containerName -Blob $blobName -Permission r -FullUri -ExpiryTime ([System.DateTime]::Now.AddHours(1))
Write-Host "Blob SAS: $blobSas"
return $blobSas
}
<#
.SYNOPSIS
Compress the test file to zip and inject an install script into the archive
Zip the test payload and add an script into the archive
to automate job submission from the VM.
#>
function CreateTestZipFile(
# Path to the source directory containing the test payload
@ -101,23 +97,27 @@ function CreateTestZipFile(
) {
Write-Host "Creating zip file containing the application to test"
$installScriptContent = @"
'$($jobParameters | ConvertTo-Json)' | Set-Content c:\Springfield\JobParams.json
& c:\Springfield\Springfield.Prevalidation.UI.Console\Springfield.Prevalidation.UI.Console.exe -unattend
"@
$tmpDir = [System.IO.Path]::GetTempFileName()
rm $tmpDir
$dir = md $tmpDir
# Copy test driver and seed files
Copy-Item $testFileFolder $tmpDir -Recurse
$testZipPath = "$tmpDir\$sampleName.zip"
$directoryToZip = "$tmpDir\$sampleName"
Set-Content -Path "$directoryToZip\install.ps1" -Value $installScriptContent
# Copy job parameters
$jobParameters | ConvertTo-Json | Set-Content -Path "$directoryToZip\JobParams.json"
# Generate script to automate job submission
$submitJobScriptContent = @"
'$($jobParameters | ConvertTo-Json)' | Set-Content c:\Springfield\JobParams.json
& c:\Springfield\Springfield.Prevalidation.UI.Console\Springfield.Prevalidation.UI.Console.exe -unattend
"@
Set-Content -Path "$directoryToZip\install.ps1" -Value $submitJobScriptContent
Add-Type -assembly "system.io.compression.filesystem"
if (Test-Path $testZipPath ){
if (Test-Path $testZipPath){
Write-host "$testZipPath already exist: removing it"
Remove-Item $testZipPath
}
@ -127,106 +127,17 @@ function CreateTestZipFile(
return $testZipPath
}
<#
.SYNOPSIS
This function shows how to interact with the Springfield service via the SDK
.DESCRIPTION
The function does the following:
- Create a job
- Wait for preparation machine associated with the job to be ready
- Inject test application to be fuzzed and associated seed files
- Monitor the job progress until it starts fuzzing
- Wait until at least one result is reported
- Delete the job
#>
function CreateAndMonitorJob {
param(
# The list of uris of the dependencies that needs to be donwloaded on the preparation machine
[Parameter(Mandatory=$true)] $dependencyUris
)
$uri = $springfieldUri
$pollingInternavalInSeconds = 60*3
$headers = @{
"SpringfieldApiToken" = $apiToken
"Content-Type" ="application/json"
}
$osImages = Invoke-RestMethod -Method GET -Uri "$uri/api/accounts/$accountId/osimages" -Headers $headers -Verbose
Write-Host "Creating a job"
$jobInfo = Invoke-RestMethod -Method POST -Uri "$uri/api/accounts/$accountId/jobs?osImageId=$($osImages[0].Id)" -Headers $headers -Verbose
$jobId = $jobInfo.Id
Write-Host "job $jobId created"
while (-not $jobInfo.IsPreparationVMReady) {
Write-Host "Waiting for the preparation vm to be ready"
Start-Sleep -Seconds $pollingInternavalInSeconds
$jobInfo = Invoke-RestMethod -Method GET -Uri "$uri/api/accounts/$accountId/jobs/$jobId" -Headers $headers -Verbose
}
Write-Host "Retrieving the machine name"
$machineName = Invoke-RestMethod -Method GET -Uri "$uri/api/accounts/$accountId/jobs/$jobId/customermachine" -Headers $headers -Verbose
Write-Host "Machine name $machineName retrieved"
# The command to execute on the job preparation machine
$executionCommand = "powershell.exe -ExecutionPolicy Unrestricted -Command `".\UnzipAndRun.ps1 -zipFile $sampleName.zip -scriptToRun install.ps1 -outputDir 'c:\$sampleName'`""
$commandParams = @{
"command" = $executionCommand
"dependencyUris" = $dependencyUris
} | ConvertTo-Json
Write-Host "Submitting command for execution $commandParams"
$commandInfo = Invoke-RestMethod -Method POST -Uri "$uri/api/accounts/$accountId/jobs/$jobId/machines/$machineName/command" -Headers $headers -Body $commandParams -ContentType 'application/json' -Verbose
while ($commandInfo.ExecutionState.IsPendingState) {
Write-Host "Waiting for the command to finish executing"
Start-Sleep -Seconds $pollingInternavalInSeconds
$commandInfo = Invoke-RestMethod -Method GET -Uri "$uri/api/accounts/$accountId/jobs/$jobId/machines/$machineName/command/$($commandInfo.CommandId)" -Headers $headers -Verbose
}
if ( $commandInfo.ExecutionState.IsErrorState ) {
throw "Error during execution of custom command : $($commandInfo.ExecutionState.GetError)"
}
Write-Host "Monitoring command job status until fuzzing or error"
while (-not $jobInfo.IsFuzzing ) {
Write-Host "Waiting for the job to start fuzzing"
Start-Sleep -Seconds $pollingInternavalInSeconds
$jobInfo = Invoke-RestMethod -Method GET -Uri "$uri/api/accounts/$accountId/jobs/$jobId" -Headers $headers -Verbose
}
Write-Host "Poll until we get at least one result"
$results = Invoke-RestMethod -Method GET -Uri "$uri/api/accounts/$accountId/jobs/$jobId/results" -Headers $headers -Verbose
while ($results.Count -eq 0){
Start-Sleep -Seconds $pollingInternavalInSeconds
$results = Invoke-RestMethod -Method GET -Uri "$uri/api/accounts/$accountId/jobs/$jobId/results" -Headers $headers -Verbose
}
Write "Got $($results.Count) results $results"
Write-Host "Deleting the job"
Invoke-RestMethod -Method DELETE -Uri "$uri/api/accounts/$accountId/jobs/$jobId" -Headers $headers -Verbose
}
##### Login into Azure
Import-Module AzureRm.Storage
$account = Login-AzureRmAccount -SubscriptionId $subscriptionId
#####
# Preparing the test payload to be copied onto the VM. This includes test driver binaries, seed files
# and the job prameters (a Json blob containing answer to the wizard's questions)
$testZipPath = CreateTestZipFile -testFileFolder $testFileFolder -jobParameters $jobParameters
#####
# Upload all the test files to the azure storage account
Write-Host "Uploading the zip file contianing the application to test"
Import-Module AzureRm.Storage
$account = Login-AzureRmAccount -SubscriptionId $subscriptionId
Write-Host "Uploading the archive with the test payload to a storage account"
$dependencyUris = `
@(
UploadFileToAzure $testZipPath
@ -236,4 +147,69 @@ $dependencyUris = `
#####
# Create the Springfield Job and monitor progress
CreateAndMonitorJob $dependencyUris
$pollingInternavalInSeconds = 60*3
$headers = @{
"SpringfieldApiToken" = $apiToken
"Content-Type" ="application/json"
}
$osImages = Invoke-RestMethod -Method GET -Uri "$springfieldUri/api/accounts/$accountId/osimages" -Headers $headers -Verbose
Write-Host "Creating a job"
$jobInfo = Invoke-RestMethod -Method POST -Uri "$springfieldUri/api/accounts/$accountId/jobs?osImageId=$($osImages[0].Id)" -Headers $headers -Verbose
$jobId = $jobInfo.Id
Write-Host "job $jobId created"
while (-not $jobInfo.IsPreparationVMReady) {
Write-Host "Waiting for the preparation vm to be ready"
Start-Sleep -Seconds $pollingInternavalInSeconds
$jobInfo = Invoke-RestMethod -Method GET -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId" -Headers $headers -Verbose
}
Write-Host "Retrieving the machine name"
$machineName = Invoke-RestMethod -Method GET -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId/customermachine" -Headers $headers -Verbose
Write-Host "Machine name $machineName retrieved"
# The command to execute on the job preparation machine
$executionCommand = "powershell.exe -ExecutionPolicy Unrestricted -Command `".\UnzipAndRun.ps1 -zipFile $sampleName.zip -scriptToRun install.ps1 -outputDir 'c:\$sampleName'`""
$commandParams = @{
"command" = $executionCommand
"dependencyUris" = $dependencyUris
} | ConvertTo-Json
Write-Host "Submitting command for execution $commandParams"
$commandInfo = Invoke-RestMethod -Method POST -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId/machines/$machineName/command" -Headers $headers -Body $commandParams -ContentType 'application/json' -Verbose
while ($commandInfo.ExecutionState.IsPendingState) {
Write-Host "Waiting for the command to finish executing"
Start-Sleep -Seconds $pollingInternavalInSeconds
$commandInfo = Invoke-RestMethod -Method GET -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId/machines/$machineName/command/$($commandInfo.CommandId)" -Headers $headers -Verbose
}
if ($commandInfo.ExecutionState.IsErrorState) {
throw "Error during execution of custom command : $($commandInfo.ExecutionState.GetError)"
}
Write-Host "Monitoring command job status until fuzzing or error"
while (-not $jobInfo.IsFuzzing) {
Write-Host "Waiting for the job to start fuzzing"
Start-Sleep -Seconds $pollingInternavalInSeconds
$jobInfo = Invoke-RestMethod -Method GET -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId" -Headers $headers -Verbose
}
Write-Host "Poll until we get at least one result"
$results = Invoke-RestMethod -Method GET -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId/results" -Headers $headers -Verbose
while ($results.Count -eq 0){
Start-Sleep -Seconds $pollingInternavalInSeconds
$results = Invoke-RestMethod -Method GET -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId/results" -Headers $headers -Verbose
}
Write "Got $($results.Count) results $results"
Write-Host "Deleting the job"
Invoke-RestMethod -Method DELETE -Uri "$springfieldUri/api/accounts/$accountId/jobs/$jobId" -Headers $headers -Verbose

Просмотреть файл

@ -1,26 +1,28 @@
#.SYNOPSIS
# Unpack a .zip file to the spefied target and start
# the specified powershell script from the package
#
#.PARAMETER zipFile
# filename of the zip archive
#.PARAMETER outputDir
# target directory where to unzip the archive (optional, by default unzip to the system temp directory)
# target directory where to unzip the archive
#.PARAMETER scripToRun
# command to run once the package has been extracted. Expressed as relative to outputDir.
#.PARAMETER scriptParameters
# parameters to pass to the script
#
#.EXAMPLE
# & ./UnzipAndRun.ps1 -zipFile sftemplatetools-2015-10-22.zip -scriptToRun SetupTemplateVm.ps1 -scriptParameters '-skipSysprep -unattend'
#
# & ./UnzipAndRun.ps1 -zipFile sftemplatetools-2015-10-22.zip -scriptToRun SetupTemplateVm.ps1 -outputDir c:\test -scriptParameters '-skipSysprep -unattend'
param(
[Parameter(Mandatory=$true)]
$zipfile,
[Parameter(Mandatory=$true)]
$outputDir,
[Parameter(Mandatory=$true)]
$scriptToRun,
$scriptParameters
)
)
$ErrorActionPreference='stop'
@ -30,11 +32,6 @@ $thisDir = [System.IO.Path]::GetDirectoryName($thisScript)
$zipFilePath = Join-Path $thisDir $zipfile
if(-not $outputDir) {
$fileName = [System.IO.Path]::GetFileNameWithoutExtension($zipFilePath)
$outputDir = "$($Env:ProgramData)\Springfield\setup\$fileName"
}
if(Test-Path $outputDir) {
rm -force -Recurse $outputDir
}
@ -47,8 +44,4 @@ rm $zipFilePath
rm $thisScript
$scriptToRunFullPath = Join-Path $outputDir $scriptToRun
try {
Invoke-Expression "$scriptToRunFullPath $scriptParameters"
} catch {
throw "Error while running script [$scriptToRunFullPath $scriptParameters]: $_"
}
Invoke-Expression "$scriptToRunFullPath $scriptParameters"

Просмотреть файл

@ -34,7 +34,6 @@ Calling the Powershell sample:
-accountId <The GUID for your account goes here> `
-apiToken <Your Api token goes here> `
-subscriptionId <You Azure subscription ID goes here> `
-resourceGroup <Name of the resource group containing the storage account> `
-storageAccountName <Name of the storage account used to upload the test driver> `
-storageAccountKey <Your Azure storage account key> `
-testFileFolder <Path to the local files on disk to be uploaded to the storage account and eventually the VM> `