Base64でエンコードされたコンテンツ内のコンテンツを識別し、行全体を置き換えます。

Base64でエンコードされたコンテンツ内のコンテンツを識別し、行全体を置き換えます。

次のように、シェルに関するいくつかの情報を出力するスクリプトがあります。

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

これをMSDOS行区切り文字を使用してs/^3\r$/new\r/mgir1に置き換えると、次のようになります。3new

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";
    }
  }'

(1行に1つしかないと仮定します-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文字があるため、正規表現は一致しません。その後、行の先頭にオプションのU + FEFF文字を受け入れる-Cように正規表現を渡して変更できます。/^\x{feff}?\s*cmdline.../i

おすすめ記事