2016-11-13 7 views
0

Ich versuche, mehr über PE-Dateien Strukturen und auch Ctypes Strukturen zu lernen. Ich habe ein paar Fragen:wie Ctypes Strukturen aus Datei zu lesen

Da diese einfache Erklärung:

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: Was ist der Grund ValueError: number of bits invalid for bit field zu bekommen ist?

Wenn ich versuche, eine vereinfachte Struktur wie folgt zu lesen:

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)) 

Ich erhalte diese Ausgabe:

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

Question2: warum print(record.e_magic) es 1 Druck ist? Ich würde erwarten, dass es "MZ" oder 0x4d5a oder 19802 ist ... aber nicht 1, was fehlt mir hier?

NS: Ich bin mir dessen bewusst pefile pypi Paket oder similars, dass Paket ist genial, aber ich möchte hier das Rad mit ctypes neu zu erfinden, auch darüber zu lernen, nur für die Aufzeichnung :)

Antwort

3

Both Fragen scheinen auf das gleiche Missverständnis hinzudeuten. Zitieren von the ctypes documentation for Structure._fields_:

Für Integer-Felder wie c_int kann ein drittes optionales Element angegeben werden. Es muss eine kleine positive Ganzzahl sein, die die Bitbreite des Feldes definiert.

Das dritte Feld ist die Anzahl der Bits, nicht die Anzahl der Werte. Sie haben also angewiesen, dass e_magic ein 2 Bit breites Feld innerhalb einer uint8 ist. Die ValueError stammt aus dem Versuch, 20 Bits aus einem 8-Bit-Wert in e_res2 zu extrahieren. Der 1 Wert kam von den niedrigsten zwei Bits von 'M': ord('M')&0b11 == 1.

Sie können Ihre Datentypen anpassen, indem Sie besser passende auswählen, wie c_uint16 für die 16-Bit-Felder, oder andere Strukturtypen wie 2*c_char erstellen. Vermeiden Sie die Verwendung des dritten Eintrags, es sei denn, Sie beschäftigen sich wirklich mit einem bit field; Ctypes kennt bereits die Größe seiner Typen.

+0

Fast. Es liest 1 Byte (Oktett) und teilt es dann in vier 2-Bit-Felder auf: e_magic bis e_crlc, da sie insgesamt 8 Bits ergeben. Oder es würde, wenn der Fehler nicht auftritt. In dem Beispiel, in dem Sie nur e_magic hatten, wurde 1 Byte gelesen, in dem die oberen 6 Bits ignoriert werden. –