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

(행당 하나만 있다고 가정합니다 -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

답변2

지금까지 작동하는 것으로 보이는 유일한 해결책은 인코딩 명령이 UTF16LE라는 것을 받아들이고 \u0000콘텐츠를 생성하는 스크립트의 검색에 null 바이트를 수동으로 포함하는 것입니다.jq

위에 주어진 예에서 (within ) 과 같이 -EncodedCommand대문자와 소문자 또는 의 가능성을 고려하십시오.-encodedcommandjq

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(" ")split(" ")[0]실제 인코딩된 명령 -EncodedCommand은 다음과 같이 powershell 명령줄을 만듭니다.split(" ")[1]split(" ")[2]

콘텐츠가 UTF16LE에 있기 때문에 @base64d | test("be encoded")이렇게 하려고 하면 UTF16LE에 null 값이 있기 때문에 실패합니다. 이렇게 하면 be encoded인코딩 명령에서 콘텐츠가 발견되면 필드가 다음과 같이 출력됩니다.Encoded payload found!

관련 정보