我有一个脚本可以在 shell 上输出一些信息,如下所示:
field1: value1
field2: value2
...
fieldn: valuen
这样的字段/值可以是:
CmdLine: C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe -EncodedCommand <base64_encodedcommand>
我一直在寻找一种方法来处理这个问题,因为编码的命令可能非常大(例如,2 个大或更多的终端屏幕)。我抽出时间去做的一件事是:
command_that_generates_strings | awk '{for (i=1;i<=NF;i++) if (tolower($i) ~/^-encodedcommand/) {i++; "echo "$i" | base64 -d | iconv -f UTF-16LE -t UTF8 | grep -i <specific_identifier_here> | sed -E \"s#.+#<better_identifier_here#g\"" | getline x; print x} else {print $i}}'
为了可读性:
command_that_generates_strings | awk '{
for (i=1;i<=NF;i++)
if (tolower($i) ~/^-encodedcommand/) {
i++; "echo "$i" |
base64 -d |
iconv -f UTF-16LE -t UTF8 |
grep -i <specific_identifier_here> |
sed -E \"s#.+#<better_identifier_here#g\"" |
getline x; print x
} else {print $i}}'
(是的,iconv
其中的原因是,雪上加霜的是,base64 内容是 grep 不喜欢的 utf16le 格式。我在 bash 和 zsh 中都“半成功”地运行了这个)
但这并不完全按预期工作...而不是替换为CmdLine: yaddayadda
,<better_identifier_here>
它只是替换编码的命令,并将其他所有内容分开,并且不知何故它似乎正在对输出进行排序,如下所示:
A-string
B-string
C-string
CmdLine:
C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe
D-string
EncodedCommand
...
N-string
<better_identifier_here>
...
Y-string
Z-string
0-string
1-string
...
(上面的“EncodedCommand”是实际的字符串,而不是来自该命令行的 base64 编码命令)
也许有另一种更好的方法来完成我正在寻找的事情?预期的结果只是:
field1: value1
field2: value2
...
<better_identifier_here>
...
fieldn: valuen
-- 让我们尝试在这里包含一个更有用的示例:
输入:
field1: value1
field2: value2
...
CmdLine: C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe -EncodedCommand PABpAG4AcwBlAHIAdAAgAHAAbwB3AGUAcgBzAGgAZQBsAGwACgBtAHUAbAB0AGkAbABpAG4AZQAKAHMAYwByAGkAcAB0AAoAaABlAHIAZQAgAC0AIABpAHQAJwBsAGwAIABiAGUAIABlAG4AYwBvAGQAZQBkACAAYQBzACAAdQB0AGYAMQA2AGwAZQAKAGEAbgBkACAAdABoAGUAbgAgAGUAbgBjAG8AZABlAGQAIABpAG4AIABiAGEAcwBlADYANAA+AA==
...
fieldn: valuen
由此,我希望能够识别该字符串"be encoded"
是该编码命令的一部分,并将整个“CmdLine”行替换为“找到编码的有效负载”。
示例输出如下:
field1: value1
field2: value2
...
Encoded payload found.
...
fieldn: valuen
答案1
假设您想要:
- 查找任意出现
-encodedcommand
(不区分大小写)后跟空格的Base64 编码数据 - 将其解码为假定为多行 UTF16-LE 编码字符串的内容
- 解码 UTF16-LE 以获取实际文本
- 将解码文本中与模式(不区分大小写)匹配的任何行替换为新行
- 将结果编码回 UTF16-LE
- 并返回base64
然后你可以这样做:
your-cmd | perl -MMIME::Base64 -MEncode -pe '
s{\s-encodedcommand\s+\K\S+}{
encode_base64(
encode(
"UTF16LE",
decode(
"UTF16LE",
decode_base64($&)
) =~ s/^.*bad content.*$/new better content/mgir
), ""
)
}gie'
例子。与your-cmd
是:
echo 'CmdLine: ... -EncodedCommand MQANAAoAMgANAAoAMwANAAoANAANAAoA'
MQANAAoAMgANAAoAMwANAAoANAANAAoA
其中 的输出的UTF16-LE 编码的base64编码seq -f $'%g\r' 4
。
替换为s/^3\r$/new\r/mgir
,用 1 替换该3
行(带有 MSDOS 行分隔符),new
给出:
CmdLine: ... -EncodedCommand MQANAAoAMgANAAoAbgBlAHcADQAKADQADQAKAA==
在哪里:
echo MQANAAoAMgANAAoAbgBlAHcADQAKADQADQAKAA== |
base64 -d |
hexdump -C
给出:
00000000 31 00 0d 00 0a 00 32 00 0d 00 0a 00 6e 00 65 00 |1.....2.....n.e.|
00000010 77 00 0d 00 0a 00 34 00 0d 00 0a 00 |w.....4.....|
0000001c
您可以在哪里识别 Microsoft 版本
1
2
new
4
如果按照您明确的要求,您只想检测编码文本中的字符串,如果存在,则用解码的内容替换整行(大概以UTF-8¹编码)
your-cmd | perl -MMIME::Base64 -MEncode -pe '
if (/^\s*cmdline:.*\s-encodedcommand\s+(\S+)/i) {
$text = decode("UTF16LE", decode_base64($1));
if ($text =~ /encoded as/) {
$_ = encode("UTF-8", "$text\n");
# or "$text\r\n" if meant to be DOS-style or:
# $_ = "Encoded payload found\n";
}
}'
(假设每行只有一个-encodedcommand
;如果有更多,则仅考虑最后一个。替换.*
为.*?
以考虑第一个)。
在你的样本上,这给出了:
field1: value1
field2: value2
...
<insert powershell
multiline
script
here - it'll be encoded as utf16le
and then encoded in base64>
...
fieldn: valuen
1 默认情况下,perl 会将输入视为采用 ISO8859-1(又名 latin1)编码。由于您要处理的部分仅是 ASCII,因此不会有任何区别,并且至少对于 latin1,您不会遇到解码问题。如果它是 UTF-8,您可以添加该-C
选项perl
并跳过该encode("UTF-8"...)
部分。
请注意,虽然字节顺序标记不属于 UTF-8,但有时会在 Microsoft 文件中找到它们。如果是这种情况并且CmdLine
位于第一行,则/^\s*cmdline.../i
正则表达式将不匹配,因为开头会有 U+FEFF BOM 字符。然后您可以传递-C
并更改正则表达式以/^\x{feff}?\s*cmdline.../i
允许在行开头使用可选的 U+FEFF 字符。
答案2
到目前为止,唯一有效的解决方案似乎是接受编码命令是 UTF16LE,并在生成内容的脚本\u0000
中手动包含搜索中的空字节...jq
对于上面给出的示例,考虑到大写和小写-EncodedCommand
或的可能性-encodedcommand
,就像(在 内jq
):
restofjq |
if(if((split(" ")[1] | ascii_downcase)=="-encodedcommand")
then (
split(" ")[2] |
@base64d |
test("\u0000b\u0000e\u0000 \u0000e\u0000n\u0000c\u0000o\u0000d\u0000e\u0000d\u0000")
) else empty end
) then "Encoded payload found!" else empty end
(添加换行符以方便阅读)
split(" ")
将使 powershell 命令行为split(" ")[0]
,而实际编码的命令-EncodedCommand
为split(" ")[1]
split(" ")[2]
因为内容采用 UTF16LE 格式,所以如果我尝试@base64d | test("be encoded")
这样做就会失败,因为 UTF16LE 中存在空值。这样,如果be encoded
在编码命令中找到内容,则该字段将输出为Encoded payload found!