Extract DNS Records to CSV with PowerShell

In some cases to do an analysis of DNS records it may be desirable to extract records into CSV format. Unfortunately PowerShell cmdlet Get-DnsServerResourceRecord has the important data in a field called “RecordData” which stores relevant data in different properties depending on the resource record type. This prevents outputting any useful information directly to CSV.
This script will add an additional field “Data” which formats RecordData based on resource record type.

Currently this script supports following resource record types:

A
NS
SOA
CNAME
SRV
AAAA
PTR
MX
TXT

Unsupported record types will still be logged but data field will have message “Unsupported Record Type”. Update the switch statement to support additional record types as requried.

To use

Get-AllDnsResourceRecords -DnsServer 8.8.8.8 | Export-Csv -NoTypeInformation -Path c:\support\DnsRecords.csv

Script is available here https://github.com/chentiangemalc/PowerShellScripts/blob/master/Get-AllDnsResourceRecords.ps1

 
[CmdletBinding()]
param(
[Parameter(Position=0)]
[String]$DNSServer)

$Zones = @(Get-DnsServerZone -ComputerName $DNSServer)
$Data = @() 
ForEach ($Zone in $Zones) {
	($Zone | Get-DnsServerResourceRecord -ComputerName $DNSServer) | `
        Select-Object -Property `
            @{Label="Zone Name";expression={( $Zone.ZoneName )}},`
            DistinguishedName,`
            HostName,`
            RecordClass,`
            RecordType,`
            Timestamp,`
            TimeToLive,`
            @{label="Data";expression={
                $r = $_.RecordData
                switch ($_.RecordType)
                {
                    "A" { $r.IPv4Address.IPAddressToString }
                    "NS" { $r.NameServer }
                    "SOA" { 
                        "ExpireLimit=$($r.ExpireLimit);"+
                        "MinimumTimeToLive=$($r.MinimumTimeToLive);"+
                        "PrimaryServer=$($r.PrimaryServer);"+
                        "RefreshInterval=$($r.RefreshInterval);"+
                        "ResponsiblePerson=$($r.ResponsiblePerson);"+
                        "RetryDelay=$($r.RetryDelay);"+
                        "SerialNumber=$($r.SerialNumber)"

                    }
                    "CNAME" {  $r.HostNameAlias }
                    "SRV"{ 
                        "DomainName=$($r.DomainName);"+
                        "Port=$($r.Port);"+
                        "Priority=$($r.Priority);"+
                        "Weight=$($r.Weight)"
                    }
                    "AAAA" { $r.IPv6Address.IPAddressToString }
                    "PTR" { $r.PtrDomainName } 
                    "MX" {
                        "MailExchange=$($r.MailExchange);"+
                        "Prefreence=$($r.Preference)"
                    }
                    "TXT" { $r.DescriptiveText }
                    Default { "Unsupported Record Type" }
                }}
            }
}
Posted in Uncategorized | Leave a comment

Export OU Structure To Image with PowerShell

Here is a PowerShell script that will generate an image of OU structure for the domain user running script is a part of.

Does not require Remote Server Administration Tools Installed.

Image can be in formats

.BMP
.GIF
.JPG
.PNG
.TIFF

Script is on GitHub here https://raw.githubusercontent.com/chentiangemalc/PowerShellScripts/master/Export-OUsToImage.ps1

 
[CmdletBinding()]
param(
[Parameter(Position=0)]
[ValidateScript({
    if( -Not ($_.DirectoryName | Test-Path) ){
        throw "File or folder does not exist"
    }
    return $true
})]
[System.IO.FileInfo]$Path)

Add-Type -AssemblyName 'System.Windows.Forms'
Add-Type -AssemblyName 'System.Drawing'
Add-Type -AssemblyName 'System.DirectoryServices'

# Folder icono, this code generated with following code
#$image = [System.Drawing.Image]::FromFile("C:\support\scripts\AD\folder.png")
#$ms = New-Object System.IO.MemoryStream
#$image.Save($ms,$image.RawFormat)
#$arr = $ms.ToArray()
#$result = "$FolderImage = @(```r`n"
#$c = 0
#ForEach ($a in $arr)
#{
#    $c++
#    $result+=("0x{0:x}," -f $a )
#    if ($c -gt 20)
#    {
#        $c =0
#        $result+="```r`n"
#    }
#
#}
#$result += ")"

[Byte[]]$folderImageBytes = @(`
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x30,0x0,`
0x0,0x0,0x30,0x8,0x6,0x0,0x0,0x0,0x57,0x2,0xf9,0x87,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,`
0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc2,0x0,0x0,`
0xe,0xc2,0x1,0x15,0x28,0x4a,0x80,0x0,0x0,0x1,0x61,0x49,0x44,0x41,0x54,0x68,0x43,0xed,0x92,0xb1,0x4a,`
0x3,0x41,0x14,0x45,0xa7,0xd0,0x3f,0x10,0x9b,0xa8,0x85,0xb8,0xc9,0x6a,0xeb,0x37,0xf8,0x5d,0xfe,0x89,0x6,`
0xd4,0x42,0x8c,0x9d,0x76,0x82,0x5d,0x36,0xbb,0xe0,0x4f,0x8,0x96,0x11,0x8d,0xfd,0x7b,0x4e,0xc2,0xad,0xe4,`
0xde,0x18,0x1b,0xf7,0x15,0x73,0xe0,0x74,0xb9,0xc3,0x99,0x9d,0xa4,0x42,0xa1,0x50,0x28,0x14,0x7e,0x62,0x17,`
0x69,0xdf,0xc6,0x69,0x92,0x5d,0xf8,0x38,0xf9,0x26,0xe6,0xdf,0x9e,0x63,0xde,0x2f,0x76,0x95,0xf6,0x72,0xcc,`
0x9c,0x45,0xfe,0x66,0x88,0x4b,0xd8,0x65,0xba,0x63,0x71,0x9b,0xda,0xfb,0x25,0xf2,0x5,0xbe,0x58,0xd8,0x5f,`
0xec,0xf5,0x12,0xab,0x88,0x9b,0x6d,0xf7,0xa7,0x81,0xfb,0x6c,0xe8,0xde,0xd5,0xbd,0x6a,0xb3,0xa1,0xd9,0xf3,`
0xc1,0x9b,0x3d,0xee,0x9e,0x21,0x71,0x3d,0x7e,0xbd,0xe5,0xde,0x54,0xf4,0xb0,0x3e,0xb5,0x69,0x65,0xfe,0xb0,`
0x73,0x8a,0x4c,0xcd,0xea,0xcb,0x93,0x3,0x22,0x98,0x5f,0xe2,0x15,0x99,0x9a,0x8,0x7f,0x1b,0xa5,0x35,0x43,`
0x43,0xa6,0x86,0xd,0x23,0x89,0x4c,0xd,0x1b,0x45,0x12,0x99,0x1a,0x36,0x8a,0x24,0x32,0x35,0x6c,0x14,0x49,`
0x64,0x6a,0xd8,0x28,0x92,0xc8,0xd4,0xb0,0x51,0x24,0x91,0xa9,0x61,0xa3,0x48,0x22,0x53,0xc3,0x46,0x91,0x44,`
0xa6,0x86,0x8d,0x22,0x89,0x4c,0xd,0x1b,0x45,0x12,0x99,0x1a,0x36,0x8a,0x24,0x32,0x35,0x6c,0x14,0x49,0x64,`
0x6a,0xd8,0x28,0x92,0xc8,0xd4,0xb0,0x51,0x24,0x91,0xa9,0x61,0xa3,0x48,0x22,0x53,0xc3,0x46,0x91,0x44,0xa6,`
0x86,0x8d,0x22,0x89,0x4c,0xd,0x1b,0x45,0x12,0x99,0x1a,0x36,0x8a,0x24,0x32,0x35,0x6c,0x14,0x49,0x64,0x6a,`
0xac,0xab,0x17,0x6c,0x18,0xc1,0xdc,0xf6,0x89,0x4c,0x8d,0xb5,0xa3,0x7b,0x36,0x8e,0xa0,0xb5,0xf5,0x4,0x99,`
0x1a,0x6b,0x8e,0x2b,0xeb,0x46,0x73,0x76,0x40,0x9f,0xe6,0xa6,0x77,0xef,0xaa,0x43,0x64,0xae,0xc7,0xa6,0xd5,`
0x20,0x3f,0xd7,0xed,0xf2,0xc9,0xd8,0x61,0xff,0x6a,0x5b,0x7f,0x2c,0xbf,0xbc,0xbd,0x9c,0x1c,0x21,0xaf,0x50,`
0x28,0x14,0xa,0x5,0x90,0xd2,0x37,0x8f,0x8a,0x6e,0xbd,0x1e,0x85,0x16,0xcf,0x0,0x0,0x0,0x0,0x49,0x45,`
0x4e,0x44,0xae,0x42,0x60,0x82)

$ms = New-Object System.IO.MemoryStream($folderImageBytes,0,$folderImageBytes.Length)
$ms.Position = 0
$folderImage = [System.Drawing.Image]::FromStream($ms,$true)
$ms.Close()

# todo: calculate dynamically depending on OU structure
$IMAGE_WIDTH = 800

# easy way $OUs = Get-ADOrganizationalUnit -Filter *
# but needs RSAT installed, so using System.DirectoryServices Instead
$rootDE = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().GetDirectoryEntry()
$searcher = New-Object System.DirectoryServices.DirectorySearcher($rootDE)
$searcher.Filter = "(objectCategory=organizationalUnit)";

$OUs = @()
foreach ($result in $searcher.FindAll()) 
{
    $OUs += $result.Properties.distinguishedname
}

$treeView = New-Object System.Windows.Forms.TreeView
$imageList = New-Object System.Windows.Forms.ImageList
$imageList.Images.Add($folderImage)
$treeView.ImageList = $imageList
$treeView.Top =0
$treeView.Left =0

ForEach ($ou in $OUs)
{

    $domain =  $OU.Substring($OU.IndexOf("DC=")+3).Replace(",DC=",".")
    $SplitDN = $OU.Substring(0,$OU.IndexOf(",DC=")).`
        Replace(",OU=","\").`
        Replace(",CN=","\").`
        Replace("OU=","").`
        Replace("CN=","").Split("\")

    $ReversedDN = New-Object System.Text.StringBuilder
    [void]$reversedDn.Append($domain)
    For ($i=$SplitDN.Count-1;$i -ge 0;$i--)
    {
        [void]$ReversedDn.Append("\$($SplitDN[$i])")
    }

    $currentNode = $null
    
    Write-Host $ReversedDN.ToString()

    ForEach ($item in $ReversedDN.ToString().Split("\"))
    { 
        if ($currentNode -eq $null)
        {
            $currentNode = $treeView.Nodes[$item]
            if ($currentNode -eq $null)
            {
                $currentNode = $treeView.Nodes.Add($item)
                $currentNode.Name = $item
            }
    
        }
        else
        {
            if ($currentNode.Nodes[$item] -eq $null)
            {
                $currentNode = $currentNode.Nodes.Add($item)
                $currentNode.Name = $item 
            }
            else
            {
                $currentNode = $currentNode.Nodes[$item]
            }
        }
    }
}

[void]$treeView.ExpandAll()

$treeView.Width = $IMAGE_WIDTH
$treeView.Height = ($treeView.GetNodeCount($true)+1) * ($treeView.ItemHeight)

$bmp = New-Object System.Drawing.Bitmap($treeView.Width, $treeView.Height)
[void]$treeView.DrawToBitmap($bmp,(New-Object System.Drawing.Rectangle(0, 0, $bmp.Width, $bmp.Height)))
[void]$bmp.Save($Path.FullName)
Posted in Uncategorized | Leave a comment

Convert NetSh Trace ETL to PCAP with PowerShell

In-built packet capture in Windows 7 / Server 2008 R2 and later operating systems is incredibly useful tool with netsh trace. Unfortunately large ETL files are super slow to load in Microsoft Message Analyzer, and for many network analysis scenarios I prefer Wireshark’s layout. While Message Analyzer can open the ETL files and convert them to suitable format for Wireshark it is quite a bit of waiting, I just want to open the logs.

Here is a script I wrote to transform the .ETL file into a .PCAP file which can be opened in Wireshark and network packets inspected.

Currently I have only tested this with .ETL files generated from Windows 10.

In this case I had to use inline C# as using native PowerShell was far too slow.

Run this script then you can perform conversions with this command:

./ConvertEtl-ToPcap.ps1 -Path C:\support\NetTrace.etl -Destination C:\support\NetTrace.pcap

A version in C# for Visual Studio is available here https://github.com/chentiangemalc/EtlToCap

The compiled version of that is located here https://github.com/chentiangemalc/EtlToCap/raw/master/EtlToCap/bin/Debug/EtlToCap.exe

Utilise compiled version:
EtlToCap NetTrace.Etl NetTrace.pcap

Script is available here on GitHub https://github.com/chentiangemalc/PowerShellScripts/blob/master/ConvertEtl-ToPcap.ps1

[CmdletBinding()]
param(
[Parameter(Position=0)]
[ValidateScript({
    if( -Not ($_ | Test-Path) ){
        throw "File or folder $_ does not exist"
    }

    if($_.Extension -ne ".etl"){
        throw "Source file must be .etl file"
    }
    return $true
})]
[System.IO.FileInfo]$Path,

[Parameter(Position=1)]
[ValidateScript({
    if( -Not ($path.DirectoryName | Test-Path) ){
        throw "File or folder does not exist"
    }

    if($_.Extension -ne ".pcap") {
        throw "Estination file must be .pcap file"
    }
    return $true
})]
[System.IO.FileInfo]$Destination,

[Parameter(Position=2)]
[Uint32]$MaxPacketSizeBytes = 65536)


$csharp_code = @'
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace chentiangemalc
{
    public static class NetworkRoutines
    {
    public static long ConvertEtlToPcap(string source, string destination, UInt32 maxPacketSize)
        {
            int result = 0;
            using (BinaryWriter writer = new BinaryWriter(File.Open(destination, FileMode.Create)))
            {

                UInt32 magic_number = 0xa1b2c3d4;
                UInt16 version_major = 2;
                UInt16 version_minor = 4;
                Int32 thiszone = 0;
                UInt32 sigfigs = 0;
                UInt32 snaplen = maxPacketSize;
                UInt32 network = 1; // LINKTYPE_ETHERNET

                writer.Write(magic_number);
                writer.Write(version_major);
                writer.Write(version_minor);
                writer.Write(thiszone);
                writer.Write(sigfigs);
                writer.Write(snaplen);
                writer.Write(network);

                long c = 0;
                long t = 0;
                using (var reader = new EventLogReader(source, PathType.FilePath))
                {
                    EventRecord record;
                    while ((record = reader.ReadEvent()) != null)
                    {
                        c++;
                        t++;
                        if (c == 10000)
                        {
                            Console.WriteLine(String.Format("Processed {0} events with {1} packets processed",t,result));
                            c = 0;
                        }
                        using (record)
                        {
                            if (record.ProviderName == "Microsoft-Windows-NDIS-PacketCapture")
                            {
                                result++;
                                DateTime timeCreated = (DateTime)record.TimeCreated;
                                UInt32 ts_sec = (UInt32)((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
                                UInt32 ts_usec = (UInt32)(((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds) - ((UInt32)((timeCreated.Subtract(new DateTime(1970, 1, 1))).TotalSeconds * 1000))) * 1000;
                                UInt32 incl_len = (UInt32)record.Properties[2].Value;
                                if (incl_len > maxPacketSize)
                                {
                                   Console.WriteLine(String.Format("Packet size of {0} exceeded max packet size {1}, packet ignored",incl_len,maxPacketSize));
                                }
                                UInt32 orig_len = incl_len;

                                writer.Write(ts_sec);
                                writer.Write(ts_usec);
                                writer.Write(incl_len);
                                writer.Write(orig_len);
                                writer.Write((byte[])record.Properties[3].Value);

                            }
                        }
                    }
                }
            }
            return result;
        }
    }
}
'@

Add-Type -Type $csharp_code

$result = [chentiangemalc.NetworkRoutines]::ConvertEtlToPcap($Path.FullName,$Destination.FullName,$MaxPacketSizeBytes)

Write-Host "$result packets converted."

Warning: IF you are a regular NetSh Trace user please remember to store log files in a path outside the user profile, or you may get numbers such as .000 appended to your user profile on Windows in-place upgrades.

Posted in Uncategorized | Leave a comment

Unable to Connect to iSCSI Targets with Authentication Type in PowerShell

Attempting to connect to iSCSI targets in PowerShell was failing when specifying Authentication Type. The authentication type was being specified as per Microsoft documentation here :

-AuthenticationType.
Specifies the type of authentication to use when logging into the target. The acceptable values for this parameter are:
  • None
  • OneWayCHAP
  • MutualCHAP

The default value is None.

Let’s check how the command makes a connection. Using PowerShell cmd

Get-Command -Type All -Name Connect-IscsiTarget | Format-List *

We can see in ScriptBlock it is using WMI Microsoft.Management.Infrastructure.CimInstance#MSFT_iSCSISession

Using cmd

find "MSFT_iSCSISession" C:\windows\system32\wbem\*.mof

We can see this is defined in MOF file C:\WINDOWS\SYSTEM32\WBEM\ISCSIWMIV2.MOF
We can open the MOF file in a text editor and note the GUID here

ClsId = “{52C84ACA-027A-4536-A74A-E0BB50C44782}”;

We can now use this to find the DLL that implements the WMI method:

C:\Windows>reg query hkcr\clsid\{52C84ACA-027A-4536-A74A-E0BB50C44782}\InProcServer32

HKEY_CLASSES_ROOT\clsid\{52C84ACA-027A-4536-A74A-E0BB50C44782}\InProcServer32
    (Default)    REG_EXPAND_SZ    %systemroot%\system32\iscsiwmiv2.dll
    ThreadingModel    REG_SZ    Both

Analysis of DLL %systemroot%\system32\iscsiwmiv2.dll shows the authentication types are all in upper case.

  • NONE
  • ONEWAYCHAP
  • MUTUALCHAP

.text:1000E437 loc_1000E437: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+27Bj
.text:1000E437 ; MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+280j
.text:1000E437 cmp byte ptr [ebx+54h], 0
.text:1000E43B jz loc_1000E50F
.text:1000E441 mov edx, [ebx+50h]
.text:1000E444 or eax, 80h
.text:1000E449 mov [esp+0B38h+var_B10], eax
.text:1000E44D mov esi, offset Str2 ; “NONE”
.text:1000E452 mov [esp+0B38h+Memory], edi
.text:1000E456 mov ecx, edx
.text:1000E458
.text:1000E458 loc_1000E458: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2C8j
.text:1000E458 mov di, [ecx]
.text:1000E45B cmp di, [esi]
.text:1000E45E jnz short loc_1000E480
.text:1000E460 test di, di
.text:1000E463 jz short loc_1000E47A
.text:1000E465 mov di, [ecx+2]
.text:1000E469 cmp di, [esi+2]
.text:1000E46D jnz short loc_1000E480
.text:1000E46F add ecx, 4
.text:1000E472 add esi, 4
.text:1000E475 test di, di
.text:1000E478 jnz short loc_1000E458
.text:1000E47A
.text:1000E47A loc_1000E47A: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2B3j
.text:1000E47A xor esi, esi
.text:1000E47C mov ecx, esi
.text:1000E47E jmp short loc_1000E487
.text:1000E480 ; —————————————————————————
.text:1000E480
.text:1000E480 loc_1000E480: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2AEj
.text:1000E480 ; MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2BDj
.text:1000E480 sbb ecx, ecx
.text:1000E482 or ecx, 1
.text:1000E485 xor esi, esi
.text:1000E487
.text:1000E487 loc_1000E487: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2CEj
.text:1000E487 neg ecx
.text:1000E489 sbb ecx, ecx
.text:1000E48B and ecx, esi
.text:1000E48D mov esi, offset aMutualchap ; “MUTUALCHAP”
.text:1000E492 mov [esp+0B38h+Memory], ecx
.text:1000E496 mov ecx, edx
.text:1000E498
.text:1000E498 loc_1000E498: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+308j
.text:1000E498 mov di, [ecx]
.text:1000E49B cmp di, [esi]
.text:1000E49E jnz short loc_1000E4C0
.text:1000E4A0 test di, di
.text:1000E4A3 jz short loc_1000E4BA
.text:1000E4A5 mov di, [ecx+2]
.text:1000E4A9 cmp di, [esi+2]
.text:1000E4AD jnz short loc_1000E4C0
.text:1000E4AF add ecx, 4
.text:1000E4B2 add esi, 4
.text:1000E4B5 test di, di
.text:1000E4B8 jnz short loc_1000E498
.text:1000E4BA
.text:1000E4BA loc_1000E4BA: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2F3j
.text:1000E4BA xor edi, edi
.text:1000E4BC mov ecx, edi
.text:1000E4BE jmp short loc_1000E4C7
.text:1000E4C0 ; —————————————————————————
.text:1000E4C0
.text:1000E4C0 loc_1000E4C0: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2EEj
.text:1000E4C0 ; MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+2FDj
.text:1000E4C0 sbb ecx, ecx
.text:1000E4C2 or ecx, 1
.text:1000E4C5 xor edi, edi
.text:1000E4C7
.text:1000E4C7 loc_1000E4C7: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+30Ej
.text:1000E4C7 test ecx, ecx
.text:1000E4C9 jnz short loc_1000E4D3
.text:1000E4CB mov [esp+0B38h+Memory], 2
.text:1000E4D3
.text:1000E4D3 loc_1000E4D3: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+319j
.text:1000E4D3 mov ecx, offset aOnewaychap ; “ONEWAYCHAP”
.text:1000E4D8
.text:1000E4D8 loc_1000E4D8: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+348j
.text:1000E4D8 mov si, [edx]
.text:1000E4DB cmp si, [ecx]
.text:1000E4DE jnz short loc_1000E4FE
.text:1000E4E0 test si, si
.text:1000E4E3 jz short loc_1000E4FA
.text:1000E4E5 mov si, [edx+2]
.text:1000E4E9 cmp si, [ecx+2]
.text:1000E4ED jnz short loc_1000E4FE
.text:1000E4EF add edx, 4
.text:1000E4F2 add ecx, 4
.text:1000E4F5 test si, si
.text:1000E4F8 jnz short loc_1000E4D8
.text:1000E4FA
.text:1000E4FA loc_1000E4FA: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+333j
.text:1000E4FA mov ecx, edi
.text:1000E4FC jmp short loc_1000E503
.text:1000E4FE ; —————————————————————————
.text:1000E4FE
.text:1000E4FE loc_1000E4FE: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+32Ej
.text:1000E4FE ; MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+33Dj
.text:1000E4FE sbb ecx, ecx
.text:1000E500 or ecx, 1
.text:1000E503
.text:1000E503 loc_1000E503: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+34Cj
.text:1000E503 test ecx, ecx
.text:1000E505 jnz short loc_1000E50F
.text:1000E507 mov [esp+0B38h+Memory], 1
.text:1000E50F
.text:1000E50F loc_1000E50F: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+28Bj
.text:1000E50F ; MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+355j
.text:1000E50F cmp byte ptr [ebx+5Ch], 0
.text:1000E513 jz short loc_1000E54A
.text:1000E515 or eax, 20h
.text:1000E518 mov [esp+50h], edi
.text:1000E51C push ecx
.text:1000E51D mov ecx, [ebx+58h]
.text:1000E520 lea edx, [esp+54h]
.text:1000E524 mov [esp+0B3Ch+var_B10], eax
.text:1000E528 call _DiscpUnicodeToAnsi@12 ; DiscpUnicodeToAnsi(x,x,x)
.text:1000E52D mov ecx, [ebx+58h]
.text:1000E530 lea edx, [ecx+2]
.text:1000E533
.text:1000E533 loc_1000E533: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+38Cj
.text:1000E533 mov ax, [ecx]
.text:1000E536 add ecx, 2
.text:1000E539 cmp ax, di
.text:1000E53C jnz short loc_1000E533
.text:1000E53E mov eax, [esp+0B38h+var_B10]
.text:1000E542 sub ecx, edx
.text:1000E544 sar ecx, 1
.text:1000E546 mov dword ptr [esp+0B38h+var_AF0], ecx
.text:1000E54A
.text:1000E54A loc_1000E54A: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+363j
.text:1000E54A cmp byte ptr [ebx+64h], 0
.text:1000E54E jz short loc_1000E581
.text:1000E550 or eax, 40h
.text:1000E553 mov [esp+54h], edi
.text:1000E557 push ecx
.text:1000E558 mov ecx, [ebx+60h]
.text:1000E55B lea edx, [esp+58h]
.text:1000E55F mov [esp+0B3Ch+var_B10], eax
.text:1000E563 call _DiscpUnicodeToAnsi@12 ; DiscpUnicodeToAnsi(x,x,x)
.text:1000E568 mov ecx, [ebx+60h]
.text:1000E56B lea edx, [ecx+2]
.text:1000E56E
.text:1000E56E loc_1000E56E: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+3C7j
.text:1000E56E mov ax, [ecx]
.text:1000E571 add ecx, 2
.text:1000E574 cmp ax, di
.text:1000E577 jnz short loc_1000E56E
.text:1000E579 sub ecx, edx
.text:1000E57B sar ecx, 1
.text:1000E57D mov [esp+4Ch], ecx
.text:1000E581
.text:1000E581 loc_1000E581: ; CODE XREF: MSFT_iSCSITarget_Invoke_Connect(x,x,x,x,x,x,x)+39Ej
.text:1000E581 cmp byte ptr [ebx+4Bh], 0
.text:1000E585 mov al, 1
.text:1000E587 jz short loc_1000E58C
.text:1000E589 mov al, [ebx+4Ah]

Changing the PowerShell cmd to specify AuthenticationType in all upper case resolves the connection problem.

This can also be observed if running PowerShell cmd

Get-IscsiSession

And noting that AuthenticationType is always listed in UPPERCASE.

Posted in Uncategorized | Leave a comment

Extracting Office Upload Center Info with PowerShell

Office 2016 Upload Center stores data about currently syncing files and errors in an Access Database file (.accdb)

With Click2Run Office installed by default we can’t programatically query Microsoft Access database, so we need to install the Access Database engines. However with Click2Run Office installed these will fail to install with an error similar to this:

 You cannot install the 64-bit version of Microsoft Access Database Engine 2016 because you currently have 32-bit Office products installed. If you want to install the 64-bit Microsoft Access Datbase Engine 2016, you will first need to remove the 32-bit installation of Office products. After uninstalling the following product(s), rerun setup in order to install 64-bit version of Microsoft Access Database Engine 2016:
Office 16 Click-to-Run Extensibility Component

You will get a similar error if you try the 32-bit installer.

Download Microsoft Access Database Engine 2016 Redistributable from https://www.microsoft.com/en-us/download/details.aspx?id=54920

To successfully install with Click2Run Office isntalled use the /quiet switch. Run the following commands from an elevated command prompt.

For use with 64-bit PowerShell:

AccessDatabaseEngine_X64.exe /quiet

For use with 32-bit PowerShell:

AccessDatabaseEngine.exe /quiet

With the engine installed we can onw query the upload center datbase. The purpose of each database table and column is left as an excercise for the reader.

$path = Join-Path -Path $env:LOCALAPPDATA `
    -ChildPath "Microsoft\Office\16.0\OfficeFileCache\CentralTable.accdb"

$tables = @( 
    "CacheProperties", 
    "EventClients",
    "EventMetaInfo"
    "IncomingEvents",
    "MasterFile",
    "OutgoingEvents",
    "ServerTarget",
    "Subcache" )

$results = @{}
$conn = New-Object System.Data.Odbc.OdbcConnection
$conn.ConnectionString = `
    "Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=$path"

$conn.Open()
$cmd = New-Object System.Data.Odbc.OdbcCommand
$cmd.Connection = $conn
ForEach ($table in $tables)
{
    Write-Host "Reading $table"
    $cmd.CommandText = "SELECT * FROM $table"
    $reader = $cmd.ExecuteReader()
    $results[$table] = New-Object System.Data.DataTable
    $results[$table].Load($reader)
}

ForEach ($table in $tables)
{
    Write-Host "Saving to $($table).csv"
    $results[$table] | Export-Csv -NoTypeInformation -Path "$($table).csv"
}
Posted in Uncategorized | Leave a comment

PowerShell Script to Backup / Restore Clipboard Contents

When Windows programs save data to the clipboard, the data can be saved in multiple formats. Analysing this process is easy with API Monitor and monitoring the Clipboard APIs such as OpenClipboard, CloseClipboard, SetClipboardData, GetClipboardData. An example of using this to diagnose a clipboard problem is here

In investigating an application that on some machines when pasting selected an undesired format, despite the correct format also being on the clipboard, I wanted to analyse the clipboard contents more closely and repeat testing on my own test machine. As I didn’t have access to the source application that put the content onto the clipboard I wrote this PowerShell script which will save the clipboard contents for all formats into an XML file which can be restored at a later time to the clipboard.

Usage is:

Backup Clipboard

Save-Clipboard -Path C:\support\clipboard_data.xml

Restore Clipboard

Load-Clipboard -Path C:\support\clipboard_data.xml

This can also be used to analyse the raw contents of the clipboard if required.

Add-Type @'
    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Collections.Generic;

public static class NativeMethods
{       

    [DllImport("user32.dll", SetLastError=true)]
    public static extern int SetClipboardData(uint uFormat, IntPtr hMem);

    [DllImport("user32.dll", SetLastError=true)]
    public static extern uint EnumClipboardFormats(uint format);

    [DllImport("user32.dll")]
    public static extern bool IsClipboardFormatAvailable(uint format);

    [DllImport("user32.dll")]
    public static extern IntPtr GetClipboardData(uint uFormat);

    [DllImport("user32.dll", SetLastError=true)]
    public static extern bool OpenClipboard(IntPtr hWndNewOwner);

    [DllImport("kernel32.dll")]
    public static extern IntPtr GlobalSize(IntPtr hMemory);

    [DllImport("kernel32.dll")]
    public static extern IntPtr GlobalLock(IntPtr hMem);

    [DllImport("user32.dll", SetLastError=true)]
    public static extern bool CloseClipboard();

    public static List GetClipboardFormats()
    {
        List formats = new List();
        uint currentFormat = 0;

        IntPtr Handle = IntPtr.Zero;
        OpenClipboard(Handle);

        do
        {
            currentFormat = EnumClipboardFormats(currentFormat);
            if (currentFormat!=0)
            {
                formats.Add(currentFormat);
            }
        } while (currentFormat != 0);
        return formats;
    }

    public static byte[] GetClipboardDataBytes(uint SelectedFormat)
    {
         if (SelectedFormat != 0)
         {
         IntPtr Handle = IntPtr.Zero;
         OpenClipboard(Handle);

         //Get pointer to clipboard data in the selected format
         IntPtr ClipboardDataPointer = GetClipboardData(SelectedFormat);

         //Do a bunch of crap necessary to copy the data from the memory
         //the above pointer points at to a place we can access it.
         IntPtr Length = GlobalSize(ClipboardDataPointer);
         IntPtr gLock = GlobalLock(ClipboardDataPointer);

         //Init a buffer which will contain the clipboard data
         byte[] Buffer = new byte[(int)Length];

         //Copy clipboard data to buffer
         Marshal.Copy(gLock, Buffer, 0, (int)Length);
         CloseClipboard();

         return Buffer;
         }

         return new byte[] {};
    }
}
'@

Function Load-Clipboard
{
    param([string]$Path)
    [xml]$Doc = Get-Content $Path
    $handle = [System.IntPtr]::Zero
    [NativeMethods]::OpenClipboard($handle)
    ForEach ($clipboard in $doc.Clipboards.Clipboard)
    {
        [UInt32]$format = $clipboard.Format
        $data = [Convert]::FromBase64String($clipboard.Data)
        Write-Host "Loading $($data.Length) bytes into clipboard format $format"
        $ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($data.Length)
        [void][System.Runtime.InteropServices.Marshal]::Copy($data, 0, $ptr, $data.Length);
        [NativeMethods]::SetClipboardData($format,$ptr)
        [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)

    }
    [NativeMethods]::CloseClipboard()

}

Function Save-Clipboard
{
    param([string]$Path)
    [xml]$Doc = New-Object System.Xml.XmlDocument
    $dec = $Doc.CreateXmlDeclaration("1.0","UTF-8",$null)
    [void]$doc.AppendChild($dec)
    [void]$doc.CreateComment("Clipboard Data from $($env:COMPUTERNAME) for $($env:USERNAME) on $(Get-Date)")
    $root = $doc.CreateNode("element","Clipboards",$null)
    $formats = [NativeMethods]::GetClipboardFormats()

    ForEach($format in $formats)
    {
        Write-Host "Capturing clipboard format $format"
        $data = [NativeMethods]::GetClipboardDataBytes($format)
        $c = $doc.CreateNode("element","Clipboard",$null)
        [void]$c.SetAttribute("Format",$format)
        [void]$c.SetAttribute("Data",[Convert]::ToBase64String($data))
        [void]$root.AppendChild($c)
    }

    $doc.AppendChild($root)
    $doc.Save($Path)
}
Posted in Uncategorized | Leave a comment

Time Travel Debugging in WinDbg Preview

The functionality similar to Microsoft’s internal Time Travel Tracing Diagnostic Tool has now added into WinDbg Preview, available only from Windows Store here

This version of WinDbg requires Windows 10 Anniversary update or later, and Windows Store access.

Time Travel Debugging is a powerful feature, allowing you to record program execution. Then you can go backwards or forwards through this execution to hit breakpoints or  perform stack analysis.

Documentation is available here

Note: You must use Run As Administrator when launching WinDbg to use Time Travel tracing.

Currently only user mode process is supported, not kernel debugging.

To test this out a friend launched a batch file that was failing, but couldn’t work out why.

They launched the application with WinDbg and selected “Record Process with Time Travel Debugging

You can also use Attach to process and select option to record process with time travel debugging.

image

Once the trace was created, they sent me the trace, and unlike a normal dmp file, I can now set breakpoints, and move forwards and backwards through the program execution with g and g- command.

Here I used tt to set time travel position, bp to set a breakpoint on SetLastError, !positions to show position in time travel trace, !error @r8 to translate error code passed to SetLastError into a human readable message, k for stack trace, and g to continue.

0:000> !tt 0
Setting position to the beginning of the trace
Setting position: 11:0
(6e00.14c4): Break instruction exception – code 80000003 (first/second chance not available)
Time Travel Position: 11:0
ntdll!NtQueryVolumeInformationFile+0x14:
00007ffb`a6ca5cc4 c3              ret
0:000> bp ntdll!RtlSetLastWin32Error “!positions;!error @r8;k;g”
0:000> g
>Thread ID=0x14C4 – Position: 5F:4EF
Error code: (Win32) 0 (0) – The operation completed successfully.
# Child-SP          RetAddr           Call Site
00 0000004b`8c94f048 00007ffb`a60ca93a ntdll!RtlSetLastWin32Error
01 0000004b`8c94f050 00007ffb`a6091040 msvcrt!getptd_noexit+0x6e
02 0000004b`8c94f080 00007ffb`a60eaa56 msvcrt!_LocaleUpdate::_LocaleUpdate+0x20
03 0000004b`8c94f0b0 00007ff7`aa04ffc6 msvcrt!wcsicmp_l+0x26
04 0000004b`8c94f110 00007ff7`aa04f5b9 cmd!FindAndFix+0x156
05 0000004b`8c94f3a0 00007ff7`aa04fcb5 cmd!FindFixAndRun+0x99
06 0000004b`8c94f840 00007ff7`aa05cf85 cmd!Dispatch+0xa5
07 0000004b`8c94f8d0 00007ff7`aa0568c9 cmd!_chkstk+0x5205
08 0000004b`8c94f970 00007ffb`a56f2774 cmd!wil::details_abi::ProcessLocalStorage<wil::details_abi::ProcessLocalData>::~ProcessLocalStorage<wil::details_abi::ProcessLocalData>+0x289
09 0000004b`8c94f9b0 00007ffb`a6c70d51 KERNEL32!BaseThreadInitThunk+0x14
0a 0000004b`8c94f9e0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
>Thread ID=0x14C4 – Position: 90:1F
Error code: (NTSTATUS) 0x569a0150 (1452933456) – <Unable to get error code text>
# Child-SP          RetAddr           Call Site
00 0000004b`8c94ea98 00007ffb`a3354357 ntdll!RtlSetLastWin32Error
01 0000004b`8c94eaa0 00007ff7`aa0497f5 KERNELBASE!CreateDirectoryW+0x3d867
02 0000004b`8c94eb90 00007ff7`aa049aa7 cmd!MdWork+0xe5
03 0000004b`8c94ee10 00007ff7`aa04995a cmd!LoopThroughArgs+0x13f
04 0000004b`8c94f370 00007ff7`aa04f7d3 cmd!eMkdir+0x1a
05 0000004b`8c94f3a0 00007ff7`aa04fcb5 cmd!FindFixAndRun+0x2b3
06 0000004b`8c94f840 00007ff7`aa05cf85 cmd!Dispatch+0xa5
07 0000004b`8c94f8d0 00007ff7`aa0568c9 cmd!_chkstk+0x5205
08 0000004b`8c94f970 00007ffb`a56f2774 cmd!wil::details_abi::ProcessLocalStorage<wil::details_abi::ProcessLocalData>::~ProcessLocalStorage<wil::details_abi::ProcessLocalData>+0x289
09 0000004b`8c94f9b0 00007ffb`a6c70d51 KERNEL32!BaseThreadInitThunk+0x14
0a 0000004b`8c94f9e0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
>Thread ID=0x14C4 – Position: B6:5CB
Error code: (Win32) 0xce (206) – The filename or extension is too long.
# Child-SP          RetAddr           Call Site
00 0000004b`8c94e7b8 00007ffb`a56f2d6e ntdll!RtlSetLastWin32Error
01 0000004b`8c94e7c0 00007ffb`a32e7ecd KERNEL32!BasepNotifyLoadStringResource+0x7e
02 0000004b`8c94e810 00007ffb`a32e7c97 KERNELBASE!BaseDllFormatMessage+0x22d
03 0000004b`8c94e940 00007ff7`aa0542c9 KERNELBASE!FormatMessageW+0x37
04 0000004b`8c94e990 00007ff7`aa054191 cmd!FindMsg+0x6d
05 0000004b`8c94ea90 00007ff7`aa05439c cmd!PutMsg+0x81
06 0000004b`8c94eb50 00007ff7`aa059ab2 cmd!PutStdErr+0x2c
07 0000004b`8c94eb90 00007ff7`aa049aa7 cmd!_chkstk+0x1d32
08 0000004b`8c94ee10 00007ff7`aa04995a cmd!LoopThroughArgs+0x13f
09 0000004b`8c94f370 00007ff7`aa04f7d3 cmd!eMkdir+0x1a
0a 0000004b`8c94f3a0 00007ff7`aa04fcb5 cmd!FindFixAndRun+0x2b3
0b 0000004b`8c94f840 00007ff7`aa05cf85 cmd!Dispatch+0xa5
0c 0000004b`8c94f8d0 00007ff7`aa0568c9 cmd!_chkstk+0x5205
0d 0000004b`8c94f970 00007ffb`a56f2774 cmd!wil::details_abi::ProcessLocalStorage<wil::details_abi::ProcessLocalData>::~ProcessLocalStorage<wil::details_abi::ProcessLocalData>+0x289
0e 0000004b`8c94f9b0 00007ffb`a6c70d51 KERNEL32!BaseThreadInitThunk+0x14
0f 0000004b`8c94f9e0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
>Thread ID=0x14C4 – Position: B6:5E5
Error code: (Win32) 0xce (206) – The filename or extension is too long.
# Child-SP          RetAddr           Call Site
00 0000004b`8c94e7b8 00007ffb`a56f2d76 ntdll!RtlSetLastWin32Error
01 0000004b`8c94e7c0 00007ffb`a32e7ecd KERNEL32!BasepNotifyLoadStringResource+0x86
02 0000004b`8c94e810 00007ffb`a32e7c97 KERNELBASE!BaseDllFormatMessage+0x22d
03 0000004b`8c94e940 00007ff7`aa0542c9 KERNELBASE!FormatMessageW+0x37
04 0000004b`8c94e990 00007ff7`aa054191 cmd!FindMsg+0x6d
05 0000004b`8c94ea90 00007ff7`aa05439c cmd!PutMsg+0x81
06 0000004b`8c94eb50 00007ff7`aa059ab2 cmd!PutStdErr+0x2c
07 0000004b`8c94eb90 00007ff7`aa049aa7 cmd!_chkstk+0x1d32
08 0000004b`8c94ee10 00007ff7`aa04995a cmd!LoopThroughArgs+0x13f
09 0000004b`8c94f370 00007ff7`aa04f7d3 cmd!eMkdir+0x1a
0a 0000004b`8c94f3a0 00007ff7`aa04fcb5 cmd!FindFixAndRun+0x2b3
0b 0000004b`8c94f840 00007ff7`aa05cf85 cmd!Dispatch+0xa5
0c 0000004b`8c94f8d0 00007ff7`aa0568c9 cmd!_chkstk+0x5205
0d 0000004b`8c94f970 00007ffb`a56f2774 cmd!wil::details_abi::ProcessLocalStorage<wil::details_abi::ProcessLocalData>::~ProcessLocalStorage<wil::details_abi::ProcessLocalData>+0x289
0e 0000004b`8c94f9b0 00007ffb`a6c70d51 KERNEL32!BaseThreadInitThunk+0x14
0f 0000004b`8c94f9e0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
>Thread ID=0x14C4 – Position: 13B:625
Error code: (Win32) 0 (0) – The operation completed successfully.
# Child-SP          RetAddr           Call Site
00 0000004b`8c94ee08 00007ffb`a60ca93a ntdll!RtlSetLastWin32Error
01 0000004b`8c94ee10 00007ffb`a6091040 msvcrt!getptd_noexit+0x6e
02 0000004b`8c94ee40 00007ffb`a60e50a2 msvcrt!_LocaleUpdate::_LocaleUpdate+0x20
03 0000004b`8c94ee70 00007ffb`a60da39c msvcrt!woutput_l+0x72
04 0000004b`8c94f380 00007ffb`a60da301 msvcrt!vsnwprintf_l+0x8c
05 0000004b`8c94f3f0 00007ff7`aa051c39 msvcrt!vsnwprintf+0x11
06 0000004b`8c94f430 00007ff7`aa051c03 cmd!StringCchPrintfW+0x79
07 0000004b`8c94f460 00007ff7`aa0685c4 cmd!StringCchPrintfW+0x43
08 0000004b`8c94f4a0 00007ff7`aa05b6ed cmd!PrintPrompt+0x230
09 0000004b`8c94f7a0 00007ff7`aa04ddbc cmd!_chkstk+0x396d
0a 0000004b`8c94f800 00007ff7`aa04d6b6 cmd!Lex+0x47c
0b 0000004b`8c94f870 00007ff7`aa04d3f8 cmd!GeToken+0x26
0c 0000004b`8c94f8a0 00007ff7`aa05cf4b cmd!Parser+0x118
0d 0000004b`8c94f8d0 00007ff7`aa0568c9 cmd!_chkstk+0x51cb
0e 0000004b`8c94f970 00007ffb`a56f2774 cmd!wil::details_abi::ProcessLocalStorage<wil::details_abi::ProcessLocalData>::~ProcessLocalStorage<wil::details_abi::ProcessLocalData>+0x289
0f 0000004b`8c94f9b0 00007ffb`a6c70d51 KERNEL32!BaseThreadInitThunk+0x14
10 0000004b`8c94f9e0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
TTD: End of trace reached.
(6e00.14c4): Break instruction exception – code 80000003 (first/second chance not available)
Time Travel Position: 15D:0
ntdll!NtDeviceIoControlFile+0x12:
00007ffb`a6ca5482 0f05            syscall

Now I could click the time travel position, or type cmd tt B6:5E5 to go position of interest. We could then set further breakpoints, or trace instruction by instruction use t command.

The great thing is you can also set breakpoints and go backwards (g-) or start again to explore alternative debugging approach.

Continuing on…

0:000> !tt B6:5E5
Setting position: B6:5E5
(6e00.14c4): Break instruction exception – code 80000003 (first/second chance not available)
Time Travel Position: B6:5E5
ntdll!RtlSetLastWin32Error:
00007ffb`a6c5a630 894c2408        mov     dword ptr [rsp+8],ecx ss:0000004b`8c94e7c0=000000ce
0:000> k
# Child-SP          RetAddr           Call Site
00 0000004b`8c94e7b8 00007ffb`a56f2d76 ntdll!RtlSetLastWin32Error
01 0000004b`8c94e7c0 00007ffb`a32e7ecd KERNEL32!BasepNotifyLoadStringResource+0x86
02 0000004b`8c94e810 00007ffb`a32e7c97 KERNELBASE!BaseDllFormatMessage+0x22d
03 0000004b`8c94e940 00007ff7`aa0542c9 KERNELBASE!FormatMessageW+0x37
04 0000004b`8c94e990 00007ff7`aa054191 cmd!FindMsg+0x6d
05 0000004b`8c94ea90 00007ff7`aa05439c cmd!PutMsg+0x81
06 0000004b`8c94eb50 00007ff7`aa059ab2 cmd!PutStdErr+0x2c
07 0000004b`8c94eb90 00007ff7`aa049aa7 cmd!_chkstk+0x1d32
08 0000004b`8c94ee10 00007ff7`aa04995a cmd!LoopThroughArgs+0x13f
09 0000004b`8c94f370 00007ff7`aa04f7d3 cmd!eMkdir+0x1a
0a 0000004b`8c94f3a0 00007ff7`aa04fcb5 cmd!FindFixAndRun+0x2b3
0b 0000004b`8c94f840 00007ff7`aa05cf85 cmd!Dispatch+0xa5
0c 0000004b`8c94f8d0 00007ff7`aa0568c9 cmd!_chkstk+0x5205
0d 0000004b`8c94f970 00007ffb`a56f2774 cmd!wil::details_abi::ProcessLocalStorage<wil::details_abi::ProcessLocalData>::~ProcessLocalStorage<wil::details_abi::ProcessLocalData>+0x289
0e 0000004b`8c94f9b0 00007ffb`a6c70d51 KERNEL32!BaseThreadInitThunk+0x14
0f 0000004b`8c94f9e0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:000> bp cmd!_chkstk+0x1d32
0:000> g
Breakpoint 2 hit
Time Travel Position: D6:42
cmd!_chkstk+0x1d32:
00007ff7`aa059ab2 90              nop
0:000> t
Time Travel Position: D6:43
cmd!_chkstk+0x1d33:
00007ff7`aa059ab3 e943fdfeff      jmp     cmd!MdWork+0xeb (00007ff7`aa0497fb)
0:000> t
Time Travel Position: D6:44
cmd!MdWork+0xeb:
00007ff7`aa0497fb 8bdf            mov     ebx,edi
0:000> t
Time Travel Position: D6:45
cmd!MdWork+0xed:
00007ff7`aa0497fd 488b8d38010000  mov     rcx,qword ptr [rbp+138h] ss:0000004b`8c94edc8=0000019f56bf0780
0:000> du 0000019f56bf0780
0000019f`56bf0780  “C:\long\long\long\long\long\long”
0000019f`56bf07c0  “\long\long\long\long\long\long\l”
0000019f`56bf0800  “ong\long\long\long\long\long\lon”
0000019f`56bf0840  “g\long\long\long\long\long\long\”
0000019f`56bf0880  “long\long\long\long\long\long\lo”
0000019f`56bf08c0  “ng\long\long\long\long\long\long”
0000019f`56bf0900  “\long\long\long\long\long\long\l”
0000019f`56bf0940  “ong\long\long\long\long\long”

From this analysis we worked out the long file path that was being supplied in a mkdir command, and was able to modify it into a permitted size.

Posted in WinDbg | Leave a comment