如何使用头文件签名(幻数)检查文件类型?

问题描述 投票:0回答:2

通过输入文件及其扩展名,我的代码成功地从“幻数”中检测到文件的类型。

magic_numbers = {'png': bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
                 'jpg': bytes([0xFF, 0xD8, 0xFF, 0xE0]),
                 #*********************#
                 'doc': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
                 'xls': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
                 'ppt': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
                 #*********************#
                 'docx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
                 'xlsx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
                 'pptx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
                 #*********************#
                 'pdf': bytes([0x25, 0x50, 0x44, 0x46]),
                 #*********************#
                 'dll': bytes([0x4D, 0x5A, 0x90, 0x00]),
                 'exe': bytes([0x4D, 0x5A]),

                 }

max_read_size = max(len(m) for m in magic_numbers.values()) 
 
with open('file.pdf', 'rb') as fd:
    file_head = fd.read(max_read_size)
 
if file_head.startswith(magic_numbers['pdf']):
    print("It's a PDF File")
else:
    print("It's not a PDF file")

我想知道如何在不指定这部分代码的情况下修改它,即一旦我生成或输入文件,它就会直接显示文件的类型。

if file_head.startswith(magic_numbers['pdf']):
    print("It's a PDF File")
else:
    print("It's not a PDF file")

希望你能理解我。

python header-files detection file-type magic-numbers
2个回答
1
投票

您最想只想迭代循环并测试所有它们。

您也可以通过使用扩展来优化或提供一些错误检查。如果您去掉扩展名并首先检查,大多数情况下您都会成功,否则您可能不想接受“baby.png”作为 xlsx 文件。这将是可疑的并且值得犯错误。

但是,如果您忽略扩展名,只需循环遍历条目即可:

for ext in magic_numbers:
    if file_head.startswith(magic_numbers[ext]):
        print("It's a {} File".format(ext))

您可能想将其放入返回类型的函数中,这样您就可以只返回类型而不是将其打印出来。

编辑 由于有些共享幻数,我们需要假设扩展是正确的,直到我们知道它不正确。我将从文件名中提取扩展名。这可以通过

Pathlib
或仅字符串分割来完成:

ext = filename.rsplit('.', 1)[-1]

那就具体测试一下吧

if ext in magic_numbers:
    if file_head.startswith(magic_numbers[ext]):
        return ext

首先进行外部测试,所以将它们放在一起:

ext = filename.rsplit('.', 1)[-1]
if ext in magic_numbers:
    if file_head.startswith(magic_numbers[ext]):
        return ext

for ext in magic_numbers:
    if file_head.startswith(magic_numbers[ext]):
        return ext

return nil

0
投票

因此,我尝试迭代 magic_numbers 并使用文件扩展名来确认正确的数字。这对我有用,希望对其他人有帮助。

from tkinter import filedialog as di

#Defines Magic Numbers by file type for comparison

magic_numbers = {'png': bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
                 'jpg': bytes([0xFF, 0xD8, 0xFF, 0xE0]),
                 #*********************#
                 'doc': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
                 'xls': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
                 'ppt': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
                 #*********************#
                 'docx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
                 'xlsx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
                 'pptx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
                 #*********************#
                 'pdf': bytes([0x25, 0x50, 0x44, 0x46]),
                 #*********************#
                 'dll': bytes([0x4D, 0x5A, 0x90, 0x00]),
                 'exe': bytes([0x4D, 0x5A]),

                 }



max_read_size = max(len(m) for m in magic_numbers.values())

#Get file from user
def open_file_selection():
    file = di.askopenfile()
    return file.name

#File Scan, opens file in binary and grabs relevant code
with open(open_file_selection(), 'rb') as fd:
    file_head = fd.read(max_read_size)
    print(file_head)
    

#Compares file to magic numbers to determine file type
for ext in magic_numbers:
    if file_head.startswith(magic_numbers[ext]) and fd.name.rsplit('.', 1)[-1] == ext:
        print(f"It's a {ext} File")
© www.soinside.com 2019 - 2024. All rights reserved.