0
# Resource Analysis
1
2
Access to embedded resources including strings, icons, version information, and other resource types. PE files can contain various resources embedded within the file structure for use by the application.
3
4
## Capabilities
5
6
### Resource Directory Parsing
7
8
Parse and navigate the resource directory tree structure.
9
10
```python { .api }
11
def parse_resources_directory(self, rva, size=0, base_rva=None, level=0, dirs=None):
12
"""
13
Parse resources directory at specified RVA.
14
15
Args:
16
rva (int): RVA of resource directory
17
size (int): Size of resource directory
18
base_rva (int, optional): Base RVA for resource calculations
19
level (int): Current directory level (0=type, 1=name, 2=language)
20
dirs (list, optional): List to collect directory entries
21
22
Populates:
23
self.DIRECTORY_ENTRY_RESOURCE: ResourceDirData object with resource tree
24
"""
25
```
26
27
### String Resource Extraction
28
29
Extract string resources embedded in the PE file.
30
31
```python { .api }
32
def get_resources_strings(self):
33
"""
34
Get all strings from string table resources.
35
36
Returns:
37
list: List of tuples (language_id, string_id, string_value)
38
39
Note:
40
Extracts strings from RT_STRING resource type, commonly used
41
for application messages, error text, and UI strings.
42
"""
43
```
44
45
### Version Information Parsing
46
47
Parse version information resources containing file metadata.
48
49
```python { .api }
50
def parse_version_information(self, version_struct):
51
"""
52
Parse version information structure.
53
54
Args:
55
version_struct: Version information resource structure
56
57
Returns:
58
dict: Parsed version information including:
59
- FileVersion, ProductVersion
60
- CompanyName, FileDescription
61
- InternalName, OriginalFilename
62
- ProductName, LegalCopyright
63
- And other version fields
64
"""
65
```
66
67
## Usage Examples
68
69
### Basic Resource Analysis
70
71
```python
72
import pefile
73
74
with pefile.PE('executable.exe') as pe:
75
# Check if resources are present
76
if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
77
print("Resource Analysis:")
78
print("-" * 40)
79
80
# Walk resource tree
81
for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
82
# Resource type (RT_ICON, RT_STRING, etc.)
83
if resource_type.name is not None:
84
type_name = resource_type.name
85
else:
86
type_name = pefile.RESOURCE_TYPE.get(resource_type.struct.Id,
87
f"Unknown({resource_type.struct.Id})")
88
89
print(f"\nResource Type: {type_name}")
90
91
# Resource names/IDs within this type
92
if hasattr(resource_type, 'directory'):
93
for resource_id in resource_type.directory.entries:
94
if resource_id.name is not None:
95
id_name = resource_id.name
96
else:
97
id_name = f"ID_{resource_id.struct.Id}"
98
99
print(f" Resource: {id_name}")
100
101
# Language versions
102
if hasattr(resource_id, 'directory'):
103
for resource_lang in resource_id.directory.entries:
104
lang_id = resource_lang.struct.Id
105
lang_name = pefile.LANG.get(lang_id >> 10, f"Lang_{lang_id >> 10}")
106
sublang_id = lang_id & 0x3ff
107
108
print(f" Language: {lang_name} (0x{lang_id:04x})")
109
110
# Get resource data
111
data_rva = resource_lang.data.struct.OffsetToData
112
data_size = resource_lang.data.struct.Size
113
print(f" Data: RVA=0x{data_rva:08x}, Size={data_size}")
114
else:
115
print("No resources found")
116
```
117
118
### String Resource Extraction
119
120
```python
121
import pefile
122
123
with pefile.PE('executable.exe') as pe:
124
# Extract string resources
125
strings = pe.get_resources_strings()
126
127
if strings:
128
print("String Resources:")
129
print("-" * 40)
130
131
for lang_id, string_id, string_value in strings:
132
# Decode language info
133
lang_name = pefile.LANG.get(lang_id >> 10, f"Unknown_{lang_id >> 10}")
134
sublang_id = lang_id & 0x3ff
135
136
print(f"Language: {lang_name} (0x{lang_id:04x})")
137
print(f"String ID: {string_id}")
138
print(f"Value: {repr(string_value)}")
139
print()
140
else:
141
print("No string resources found")
142
```
143
144
### Version Information Analysis
145
146
```python
147
import pefile
148
149
def extract_version_info(pe):
150
"""Extract and display version information."""
151
if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
152
return None
153
154
# Look for version information resource
155
for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
156
if resource_type.struct.Id == pefile.RESOURCE_TYPE['RT_VERSION']:
157
for resource_id in resource_type.directory.entries:
158
for resource_lang in resource_id.directory.entries:
159
# Get version data
160
data_rva = resource_lang.data.struct.OffsetToData
161
data_size = resource_lang.data.struct.Size
162
data = pe.get_data(data_rva, data_size)
163
164
# Parse version information
165
version_info = pe.parse_version_information(data)
166
return version_info
167
168
return None
169
170
# Usage
171
with pefile.PE('executable.exe') as pe:
172
version_info = extract_version_info(pe)
173
174
if version_info:
175
print("Version Information:")
176
print("-" * 30)
177
178
# Display common version fields
179
common_fields = [
180
'FileVersion', 'ProductVersion', 'CompanyName',
181
'FileDescription', 'InternalName', 'OriginalFilename',
182
'ProductName', 'LegalCopyright'
183
]
184
185
for field in common_fields:
186
if field in version_info:
187
value = version_info[field]
188
if isinstance(value, bytes):
189
value = value.decode('utf-8', errors='ignore')
190
print(f"{field}: {value}")
191
else:
192
print("No version information found")
193
```
194
195
### Icon Resource Extraction
196
197
```python
198
import pefile
199
200
def extract_icons(pe, output_dir='icons'):
201
"""Extract icon resources from PE file."""
202
import os
203
204
if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
205
return []
206
207
os.makedirs(output_dir, exist_ok=True)
208
extracted_icons = []
209
210
# Find icon resources
211
for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
212
if resource_type.struct.Id == pefile.RESOURCE_TYPE['RT_ICON']:
213
print("Found icon resources:")
214
215
for resource_id in resource_type.directory.entries:
216
icon_id = resource_id.struct.Id
217
218
for resource_lang in resource_id.directory.entries:
219
lang_id = resource_lang.struct.Id
220
221
# Get icon data
222
data_rva = resource_lang.data.struct.OffsetToData
223
data_size = resource_lang.data.struct.Size
224
icon_data = pe.get_data(data_rva, data_size)
225
226
# Save icon file
227
filename = f"{output_dir}/icon_{icon_id}_{lang_id:04x}.ico"
228
with open(filename, 'wb') as f:
229
f.write(icon_data)
230
231
extracted_icons.append(filename)
232
print(f" Extracted icon {icon_id}: {filename} ({data_size} bytes)")
233
234
elif resource_type.struct.Id == pefile.RESOURCE_TYPE['RT_GROUP_ICON']:
235
print("Found icon group resources (metadata)")
236
237
return extracted_icons
238
239
# Usage
240
with pefile.PE('executable.exe') as pe:
241
icons = extract_icons(pe)
242
print(f"Extracted {len(icons)} icons")
243
```
244
245
### Manifest Resource Analysis
246
247
```python
248
import pefile
249
import xml.etree.ElementTree as ET
250
251
def extract_manifest(pe):
252
"""Extract and parse application manifest."""
253
if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
254
return None
255
256
# Look for manifest resource (RT_MANIFEST = 24)
257
for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
258
if resource_type.struct.Id == 24: # RT_MANIFEST
259
for resource_id in resource_type.directory.entries:
260
for resource_lang in resource_id.directory.entries:
261
# Get manifest data
262
data_rva = resource_lang.data.struct.OffsetToData
263
data_size = resource_lang.data.struct.Size
264
manifest_data = pe.get_data(data_rva, data_size)
265
266
try:
267
# Parse XML manifest
268
manifest_text = manifest_data.decode('utf-8')
269
return manifest_text
270
except UnicodeDecodeError:
271
# Try other encodings
272
try:
273
manifest_text = manifest_data.decode('utf-16')
274
return manifest_text
275
except:
276
return manifest_data # Return raw data
277
278
return None
279
280
# Usage
281
with pefile.PE('executable.exe') as pe:
282
manifest = extract_manifest(pe)
283
284
if manifest:
285
print("Application Manifest:")
286
print("-" * 30)
287
288
if isinstance(manifest, str):
289
# Try to parse XML for better display
290
try:
291
root = ET.fromstring(manifest)
292
293
# Extract key information
294
print("Manifest parsed successfully")
295
296
# Look for UAC level
297
for elem in root.iter():
298
if 'level' in elem.attrib:
299
print(f"UAC Level: {elem.attrib['level']}")
300
if 'uiAccess' in elem.attrib:
301
print(f"UI Access: {elem.attrib['uiAccess']}")
302
303
print("\nFull manifest:")
304
print(manifest)
305
306
except ET.ParseError:
307
print("Manifest (not valid XML):")
308
print(manifest)
309
else:
310
print("Manifest (binary data):")
311
print(manifest[:200], "..." if len(manifest) > 200 else "")
312
else:
313
print("No manifest found")
314
```
315
316
### Resource Statistics
317
318
```python
319
import pefile
320
321
def resource_statistics(pe):
322
"""Generate statistics about resources in PE file."""
323
if not hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
324
print("No resources found")
325
return
326
327
stats = {}
328
total_size = 0
329
330
# Count resources by type
331
for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
332
if resource_type.name is not None:
333
type_name = str(resource_type.name)
334
else:
335
type_name = pefile.RESOURCE_TYPE.get(resource_type.struct.Id,
336
f"Type_{resource_type.struct.Id}")
337
338
type_count = 0
339
type_size = 0
340
341
if hasattr(resource_type, 'directory'):
342
for resource_id in resource_type.directory.entries:
343
if hasattr(resource_id, 'directory'):
344
for resource_lang in resource_id.directory.entries:
345
type_count += 1
346
size = resource_lang.data.struct.Size
347
type_size += size
348
total_size += size
349
350
stats[type_name] = {'count': type_count, 'size': type_size}
351
352
# Display statistics
353
print("Resource Statistics:")
354
print("-" * 50)
355
print(f"{'Type':<20} {'Count':<8} {'Size':<12} {'Percentage':<10}")
356
print("-" * 50)
357
358
for type_name, info in sorted(stats.items()):
359
count = info['count']
360
size = info['size']
361
percentage = (size / total_size * 100) if total_size > 0 else 0
362
363
print(f"{type_name:<20} {count:<8} {size:<12} {percentage:.1f}%")
364
365
print("-" * 50)
366
print(f"{'Total':<20} {sum(s['count'] for s in stats.values()):<8} {total_size:<12} 100.0%")
367
368
# Usage
369
with pefile.PE('executable.exe') as pe:
370
resource_statistics(pe)
371
```