使用python 3 winreg正确解密注册表REG_BINARY?

时间:2019-01-18 16:14:17

标签: windows binary registry decode winreg

试图读取“ Computer \ HKEY_USERS \ S-1-5-19 \ Software \ Microsoft \ Windows \ CurrentVersion \ Audio \ Journal”项中的“渲染”子项的信息。

在切换音频输出设备时,windows对该注册表REG_BINARY条目进行更改。

我尝试使用ascii,utf-8,cp1252和iso-8859-15以及this列表中的其他几个进行解码。 ascii和utf-8似乎产生了最“可读”的字符串,但它们仍然无法解码完整的字符串。

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"))

它打印此:

SWD \ MMDEVAPI {0.0.0.00000000}。{01921bca-0488-492c-b0ac-c8a3f5e42f9d} S @ SWD \ MMDEVAPI {0.0.0.00000000}。{93f5ee17-4bef-4b43-8507-e27271065e61} iW @

尝试解密那些奇怪的字符(靠近“ S @”和“ iW @ “,stackoverflow似乎无法渲染它们。)因此,我可以更好地理解这一切。

到目前为止,我的猜测是:

  • “ SWD \ MMDEVAPI \”是注册表路径的缩写吗? MultiMediaDEviceApi?不确定SWD
  • {0.0.0.00000000}可能是时间戳记?尽管看起来全零很奇怪。
  • {01921bca-0488-492c-b0ac-c8a3f5e42f9d}和{93f5ee17-4bef-4b43-8507-e27271065e61}是注册表项。

1 个答案:

答案 0 :(得分:0)

要解密复杂的 binary 值,您需要知道它的结构。让我们开始分析以下原始输出:

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

下表显示了Render注册表项的结构(根据我自己的发现):

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                                               

以上结构在Render值内迭代了3次(甚至更多?)。以unknown_*命名的所有部分始终保持零值,因此很难猜测其格式和含义,即使强制以视觉方式显示系统声音(音频警报),也不会更改(在 Ease中访问权限设置)。

让我们解密Render值-一旦它的结构至少部分被了解。在 Python 中,使用struct module(在Python值和以Python字节对象表示的C结构之间进行转换)。

不幸的是,我对流利的 Python 不够流利;这是我的Powershell解决方案:

#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

样品用量:

  • D:\PShell\tests\MMDEVAPI_Journal_Registry.ps1检索当前的Render值。
  • D:\PShell\tests\MMDEVAPI_Journal_Registry.ps1 x在检索Render值之前播放系统声音(在Render值由于未知原因突然变为零之后添加)。
  • D:\PShell\tests\MMDEVAPI_Journal_Registry.ps1 -InformationAction Continue打印Strange_a8子值的其他分析(显示为各种数值类型的结构)。

输出(格式为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                                                  

注意EndPointNo部分似乎与晦涩的注册表项HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio有关,如以下脚本所示:

$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"
    }
}

输出:

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