Eu sou um funileiro que faz muitos hacks de registro e odeio ter que clicar em muitos .reg
arquivos um por um; como faço para converter .reg
arquivos em Set-ItemProperty
comandos do PowerShell automaticamente?
- Encontrei um site que faz isso [ Registry to PowerShell Converter ], porém a saída não está no formato que eu queria; Eu quero que ele tenha exatamente a mesma sintaxe abaixo usando
Set-ItemProperty
//Remove-Item
eNew-Item
nada mais:Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\CurrentVersion\PushNotifications] "NoToastApplicationNotification"=dword:00000001
cmd
:Reg Add "HKLM\Software\Policies\Microsoft\Windows\CurrentVersion\PushNotifications" /v "NoToastApplicationNotification" /t REG_DWORD /d 1
powershell
:Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\CurrentVersion\PushNotifications" -Name "NoToastApplicationNotification" -Type DWord -Value 1
- O comando para produzir o resultado pretendido deve ser:
"Set-ItemProperty -Path " + $path + "-Name " + $name + "-Value " + $value
- Criei uma tabela ASCII com informações encontradas aqui e carreguei aqui , gerenciando esta [ saída ]:
$ASCII=import-csv ".\desktop\ascii.csv" [array]$AsciiTable=0..255 | foreach-object{ $Decimal=$ASCII[$_].DEC $Hexadecimal=$ASCII[$_].HEX $Binary=$ASCII[$_].BIN $Octonary=$ASCII[$_].OCT $Symbol=$ASCII[$_].Symbol $Value=[char]$_ $Description=$ASCII[$_].Description $HTMLName=$ASCII[$_].HTMLName $HTMLNumber=$ASCII[$_].HTMLNumber [pscustomobject]@{Decimal=$Decimal;Hexadecimal=$Hexadecimal;Binary=$Binary;Octonary=$Octonary;Symbol=$Symbol;Value=$Value;Description=$Description;HTMLName=$HTMLName;HTMLNumber=$HTMLNumber} } $AsciiTable | Export-csv ".\Desktop\AsciiTable.csv"
- Criei uma tabela ASCII com informações encontradas aqui e carreguei aqui , gerenciando esta [ saída ]:
Atualmente, consegui isso, que está incompleto, mas a ideia é percorrer o arquivo por index
, atribuindo valores às variáveis por meio de correspondência de regex, alterando o tipo e o nome do hive para os usados no PowerShell:
$registry=get-content $regfile
for ($i=0;$i -lt $registry.count;$i++){
$line=$registry | select-object -index $i
if ($line -match '\[' -and '\]') {
$path=$line -replace '\[|\]'
switch ($path)
{
{$path -match "HKEY_CLASSES_ROOT"} {$path=$path -replace "HKEY_CLASSES_ROOT","HKCR:"}
{$path -match "HKEY_CURRENT_USER"} {$path=$path -replace "HKEY_CURRENT_USER","HKCU:"}
{$path -match "HKEY_LOCAL_MACHINE"} {$path=$path -replace "HKEY_LOCAL_MACHINE","HKLM:"}
{$path -match "HKEY_USERS"} {$path=$path -replace "HKEY_USERS","HKU:"}
{$path -match "HKEY_CURRENT_CONFIG"} {$path=$path -replace "HKEY_CURRENT_CONFIG","HKCC:"}
}
}
else {
$name=($line | select-string -pattern "`"([^`"=]+)`"").matches.value | select-object -first 1
switch ($line)
{
{$line -match}
}
Existem seis tipos de valor de registro [ REG_SZ
, REG_BINARY
, REG_DWORD
, REG_QWORD
, REG_MULTI_SZ
, REG_EXPAND_SZ
] e vi apenas um DWORD
tipo de valor em .reg
arquivos, embora tenha conseguido criar uma chave de registro contendo todos os tipos:
RegEdit
:
.reg
:Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AarSvc] "DependOnService"=hex(7):41,00,75,00,64,00,69,00,6f,00,73,00,72,00,76,00,00,00,\ 00,00 "Description"="@%SystemRoot%\\system32\\AarSvc.dll,-101" "DisplayName"="@%SystemRoot%\\system32\\AarSvc.dll,-100" "ErrorControl"=dword:00000001 "FailureActions"=hex:80,51,01,00,00,00,00,00,00,00,00,00,04,00,00,00,14,00,00,\ 00,01,00,00,00,10,27,00,00,01,00,00,00,10,27,00,00,01,00,00,00,10,27,00,00,\ 00,00,00,00,00,00,00,00 "ImagePath"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,\ 74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,\ 00,76,00,63,00,68,00,6f,00,73,00,74,00,2e,00,65,00,78,00,65,00,20,00,2d,00,\ 6b,00,20,00,41,00,61,00,72,00,53,00,76,00,63,00,47,00,72,00,6f,00,75,00,70,\ 00,20,00,2d,00,70,00,00,00 "ObjectName"="NT Authority\\LocalService" "RequiredPrivileges"=hex(7):53,00,65,00,49,00,6d,00,70,00,65,00,72,00,73,00,6f,\ 00,6e,00,61,00,74,00,65,00,50,00,72,00,69,00,76,00,69,00,6c,00,65,00,67,00,\ 65,00,00,00,00,00 "ServiceSidType"=dword:00000001 "Start"=dword:00000003 "Type"=dword:00000060 "UserServiceFlags"=dword:00000003 "New Value #1"=hex(b):00,00,00,00,00,00,00,00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AarSvc\Parameters] "ServiceDll"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,\ 00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\ 41,00,61,00,72,00,53,00,76,00,63,00,2e,00,64,00,6c,00,6c,00,00,00 "ServiceDllUnloadOnStop"=dword:00000001 "ServiceMain"="ServiceMain"
Como os tipos de registro são determinados em um .reg
, já que o resultado final pretendido é um arquivo de texto/matriz de string/script do PowerShell que contém os comandos convertidos?
- Em um
.reg
, eu sei que os valores para o tipoREG_DWORD
são escritos comodword
,REG_SZ
como texto simples entre aspas,REG_QWORD
comoqword
(mostrado aqui ), e já mapeei os tipos de registro para suas propriedades correspondentes do PowerShell:
Com as relações inferidas acima:REG_SZ → String REG_EXPAND_SZ → ExpandString REG_MULTI_SZ → MultiString REG_BINARY → Binary REG_DWORD → DWord REG_QWORD → QWord
switch ($line) { {$line -match '"="'} {$type="string"} {$line -match "dword"} {$type="dword"} {$line -match "qword"} {$type="qword"} {$line -match "hex\(2\)"} {$type="expandstring";break} {$line -match "hex\(7\)"} {$type="multistring";break} {$line -match "hex\(b\)"} {$type="qword";break} {$line -match "hex"} {$type="binary"} }
Como posso detectar e decodificar os balbucios hexadecimais do registro e existem outras maneiras de escrever REG_EXPAND_SZ
, REG_MULTI_SZ
e REG_BINARY
tipos em a .reg
(ou seja ExpandString
, como MultiString
e Binary
respectivamente)?
- Script para analisar valores de string expansíveis do registro para texto simples:
function parse-expandstring { PARAM ( [Parameter(ValueFromPipeline=$true, Mandatory=$true)] [System.String]$expandstring ) $AsciiTable=import-csv ".\desktop\AsciiTable.csv" [array]$hex=$expandstring -split'[\,\\]' | where {-not ([string]::IsNullOrWhiteSpace($_))} | %{$_.trimstart()} $hexadecimal=0..($hex.count-1) | where {$_ % 2 -ne 1} | foreach-object {$hex[$_]} $text=@() foreach ($hexadecima in $hexadecimal) { for ($i=0;$i -le 255;$i++) { if ($AsciiTable[$i].hexadecimal -eq $hexadecima) { $text+=$AsciiTable[$i].value } } } $text=$text -join "" $text }
Function
para analisarREG_QWORD
:function parse-qword { PARAM ( [Parameter(ValueFromPipeline=$true, Mandatory=$true)] [System.String]$qword ) [array]$qword=$qword -split',' $qword=for ($i=$qword.count-1;$i -ge 0;$i--) {$qword[$i]} $hexvalue=$qword -join "" $hexvalue=$hexvalue.trimstart("0") $hexvalue }
Function
para analisarREG_BINARY
:function parse-binary { PARAM ( [Parameter(ValueFromPipeline=$true, Mandatory=$true)] [System.String]$binary ) [array]$hex=$binary -split'[,\\]' | where {-not ([string]::IsNullOrWhiteSpace($_))} | %{$_.trimstart()} $hex=$hex -join "" $hex }
Function
para analisarREG_MULTI_SZ
:function parse-multistring { PARAM ( [Parameter(ValueFromPipeline=$true, Mandatory=$true)] [System.String]$multistring ) $AsciiTable=import-csv ".\desktop\AsciiTable.csv" [array]$hex=$multistring -split'[\,\\]' | where {-not ([string]::IsNullOrWhiteSpace($_))} | %{$_.trimstart()} $hexadecimal=0..($hex.count-1) | where {$_ % 2 -ne 1} | foreach-object {$hex[$_]} $text=@() foreach ($hexadecima in $hexadecimal) { for ($i=0;$i -le 255;$i++) { if ($AsciiTable[$i].hexadecimal -eq $hexadecima) { if ($i -ne 0) {$text+=$AsciiTable[$i].value} else {$text+="\0"} } } } $text=$text -join "" $text }
O script está quase completo, já tendo criado Remove-Item
, New-Item
e Remove-ItemProperty
condições de alternância; agora, a peça final do quebra-cabeça é escrever uma regex que corresponda aos valores. Quando isso for feito, postarei como resposta aqui.
- Pseudo-código:
if $line match [ and ]->$line match [-HKEY -> Remove-Item else $registry[$i+1] eq ""->New-Item elseif $line match "=-" -> Remove-ItemProperty
- Criei uma tabela de hash ASCII para usar como dicionário:
$asciihex=@{} 0..255 | % { $number=$_ [string]$hex=$number.tostring('x') if ($hex.length -eq 1) {$hex='{1}{0}' -f $hex,'0'} $char=[char]$number $asciihex.add($hex,$char) }
- Para procurar um caractere em um determinado codepoint:
# Change: $asciihex.'00' # to: $asciihex.'ff'
- Para procurar um caractere em qualquer codepoint:
# Don't use $asciihex to print it $asciihex.$codepoint
- Para procurar um caractere em um determinado codepoint:
Para grep valores de linhas, use -replace $name+$type
para obter o valor.
Versão final:
Esta é a versão final, baseada no meu roteiro anterior e no roteiro fornecido por SimonS. O script está realmente completo, todos os bugs corrigidos, ele pode analisar corretamente todos os 6 tipos de valor do registro:
REG_SZ
,REG_DWORD
,REG_QWORD
, eREG_BINARY
, converte cada linha em uma linha, cada uma em uma linha, cada linha em uma linha e cada linha em um linha com base no tipo de propriedade. Ele aceita um caminho inserido, detecta automaticamente se o caminho aponta para um arquivo ou uma pasta, se for um arquivo com extensão .reg, ele envia comandos convertidos para um arquivo na pasta pai do arquivo com o nome do arquivo; Se for uma pasta, converte todos os arquivos .reg dentro dessa pasta e gera umREG_MULTI_SZ
REG_EXPAND_SZ
[HKEY_*
New-Item
[-HKEY_*
Remove-Item
"([^"=]+)"=-
Remove-ItemProperty
"([^"=]+)"=
Set-ItemProperty
${filename}_reg.ps1
${filename}_reg.ps1
arquivo para cada arquivo .reg para essa pasta e, em seguida, coloque todos os_reg.ps1
comandos em umallcommands.ps1
na pasta.Fiz vários testes e confirmei que realmente está funcionando. O script agora está completo. Fiz grandes melhorias, usei formatos melhores e simplifiquei bastante o código, usei lógicas melhores e fiz muitos outros aprimoramentos.
Isso é realmente completo, para usar minha versão final, copie e cole a função em uma janela do powershell aberta e invoque-a como reg2ps1 "full\path\to\content" ou salve-a como um arquivo .ps1 e execute-a por cd $scriptdir e .\reg2ps1.ps1, então insira full\path\to\content, observe que você não deve usar aspas, ou o caminho não pode ser encontrado...
Atualizar
Cometi um erro no código, especificando o
-Force
parâmetro ao usarNew-Item
, caso o item já exista, ele irá recriar o item, esvaziando o item no processo, não era isso que eu pretendia, agora está corrigido. Ao remover-Force
o parâmetro naNew-Item
linha, tentar criar um item que já existe gerará um erro informando que o item existe e não redefinirá o item. A mensagem de erro é ocultada por-ErrorAction SilentlyContinue
. Se o item não existir, ele será criado, o item ficará vazio, o processo exibirá uma mensagem informando que o item foi criado, a mensagem será ocultada por| Out-Null
.Isso é muito bom, mas você tem alguns erros no seu código de conversão.
Provavelmente vale a pena consertar