36 |
37 | [hide private]
39 |
40 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/pype32/caching.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Copyright (c) 2015, Sandor Nemes
5 | # All rights reserved.
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # * Redistributions of source code must retain the above copyright notice,
11 | # this list of conditions and the following disclaimer.
12 | # * Redistributions in binary form must reproduce the above copyright
13 | # notice,this list of conditions and the following disclaimer in the
14 | # documentation and/or other materials provided with the distribution.
15 | # * Neither the name of the copyright holder nor the names of its
16 | # contributors may be used to endorse or promote products derived from
17 | # this software without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | # POSSIBILITY OF SUCH DAMAGE.
30 |
31 | caches = {}
32 |
33 | class Cache(object):
34 |
35 | def __init__(self, name):
36 | self.name = name
37 | self.cache = {}
38 |
39 | def get(self, key):
40 | return self.cache.get(key)
41 |
42 | def put(self, key, value):
43 | self.cache.update({ key: value })
44 |
45 | def getCache(name):
46 | cache = caches.get(name)
47 | if cache is None:
48 | cache = Cache(name)
49 | caches[name] = cache
50 | return cache
51 |
52 | def cached(*ids):
53 | def decorator(func):
54 | def decorated(self, *args):
55 | funcname = "#".join([func.__name__] + [str(_) for _ in ids])
56 | cache = getCache(funcname)
57 | key = hash(args)
58 | result = cache.get(key)
59 | if result is None:
60 | result = func(self, *args)
61 | cache.put(key, result)
62 | return result
63 | return decorated
64 | return decorator
65 |
--------------------------------------------------------------------------------
/doc/toc-pype32.pype32-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | pype32
7 |
8 |
9 |
10 |
11 |
13 |
When javascript is enabled, this page will redirect URLs of
22 | the form redirect.html#dotted.name to the
23 | documentation for the object with the given fully-qualified
24 | dotted name.
74 |
75 | [hide private]
77 |
78 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Copyright (c) 2013, Nahuel Riva
5 | # All rights reserved.
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # * Redistributions of source code must retain the above copyright notice,
11 | # this list of conditions and the following disclaimer.
12 | # * Redistributions in binary form must reproduce the above copyright
13 | # notice,this list of conditions and the following disclaimer in the
14 | # documentation and/or other materials provided with the distribution.
15 | # * Neither the name of the copyright holder nor the names of its
16 | # contributors may be used to endorse or promote products derived from
17 | # this software without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | # POSSIBILITY OF SUCH DAMAGE.
30 |
31 | __revision__ = "$Id$"
32 |
33 | __all__ = ['metadata', 'setup']
34 |
35 | from distutils.core import setup
36 | from distutils import version
37 | from warnings import warn
38 |
39 | import re
40 | import os
41 | import sys
42 | import glob
43 |
44 | # Distutils hack: in order to be able to build MSI installers with loose
45 | # version numbers, we subclass StrictVersion to accept loose version numbers
46 | # and convert them to the strict format. This works because Distutils will
47 | # happily reinstall a package even if the version number matches exactly the
48 | # one already installed on the system - so we can simply strip all extraneous
49 | # characters and beta/postrelease version numbers will be treated just like
50 | # the base version number.
51 | if __name__ == '__main__':
52 | StrictVersion = version.StrictVersion
53 | class NotSoStrictVersion (StrictVersion):
54 | def parse (self, vstring):
55 | components = []
56 | for token in vstring.split('.'):
57 | token = token.strip()
58 | match = re.search('^[0-9]+', token)
59 | if match:
60 | number = token[ match.start() : match.end() ]
61 | components.append(number)
62 | vstring = '.'.join(components)
63 | return StrictVersion.parse(self, vstring)
64 | version.StrictVersion = NotSoStrictVersion
65 |
66 | # Get the base directory
67 | here = os.path.dirname(__file__)
68 | if not here:
69 | here = os.path.curdir
70 |
71 | # Text describing the module (reStructured text)
72 | try:
73 | readme = os.path.join(here, 'README')
74 | long_description = open(readme, 'r').read()
75 | except Exception:
76 | warn("README file not found or unreadable!")
77 | long_description = """pype32 is python library to read and write PE/PE+ binary files."""
78 |
79 | # Get the list of scripts in the "tools" folder
80 | scripts = glob.glob(os.path.join(here, 'tools', '*.py'))
81 |
82 | # Set the parameters for the setup script
83 | metadata = {
84 |
85 | # Setup instructions
86 | 'provides' : ['pype32'],
87 | 'packages' : ['pype32'],
88 | 'scripts' : scripts,
89 |
90 | # Metadata
91 | 'name' : 'pype32',
92 | 'version' : '0.1-alpha5',
93 | 'description' : 'Yet another Python library to read and write PE/PE+ files.',
94 | 'long_description' : long_description,
95 | 'author' : 'Nahuel Riva',
96 | 'author_email' : 'crackinglandia'+chr(64)+'gmail'+chr(0x2e)+'com',
97 | 'url' : 'https://github.com/crackinglandia/pype32',
98 | 'keywords' : ['pecoff', 'x86', 'x64', '.net', 'parser'],
99 | 'download_url' : 'https://github.com/crackinglandia/pype32/tarball/v0.1-alpha5',
100 | }
101 |
102 | # Execute the setup script
103 | if __name__ == '__main__':
104 | setup(**metadata)
105 |
--------------------------------------------------------------------------------
/html/redirect.html:
--------------------------------------------------------------------------------
1 | Epydoc Redirect Page
2 |
3 |
4 |
5 |
6 |
7 |
8 |
18 |
19 |
Epydoc Auto-redirect page
20 |
21 |
When javascript is enabled, this page will redirect URLs of
22 | the form redirect.html#dotted.name to the
23 | documentation for the object with the given fully-qualified
24 | dotted name.
105 |
106 | [hide private]
108 |
109 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/pype32/excep.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Copyright (c) 2013, Nahuel Riva
5 | # All rights reserved.
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # * Redistributions of source code must retain the above copyright notice,
11 | # this list of conditions and the following disclaimer.
12 | # * Redistributions in binary form must reproduce the above copyright
13 | # notice,this list of conditions and the following disclaimer in the
14 | # documentation and/or other materials provided with the distribution.
15 | # * Neither the name of the copyright holder nor the names of its
16 | # contributors may be used to endorse or promote products derived from
17 | # this software without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | # POSSIBILITY OF SUCH DAMAGE.
30 |
31 | """
32 | Exceptions used by the entire library.
33 |
34 | @group Base exceptions:
35 | PyPe32Exception, PyPe32Warning
36 |
37 | @group Warnings:
38 | PEWarning
39 |
40 | @group Exceptions:
41 | PEException,NotValidPathException,WrongOffsetValueException,DirectoryEntriesLengthException,
42 | TypeNotSupportedException,ArrayTypeException,DataLengthException,ReadDataOffsetException,
43 | WriteDataOffsetException,InstanceErrorException,DataMismatchException,SectionHeadersException,
44 | DirectoryEntryException,InvalidParameterException
45 | """
46 |
47 | __revision__ = "$Id$"
48 |
49 | __all__ = [
50 | "PyPe32Exception",
51 | "PyPe32Warning",
52 | "PEWarning",
53 | "PEException",
54 | "NotValidPathException",
55 | "WrongOffsetValueException",
56 | "DirectoryEntriesLengthException",
57 | "TypeNotSupportedException",
58 | "ArrayTypeException",
59 | "DataLengthException",
60 | "ReadDataOffsetException",
61 | "WriteDataOffsetException",
62 | "InstanceErrorException",
63 | "DataMismatchException",
64 | "SectionHeadersException",
65 | "DirectoryEntryException",
66 | "InvalidParameterException",
67 | ]
68 |
69 | class PyPe32Exception(Exception):
70 | """Base exception class."""
71 | pass
72 |
73 | class PyPe32Warning(Exception):
74 | """Base warning class."""
75 | pass
76 |
77 | class PEWarning(PyPe32Warning):
78 | """Raised when a suspicious value is found into the PE instance."""
79 | pass
80 |
81 | class PEException(PyPe32Exception):
82 | """Raised when an invalid field on the PE instance was found."""
83 | pass
84 |
85 | class NotValidPathException(PyPe32Exception):
86 | """Raised when a path wasn't found or it is an invalid path."""
87 | pass
88 |
89 | class WrongOffsetValueException(PyPe32Exception):
90 | """
91 | Used primary by the L{ReadData} and L{WriteData} object in read/write operations when an invalid
92 | offset value was used.
93 | """
94 | pass
95 |
96 | class DirectoryEntriesLengthException(PyPe32Exception):
97 | """Raised when the the number of entries in a L{DataDirectory} object is different from L{consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES}."""
98 | pass
99 |
100 | class TypeNotSupportedException(PyPe32Exception):
101 | """This exception must be used when an invalid data type is used within the library."""
102 | pass
103 |
104 | class ArrayTypeException(PyPe32Exception):
105 | """Raised when creating an unsupported type of array."""
106 | pass
107 |
108 | class DataLengthException(PyPe32Exception):
109 | """Raised when data lengths does not match."""
110 | pass
111 |
112 | class ReadDataOffsetException(PyPe32Exception):
113 | """This exception must be raised when reading from an invalid offset."""
114 | pass
115 |
116 | class WriteDataOffsetException(PyPe32Exception):
117 | """This exception must be raised when writing to an invalid offset."""
118 | pass
119 |
120 | class InstanceErrorException(PyPe32Exception):
121 | """This exception is raised when an instance parameter was not specified."""
122 | pass
123 |
124 | class DataMismatchException(PyPe32Exception):
125 | """Raised when two different types of data does not match."""
126 | pass
127 |
128 | class SectionHeadersException(PyPe32Exception):
129 | """Raised when an error related to a L{pype32.SectionHeader} or L{pype32.SectionHeaders} is found."""
130 | pass
131 |
132 | class DirectoryEntryException(PyPe32Exception):
133 | """This exception must be raised when an error with the L{Directory} is found."""
134 | pass
135 |
136 | class InvalidParameterException(PyPe32Exception):
137 | """Raised when an invalid parameter is received."""
138 | pass
139 |
140 |
--------------------------------------------------------------------------------
/doc/toc-pype32.directories-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | directories
7 |
8 |
9 |
10 |
11 |
13 |
127 |
128 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/pype32/datadirs.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | # Copyright (c) 2013, Nahuel Riva
5 | # All rights reserved.
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | #
10 | # * Redistributions of source code must retain the above copyright notice,
11 | # this list of conditions and the following disclaimer.
12 | # * Redistributions in binary form must reproduce the above copyright
13 | # notice,this list of conditions and the following disclaimer in the
14 | # documentation and/or other materials provided with the distribution.
15 | # * Neither the name of the copyright holder nor the names of its
16 | # contributors may be used to endorse or promote products derived from
17 | # this software without specific prior written permission.
18 | #
19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | # POSSIBILITY OF SUCH DAMAGE.
30 |
31 | """
32 | Data directory classes.
33 | """
34 |
35 | __revision__ = "$Id$"
36 |
37 | __all__ = [
38 | "Directory",
39 | "DataDirectory",
40 | ]
41 |
42 | import consts
43 | import excep
44 | import datatypes
45 |
46 | from struct import pack
47 |
48 | dirs = ["EXPORT_DIRECTORY","IMPORT_DIRECTORY","RESOURCE_DIRECTORY","EXCEPTION_DIRECTORY","SECURITY_DIRECTORY",\
49 | "RELOCATION_DIRECTORY","DEBUG_DIRECTORY","ARCHITECTURE_DIRECTORY","RESERVED_DIRECTORY","TLS_DIRECTORY",\
50 | "CONFIGURATION_DIRECTORY","BOUND_IMPORT_DIRECTORY","IAT_DIRECTORY","DELAY_IMPORT_DIRECTORY","NET_METADATA_DIRECTORY",\
51 | "RESERVED_DIRECTORY"]
52 |
53 | class Directory(object):
54 | """Directory object."""
55 | def __init__(self, shouldPack = True):
56 | """
57 | Class representation of the C{IMAGE_DATA_DIRECTORY} structure.
58 | @see: U{http://msdn.microsoft.com/es-es/library/windows/desktop/ms680305%28v=vs.85%29.aspx}
59 |
60 | @type shouldPack: bool
61 | @param shouldPack: If set to C{True} the L{Directory} object will be packed. If set to C{False} the object won't be packed.
62 | """
63 | self.name = datatypes.String("")
64 | self.rva = datatypes.DWORD(0) #: L{DWORD} rva.
65 | self.size = datatypes.DWORD(0) #: L{DWORD} size.
66 | self.info = None #: This variable holds the information of the directory.
67 | self.shouldPack = shouldPack
68 |
69 | def __str__(self):
70 | return str(self.rva) + str(self.size)
71 |
72 | def __len__(self):
73 | return len(str(self))
74 |
75 | def __dir__(self):
76 | return sorted(self.__dict__.keys())
77 |
78 | @staticmethod
79 | def parse(readDataInstance):
80 | """
81 | Returns a L{Directory}-like object.
82 |
83 | @type readDataInstance: L{ReadData}
84 | @param readDataInstance: L{ReadData} object to read from.
85 |
86 | @rtype: L{Directory}
87 | @return: L{Directory} object.
88 | """
89 | d = Directory()
90 | d.rva.value = readDataInstance.readDword()
91 | d.size.value = readDataInstance.readDword()
92 | return d
93 |
94 | def getType(self):
95 | """Returns a value that identifies the L{Directory} object."""
96 | return consts.IMAGE_DATA_DIRECTORY
97 |
98 | class DataDirectory(list):
99 | """DataDirectory object."""
100 | def __init__(self, shouldPack = True):
101 | """
102 | Array of L{Directory} objects.
103 |
104 | @type shouldPack: bool
105 | @param shouldPack: If set to C{True} the L{DataDirectory} object will be packed. If set to C{False} the object won't packed.
106 | """
107 | self.shouldPack = shouldPack
108 |
109 | for i in range(consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES):
110 | dir = Directory()
111 | dir.name.value = dirs[i]
112 | self.append(dir)
113 |
114 | def __str__(self):
115 | packedRvasAndSizes = ""
116 | for directory in self:
117 | packedRvasAndSizes += str(directory)
118 | return packedRvasAndSizes
119 |
120 | @staticmethod
121 | def parse(readDataInstance):
122 | """Returns a L{DataDirectory}-like object.
123 |
124 | @type readDataInstance: L{ReadData}
125 | @param readDataInstance: L{ReadData} object to read from.
126 |
127 | @rtype: L{DataDirectory}
128 | @return: The L{DataDirectory} object containing L{consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES} L{Directory} objects.
129 |
130 | @raise DirectoryEntriesLengthException: The L{ReadData} instance has an incorrect number of L{Directory} objects.
131 | """
132 | if len(readDataInstance) == consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES * 8:
133 | newDataDirectory = DataDirectory()
134 | for i in range(consts.IMAGE_NUMBEROF_DIRECTORY_ENTRIES):
135 | newDataDirectory[i].name.value = dirs[i]
136 | newDataDirectory[i].rva.value = readDataInstance.readDword()
137 | newDataDirectory[i].size.value = readDataInstance.readDword()
138 | else:
139 | raise excep.DirectoryEntriesLengthException("The IMAGE_NUMBEROF_DIRECTORY_ENTRIES does not match with the length of the passed argument.")
140 | return newDataDirectory
141 |
142 |
--------------------------------------------------------------------------------
/html/toc-pype32.directories-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | directories
7 |
8 |
9 |
10 |
11 |
13 |