Skip to content

Commit ba44e8e

Browse files
author
John Andersen
committed
file: Change from class to functions
Fixes: #92 Signed-off-by: John Andersen <[email protected]>
1 parent 8ba4293 commit ba44e8e

File tree

5 files changed

+46
-56
lines changed

5 files changed

+46
-56
lines changed

cve_bin_tool/cli.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@
1919
import subprocess
2020
import logging
2121
import argparse
22-
import binascii
2322
import pkg_resources
2423

2524
from .util import DirWalk, inpath
2625
from .extractor import Extractor
2726
from .strings import Strings
28-
from .file import File
27+
from .file import is_binary
2928
from .NVDAutoUpdate import NVDSQLite
3029
from .log import LOGGER
3130

@@ -105,8 +104,7 @@ def scan_file(self, filename):
105104
raise InvalidFileError(filename)
106105

107106
# step 1: check if it's an ELF binary file
108-
f = File(filename)
109-
if not f.check():
107+
if not is_binary(filename):
110108
return None
111109
# parse binary file's strings
112110
s = Strings(filename)

cve_bin_tool/file.py

+26-45
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,31 @@
1-
#!/usr/bin/python3
2-
31
"""
4-
This is the customized file class, by doing this
5-
the tool is able to support other operating systems like Windows
6-
and MacOS.
2+
To determine if a file is executable we read the first few bytes of a file and
3+
check it against various signatures for different executable file formats.
74
"""
8-
9-
import string
105
import sys
11-
import platform
6+
import inspect
127
import binascii
138

14-
class File(object):
15-
16-
def __init__(self, filename = ''):
17-
self.filename = filename
18-
self.output = ''
19-
self.os = platform.system()
20-
self.signature = ''
21-
if filename == '':
22-
pass
23-
else:
24-
self.signature = self.read_signature().decode('utf-8')
25-
26-
def read_signature(self):
27-
# read signature (first 4 bytes) of the file
28-
with open(self.filename, 'rb') as f:
29-
byte = f.read(4)
30-
return binascii.hexlify(byte)
31-
32-
def check(self):
33-
# make sure class has signature before check
34-
if self.signature == '':
35-
self.signature = self.read_signature().decode('utf-8')
36-
return self.check_linux() or self.check_windows()
37-
38-
def check_linux(self):
39-
# by decoding we could ignore the affect caused by python version
40-
if sys.byteorder == 'little':
41-
return self.signature == '7f454c46'
42-
else:
43-
return self.signature == '457f464c'
44-
45-
def check_windows(self):
46-
# in windows/dos, the signature of exectuable is 0x5a4d
47-
if sys.byteorder == 'little':
48-
return self.signature[:4] == '4d5a'
49-
else:
50-
return self.signature[:4] == '5a4d'
9+
def is_binary(filename):
10+
""" Read the magic bytes from a file and determine if it is an executable
11+
binary."""
12+
signature = read_signature(filename)
13+
for name, method in inspect.getmembers(sys.modules[__name__],
14+
predicate=inspect.isfunction):
15+
if name.startswith('check_'):
16+
if method(filename, signature):
17+
return True
18+
return False
19+
20+
def read_signature(filename, length=4):
21+
""" Read the signature, first length bytes, from filename."""
22+
with open(filename, 'rb') as file_handle:
23+
return file_handle.read(length)
24+
25+
def check_elf(_filename, signature):
26+
""" Check for an ELF signature."""
27+
return signature == b'\x7f\x45\x4c\x46'
28+
29+
def check_pe(_filename, signature):
30+
""" Check for windows/dos PE signature, aka 0x5a4d."""
31+
return signature[:4] == b'\x4d\x5a'

test/assests/single-byte.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

test/assests/windows.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
MZ

test/test_file.py

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
"""
2-
CVE-bin-tool File tests
2+
CVE-bin-tool file tests
33
"""
44
import os
55
import sys
66
import unittest
77
import subprocess
88

9-
from cve_bin_tool.file import File
9+
from cve_bin_tool.file import is_binary
1010

11+
ASSETS_PATH = os.path.join(
12+
os.path.abspath(os.path.dirname(__file__)), 'assests')
1113
BINARIES_PATH = os.path.join(
1214
os.path.abspath(os.path.dirname(__file__)), 'binaries')
1315

14-
1516
class TestFile(unittest.TestCase):
16-
""" Tests the CVE Bin Tool Strings"""
17+
""" Tests the CVE Bin Tool file binary checker."""
1718

1819
@classmethod
1920
def setUpClass(cls):
2021
# build binaries
2122
subprocess.call(["make", "clean"], cwd=BINARIES_PATH)
2223
subprocess.call(["make", "all"], cwd=BINARIES_PATH)
23-
cls.file = File()
2424

2525
def _check_test(self, filename, is_executable):
2626
"""Helper function to parse a binary file and check whether
2727
the given string is in the parsed result"""
28-
self.file.filename = os.path.join(BINARIES_PATH, filename)
29-
self.assertEqual(self.file.check(), is_executable)
28+
self.assertEqual(is_binary(os.path.join(BINARIES_PATH, filename)),
29+
is_executable)
3030

3131
def test_curl_7_34_0_out(self):
3232
"""file test-curl-7.34.0.out"""
@@ -35,3 +35,12 @@ def test_curl_7_34_0_out(self):
3535
def test_curl_7_34_0_source(self):
3636
"""file test-curl-7.34.0.c"""
3737
self._check_test('test-curl-7.34.0.c', False)
38+
39+
def test_single_byte_file(self):
40+
"""file single-byte"""
41+
self.assertFalse(is_binary(os.path.join(ASSETS_PATH,
42+
'single-byte.txt')))
43+
44+
def test_windows(self):
45+
"""file single-byte"""
46+
self.assertTrue(is_binary(os.path.join(ASSETS_PATH, 'windows.txt')))

0 commit comments

Comments
 (0)