바이너리 파일에서 일치하기 전의 바이트 수를 Grep으로 설정합니까?

바이너리 파일에서 일치하기 전의 바이트 수를 Grep으로 설정합니까?

grep -ao ...word file.bin나는 종종 텍스트 내용("단어")과 그 앞에 있는 몇 가지 주의 사항을 찾는 데 사용합니다 .

   -a, --text
          Process a binary file as if it were text; this is equivalent to the --binary-files=text option.
   -o, --only-matching
          Print  only  the  matched  (non-empty) parts of a matching line, with each such part on a separate
          output line.

맞습니다. 이제 막 다음과 같이 동작한다는 것을 깨달았습니다. 먼저 문자열 war과 그 앞에 있는 문자 하나를 찾으려고 합니다.

$ grep -ao .war myfile.zip
/war
9war
$war
ʆwar

좋아요, 여기에서 4번의 클릭이 발생했습니다. 이제 문자열 war과 그 앞의 두 문자를 찾으려면 다음을 수행하십시오 .

$ grep -ao ..war myfile.zip
>$war

그러면 이제 어떤 이유에서인지 결과가 하나만 표시됩니까? !

내 생각엔 3개가 누락된 경우 "처음 두 문자"의 값은 0x00(C 문자열의 끝)이므로 grep해당 일치 항목은 출력되지 않을 것입니다. 그렇지 않으면 여전히 4개의 결과가 나올 것으로 예상됩니다(예를 들어 이전 첫 번째 일치 항목은 파일의 시작 부분에 있습니다. 그렇지 않으면 3개의 결과를 얻게 됩니다.

grep일치 항목에서 null 바이트를 단순히 "무시"(또는 점 등으로 대체)하고 이를 포함할 수 있는 일치 항목을 계속 인쇄하도록 설득할 수 있습니까 ? 그렇지 않은 경우 grep이를 수행할 수 있는 다른 도구가 있습니까?

답변1

귀하의 접근 방식에는 적어도 두 가지(바람직하게는 세 가지)의 문제가 있습니다.

non-standard 를 사용하는 경우에도 라인 기반 -o입니다 grep. 각 라인의 출력과 일치하는 모든 항목을 찾기 때문입니다 o. 이는 줄 바꿈으로 구분된 문자 시퀀스입니다(ASCII 기반 시스템에서 값이 10/0x0a인 바이트).

그래서:

grep -o ..war

war2 이후의 인스턴스 만 반환됩니다.수치(여기서 세 가지 문제 중 하나인 바이트가 아님) 줄 바꿈을 제외하고.

예를 들어 유사한 입력에서 <0x0a>Xwar0x0a 바이트는 이전 줄을 구분하고 다음 줄은 Xwar이전에 단 한 문자였던 곳에서 시작됩니다 war.

UTF-8 로케일에서는 유사한 입력에서 <0xff><0xc3><0xa9>war2바이트가 문자를 <0xc3><0xa9>형성 é하지만 앞의 0xff 바이트는 유효하지 않으므로 문자를 형성할 수 없습니다.

grepgrep일반적으로 텍스트에서만 작동하므로 구현에 따라 NUL 문자나 지나치게 긴 줄 또는 줄바꿈으로 끝나지 않는 입력으로 작업하면 문제가 발생할 수 있습니다.

그런 다음 에서 xxwarwar발견 grep -o되지만 xxwar더 많은 일치 항목에 대한 검색이 계속되므로 찾을 수 없습니다 arwar.

이러한 문제는 다음 방법을 사용하여 해결할 수 있습니다 perl.

perl -l -0777 -ne 'print "$1$2" while m{(?<=(..))(war)}sg'

war인스턴스 앞의 2바이트(사용자 로케일의 문자가 아님)를 찾고 , 입력 소비를 방지하기 위해 이러한 앞의 바이트에 역방향 연산자를 사용합니다. 레코드 구분 기호를 불가능한 것으로 설정하는 를 사용하여 -0777입력의 각 줄 대신 전체 입력을 처리합니다.

답변2

또 다른 방법은 바이너리를 16진수로 변환하여 일치시키는 것입니다.

hexdump -v -e '/1 "%02X" " "' file.bin | grep -o ".. .. $(printf "war" | hexdump -v -e '/1 "%02X" " "')"

string 앞에 일치시키려는 모든 바이트에 대해 ..하나씩 필요합니다 . .단점은 grep이나 Perl의 직접 일치보다 느리고 warwarPerl 솔루션처럼 연속적인 패턴에서 후속 일치 항목을 찾지 못한다는 것입니다.

결과는 16진수 값으로 인쇄됩니다. 결과를 문자열로 인쇄하려면 다음과 같이 바이트를 다시 변환하십시오.

hexdump -v -e '/1 "%02X" " "' file.bin | \
    grep -o ".. .. $(printf "war" | hexdump -v -e '/1 "%02X" " "')" | \
    xargs -d '\n' -n 1 bash -c '<<<"$1" xxd -r -p -; echo' bash

그러나 앞에 문자열과 다른 많은 제어 문자가 \n있으면 출력이 엉망이 될 수 있습니다.\r

각 바이트 뒤에 공백을 인쇄하지 않음으로써 검색 속도를 높일 수도 있지만, 16진수 문자열이 바이트 중간에서 일치하므로 잘못된 긍정이 발생할 수 있다는 점에 유의하세요. 이렇게 하면 각각 ..대신 일치시킬 수 있습니다....

hexdump -v -e '/1 "%02X" ""' file.bin | \
    grep -o "....$(printf "war" | hexdump -v -e '/1 "%02X" ""')" | \
    xargs -d '\n' -n 1 bash -c '<<<"$1" xxd -r -p -; echo' bash

관련 정보