Parses the rich header see http://www.ntcore.com/files/richsign.htm for more information Structure: 00 DanS ^ checksum, checksum, checksum, checksum 10 Symbol RVA ^ checksum, Symbol size ^ checksum... ... XX Rich, checksum, 0, 0,...
(self)
| 3188 | self.full_load() |
| 3189 | |
| 3190 | def parse_rich_header(self): |
| 3191 | """Parses the rich header |
| 3192 | see http://www.ntcore.com/files/richsign.htm for more information |
| 3193 | |
| 3194 | Structure: |
| 3195 | 00 DanS ^ checksum, checksum, checksum, checksum |
| 3196 | 10 Symbol RVA ^ checksum, Symbol size ^ checksum... |
| 3197 | ... |
| 3198 | XX Rich, checksum, 0, 0,... |
| 3199 | """ |
| 3200 | |
| 3201 | # Rich Header constants |
| 3202 | # |
| 3203 | DANS = 0x536E6144 # 'DanS' as dword |
| 3204 | RICH = 0x68636952 # 'Rich' as dword |
| 3205 | |
| 3206 | rich_index = self.__data__.find( |
| 3207 | b"Rich", 0x80, self.OPTIONAL_HEADER.get_file_offset() |
| 3208 | ) |
| 3209 | if rich_index == -1: |
| 3210 | return None |
| 3211 | |
| 3212 | # Read a block of data |
| 3213 | try: |
| 3214 | # The end of the structure is 8 bytes after the start of the Rich |
| 3215 | # string. |
| 3216 | rich_data = self.__data__[0x80 : rich_index + 8] |
| 3217 | # Make the data have length a multiple of 4, otherwise the |
| 3218 | # subsequent parsing will fail. It's not impossible that we retrieve |
| 3219 | # truncated data that it's not a multiple. |
| 3220 | rich_data = rich_data[: 4 * int(len(rich_data) / 4)] |
| 3221 | data = list( |
| 3222 | struct.unpack("<{0}I".format(int(len(rich_data) / 4)), rich_data) |
| 3223 | ) |
| 3224 | if RICH not in data: |
| 3225 | return None |
| 3226 | except PEFormatError: |
| 3227 | return None |
| 3228 | |
| 3229 | # get key, raw_data and clear_data |
| 3230 | key = struct.pack("<L", data[data.index(RICH) + 1]) |
| 3231 | result = {"key": key} |
| 3232 | |
| 3233 | raw_data = rich_data[: rich_data.find(b"Rich")] |
| 3234 | result["raw_data"] = raw_data |
| 3235 | |
| 3236 | ord_ = lambda c: ord(c) if not isinstance(c, int) else c |
| 3237 | |
| 3238 | clear_data = bytearray() |
| 3239 | for idx, val in enumerate(raw_data): |
| 3240 | clear_data.append((ord_(val) ^ ord_(key[idx % len(key)]))) |
| 3241 | result["clear_data"] = bytes(clear_data) |
| 3242 | |
| 3243 | # the checksum should be present 3 times after the DanS signature |
| 3244 | # |
| 3245 | checksum = data[1] |
| 3246 | if data[0] ^ checksum != DANS or data[2] != checksum or data[3] != checksum: |
| 3247 | return None |