2016-11-13 12 views
0

私はPEファイル構造とctypes構造についてもっと学びたいと思っています。ファイルからctypes構造を読み取る方法

この簡単な宣言を考える:

from ctypes import * 

class ImageDosHeader(Structure): 
    _fields_ = [ 
     ('e_magic', c_uint8, 2), 
     ('e_cblp', c_uint8, 2), 
     ('e_cp', c_uint8, 2), 
     ('e_crlc', c_uint8, 2), 
     ('e_cparhdr', c_uint8, 2), 
     ('e_minalloc', c_uint8, 2), 
     ('e_maxalloc', c_uint8, 2), 
     ('e_ss', c_uint8, 2), 
     ('e_sp', c_uint8, 2), 
     ('e_csum', c_uint8, 2), 
     ('e_ip', c_uint8, 2), 
     ('e_cs', c_uint8, 2), 
     ('e_lfarlc', c_uint8, 2), 
     ('e_ovno', c_uint8, 2), 
     ('e_res', c_uint8, 2), 
     ('e_oemid', c_uint8, 2), 
     ('e_oeminfo', c_uint8, 2), 
     ('e_res2', c_uint8, 2 * 10), 
     ('e_lfanew', c_uint8, 4), 
    ] 

Question1:ValueError: number of bits invalid for bit fieldを取得する理由は何私が質問のカップルを得ましたか。

私はこのような簡単な構造の読み取りしようとした場合:

class ImageDosHeader(Structure): 
    _fields_ = [ 
     ('e_magic', c_uint8, 2), 
    ] 


filename = 'example1_crinkler.exe' 
with open(filename, 'rb') as f: 
    record = ImageDosHeader() 
    f.readinto(record) 
    print(record.e_magic) 

print('-' * 80) 
with open(filename, 'rb') as f: 
    content = f.read() 
    print(binascii.hexlify(content)) 
print(len(content)) 

を、私はこの出力を取得しています:

1 
-------------------------------------------------------------------------------- 
b'4d5a3230504500004c01000001db617f10d017737547ebf9080002000b0111c94585c0791f01d350f7e2903d5c000000f7f339c119dbeb480000400004000000040000000fa32d320140008d0400ebce00000000ebb64206400000005331edbb0300000090be1c0140006a0158bf00004200b1009057eb1200000000000000005a72079229d1040029d060ad01f8742c6a0a5a89145489542410ad31ed4d4501c072fb74af60ac88c232076bc06f028700000000484f00d272ef75f9bf16104200b923e91f03730cf366ab0a06618d760e7bb7c3f7f18d3c5789e931c0ae74040007750241410fb61407d3e201548434487af385db7f0dd02c1f7503d0141ff7d3fe041f6146eb95e86aa6384b0b237bc66f82e9197a11121b13094ff4efbdfffeff7d96008180c090caeaefbdffffffffff44bec48b813eee1868379da18dcb827772cd7a49fe835cc82cc3850cb06603a8fff8e2d9becd3629b3268d3d6cb5ce9fd714516822c6dcc349482dc1e6868f92ed3df97e79469ad174b79b0479d9afb758dd7dd85c9218edef5ca0b47d5dd8aa46494ef4242201baeb2853c31d6f5ac630668462c5543f23a23616db595d1cd08993fce7231e8716b5f79480a1cacd10498fe4864843e744ae3e124c00e74af0173c8346860d98fb9882688c896737e07d3f16ee0d08238b0f0ed89553dbe2b177b64249ca712b9051e88c73' 
510 

Question2:なぜprint(record.e_magic)それは1を印刷していますか?私はそれが "MZ"、または0x4d5a、または19802であると期待します...しかし1ではなく、私はここで何が欠けていますか?

NS:私はそのパッケージが素晴らしいですが、私はちょうど、レコード:)

答えて

3

両方のために、それについても学ぶことのctypesを使って、ここで車輪の再発明をしたいのですが、pefileのは、PyPIパッケージまたはsimilarsの承知しています質問は同じ誤解を示すようです。 the ctypes documentation for Structure._fields_から引用:

c_intのような整数型フィールドの場合、3番目のオプション項目を指定できます。これは、フィールドのビット幅を定義する小さな正の整数でなければなりません。

これは、3番目のフィールドが値の数ではなくビットの数であることを意味します。したがって、あなたはがuint8の2ビット幅のフィールドであることを指示しました。 ValueErrorは、e_res2の8ビット値のうち20ビットを抽出しようとしています。 1の値は、'M'の下位2ビット:ord('M')&0b11 == 1からの値です。

16ビットフィールドの場合はc_uint162*c_charなどの他の構造タイプを作成するなど、一致するものを選択することでデータタイプを調整できます。 bit fieldを本当に扱っていない限り、3番目のエントリを使用しないでください。 ctypesはすでにその型のサイズを知っています。

+0

ほぼ。それは1バイト(オクテット)を読み取り、4ビットの2つのフィールド(e_magic〜e_crlc)に分割します。これらは合計8ビットになるためです。または、エラーが発生しなかった場合にはe_magicだけを持っていた例では、1バイトが読み込まれ、その中で上位6ビットは無視されます。 –

関連する問題