pythonのstructモジュールを触ってみる

CTFのwrteup等を読んでいるとシェルコードやバイナリの読み込み、書き出しに
pythonのstructモジュールを利用しているケースが多く、
自分は使ったことがなかったので、調べてまとめてみました。

structモジュールとは

structモジュール -公式-

このモジュールは、Python の値とPython上で文字列データとして表される
Cの構造体データとの間の変換を実現します。このモジュールでは、C構造体の
レイアウトおよびPythonの値との間で行いたい変換をコンパクトに表現するために
フォーマット文字列を使います。このモジュールは特に、ファイルに保存されたり
ネットワーク接続を経由したバイナリデータを扱うときに使われます。

なにやら書いてありますが、すんごくざっくり言うと、

  • 文字列(や数値) -> バイナリ (pack)
  • バイナリ -> 文字列(や数値) (unpack)

を行ってくれるモジュールらしいです。

基本的な使い方

よく使うメソッドは2つだけ!(全部で3つしかないっぽいけど)

フォーマットには

  • pack() -> 値をどのようなデータ型と評価してバイナリに変換するか
  • unpack() -> バイナリをどのようなデータ型に変換するか

をそれぞれ指定します。

こんな感じ。フォーマットの記述方法は後ほど。

フォーマット指定

format c data python size
pad bbyte no value
c char 長さ1の文字列 1
b signed char 整数型 1
B unsigned char 整数型 1
? _Bool 真偽値型 1
h short 整数型 1
H unsigned short 整数型 2
i int 整数型 4
I unsigned int 整数型 4
l long 整数型 4
L unsigned long 整数型 4
q long long 整数型 8
Q unsigned long long 整数型 8
f float 浮動小数点型 4
d double 浮動小数点型 8
s char[] 文字列
p char[] 文字列
P void* 整数型

この表を見ると、Cのデータ型とpythonのデータ型の相互変換に
利用できる、ということがわかりますね。
(単純にバイナリと値の相互変換というだけでなく)

文字列指定をするときはsやpの前に文字数を指定してやる必要が
あります。指定しないと1文字以上の文字列はエラーになっちゃいます。
文字列のサイズより大きな数字を指定したときは
nullバイトで埋められます。

フォーマット文字列の前に整数をつけると、繰り返しを表現できます。
ex) ‘4h’ == ‘hhhh’

バイトオーダー

リトルエンディアンとか、ビックエンディアンとか。

format byte order size alignment
@ native native native
= native standard none
< little endian standard none
> big endian standard none
! network standard none

指定がなければ@が利用され、ホストPCの環境にあわせてオートで
やってくれる。

対象のシステムでのエンディアンはsys.byteorderで調べることができます。

‘!’ 表記法はネットワークバイトオーダがビッグエンディアンかリトルエンディアンか忘れちゃったという熱意に乏しい人向けに用意されています。
python structモジュール 公式

だそうです。ありがとうございますありがとうございます。

アラインメントに関しては、僕も後で読む用に

データ型のアラインメントとは何か,なぜ必要なのか?

検証コード


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です