10

この質問はしばらく前からありましたが、それを機能させることができれば、いくつかのボーナスポイントを提供する必要があると思いました.

私は何をしましたか…</h1>

最近、職場で、バイナリ ファイルを読み取り可能な形式に変換するパーサーを作成しました。バイナリ ファイルは、10101010文字を含む ASCII ファイルではありません。バイナリでエンコードされています。したがってcat、ファイルに対して a を実行すると、次のようになります-

[jaypal~/Temp/GTP]$ cat T20111017153052.NEW 
==?sGTP?ղ?N????W????&Xx1?T?&Xx1?;
?d@#e?
      ?0H????????|?X?@@(?ղ??VtPOC01
cceE??k@9??W傇??R?K?i2??d@#e???&Xx1&Xx??!?
blackberrynet?/??!

??!

??#ripassword??W傅?W傆??0H??
                            #R??@Vtc@@(?ղ??n?POC01

そこでhexdump、ユーティリティを使用してコンテンツに続いてファイルを表示し、ファイルにリダイレクトしました。これで、16 進値を含むテキスト ファイルである出力ファイルができました。

[jaypal~/Temp/GTP]$ hexdump -C T20111017153052.NEW 
00000000  3d 3d 01 f8 73 47 54 50  02 f1 d5 b2 be 4e e4 d7  |==..sGTP.....N..|
00000010  00 01 01 00 01 80 00 cc  57 e5 82 00 00 00 00 00  |........W.......|
00000020  00 00 00 00 00 00 00 00  87 d3 f5 13 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 01 00 10  |................|
00000040  01 01 0f 00 00 00 00 00  26 58 78 31 00 b3 54 c5  |........&Xx1..T.|
00000050  26 58 78 31 00 b4 3b 0a  00 00 ad 64 13 40 01 03  |&Xx1..;....d.@..|
00000060  23 16 65 f3 01 01 0b 91  30 19 48 99 f2 ff ff ff  |#.e.....0.H.....|
00000070  ff ff ff 02 00 7c 00 dc  01 58 00 a0 40 40 28 02  |.....|...X..@@(.|
00000080  f1 d5 b2 b8 ca 56 74 50  4f 43 30 31 00 00 00 00  |.....VtPOC01....|
00000090  00 04 0a 63 63 07 00 00  00 00 00 00 00 00 00 00  |...cc...........|
000000a0  00 00 00 65 45 00 00 b4  fb 6b 40 00 39 11 16 cd  |...eE....k@.9...|
000000b0  cc 57 e5 82 87 d3 f5 52  85 a1 08 4b 00 a0 69 02  |.W.....R...K..i.|
000000c0  32 10 00 90 00 00 00 00  ad 64 00 00 02 13 40 01  |2........d....@.|

大量のawksedおよびのcut後、スクリプトは 16 進値を読み取り可能なテキストに変換しました。そのために、変換された各パラメータの開始位置と終了位置をマークするオフセット位置を使用しました。すべての変換後の結果ファイルは次のようになります

[jaypal:~/Temp/GTP] cat textfile.txt 
Beginning of DB Package Identifier: ==
Total Package Length: 508
Offset to Data Record Count field: 115
Data Source: GTP
Timestamp: 2011-10-25
Matching Site Processor ID: 1
DB Package format version: 1
DB Package Resolution Type: 0
DB Package Resolution Value: 1
DB Package Resolution Cause Value: 128
Transport Protocol: 0
SGSN IP Address: 220.206.129.47
GGSN IP Address: 202.4.210.51

なぜ私はそれをしたのですか

私はテスト エンジニアであり、バイナリ ファイルを手動で検証することは大きな苦痛でした。手動でオフセットを解析し、電卓を使用してそれらを変換し、Wireshark と GUI に対して検証する必要がありました。

さて質問部分

今までと逆のことをしたい。これが私の計画だった -

  • 読みやすい入力テキスト ファイルを用意しますParameters : Values
  • ユーザーは単純にそれらの横に値を入力できます (たとえば、日付はパラメーターであり、ユーザーはデータ ファイルに含める日付を指定できます)。
  • スクリプトは、入力テキスト ファイルからすべての関連情報 (ユーザーが提供した情報) を切り取り、それらを 16 進数値に変換します。
  • ファイルが 16 進値に変換されたら、それをバイナリにエンコードしたいと思います。

最初の 3 つのステップが完了しました

問題

スクリプトが入力テキスト ファイルを 16 進数値のテキスト ファイルに変換すると、次のようなファイルが得られます (これで実行できることに注意catしてください)。

[visdba@hw-diam-test01 ParserDump]$ cat temp_file | sed 's/.\{32\}/&\n/g' | sed 's/../& /g'
3d 3d 01 fc 73 47 54 50 02 f1 d6 55 3c 9f 49 9c
00 01 01 00 01 80 00 dc ce 81 2f 00 00 00 00 00
00 00 00 00 00 00 00 00 ca 04 d2 33 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10
01 01 0f 00 00 07 04 ea 00 00 ff ff 00 00 14 b7
00 00 ff ff 00 00 83 ec 00 00 83 62 54 14 59 00
60 38 34 f5 01 01 0b 58 62 70 11 60 f6 ff ff ff
ff ff ff 02 00 7c 00 d0 01 4c 00 b0 40 40 28 02
f1 d6 55 38 cb 2b 23 50 4f 43 30 31 00 00 00 00
00 04 0a 63 63 07 00 00 00 00 00 00 00 00 00 00

私の意図は、この変換されたファイルをバイナリにエンコードして、ファイルを処理すると大量のガベージ値が得られるようにすることです。cat

[jaypal~/Temp/GTP]$ cat temp.file 
==?sGTP?ղ?N????W????&Xx1?T?&Xx1?;
?d@#e?
      ?0H????????|?X?@@(?ղ??VtPOC01
cceE??k@9??W傇??R?K?i2??d@#e???&Xx1&Xx??!?
blackberrynet?/??!

??!

質問はこれです。この形式でエンコードするにはどうすればよいですか?

なぜ私はこれをしたいのですか?

本番環境では、多くの GTP (GPRS Tunneling Protocol) メッセージはありません。これをリバースエンジニアリングすれば、効果的にデータジェネレーターを作成し、独自のデータを作成できると思いました。

まとめて

世の中には洗練されたツールがあるかもしれませんが、私はそれらの学習にあまり時間をかけたくありません。約 2 か月が経ちました。*nix プラットフォームの作業を開始し、 や などのパワー ツールを使い始めましsedawk

私が欲しいのは、これを実現するための助けとガイダンスです。

読んでくれてありがとう!正しい方向に私を導くことができる誰かを 200 ポイントが待っています。:)

サンプルファイル

元のバイナリ ファイルのサンプルを次に示します。

ユーザーが値を入力できる入力テキスト ファイルのサンプルを次に示します。

以下は、入力テキスト ファイルからのすべての変換が完了した後にスクリプトが作成するファイルのサンプルです。

File 3のエンコーディングをに変更するにはどうすればよいFile 1ですか?

4

5 に答える 5

16

xxdを使用して、バイナリ ファイル/hexdumps との変換を非常に簡単に行うことができます。

データを 16 進数に

echo  Hello | xxd -p 
48656c6c6f0a

16 進数からデータへ

echo 48656c6c6f0a | xxd -r -p
Hello

また

echo 48 65 6c 6c 6f 0a | xxd -r -p
Hello

-pは、より自由な形式の入力を可能にするポストスクリプト モードです 。

これは、xxd -r -p textテキストが上記のデータである場所からの出力です

==▒sGTP▒▒U<▒I▒▒▒΁/▒▒3▒▒▒▒▒▒▒▒▒bTY`84▒
                                     Xbp`▒▒▒▒▒▒▒|▒L▒@@(▒▒U8▒+#POC01
:▒ިv▒b▒▒▒▒TY`84Ud▒▒▒▒>▒▒▒▒▒▒▒!▒
blackberrynet▒/▒▒!
M
▒▒!
N
▒▒#Oripassword▒▒΁/▒▒΁/▒▒Xbp`▒@@(▒▒U8▒IvPOC01
:qU▒b▒▒▒▒▒▒TY`84U▒▒▒*:▒▒!
▒k▒▒▒#O Welcmme!
▒!
M
于 2011-11-28T20:35:26.730 に答える
3

とを使用するcutと、 (GNU Awk) 拡張関数awkを使用してかなり簡単に実行できます。gawkstrtonum()

cut -c11-60 inputfile |
awk '{ for (i = 1; i <= NF; i++)
       {
           c = strtonum("0x" $i)
           printf("%c", c);
       }
     }' > outputfile

または、'new' の非 GNU バージョンを使用している場合はawk、次を使用できます。

cut -c11-60 inputfile |
awk '{  for (i = 1; i <= NF; i++)
        {
            s = toupper($i)
            c0 = index("0123456789ABCDEF", substr(s, 1, 1)) - 1
            c1 = index("0123456789ABCDEF", substr(s, 2, 1)) - 1
            printf("%c", c0*16 + c1);
        }
     }' > outputfile

他のツール (Perl と Python スプリントを思い浮かべてください。Ruby も別の可能性です) を使用したい場合は、十分に簡単に行うことができます。

odxプログラムに似たhexdumpプログラムです。上記のスクリプトは、入力ファイルとして「hexdump.out」を読み取るように変更され、出力odxはファイルの代わりにパイプされ、次の出力が得られます。

$ cat hexdump.out
00000000  3d 3d 01 fc 73 47 54 50  02 f1 d6 55 3c 9f 49 9c  |==..sGTP...U<.I.|
00000010  00 01 01 00 01 80 00 dc  ce 81 2f 00 00 00 00 00  |........../.....|
00000020  00 00 00 00 00 00 00 00  ca 04 d2 33 00 00 00 00  |...........3....|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 10  |................|
00000040  01 01 0f 00 00 07 04 ea  00 00 ff ff 00 00 14 b7  |................|
00000050  00 00 ff ff 00 00 83 ec  00 00 83 62 54 14 59 00  |...........bT.Y.|
00000060  60 38 34 f5 01 01 0b 58  62 70 11 60 f6 ff ff ff  |`84....Xbp.`....|
00000070  ff ff ff 02 00 7c 00 d0  01 4c 00 b0 40 40 28 02  |.....|...L..@@(.|
$ sh -x revdump.sh | odx
+ cut -c11-60 hexdump.out
+ awk '{  for (i = 1; i <= NF; i++)
        {
            #c = strtonum("0x" $i)
            #printf("%c", c);
            s = toupper($i)
            c0 = index("0123456789ABCDEF", substr(s, 1, 1)) - 1
            c1 = index("0123456789ABCDEF", substr(s, 2, 1)) - 1
            printf("%c", c0*16 + c1);
        }
     }'
0x0000: 3D 3D 01 FC 73 47 54 50 02 F1 D6 55 3C 9F 49 9C   ==..sGTP...U<.I.
0x0010: 00 01 01 00 01 80 00 DC CE 81 2F 00 00 00 00 00   ........../.....
0x0020: 00 00 00 00 00 00 00 00 CA 04 D2 33 00 00 00 00   ...........3....
0x0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10   ................
0x0040: 01 01 0F 00 00 07 04 EA 00 00 FF FF 00 00 14 B7   ................
0x0050: 00 00 FF FF 00 00 83 EC 00 00 83 62 54 14 59 00   ...........bT.Y.
0x0060: 60 38 34 F5 01 01 0B 58 62 70 11 60 F6 FF FF FF   `84....Xbp.`....
0x0070: FF FF FF 02 00 7C 00 D0 01 4C 00 B0 40 40 28 02   .....|...L..@@(.
0x0080:
$ 

または、次hexdump -Cの代わりに使用しodxます。

$ sh -x revdump.sh | hexdump -C
+ cut -c11-60 hexdump.out
+ awk '{  for (i = 1; i <= NF; i++)
        {
            #c = strtonum("0x" $i)
            #printf("%c", c);
            s = toupper($i)
            c0 = index("0123456789ABCDEF", substr(s, 1, 1)) - 1
            c1 = index("0123456789ABCDEF", substr(s, 2, 1)) - 1
            printf("%c", c0*16 + c1);
        }
     }'
00000000  3d 3d 01 fc 73 47 54 50  02 f1 d6 55 3c 9f 49 9c  |==..sGTP...U<.I.|
00000010  00 01 01 00 01 80 00 dc  ce 81 2f 00 00 00 00 00  |........../.....|
00000020  00 00 00 00 00 00 00 00  ca 04 d2 33 00 00 00 00  |...........3....|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 10  |................|
00000040  01 01 0f 00 00 07 04 ea  00 00 ff ff 00 00 14 b7  |................|
00000050  00 00 ff ff 00 00 83 ec  00 00 83 62 54 14 59 00  |...........bT.Y.|
00000060  60 38 34 f5 01 01 0b 58  62 70 11 60 f6 ff ff ff  |`84....Xbp.`....|
00000070  ff ff ff 02 00 7c 00 d0  01 4c 00 b0 40 40 28 02  |.....|...L..@@(.|
00000080
$
于 2011-11-27T02:39:41.600 に答える
1

いくつかのバイナリ データをテキスト形式で記述し、バイナリ ファイルを生成 (または stdout に出力) できるツールbinmakeがあります。エンディアンと数値形式を変更し、コメントを受け入れることができます。

最初にbinmakeを取得してコンパイルします(バイナリ プログラムは にありますbin/)。

$ git clone https://github.com/dadadel/binmake
$ cd binmake
$ make

テキスト ファイルを作成しますfile.txt

# an exemple of file description of binary data to generate
# set endianess to big-endian
big-endian

# default number is hexadecimal
00112233

# man can explicit a number type: %b means binary number
%b0100110111100000

# change endianess to little-endian
little-endian

# if no explicit, use default
44556677

# bytes are not concerned by endianess
88 99 aa bb

# change default to decimal
decimal

# following number is now decimal
0123

# strings are delimited by " or '
"this is some raw string"

# explicit hexa number starts with %x
%xff

バイナリ ファイルを生成しますfile.bin

$ ./binmake file.txt file.bin
$ hexdump file.bin -C
00000000  00 11 22 33 4d e0 77 66  55 44 88 99 aa bb 7b 74  |.."3M.wfUD....{t|
00000010  68 69 73 20 69 73 20 73  6f 6d 65 20 72 61 77 20  |his is some raw |
00000020  73 74 72 69 6e 67 ff                              |string.|
00000027

stdinandを使用してパイプすることもできますstdout

$ echo '32 decimal 32 %x61 61' | ./binmake | hexdump -C
00000000  32 20 61 3d                                       |2 a=|
00000004
于 2017-01-03T21:30:02.423 に答える
1

エンコーディングを File3 から File1 に変更するには、次のようなスクリプトを使用します。

#!/bin/bash

# file name: tobin.sh

fileName="tobin.txt"   # todo: pass it as parameter
                       #       or prepare it to be used via the pipe...
while read line; do
  for hexValue in $line; do
    echo -n -e "\x$hexValue"
  done
done < $fileName

または、単にパイプしたいだけで、このスレッドの xxd の例のように使用する場合:

#!/bin/bash

# file name: tobin.sh
# usage: cat file3.txt | ./tobin.sh > file1.bin

while read line; do
  for hexValue in $line; do
    echo -n -e "\x$hexValue"
  done
done

本当にこれに BASH を使用したい場合は、配列を使用してパケットを適切に構築することをお勧めします。開始コードは次のとおりです。

#!/bin/sh

# We assume the script will run on a LSB architecture.

hexDump() {
  for idx in $(seq 0 ${#buffer[@]}); do
    printf "%02X", ${buffer[$idx]}
  done
} # hexDump() function

###
# dump() dumps the current content of the buffer[] array to the STDOUT.
#
dump() {
  # or, use $ptr here...
  for idx in $(seq 0 ${#buffer[@]}); do
    printf "%c" ${buffer[$idx]}
  done
} # dump() function

# Beginning of DB Package Identifier: ==
buffer[0]=$'\x3d' # =
buffer[1]=$'\x3d' # =
size=2

# Total Package Length: 2
# We start with 2, and later on we update it once we know the exact size...
# Assuming 32bit architecture, LSB, this is how we encode number 2 (that is our current size of the packet)
buffer[2]=$'\x02'
buffer[3]=$'\x00'
buffer[4]=$'\x00'
buffer[5]=$'\x00'

# Offset to Data Record Count field: 115
# I assume this is also a 32bit field of unsigned int type
ptr=5
buffer[++ptr]=$'\x73'  # 115
buffer[++ptr]=$'\x00'
buffer[++ptr]=$'\x00'
buffer[++ptr]=$'\x00'

#hexDump
dump

出力:

$ ./tobin2.sh | hexdump -C
00000000  3d 3d 02 00 00 00 73 00  00 00 00                 |==....s....|
0000000b

確かに、これは元の投稿の解決策ではありません...解決策は、このようなものを使用してバイナリ出力を生成します。最大の問題は、パケット内のフィールドのタイプがまだわかっていないことです。また、アーキテクチャもわかりません (bigendian なのか、littleendian なのか、32bit なのか 64bit なのか)。仕様を提供する必要があります。たとえば、パッケージの長さはどのタイプですか? そのTXTファイルからはわかりません!

あなたがしなければならないことをするのを助けるために、それらのフィールドのサイズに関する仕様を見つける必要があります.

ただし、それは良いスタートであることに注意してください。たとえば、16 進値でエンコードされた文字列からの値で buffer[] を自動的に埋めるために、便利な関数を実装する必要があります。したがって、次のようなことができますwrite $offset "ff c0 d3 ba be"

于 2011-11-28T20:07:43.613 に答える
0

awk はここでの仕事には不適切なツールですが、それを行う方法は無数にあります。最も簡単な方法は、多くの場合、小さな C プログラム、または文字と 10 進数の文字列を明示的に区別するその他の言語です。

ただし、awk で行うには、「%c」printf 形式を使用します。

于 2011-11-10T21:03:45.343 に答える