다음과 같이 셸에 대한 일부 정보를 출력하는 스크립트가 있습니다.
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/mgir
1로 바꾸면 다음과 같습니다.3
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 문자가 있으므로 정규식은 일치하지 않습니다. 그런 다음 줄 시작 부분에 선택적 U+FEFF 문자를 허용 -C
하도록 정규식을 전달하고 변경할 수 있습니다 ./^\x{feff}?\s*cmdline.../i
답변2
지금까지 작동하는 것으로 보이는 유일한 해결책은 인코딩 명령이 UTF16LE라는 것을 받아들이고 \u0000
콘텐츠를 생성하는 스크립트의 검색에 null 바이트를 수동으로 포함하는 것입니다.jq
위에 주어진 예에서 (within ) 과 같이 -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(" ")
split(" ")[0]
실제 인코딩된 명령 -EncodedCommand
은 다음과 같이 powershell 명령줄을 만듭니다.split(" ")[1]
split(" ")[2]
콘텐츠가 UTF16LE에 있기 때문에 @base64d | test("be encoded")
이렇게 하려고 하면 UTF16LE에 null 값이 있기 때문에 실패합니다. 이렇게 하면 be encoded
인코딩 명령에서 콘텐츠가 발견되면 필드가 다음과 같이 출력됩니다.Encoded payload found!