Reputation: 63
trying to read the information of the subkey Render in the key "Computer\HKEY_USERS\S-1-5-19\Software\Microsoft\Windows\CurrentVersion\Audio\Journal".
windows makes changes to that registry REG_BINARY entry when switching audio output devices.
i've tried to decode with ascii, utf-8, cp1252 and iso-8859-15 and a couple others from this list. ascii and utf-8 seem to yield the most "readable" string but they still don't decode the full string.
import winreg
from codecs import decode
reg_hive = winreg.HKEY_USERS
main_key = r"S-1-5-19\Software\Microsoft\Windows\CurrentVersion\Audio\Journal"
with winreg.ConnectRegistry(None, reg_hive) as hive:
with winreg.OpenKey(
hive, main_key, 0, winreg.KEY_READ) as target_key:
renderInfo = winreg.EnumValue(target_key, 2)
# print(renderInfo)
print(decode(renderInfo[1], "ascii", "ignore"))
it prints this:
SWD\MMDEVAPI{0.0.0.00000000}.{01921bca-0488-492c-b0ac-c8a3f5e42f9d}S@SWD\MMDEVAPI{0.0.0.00000000}.{93f5ee17-4bef-4b43-8507-e27271065e61} iW@
trying to decrypt those weird characters (close to "S@" and "iW@ ", stackoverflow doesn't seem to be able to render them.) so i can make better sense of it all.
sofar my guesses are:
Upvotes: 2
Views: 1655
Reputation: 30103
To decipher a complex binary value, you need to know it's structure. Let's start analyzing the following raw output:
reg query HKEY_USERS\S-1-5-19\Software\Microsoft\Windows\CurrentVersion\Audio\Journal -v Render
HKEY_USERS\S-1-5-19\Software\Microsoft\Windows\CurrentVersion\Audio\Journal
Render REG_BINARY 5300570044005C004D004D004400450056004100500049005C007B0030002E0030002E0030002E00300030003000300030003000300030007D002E007B00650033003700380063003900310035002D0064003000360039002D0034003900310066002D0038003000380039002D006200310030003600310039003000360061006100390034007D000000000000000000010000004B000000000000000000000000000000000000006A9A65709D075F400000000000000000000000000000000000000000000000005300570044005C004D004D004400450056004100500049005C007B0030002E0030002E0030002E00300030003000300030003000300030007D002E007B00340032003000620063006500650064002D0037003500370031002D0034003300350030002D0039003300610034002D003500650030006300310065003200350035003400660030007D0000000000000000000300000001000000000000000000000000000000000000004162F5AC588503400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The following table shows above Render
registry entry structure (based on my own finding):
offset bytes caption format comment
------ ----- ------- ------ -------
0x0000 136 DeviceID char[] (68 chars; encoding UCS-2 LE)
0x0088 8 unknown_88 uint64
0x0090 4 EndPointNo uint32 (LE); constant for given end point
0x0094 4 Counter_94 uint32 (LE); increases if a sound is played
0x0098 8 unknown_98 uint64
0x00a0 8 unknown_a0 uint64
0x00a8 8 Strange_a8 uint64 changes unpredictably even for identical sound
0x00b0 8 unknown_b0 uint64
0x00b8 8 unknown_b8 uint64
0x00c0 8 unknown_c0 uint64
The above structure iterates three (or even more?) times within the Render
value. All the parts denominated unknown_*
constantly keep zero value so it's hard to guess their format and meaning, and don't change even if the system sounds (audio alerts) are forced to be shown visually (in the Ease of access settings).
Let's decrypt the Render
value - as soon as it's structure is at least partially known. In Python, use the struct
module (performs conversions between Python values and C structs represented as Python bytes objects).
Unfortunately, I don't speak Python fluently enough; so here is my Powershell solution:
#Requires -RunAsAdministrator
[CmdletBinding()]param(
[Parameter(Mandatory=$False,Position=0)][string]$PlaySound=''
)
if ( $PlaySound -eq '' ) {
Write-Information -infa Continue "Retrieving current values"
} else {
# play the file once
$soundLoc = "c:\WINDOWS\Media\notify.wav"
Write-Information -infa Continue "Playing $soundLoc"
$sound = new-Object System.Media.SoundPlayer
$sound.SoundLocation = $soundLoc
$sound.Play()
Start-Sleep -Seconds 1
}
$key = 'Registry::HKEY_USERS\S-1-5-19\Software\Microsoft\Windows' +
'\CurrentVersion\Audio\Journal'
$keyItems = Get-ItemProperty -Path $key
$render = $keyItems.Render
$csvStruct=@"
offset,bytes,caption,format,comment
0x0000, 136,DeviceID,char[],(68 chars; encoding UCS-2 LE)
0x0088, 8,unknown_88,uint64,
0x0090, 4,EndPointNo,uint32,(LE); constant for given end point
0x0094, 4,Counter_94,uint32,(LE); increases if a sound is played
0x0098, 8,unknown_98,uint64,
0x00a0, 8,unknown_a0,uint64,
0x00a8, 8,Strange_a8,uint64,changes unpredictably even for identical sound
0x00b0, 8,unknown_b0,uint64,
0x00b8, 8,unknown_b8,uint64,
0x00c0, 8,unknown_c0,uint64,
"@ | ConvertFrom-Csv
$unicode=[System.Text.UnicodeEncoding]::Unicode
$renderParts=@()
$renderInfos=@()
$renderNext = $renderCnt = 0
While ( $renderNext -lt $render.Count -and ( <# go over all value #>
$render[$renderNext + 0xaf] -ne 0 -or <# 0x40 if not zero #>
$render[$renderNext] -ne 0 )) { <# DeviceID not empty #>
for ($i=0; $i -lt $csvStruct.Count; $i++) {
$part = $csvStruct[$i]
If ( $part.format -eq 'char[]' ) {
$renderParts += @{
$part.caption = $unicode.GetString($render,
$renderNext + [int]$part.offset, [int]$part.bytes)
}
} else {
$hexLE='0x' # Little Endian
for ($j=[int]$part.bytes -1; $j -ge 0; $j--) {
$hexLE+= '{0:x2}' -f $render[$renderNext + [int]$part.offset + $j]
}
$hexBE='0X' # Big Endian
for ($j=0; $j -le [int]$part.bytes -1; $j++) {
$hexBE+= '{0:x2}' -f $render[$renderNext + [int]$part.offset + $j]
}
$hexBE = $hexBE.ToUpper()
$renderParts += @{
$part.caption = $hexLE
}
if ( $part.caption -eq 'Strange_a8') {
Write-Information $(
[System.Environment]::NewLine +
$renderParts[ $renderCnt ].DeviceID )
Write-Information $(
'EndPointNo = ' +
[int32]$renderParts[ 2 + $renderCnt ].EndPointNo +
', Counter_94 = ' +
[int32]$renderParts[ 3 + $renderCnt ].Counter_94 )
Write-Information $( "$($part.caption)`t`t$hexLE`t`t$hexBE" )
#Write-Information $(
# [System.Text.UnicodeEncoding]::Default.GetString($render,
# 0x00a8 + $renderNext, 8) )
Write-Information $(
'uint64 {0,20}' -f [uint64]$hexLE )
Write-Information $(
'uint32 {0,10} {1,10}' -f
[uint32]('0x' + $hexLE.Substring(10,8)),
[uint32]('0x' + $hexLE.Substring( 2,8)) )
Write-Information $(
' int16 {0,6} {1,6} {2,6} {3,6}' -f
[int16]('0x' + $hexLE.Substring(14,4)),
[int16]('0x' + $hexLE.Substring(10,4)),
[int16]('0x' + $hexLE.Substring( 6,4)),
[int16]('0x' + $hexLE.Substring( 2,4)) )
Write-Information $(
'uint16 {0,6} {1,6} {2,6} {3,6}' -f
[uint16]('0x' + $hexLE.Substring(14,4)),
[uint16]('0x' + $hexLE.Substring(10,4)),
[uint16]('0x' + $hexLE.Substring( 6,4)),
[uint16]('0x' + $hexLE.Substring( 2,4)) )
Write-Information $(
' byte {0,3} {1,3} {2,3} {3,3} {4,3} {5,3} {6,3} {7,3}' -f
[byte]('0x' + $hexLE.Substring(16,2)),
[byte]('0x' + $hexLE.Substring(14,2)),
[byte]('0x' + $hexLE.Substring(12,2)),
[byte]('0x' + $hexLE.Substring(10,2)),
[byte]('0x' + $hexLE.Substring( 8,2)),
[byte]('0x' + $hexLE.Substring( 6,2)),
[byte]('0x' + $hexLE.Substring( 4,2)),
[byte]('0x' + $hexLE.Substring( 2,2)) )
}
}
}
$renderNext+=200
$renderCnt +=10
}
$renderParts
Sample usage:
D:\PShell\tests\MMDEVAPI_Journal_Registry.ps1
retrieves current Render
value.D:\PShell\tests\MMDEVAPI_Journal_Registry.ps1 x
plays a system sound before retrieving the Render
value (added after the Render
value suddenly became zeroized for unknown reason).D:\PShell\tests\MMDEVAPI_Journal_Registry.ps1 -InformationAction Continue
prints additional analysis of the Strange_a8
subvalue (shows it as structured in various numeric types).Output (formatted by piping to Format-Table -Autosize
):
Name Value
---- -----
DeviceID SWD\MMDEVAPI\{0.0.0.00000000}.{e378c915-d069-491f-8089-b1061906aa94}
unknown_88 0x0000000000000000
EndPointNo 0x00000001
Counter_94 0x0000004a
unknown_98 0x0000000000000000
unknown_a0 0x0000000000000000
Strange_a8 0x405eb3c4b7ffda6f
unknown_b0 0x0000000000000000
unknown_b8 0x0000000000000000
unknown_c0 0x0000000000000000
DeviceID SWD\MMDEVAPI\{0.0.0.00000000}.{420bceed-7571-4350-93a4-5e0c1e2554f0}
unknown_88 0x0000000000000000
EndPointNo 0x00000003
Counter_94 0x00000001
unknown_98 0x0000000000000000
unknown_a0 0x0000000000000000
Strange_a8 0x40038558acf56241
unknown_b0 0x0000000000000000
unknown_b8 0x0000000000000000
unknown_c0 0x0000000000000000
Note. The EndPointNo
part seems to be related to the obscure registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio
as shown in the following script:
$computer = $env:COMPUTERNAME
$namespace = "ROOT\CIMV2"
$classname = "Win32_PnPEntity"
$auxPnP = Get-WmiObject -Class $classname `
-ComputerName $computer `
-Namespace $namespace |
Where-object PNPDeviceID -match `
'\{[0-9a-fA-F]\.[0-9a-fA-F]\.[0-9a-fA-F]\.[0-9a-fA-F]{8}\}' |
Select-Object * -ExcludeProperty PSComputerName,
Scope, Path, Options, ClassPath, Properties,
SystemProperties, Qualifiers, Site, Container
$auxPnP | Format-List -property Name,DeviceID <# -Property [a-z]* <##>
'--- DeviceId index ---'
$devIndex = '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e},0'
$devDriver= '{b3f8fa53-0004-438e-9003-51a46e139bfc},6'
$devDevice= '{a45c254e-df1c-4efd-8020-67d146a850e0},2'
$keyAbove = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows' +
'\CurrentVersion\MMDevices\Audio'
$keyTempl = $keyAbove + '\Render\DeviceIdEnding\Properties'
$auxPnP | ForEach-Object {
$DeviceIdEnding = $_.DeviceID.Substring($_.DeviceID.LastIndexOf('.')+1)
$keyItems = Get-ItemProperty -ErrorAction SilentlyContinue `
-Path $keyTempl.Replace('DeviceIdEnding',$DeviceIdEnding)
if ( $keyItems ) {
@($DeviceIdEnding,
$keyItems.$devIndex, # index
$keyItems.$devDriver, # driver
$keyItems.$devDevice # device
) -join "`t"
}
}
Output:
Name : Mikrofon (VIA HD Audio)
DeviceID : SWD\MMDEVAPI\{0.0.1.00000000}.{D2E3C581-8C7B-4A32-A35B-1F42DA18733D}
Name : Reproduktory (VIA HD Audio)
DeviceID : SWD\MMDEVAPI\{0.0.0.00000000}.{E378C915-D069-491F-8089-B1061906AA94}
Name : Headphone (VIA HD Audio)
DeviceID : SWD\MMDEVAPI\{0.0.0.00000000}.{420BCEED-7571-4350-93A4-5E0C1E2554F0}
--- DeviceId index ---
{E378C915-D069-491F-8089-B1061906AA94} 1 VIA HD Audio Reproduktory
{420BCEED-7571-4350-93A4-5E0C1E2554F0} 3 VIA HD Audio Headphone
Upvotes: 2