그래서 저는 binaryFile.dd의 처음 512바이트를 myProgram의 두 번째 인수로 전달하고 싶지만 bash는 모든 NUL 문자를 제거합니다. Bash에서 이것을 피할 수 있는 방법이 있습니까, 아니면 모든 것을 숨기고 있습니까?
myProgram parameter1 "$(head -c 512 binaryFile.dd)"
답변1
명령 매개변수에 널 바이트를 전달할 수 없습니다. bash에도 이러한 제한이 있지만 이는 bash의 제한 때문이 아닙니다. 이는 명령을 실행하는 인터페이스의 제한 사항입니다. null 바이트를 인수의 끝으로 처리합니다. 탈출 메커니즘이 없습니다.
대부분의 쉘은 함수 및 내장 함수에 대한 변수나 인수에서 널 바이트를 지원하지 않습니다. Zsh는 주목할만한 예외입니다.
$ ksh -c 'a=$(printf foo\\0bar); printf "$a"' | od -t x1
0000000 66 6f 6f
0000003
$ bash -c 'a=$(printf foo\\0bar); printf "$a"' | od -t x1
0000000 66 6f 6f 62 61 72
0000006
$ zsh -c 'a=$(printf foo\\0bar); printf "$a"' | od -t x1
0000000 66 6f 6f 00 62 61 72
0000007
그러나 zsh를 사용하더라도 매개변수를 외부 명령에 전달하려고 하면 null 바이트 이후의 모든 내용은 zsh가 아니라 커널에서 무시됩니다.
$ zsh -c 'a=$(printf foo\\0bar); /usr/bin/printf "$a"' | od -t x1
0000000 66 6f 6f
0000003
프로그램에 널 바이트를 전달하려면 명령줄 인수가 아닌 다른 방법을 찾아야 합니다.
head -c 512 binaryFile.dd | myProgram --read-parameter2-from-stdin parameter1
myProgram --read-parameter2-from-file=<(head -c 512 binaryFile.dd) parameter1
답변2
bash
바이너리 데이터를 직접 처리하는 데는 적합하지 않습니다.
파일에 이진 데이터를 사용하거나 데이터를 나타내는 16진수 문자열을 사용할 수 있습니다.
hexdump
16진수로 변환하려면 , xxd
, 를 사용할 수 있습니다 od
.
예를 들어, 512바이트를 16진수 문자열로 변환하려면 다음을 사용합니다.
xxd -ps -c 512 file.bin
다음을 사용하여 다시 바이너리로 변환합니다.
echo "$myhexstring" | xxd -r -ps > file.bin
답변3
아니요, Bash의 문자열에는 NUL( )이 포함될 수 없습니다 \0
.
따라서 변수(문자열 포함)에는 NUL이 포함될 수 없습니다.
c
그 이유는 bash가 "문자열은 NUL로 종료됩니다" 패러다임으로 작성 되었기 때문입니다 . [1] Linux 커널도 이러한 제한을 적용합니다. [2] 그러나 커널이 문자열 [3] (매개변수)에서 NUL을 허용하더라도 대부분의 쉘, 특히 bash는 변수 [4] 에 NUL을 포함 할 수 없습니다.
위치 매개변수( $1
등 $2
)는 변수와 동일하며 NUL을 포함할 수 없습니다.
그러나 파일, 스트림 및 printf에는 nul이 존재할 수 있습니다.
$ printf 'test\0nuls\n' | od -vAn -tx1c
74 65 73 74 00 6e 75 6c 73 0a
t e s t \0 n u l s \n
보시다시피 printf는 NUL을 생성하고 파이프( |
)를 통해 흐릅니다. 그러나 NUL은 "명령 실행"에서 제거됩니다.
$ echo $(printf 'test\0nuls\n') | od -vAn -tx1c
bash: warning: command substitution: ignored null byte in input
74 65 73 74 6e 75 6c 73 0a
t e s t n u l s \n
Bash 4.4에서는 경고도 표시됩니다. 이 경우 zsh는 자동으로 NUL을 공백으로 바꿉니다.
$ zsh -c ' echo $(printf "test\0nuls\n") | od -vAn -tx1c'
74 65 73 74 20 6e 75 6c 73 0a
t e s t n u l s \n
printf와 NUL을 포함 하는 파일의 또는 dd cat
부분 을 사용하여 NUL을 포함하는 파일을 만들 수 있습니다 .head
tail
$ printf 'test\0nuls\0in\0files\0\n' > testnul.bin
$ cat testnul.bin | xxd -ps
74657374006e756c7300696e0066696c6573000a
$ head -c 7 testnul.bin | xxd -ps
74657374006e75
$ dd if=testnul.bin bs=7 count=1 | xxd -ps
74657374006e75
1+0 records in
1+0 records out
7 bytes copied, 0.000655689 s, 10.7 kB/s
$ dd if=testnul.bin bs=7 count=1 2>/dev/null| xxd -ps
74657374006e75
귀하의 경우에는 바이너리 파일의 내용을 매개변수로 사용하는 쉬운 [5] 방법이 없습니다 . 아마도 16진수 표현이 작동할 것입니다:
$ myProgram "$parameter1" "$(xxd -ps -c 512 binaryFile.dd)"
모든 추가 작업(및 세부 사항)에 대해 @Gilles에게 감사드립니다.
1
[1]
모든 것은 옛날로 귀결된다정의C string
« \0
NUL( )으로 끝나는 문자열». 이 예제는 C
POSIX에 대한 여러 예제를 포함하여 여러 라이브러리와 도구로 코딩 되었습니다 . 좋다strcpy
여기 있어요그것은 다음과 같이 말합니다(강조).
strcpy() 함수는 s2가 가리키는 문자열을 복사해야 합니다(종료 NUL 문자 포함)을 s1이 가리키는 배열에 넣습니다.
이는 문자열이 NUL로 끝나는 것으로 가정함을 의미합니다.
즉, 마지막 NUL이 하나만 있을 수 있습니다.
2
[2] 시스템 execve()
호출,POSIX에서도 정의됨, 문자열(명령 매개변수)이 NUL로 종료될 것으로 예상합니다. 이것이 NUL과 함께 쉘을 사용할 수 있는 이유입니다(대부분은 사용할 수 없지만 zsh는 주목할만한 예외입니다).
$ zsh -c 'a=$(printf "included\0null"); printf "$a"' | od -vAn -tx1c
69 6e 63 6c 75 64 65 64 00 6e 75 6c 6c
i n c l u d e d \0 n u l l
할 수 있는아니요호출에 전달된 매개변수에 NUL을 사용하세요 execve()
.
$ zsh -c 'a=$(printf "included\0null"); /usr/bin/printf "$a"' | od -vAn -tx1c
69 6e 63 6c 75 64 65 64
i n c l u d e d
삼
[3] 그러나 커널이 인수에 NUL을 포함할 수 있더라도 bash는 이를 허용하지 않습니다.
$ bash -c 'a=$(printf "included\0null"); /usr/bin/printf "$a"' | od -vAn -tx1c
bash: warning: command substitution: ignored null byte in input
69 6e 63 6c 75 64 65 64 6e 75 6c 6c
i n c l u d e d n u l l
Bash 4.4에서는 NUL이 제거되면 경고도 표시됩니다.
4
[4] 대부분의 쉘, 특히 bash는 변수에 NUL을 포함할 수 없습니다.
$ printf 'included\0null' | od -vAn -tx1c
69 6e 63 6c 75 64 65 64 00 6e 75 6c 6c
i n c l u d e d \0 n u l l
$ printf 'included\0null' | ( read a; printf '%s\n' "$a" | od -vAn -tx1c )
69 6e 63 6c 75 64 65 64 6e 75 6c 6c
i n c l u d e d n u l l
실행 중인 셸이 zsh인 경우 대신 null이 사용됩니다.
$ zsh -c 'printf "included\0null" | ( read a; printf "%s\n" "$a" | od -vAn -tx1c )'
69 6e 63 6c 75 64 65 64 00 6e 75 6c 6c 0a
i n c l u d e d \0 n u l l \n
5
[5] 이는 값이 0( )인 바이트를 "직접"(간단히) 포함하는 \0
것이 불가능하다는 것을 의미합니다. 그러나 16진수, 64진수 또는 이와 동등한 형태의 C-문자열 인코딩(복소수)을 사용하면 $'\0'
0 값이 포함될 수 있습니다.