如何用Python 3.1.1获取dll的目标平台信息?

2 投票
1 回答
598 浏览
提问于 2025-04-15 16:55

我有很多dll文件,我想把它们分到两个不同的文件夹里(一个是PC,一个是PPC)。为此,我需要知道每个dll文件的目标平台或者其他一些关于它们平台的详细信息。

我使用的是Python 3.1.1。我尝试过使用win32api,但这个版本的Python不支持它。所以,我试着用ctypes.windll配合try-except的方法:如果try成功了,说明加载的dll是“PC”的;如果失败了,就说明是“PPC”的。但是,这个想法遇到了一些问题。

有些dll文件我知道是“PC”的,但却无法加载到内存中。对于这些文件,try-except的方法不起作用。所以,我需要从dll文件中请求关于它自身目标平台的信息。

你对这个问题有什么想法吗?

非常感谢。

1 个回答

1

我找到了一种基于dll文件结构的解决方案。下面是我代码的一部分:

def DLLIdentifier( self ):
    '''
     Microsoft Portable Executable and Common Object File Format Specification
     http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx 

     After the MS DOS stub, at the file offset specified at offset 0x3c, 
     is a 4-byte signature that identifies the file as a PE format image file. 
     This signature is "PE\0\0" (the letters "P" and "E" followed by two null bytes).
     At the beginning of an object file, or immediately after the signature of an image file, 
     is a standard COFF file header in the following format. 
     Note that the Windows loader limits the number of sections to 96.
     The Machine field has one of the following values that specifies its CPU type. 
     An image file can be run only on the specified machine or on a system that emulates the specified machine.
    '''
    Platform = 'UNKNOWN'
    for Row in codecs.open( os.path.join( self.Root, self.File ), 'rb' ):
        if b'\x00PE\x00\x00' in Row:
            # IMAGE_FILE_MACHINE_UNKNOWN      0x0         The contents of this field are assumed to be applicable to any machine type
            if b'\x00PE\x00\x00\x00\x00' in Row:
                Platform = 'UNKNOWN'
                break
            # IMAGE_FILE_MACHINE_AM33         0x1d3       Matsushita AM33
            elif b'\x00PE\x00\x00\xD3\x01' in Row:
                Platform = 'AM33'
                break
            # IMAGE_FILE_MACHINE_AMD64        0x8664      x64
            elif b'\x00PE\x00\x00\x664\x08' in Row:
                Platform = 'AMD64'
                break
            # IMAGE_FILE_MACHINE_ARM          0x1c0       ARM little endian
            elif b'\x00PE\x00\x00\xC0\x01' in Row:
                Platform = 'ARM'
                break
            # IMAGE_FILE_MACHINE_EBC          0xebc       EFI byte code
            elif b'\x00PE\x00\x00\xBC\x0E' in Row:
                Platform = 'EBC'
                break
            # IMAGE_FILE_MACHINE_I386         0x14c       Intel 386 or later processors and compatible processors
            elif b'\x00PE\x00\x00\x4C\x01' in Row:
                Platform = 'I386'
                break
            # IMAGE_FILE_MACHINE_IA64         0x200       Intel Itanium processor family
            elif b'\x00PE\x00\x00\x00\x02' in Row:
                Platform = 'IA64'
                break
            # IMAGE_FILE_MACHINE_M32R         0x9041      Mitsubishi M32R little endian
            elif b'\x00PE\x00\x00\x041\x09' in Row:
                Platform = 'M32R'
                break
            # IMAGE_FILE_MACHINE_MIPS16       0x266       MIPS16
            elif b'\x00PE\x00\x00\x66\x02' in Row:
                Platform = 'MIPS16'
                break
            # IMAGE_FILE_MACHINE_MIPSFPU      0x366       MIPS with FPU
            elif b'\x00PE\x00\x00\x66\x03' in Row:
                Platform = 'MIPSFPU'
                break
            # IMAGE_FILE_MACHINE_MIPSFPU16    0x466       MIPS16 with FPU
            elif b'\x00PE\x00\x00\x66\x04' in Row:
                Platform = 'MIPSFPU16'
                break
            # IMAGE_FILE_MACHINE_POWERPC      0x1f0       Power PC little endian
            elif b'\x00PE\x00\x00\xF0\x01' in Row:
                Platform = 'POWERPC'
                break
            # IMAGE_FILE_MACHINE_POWERPCFP    0x1f1       Power PC with floating point support
            elif b'\x00PE\x00\x00\xF1\x01' in Row:
                Platform = 'POWERPCFP'
                break
            # IMAGE_FILE_MACHINE_R4000        0x166       MIPS little endian
            elif b'\x00PE\x00\x00\x66\x01' in Row:
                Platform = 'R4000'
                break
            # IMAGE_FILE_MACHINE_SH3          0x1a2       Hitachi SH3
            elif b'\x00PE\x00\x00\xA2\x01' in Row:
                Platform = 'SH3'
                break
            # IMAGE_FILE_MACHINE_SH3DSP       0x1a3       Hitachi SH3 DSP
            elif b'\x00PE\x00\x00\xA3\x01' in Row:
                Platform = 'SH3DSP'
                break
            # IMAGE_FILE_MACHINE_SH4          0x1a6       Hitachi SH4
            elif b'\x00PE\x00\x00\xA6\x01' in Row:
                Platform = 'SH4'
                break
            # IMAGE_FILE_MACHINE_SH5          0x1a8       Hitachi SH5
            elif b'\x00PE\x00\x00\xA8\x01' in Row:
                Platform = 'SH5'
                break
            # IMAGE_FILE_MACHINE_THUMB        0x1c2       Thumb
            elif b'\x00PE\x00\x00\xC2\x01' in Row:
                Platform = 'THUMB'
                break
            # IMAGE_FILE_MACHINE_WCEMIPSV2    0x169       MIPS little - endian WCE v2
            elif b'\x00PE\x00\x00\x69\x01' in Row:
                Platform = 'WCEMIPSV2'
                break
            else:
                StartIndex = Row.find( b'\x00PE\x00\x00' )
                EndIndex = StartIndex + 7
                PlatformCode = Row[StartIndex:EndIndex]
                self.ErrorState = False
                self.oLogger.critical( 'The unknown platform code is "{}".'.format( PlatformCode ) )

    assert Platform != 'UNKNOWN', 'Unknown .dll file "{}" at\n{}'.format( self.File, os.path.join( self.Root, self.File ) )

    if Platform == 'I386':
        self.PlatformType = 'PC'
    elif Platform in ( 'ARM', 'THUMB' ):
        self.PlatformType = 'PPC'
    else:
        self.ErrorState = False
        self.oLogger.critical( 'The unknown dll file with "{}" platform code.'.format( Platform ) )

撰写回答