dod-cyber-crime-center / DC3-MWCP

DC3 Malware Configuration Parser (DC3-MWCP) is a framework for parsing configuration information from malware. The information extracted from malware includes items such as addresses, passwords, filenames, and mutex names.
Other
300 stars 59 forks source link

Pecon's PE object initialization is broken #25

Closed tamas-boczan closed 4 years ago

tamas-boczan commented 4 years ago

Pecon's recommended way to initialize a PE object results in an error. https://github.com/Defense-Cyber-Crime-Center/DC3-MWCP/blob/586707c7e98275a2177afd3d49af0ad79b127c29/mwcp/utils/pecon.py#L8

>>> from mwcp.utils import pecon
>>> pe = pecon.PE()
Traceback (most recent call last):
  File "<venv_path>\lib\site-packages\mwcp\utils\construct\version28.py", line 565, in _sizeof
    return sum(sc._sizeof(nest(context, sc), path) for sc in self.subcons)
  File "<venv_path>\lib\site-packages\mwcp\utils\construct\version28.py", line 565, in <genexpr>
    return sum(sc._sizeof(nest(context, sc), path) for sc in self.subcons)
  File "<venv_path>\lib\site-packages\construct\core.py", line 2476, in _sizeof
    return self.subcon._sizeof(context, path)
  File "<venv_path>\lib\site-packages\construct\core.py", line 3605, in _sizeof
    condfunc = condfunc(context)
  File "<venv_path>\lib\site-packages\construct\expr.py", line 160, in __call__
    lhs = self.lhs(obj) if callable(self.lhs) else self.lhs
  File "<venv_path>\lib\site-packages\construct\expr.py", line 188, in __call__
    return self.__parent(obj)[self.__field]
KeyError: 'Magic'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<venv_path>\lib\site-packages\mwcp\utils\pecon.py", line 284, in __init__
    'SizeOfOptionalHeader': construct.IMAGE_OPTIONAL_HEADER.sizeof(NumberOfRvaAndSizes=16),
  File "<venv_path>\lib\site-packages\construct\core.py", line 398, in sizeof
    return self._sizeof(context, "(sizeof)")
  File "<venv_path>\lib\site-packages\mwcp\utils\construct\version28.py", line 567, in _sizeof
    raise SizeofError("cannot calculate size, key not found in context")
construct.core.SizeofError: cannot calculate size, key not found in context

The exception happens because the initialization of the PE object attempts to calculate the size of the IMAGE_OPTIONAL_HEADER struct to set the SizeOfOptionalHeader variable. The size depends on whether the binary is 32-bit of 64-bit, set by the Magic value of the struct. This Magic value is not provided, causing the crash. https://github.com/Defense-Cyber-Crime-Center/DC3-MWCP/blob/586707c7e98275a2177afd3d49af0ad79b127c29/mwcp/utils/pecon.py#L284

Simply providing the constant for the 32-bit option fixes the crash, but limits the library to generating 32-bit PE files.

'SizeOfOptionalHeader': construct.IMAGE_OPTIONAL_HEADER.sizeof(Magic=IMAGE_NT_OPTIONAL_HDR32_MAGIC, NumberOfRvaAndSizes=16),

To overcome the 32-bit limitation, constants also need to be changed in other places where it was assumed that the binary is 32-bit and the constant was hard-coded (often with an attached TODO comment):

Perhaps the architecture of the PE file should be an argument of the PE object constructor, allowing setting the right constants for the architecture.