간단히 말해서:최신 버전의 busybox(1.23.2)에는 head
문제가 있으며 제공된 데이터에서 NUL 문자를 기꺼이 제거합니다. 바이너리를 교체하는 것은 옵션이 아닙니다. 내 스크립트에서 이것을 사용하고 있습니다 head -[nc] -X
. busybox에서 제공하는 다른 도구를 사용하여 시뮬레이션할 수 있는 방법이 있습니까?
파일 업로드와 busybox httpd가 이를 처리하는 방법에 익숙하지 않은 사람들은 읽어보고 싶을 수도 있습니다.이것계속하기 전에.
Busybox가 설치된 임베디드 시스템에서 CGI 스크립트로 수신된 데이터 업로드를 처리하려고 합니다. 전송된 데이터는 다음과 같습니다.
$ hexdump -C foo.bin
00000000 03 15 20 00 00 00 75 73 74 61 72 30 30 30 2e 30 |.. ...ustar000.0|
00000010 00 11 00 |...|
00000013
POST 요청을 통해 전송되면 데이터를 처리하는 CGI 스크립트는 다음 데이터를 수신합니다.
$ hexdump -C 24593.tmp
00000000 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d |----------------|
00000010 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 30 65 34 32 32 64 |----------0e422d|
00000020 63 39 65 64 65 32 34 36 34 30 0d 0a 43 6f 6e 74 |c9ede24640..Cont|
00000030 65 6e 74 2d 44 69 73 70 6f 73 69 74 69 6f 6e 3a |ent-Disposition:|
00000040 20 66 6f 72 6d 2d 64 61 74 61 3b 20 6e 61 6d 65 | form-data; name|
00000050 3d 22 66 69 6c 65 22 3b 20 66 69 6c 65 6e 61 6d |="file"; filenam|
00000060 65 3d 22 66 6f 6f 2e 62 69 6e 22 0d 0a 43 6f 6e |e="foo.bin"..Con|
00000070 74 65 6e 74 2d 54 79 70 65 3a 20 61 70 70 6c 69 |tent-Type: appli|
00000080 63 61 74 69 6f 6e 2f 6f 63 74 65 74 2d 73 74 72 |cation/octet-str|
00000090 65 61 6d 0d 0a 0d 0a 03 15 20 00 00 00 75 73 74 |eam...... ...ust|
000000a0 61 72 30 30 30 2e 30 00 11 00 0d 0a 2d 2d 2d 2d |ar000.0.....----|
000000b0 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d |----------------|
000000c0 2d 2d 2d 2d 2d 2d 30 65 34 32 32 64 63 39 65 64 |------0e422dc9ed|
000000d0 65 32 34 36 34 30 2d 2d 0d 0a |e24640--..|
000000da
위에서 원시 데이터를 검색하는 것은 쉽습니다.
$ tail -n +5 24593.tmp | head -n -1 | head -c -2 | hexdump -C
00000000 03 15 20 00 00 00 75 73 74 61 72 30 30 30 2e 30 |.. ...ustar000.0|
00000010 00 11 00 |...|
00000013
그러나 busybox에는 단점이 있습니다 head
. 데이터의 모든 NUL 문자가 제거됩니다.
$ /firmware/system/xbin/tail -n +5 24593.tmp | /firmware/system/xbin/head -n -1 | /firmware/system/xbin/head -c -2 | hexdump -C
00000000 03 15 20 75 73 74 61 72 30 30 30 2e 30 11 |.. ustar000.0.|
0000000e
head -[nc] -X
busybox에서 제공하는 다른 도구를 사용하여 동작을 시뮬레이션하거나 최소한 작업할 수 있는 다른 방법이 있습니까 ?
가장 신중하게 해야 할 일은 새 바이너리를 올바른 동작으로 도입/교체하는 것이지만 이는 여러 가지 이유로 불가능합니다(여기서는 논의할 필요가 없음).
이 기사는 주로 당면한 문제와 관련이 없는 세부 사항을 언급하는 데 집중되어 있는 것처럼 보이지만, 이를 방지하기 위해 여기에 세부 사항을 제시합니다.XY 문제.
답변1
귀하의 질문을 올바르게 이해했다면 다음을 포함하는 요청에서 업로드된 파일을 추출하고 싶습니다.
- 대시와 그 뒤에 오는 16진수로 구성된 줄입니다.
- 더 많은 공백이 아닌 줄(제목);
- 빈 줄;
- 추출할 콘텐츠;
- 개행 문자;
- 첫 번째 줄을 반복합니다.
여기서 개행 문자는 CRLF 시퀀스이고 내용에는 모든 바이트가 포함될 수 있지만 헤더에는 널 바이트가 포함되지 않습니다.
head
행에 의존 하고 tail
구문 분석하는 대신 다음 두 단계로 이 작업을 수행할 수 있습니다 .
- 추출할 바이트 위치의 범위를 결정합니다.
- 이 바이트를 추출하십시오.
첫 번째 단계에서는 널 바이트 문제를 방지하려면 tr
. 그런 다음 줄 기반 도구를 사용하여 첫 번째 빈 줄을 감지하고 마지막 줄의 시작을 감지할 수 있습니다. 나는 아래에서 awk를 사용하고 있으며 파일 이름도 추출할 기회를 얻고 있습니다. awk가 없으면 head
, tail
, sed
, ...을 사용할 수 있습니다.
dd
두 번째 단계에서는 블록 크기가 1인 블록을 사용할 수 있습니다 . 느리지만 안정적입니다.
upload=24593.tmp
filename=$(<"$upload" tr '\0' _ | awk '
{line_start = line_end; line_end += length($0)+1}
!content_start && /^Content-Disposition:.*filename="/ {
sub(/.*filename="/, ""); sub(/".*/, "");
filename = $0
}
!content_start && $0=="\r" {content_start=line_end}
END {print content_start, line_start-2-content_start, filename}
')
skip=${filename%% *}; filename=${filename#* }
count=${filename%% *}; filename=${filename#* }
if [ -z "$filename" ]; then filename=$(mktemp); fi
<$upload dd bs=1 skip="$skip" count="$count" >"$filename"
답변2
Busybox는 고도로 구성 가능하므로 대답은 컴파일된 항목에 따라 달라집니다. 다음은 몇 가지 옵션입니다.
catv -v
Null 값은 "^@"로 표시됩니다.
split -l 1
각각 한 줄씩 포함된 파일 xaa
xab
등이 생성됩니다.