class IMAGE_RESOURCE_DIRECTORY(pstruct.type): _fields_ = [ (dword, 'Characteristics'), (TimeDateStamp, 'TimeDateStamp'), (word, 'MajorVersion'), (word, 'MinorVersion'), (word, 'NumberOfNamedEntries'), (word, 'NumberOfIdEntries'), (lambda self: dyn.clone(IMAGE_RESOURCE_DIRECTORY_NAME, length=self['NumberOfNamedEntries'].li.int()), 'Names'), (lambda self: dyn.clone(IMAGE_RESOURCE_DIRECTORY_ID, length=self['NumberOfIdEntries'].li.int()), 'Ids'), ] def iterate(self): names = (item.Name() for item in self['Names']) identifiers = (item.Name() for item in self['Ids']) return itertools.chain(names, identifiers) def list(self): return [item for item in self.iterate()] def entry(self, name): iterable = (item['Entry'].d for item in itertools.chain(iter(self['Names']), iter(self['Ids'])) if name == item.Name()) return next(iterable, None) # aliases Iterate = iterate List = list Entry = entry
class IMAGE_COR20_HEADER(pstruct.type): def blocksize(self): return self['cb'].li.int() _fields_ = [ (pint.uint32_t, 'cb'), (pint.uint16_t, 'MajorRuntimeVersion'), (pint.uint16_t, 'MinorRuntimeVersion'), (dyn.clone(IMAGE_DATA_DIRECTORY, _object_=MetaDataRoot), 'MetaData'), (CORIMAGE_FLAGS_, 'Flags'), (pint.uint32_t, 'EntryPoint'), (dyn.clone(IMAGE_DATA_DIRECTORY, _object_=lambda s: dyn.blockarray( ResourceInfo, s.getparent(IMAGE_DATA_DIRECTORY)['Size'].li.int())), 'Resources'), (IMAGE_DATA_DIRECTORY, 'StrongNameSignature'), (IMAGE_DATA_DIRECTORY, 'CodeManagerTable'), (dyn.clone(IMAGE_DATA_DIRECTORY, _object_=lambda s: dyn.blockarray( VtableFixup, s.getparent(IMAGE_DATA_DIRECTORY)['Size'].li.int())), 'VTableFixups'), (IMAGE_DATA_DIRECTORY, 'ExportAddressTableJumps'), (IMAGE_DATA_DIRECTORY, 'ManagedNativeHeader'), ]
def __e_data(self): e_ident = self['e_ident'].li type = e_ident['EI_CLASS'].int() order = e_ident['EI_DATA'].order() if type == 1: return dyn.clone(header.Elf32_Ehdr, recurse=dict(byteorder=order)) elif type == 2: return dyn.clone(header.Elf64_Ehdr, recurse=dict(byteorder=order)) raise ValueError(type)
def __Index(self): htables = self.getparent(HTables) # get indices of all tables that tag can point into indices = self.Tables() # figure out the maximum number of rows for the tables specified by self.Tag res = htables['Rows'].li count = max(res[index].int() for index in indices) # return a uint16_t if the tagged index is able to store the maximum number of rows otherwise use a uint32_t return dyn.clone(pint.uint_t, length=1) if count < 2**( 16 - self.Tag.width) else dyn.clone(pint.uint_t, length=3)
class record0085(pstruct.type): _fields_ = [ (pint.uint16_t, 'unknown'), (pint.uint32_t, 'skipped'), (pint.uint16_t, 'sheetname_length'), (lambda s: dyn.clone(pstr.wstring, length=s['sheetname_length'].li.int()), 'sheetname'), ]
def _object_(self): res = self.getparent(StreamHdr) cb = res['Size'].int() t = Stream.withdefault(res['Name'].str(), blocksize=lambda s, cb=cb: cb) if issubclass(t, parray.block): return dyn.clone(t, blocksize=lambda s, cb=cb: cb) return t
class IMAGE_RESOURCE_DIRECTORY_STRING(pstruct.type): _fields_ = [ (word, 'Length'), (lambda s: dyn.clone(pstr.wstring, length=s['Length'].li.int()), 'String') ] def str(self): return self['String'].str()
def _object_(self): res = self.getparent(HTables) index, lengths = len(self.value), res['Rows'].li count = lengths[index].int() if count: cls = self.__class__ logging.debug( "{:s} : {:s} : Loading {:s}({:d}) table with {:d} rows. : {:d} of {:d}" .format('.'.join((res.typename(), cls.__name__)), self.instance(), TableType.byvalue(index, 'undefined'), index, count, 1 + len(self.value), self.length)) rowtype = Table.withdefault(index, type=index) rowsize = rowtype.PreCalculateSize(res) if Table.has(index) else 0 tr, tn = TableRow.__name__, TableType.byvalue(index, None) t = dyn.clone( TableRow, _object_=rowtype, _value_=dyn.block(rowsize), typename=classmethod(lambda cls: "{:s}({:s})".format(tr, tn) if tn else tr)) def Get(self, index): if index > 0: return self[index - 1] raise IndexError(index) return dyn.array(t, count, Get=Get, blocksize=(lambda s, cb=rowsize * count: cb))
class IMAGE_BASERELOC_DIRECTORY_ENTRY(pstruct.type): _fields_ = [ (uint32, 'Page RVA'), # FIXME: this can be a virtualaddress(...) to the page (uint32, 'Size'), (lambda s: dyn.clone(BaseRelocationBlock, length=s['Size'].li.int() - 8), 'Relocations'), # (lambda s: dyn.clone(pbinary.blockarray,_object_=BaseRelocationEntry, blockbits=lambda _:(s['Size'].li.int()-8)*8), 'Relocations') # (lambda s: dyn.clone(BaseRelocationArray, blocksize=lambda _:s['Size'].li.int()-8), 'Relocations') ] def extract(self): '''Return a list of tuples containing the relocation type and offset contained within this entry.''' block = self['Relocations'].serialize() relocations = array.array( 'I' if len(array.array('I', 4 * b'\0')) > 1 else 'H', block) return [((item & 0xf000) // 0x1000, item & 0x0fff) for item in relocations] def getrelocations(self, section): pageoffset = self['Page RVA'].int() - section['VirtualAddress'].int() if not (pageoffset >= 0 and pageoffset < section.getloadedsize()): raise AssertionError( "Page Offset in RVA outside bounds of section : not(0 <= {:#x} < {:#x}) : Page RVA {:#x}, VA = {:#x}, Section = {:s}" .format(pageoffset, section.getloadedsize(), self['Page RVA'].int(), section['VirtualAddress'].int(), section['Name'].str())) for type, offset in self.extract(): if type == 0: continue yield type, pageoffset + offset return
def __Children(self): bs = self['wLength'].li.num() - self.blocksize() assert bs >= 0,bs class Member(pstruct.type): _fields_ = [ (dyn.align(4), 'Padding'), (self.Child(), 'Child'), ] return dyn.clone(parray.block, _object_=Member, blocksize=lambda s:bs)
class FileAuxiliaryRecord(pstruct.type): type = 103 _fields_ = [ #(dyn.block(18), 'File Name') (dyn.clone(pstr.string, length=18), 'File Name') ] def summary(self): return ptypes.utils.strdup(self['File Name'].str(), terminator='\0')
def __IAT(self): res = IMAGE_IMPORT_ADDRESS_TABLE64 if self.getparent( Header)['OptionalHeader'].is64() else IMAGE_IMPORT_ADDRESS_TABLE if hasattr(ptypes.provider, 'Ida') and self.source is ptypes.provider.Ida: entry = self.getparent(IMAGE_DELAYLOAD_DIRECTORY_ENTRY) count = entry['DINT'].li.d.l return dyn.clone(res, length=len(count)) return res
class IMAGE_DEBUG_DATA_CODEVIEW(pstruct.type): type = IMAGE_DEBUG_TYPE_.byname('CODEVIEW') def __Info(self): res = self['Signature'].li.serialize() return CodeViewInfo.lookup(res) _fields_ = [ (dyn.clone(pstr.string, length=4), 'Signature'), (__Info, 'Info'), ]
class IMAGE_DEBUG_DATA_MISC(pstruct.type): type = IMAGE_DEBUG_TYPE_.byname('MISC') _fields_ = [ (IMAGE_DEBUG_MISC_, 'DataType'), (uint32, 'Length'), (uint8, 'Unicode'), (dyn.block(3), 'align(Unicode)'), (lambda s: dyn.clone(pstr.wstring if s['Unicode'].int() else pstr.string, length=s['Length'].li.int()), 'Data'), ]
def __Index(self): htables = self.getparent(HTables) # get indices of all tables that tag can point into indices = self.Tables() # figure out the maximum number of rows for the tables specified by self.Tag res = htables['Rows'].li count = max(res[index].int() for index in indices) # return a uint16_t if the tagged index is able to store the maximum number of rows otherwise use a uint32_t return dyn.clone(pint.uint_t, length=1) if count < 2**(16 - self.Tag.width) else dyn.clone(pint.uint_t, length=3)
class ResourceString(pstruct.type): _fields_ = [ (EncodedInteger, 'Length'), (lambda s: dyn.clone(pstr.string, length=s['Length'].li.int()), 'Name'), ] def str(self): return self['Name'].str() def summary(self): return "{:d} {!r}".format(self['Length'].int(), self['Name'].str())
class SerString(pstruct.type): _fields_ = [ (CInt, 'length'), (lambda s: dyn.clone(pstr.string, length=s['length'].li.Get()), 'string'), ] def str(self): return self['string'].str() def summary(self): return '{:d} : {!r}'.format(self['length'].Get(), self['string'].str())
class MetaDataRoot(pstruct.type): class _Signature(pint.uint32_t): def properties(self): res = super(MetaDataRoot._Signature, self).properties() res['valid'] = self.valid() return res def valid(self): return self.int() == 0x424a5342 class _StreamHeaders(parray.type): _object_ = StreamHdr def Get(self, name): res = next((stream for stream in self if stream.Name() == name), None) if res is None: raise NameError(name) return res def __StreamHeaders(self): res = self['Streams'].li.int() return dyn.clone(self._StreamHeaders, length=res) def __StreamData(self): cb = self.getparent(IMAGE_DATA_DIRECTORY)['Size'].int() total = sum(self[n].li.size() for _, n in self._fields_[:-1]) res = max((0, cb - total)) return dyn.block(res) @pbinary.littleendian class StorageFlags(pbinary.flags): _fields_ = [ (15, 'Reserved'), (1, 'ExtraData'), ] _fields_ = [ (_Signature, 'Signature'), (pint.uint16_t, 'MajorVersion'), (pint.uint16_t, 'MinorVersion'), (pint.uint32_t, 'Reserved'), (pint.uint32_t, 'Length'), (lambda s: dyn.clone(pstr.string, length=s['Length'].li.int()), 'Version'), (dyn.align(4), 'aligned(Version)'), (StorageFlags, 'Flags'), (pint.uint16_t, 'Streams'), (__StreamHeaders, 'StreamHeaders'), (__StreamData, 'StreamData'), ]
def __Children(self): fields = self._fields_[:-1] length, cb = self['wLength'].li.int(), sum(self[name].li.size() for _, name in fields) if cb > length: raise AssertionError("Invalid block size returned for child: {:d}".format(bs)) ct = self.__ChildType() class Member(pstruct.type): _fields_ = [ (dyn.align(4), 'Padding'), (ct, 'Child'), ] return dyn.clone(parray.block, _object_=Member, blocksize=lambda s, bs=length-cb:bs)
def __Children(self): fields = ['wLength', 'wValueLength', 'wType', 'szKey', 'Alignment', 'Value'] length, cb = self['wLength'].li.int(), sum(self[fld].li.size() for fld in fields) if cb > length: raise AssertionError("Invalid block size returned for child: {:d}".format(bs)) ct = self.__ChildType() class Member(pstruct.type): _fields_ = [ (dyn.align(4), 'Alignment'), (ct, 'Child'), ] return dyn.clone(parray.block, _object_=Member, blocksize=lambda self, bs=length - cb: bs)
class IMAGE_RESOURCE_DIRECTORY(pstruct.type): _fields_ = [ (dword, 'Characteristics'), (TimeDateStamp, 'TimeDateStamp'), (word, 'MajorVersion'), (word, 'MinorVersion'), (word, 'NumberOfNames'), (word, 'NumberOfIds'), (lambda s: dyn.clone(IMAGE_RESOURCE_DIRECTORY_NAME, length=s['NumberOfNames'].li.int()), 'Names'), (lambda s: dyn.clone(IMAGE_RESOURCE_DIRECTORY_ID, length=s['NumberOfIds'].li.int()), 'Ids'), ] def Iterate(self): return itertools.chain((n.Name() for n in self['Names']), (n.Name() for n in self['Ids'])) def List(self): return list(self.Iterate()) def Entry(self, name): iterable = (n['Entry'].d for n in itertools.chain(iter(self['Names']), iter(self['Ids'])) if name == n.Name()) return next(iterable, None) # aliases iterate = Iterate list = List entry = Entry
class IMAGE_DEBUG_DATA_CODEVIEW(pstruct.type): type = IMAGE_DEBUG_TYPE_.byname('CODEVIEW') def __Info(self): res = self['Signature'].li.serialize() return CodeViewInfo.lookup(res) def __Extra(self): bs, res = self.blocksize(), sum(self[fld].li.size() for fld in ['Signature', 'Info']) return dyn.block(max(0, bs - res)) _fields_ = [ (dyn.clone(pstr.string, length=4), 'Signature'), (__Info, 'Info'), (__Extra, 'Extra'), ]
class IMAGE_DEBUG_DATA_MISC(pstruct.type): type = IMAGE_DEBUG_TYPE_.byname('MISC') def __Extra(self): bs, res = self.blocksize(), sum( self[fld].li.size() for fld in ['DataType', 'Length', 'Unicode', 'align(Unicode)', 'Data']) return dyn.block(max(0, bs - res)) _fields_ = [ (IMAGE_DEBUG_MISC_, 'DataType'), (DWORD, 'Length'), (BYTE, 'Unicode'), (dyn.block(3), 'align(Unicode)'), (lambda self: dyn.clone(pstr.wstring if self['Unicode'].int() else pstr.string, length=self['Length'].li.int()), 'Data'), (__Extra, 'Extra'), ]
class TryBlockMapEntry(pstruct.type): class _pHandlerArray(parray.type): _object_ = HandlerType def details(self): items = [] for item in self: position = ptypes.utils.repr_position(item.getposition()) description = ptypes.utils.repr_instance( item.classname(), item.name()) res = item['adjectives'] iterable = (fld if item[fld] in {1} else "{:s}={:#x}".format( fld, item[fld]) for fld in item if item[fld]) adjectives = '|'.join(iterable) or "{:#x}".format(res.int()) if item['dispFrame'].int(): res = "[{:s}] {:s} dispCatchObj={:+#x} dispFrame={:+#x} addressOfHandler={:#x} adjectives={:s}".format( position, description, item['dispCatchObj'].int(), item['dispFrame'].int(), item['addressOfHandler'].int(), adjectives) else: res = "[{:s}] {:s} dispCatchObj={:+#x} addressOfHandler={:#x} adjectives={:s}".format( position, description, item['dispCatchObj'].int(), item['addressOfHandler'].int(), adjectives) items.append(res) return '\n'.join(items) def repr(self): if self.initializedQ(): return self.details() + '\n' return self.summary() _fields_ = [ (int32, 'tryLow'), (int32, 'tryHigh'), (int32, 'catchHigh'), (int32, 'nCatches'), (lambda self: virtualaddress(dyn.clone( self._pHandlerArray, length=self['nCatches'].li.int()), type=dword), 'pHandlerArray'), ]
def _object_(self): res = self.getparent(HTables) index, lengths = len(self.value), res['Rows'].li count = lengths[index].int() if count: cls = self.__class__ logging.debug("{:s} : {:s} : Loading {:s}({:d}) table with {:d} rows. : {:d} of {:d}".format('.'.join((res.typename(),cls.__name__)), self.instance(), TableType.byvalue(index, 'undefined'), index, count, 1+len(self.value), self.length)) rowtype = Table.withdefault(index, type=index) rowsize = rowtype.PreCalculateSize(res) if Table.has(index) else 0 tr, tn = TableRow.__name__, TableType.byvalue(index, None) t = dyn.clone(TableRow, _object_=rowtype, _value_=dyn.block(rowsize), typename=classmethod(lambda cls: "{:s}({:s})".format(tr, tn) if tn else tr)) def Get(self, index): if index > 0: return self[index - 1] raise IndexError(index) return dyn.array(t, count, Get=Get, blocksize=(lambda s, cb=rowsize*count: cb))
def Value(self): # wValueLength = number of 16-bit words of wValue l = self['wValueLength'].li.num() return dyn.clone(pstr.wstring, length=l)
def __Address(self): t = self._object_ if ptypes.iscontainer(t): return self.addressing(dyn.clone(t, blocksize=lambda s: s.getparent(IMAGE_DATA_DIRECTORY)['Size'].li.int()), type=uint32) return self.addressing(t, type=uint32)
def Type(self): l = self['wValueLength'].li.int() return dyn.clone(parray.block, _object_=dword, blocksize=lambda s:l)
def Value(self): l = self['wValueLength'].li.num() return dyn.clone(parray.block, _object_=dword, blocksize=lambda s:l)
def _object_(self): res = self.getparent(Header)['OptionalHeader'].li res = loader.IMAGE_LOADCONFIG_DIRECTORY64 if res.is64() else loader.IMAGE_LOADCONFIG_DIRECTORY return dyn.clone(res, blocksize=lambda s, cb=self['Size'].li.int(): cb)
def Type(self): # wValueLength = number of 16-bit words of wValue l = self['wValueLength'].li.int() return dyn.clone(pstr.wstring, length=l)
def _object_(self): res = self.getparent(Header)['OptionalHeader'].li res = loader.IMAGE_LOADCONFIG_DIRECTORY64 if res.is64( ) else loader.IMAGE_LOADCONFIG_DIRECTORY return dyn.clone(res, blocksize=lambda s, cb=self['Size'].li.int(): cb)
def __StreamHeaders(self): res = self['Streams'].li.int() return dyn.clone(self._StreamHeaders, length=res)
def __data(self): cb = self['length'].li.Get() return dyn.clone(pstr.wstring, length= cb / 2)
def __Data(self): res = self.blocksize() - sum(self[n].li.size() for n in ('Manager', 'Reader')) return dyn.clone(self.ResourceData, _value_=dyn.block(res), _object_=self._ResourceData)
def __Address(self): t = self._object_ if ptypes.iscontainer(t): return self.addressing(dyn.clone(t, blocksize=lambda s: s.getparent(Entry)["Size"].li.num()), type=uint32) return self.addressing(t, type=uint32)
class IMAGE_SECTION_HEADER(pstruct.type): """PE Executable Section Table Entry""" class IMAGE_SCN(pbinary.flags): _fields_ = [ (1, 'MEM_WRITE'), # 0x80000000 (1, 'MEM_READ'), # 0x40000000 (1, 'MEM_EXECUTE'), # 0x20000000 (1, 'MEM_SHARED'), # 0x10000000 (1, 'MEM_NOT_PAGED'), # 0x08000000 (1, 'MEM_NOT_CACHED'), # 0x04000000 (1, 'MEM_DISCARDABLE'), # 0x02000000 (1, 'LNK_NRELOC_OVFL'), # 0x01000000 # (1, 'ALIGN_8192BYTES'), # 0x00e00000 # (1, 'ALIGN_4096BYTES'), # 0x00d00000 # (1, 'ALIGN_2048BYTES'), # 0x00c00000 # (1, 'ALIGN_1024BYTES'), # 0x00b00000 # (1, 'ALIGN_512BYTES'), # 0x00a00000 # (1, 'ALIGN_256BYTES'), # 0x00900000 # (1, 'ALIGN_128BYTES'), # 0x00800000 # (1, 'ALIGN_64BYTES'), # 0x00700000 # (1, 'ALIGN_32BYTES'), # 0x00600000 # (1, 'ALIGN_16BYTES'), # 0x00500000 # (1, 'ALIGN_8BYTES'), # 0x00400000 # (1, 'ALIGN_4BYTES'), # 0x00300000 # (1, 'ALIGN_2BYTES'), # 0x00200000 # (1, 'ALIGN_1BYTES'), # 0x00100000 (4, 'ALIGN'), # 0x00?00000 (1, 'MEM_PRELOAD'), # 0x00080000 (1, 'MEM_LOCKED'), # 0x00040000 # (1, 'MEM_16BIT'), # 0x00020000 # ARM (1, 'MEM_PURGEABLE'), # 0x00020000 (1, 'reserved_16'), (1, 'GPREL'), # 0x00008000 (2, 'reserved_14'), (1, 'LNK_COMDAT'), # 0x00001000 (1, 'LNK_REMOVE'), # 0x00000800 (1, 'reserved_11'), (1, 'LNK_INFO'), # 0x00000200 (1, 'LNK_OTHER'), # 0x00000100 (1, 'CNT_UNINITIALIZED_DATA'), # 0x00000080 (1, 'CNT_INITIALIZED_DATA'), # 0x00000040 (1, 'CNT_CODE'), # 0x00000020 (1, 'reserved_4'), (1, 'TYPE_NO_PAD'), # 0x00000008 (3, 'reserved_0'), ] # FIXME: we can store a longer than 8 byte Name if we want to implement code that navigates to the string table # apparently executables don't care though... _fields_ = [ (dyn.clone(pstr.string, length=8), 'Name'), (uint32, 'VirtualSize'), (virtualaddress(lambda s:dyn.block(s.parent.getloadedsize()), type=uint32), 'VirtualAddress'), (uint32, 'SizeOfRawData'), (fileoffset(lambda s:dyn.block(s.parent.getreadsize()), type=uint32), 'PointerToRawData'), (fileoffset(lambda s:dyn.array(relocations.MachineRelocation.lookup(s.getparent(Header).Machine().int()), s.parent['NumberOfRelocations'].li.int()), type=uint32), 'PointerToRelocations'), (fileoffset(lambda s:dyn.array(linenumbers.LineNumber, s.parent['NumberOfLinenumbers'].li.int()), type=uint32), 'PointerToLinenumbers'), (uint16, 'NumberOfRelocations'), (uint16, 'NumberOfLinenumbers'), (pbinary.littleendian(IMAGE_SCN), 'Characteristics'), ] def getreadsize(self): portable = self.getparent(SectionTableArray) # if it's a portable executable, then apply the alignment try: nt = portable.p alignment = nt['OptionalHeader']['FileAlignment'].int() mask = alignment - 1 # otherwise, there's no alignment necessary except KeyError: mask = 0 res = (self['SizeOfRawData'].int() + mask) & ~mask return min((self.source.size() - self['PointerToRawData'].int(), res)) if hasattr(self.source, 'size') else res def getloadedsize(self): # XXX: even though the loadedsize is aligned to SectionAlignment, # the loader doesn't actually map data there and thus the # actual mapped size is rounded to pagesize # nt = self.getparent(Header) # alignment = nt['OptionalHeader']['SectionAlignment'].int() alignment = 0x1000 # pagesize mask = alignment - 1 return (self['VirtualSize'].int() + mask) & ~mask def containsaddress(self, address): start = self['VirtualAddress'].int() return True if (address >= start) and (address < start + self.getloadedsize()) else False def containsoffset(self, offset): start = self['PointerToRawData'].int() return True if (offset >= start) and (offset < start + self.getreadsize()) else False def data(self): return self['PointerToRawData'].d getrelocations = lambda self: self['PointerToRelocations'].d getlinenumbers = lambda self: self['NumberOfLinenumbers'].d ## offset means file offset def getoffsetbyaddress(self, address): return address - self['VirtualAddress'].int() + self['PointerToRawData'].int() def getaddressbyoffset(self, offset): return offset - self['PointerToRawData'].int() + self['VirtualAddress'].int()
def __Symbols(self): p = self.getparent(Header) header = p.FileHeader() return dyn.clone(SymbolTable, length=header['NumberOfSymbols'].int())
import ptypes from ptypes import pint,pfloat,dyn class Header(object): pass ## primitives byte = dyn.clone(pint.uint8_t) word = dyn.clone(pint.uint16_t) dword = dyn.clone(pint.uint32_t) float = dyn.clone(pfloat.single) double = dyn.clone(pfloat.double) uint8 = dyn.clone(pint.uint8_t) int8 = dyn.clone(pint.int8_t) int16 = dyn.clone(pint.int16_t) uint16 = dyn.clone(pint.uint16_t) int32 = dyn.clone(pint.int32_t) uint32 = dyn.clone(pint.uint32_t) uint64 = dyn.clone(pint.uint64_t) class off_t(pint.uint32_t): pass class addr_t(pint.uint32_t): pass import datetime class TimeDateStamp(uint32): epoch = datetime.datetime(1970, 1, 1, 0, 0, 0) def details(self): x = self.epoch + datetime.timedelta( seconds=int(self) ) return x.strftime('%Y-%m-%d %H:%M:%S') def summary(self): return '0x{:x} {!r}'.format(self.num(), self.details())
import ptypes, datetime, time from ptypes import pstruct, parray, ptype, dyn, pstr, pint, pfloat, pbinary ## primitives byte = dyn.clone(pint.uint8_t) word = dyn.clone(pint.uint16_t) dword = dyn.clone(pint.uint32_t) float = dyn.clone(pfloat.single) double = dyn.clone(pfloat.double) uint0 = dyn.clone(pint.uint_t) int0 = dyn.clone(pint.int_t) uint8 = dyn.clone(pint.uint8_t) int8 = dyn.clone(pint.int8_t) int16 = dyn.clone(pint.int16_t) uint16 = dyn.clone(pint.uint16_t) int32 = dyn.clone(pint.int32_t) uint32 = dyn.clone(pint.uint32_t) uint64 = dyn.clone(pint.uint64_t) class off_t(pint.uint32_t): pass class addr_t(pint.uint32_t): pass class VOID(ptype.undefined): pass