У меня есть код вроде:
$x = "This text needs to be encoded"
$z = [System.Text.Encoding]::Unicode.GetBytes($x)
$y = [System.Convert]::ToBase64String($z)
Write-Host("$y")
И в консоль выводится следующее:
VABoAGkAcwAgAHQAZQB4AHQAIABuAGUAZQBkAHMAIAB0AG8AIABiAGUAIABlAG4AYwBvAGQAZQBkAA==
Теперь, если бы я расшифровал этот b64 с помощью powershell, например:
$v = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($y))
Write-Host("$v")
Он будет правильно декодирован, например:
Этот текст нужно закодировать
Однако, если бы я поместил вышеупомянутую закодированную строку b64, скажем, в CyberChef и попытался декодировать ее с помощью рецепта «Из base64», декодированная строка была бы заполнена точками, например:
Этот. .текст. .н.э.д.с. .к. .быть. .e.n.c.o.d.e.d.
Мой вопрос, почему это происходит?
Кроме того, не используйте здесь скобки Write-Host("$y")
. Вместо этого используйте пробел между командлетом и тем, что вы хотите написать. Write-Host — это командлет, а не объектный метод.
Еще одно замечание: Write-Host, как правило, не тот инструмент для использования , если только цель не состоит в том, чтобы записывать только на дисплей, минуя поток успешных выходных данных и, вместе с ним, возможность отправлять выходные данные другим командам, записывать их в переменную. или перенаправить его в файл. Чтобы вывести значение, используйте его отдельно; например, $value
вместо Write-Host $value
(или используйте Write-Output $value
); см. этот ответ. Чтобы явно печатать только на дисплей, но с расширенным форматированием, используйте Out-Host
.
Сантьяго Скуарзон предоставил важный указатель:
Скорее всего, рецепт CyberChef ожидает, что байты, которые кодирует строка Base64, будут основаны на кодировке UTF-8 исходной строки.
Напротив, - плохо названная - кодировка [System.Text.Encoding]::Unicode является кодировкой UTF-16LE, где символы представлены (по крайней мере) двумя байтами (с наименее значащим байтом, первый).
0xFF
(255
), которая включает в себя весь диапазон ASCII, в который попадают все символы в вашей входной строке, поэтому имеют байт NUL
(значение 0x0
) в качестве второго байта их двухбайтового представление; например, буква T
, закодированная как UTF-16LE, состоит из двухбайтовой последовательности 0x54 0x0
, где 0x54
сама по себе представляет букву T
в кодировке ASCII — и, следовательно, также в UTF-8, которая является надмножеством ASCII, представляющим (только ) символы, отличные от ASCII, как многобайтовые последовательности.0x54 0x0
интерпретируется как два символа в контексте UTF-8: буква T
(0x54
) и NUL
(0x0
). NUL
не имеет визуального представления как такового (это непечатаемый символ), но принято визуализировать его как .
, что вы и видели.Поэтому создайте строку в кодировке Base64 следующим образом:
$orig = "This text needs to be encoded"
$base64 =
[System.Convert]::ToBase64String(
[System.Text.Encoding]::UTF8.GetBytes($orig)
)
Note: Even though [System.Text.Encoding]::UTF8 is - up to at least .NET 6 - a UTF-8 encoding with BOM, a BOM is (fortunately) not prepended to the input string by the .GetBytes()
method. As an aside: Changing this encoding to be BOM-less altogether is being considered prior to .NET 7.
$base64
затем содержит: VGhpcyB0ZXh0IG5lZWRzIHRvIGJlIGVuY29kZWQ=
Итак, вам нужно понять, какое кодирование использует CyberChef ... возможно, это
[System.Text.Encoding]::UTF8
, чтобы вы могли попробовать вместо использованияUnicode