Last active
October 6, 2024 20:09
-
-
Save utkonos/86585b85a313a2e41d33471c22cc26c6 to your computer and use it in GitHub Desktop.
View any resources in PE EXE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "f948162c-7083-4959-a9f3-ca5680058269", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import enum\n", | |
"import hashlib\n", | |
"import itertools\n", | |
"import pathlib\n", | |
"import subprocess" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "dcee1abb-dfc6-4c0e-b0fa-38309cb0df53", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import pefile" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "1f2fe99f-9afb-49d3-aad3-132bff543b3f", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class ResourceType(enum.Enum):\n", | |
" RT_CURSOR = 1\n", | |
" RT_BITMAP = 2\n", | |
" RT_ICON = 3\n", | |
" RT_MENU = 4\n", | |
" RT_DIALOG = 5\n", | |
" RT_STRING = 6\n", | |
" RT_FONTDIR = 7\n", | |
" RT_FONT = 8\n", | |
" RT_ACCELERATOR = 9\n", | |
" RT_RCDATA = 10\n", | |
" RT_MESSAGETABLE = 11\n", | |
" RT_GROUP_CURSOR = 12\n", | |
" RT_GROUP_ICON = 14\n", | |
" RT_VERSION = 16\n", | |
" RT_DLGINCLUDE = 17\n", | |
" RT_PLUGPLAY = 19\n", | |
" RT_VXD = 20\n", | |
" RT_ANICURSOR = 21\n", | |
" RT_ANIICON = 22\n", | |
" RT_HTML = 23\n", | |
" RT_MANIFEST = 24" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "48368ca6-1fcf-4910-918a-65452b6d410f", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"resource_type = ResourceType.RT_MANIFEST\n", | |
"local = False" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "310e45a9-cdfd-47b7-8232-895865782fe2", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"target = pathlib.Path('example.exe')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "8091302d-7ceb-4bb1-89d2-9bd12335918f", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"target.exists()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "069134c4-00ec-4e33-83ab-3a75240b0e43", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"if local:\n", | |
" process = subprocess.run(['hexf', target], capture_output=True)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "450a33c8-813d-4524-a8e8-56a1b3c452af", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"if local:\n", | |
" process = subprocess.run(['010editor \"{}\"'.format(str(target))], capture_output=True, shell=True)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "71b6113a-3b88-4672-a7a6-2519da194abc", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"pe = pefile.PE(target)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "5ce7e833-f1d2-4970-9fb5-dc36fc87936b", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_sections(pe):\n", | |
" sections = list()\n", | |
" for section in pe.sections:\n", | |
" va = section.VirtualAddress\n", | |
" end = section.VirtualAddress + section.SizeOfRawData\n", | |
" ptrd = section.PointerToRawData\n", | |
" sections.append((va, end, ptrd, ))\n", | |
"\n", | |
" return sections" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "b4a564d1-b787-4c28-985c-35d353b00863", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def find_section(rva, sections):\n", | |
" for entry in sections:\n", | |
" va, end, ptrd = entry\n", | |
" if rva > va and rva < end:\n", | |
"\n", | |
" return va, ptrd" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "ba97c27e-a57b-4779-b97a-cf2b2bd070f9", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_resource_location(entry):\n", | |
" if hasattr(entry, 'data'):\n", | |
" rva = entry.data.struct.OffsetToData\n", | |
" size = entry.data.struct.Size\n", | |
"\n", | |
" return [(rva, size, )]\n", | |
"\n", | |
" elif hasattr(entry, 'directory'):\n", | |
" locations = list()\n", | |
" for subdir in entry.directory.entries:\n", | |
" locations.extend(get_resource_location(subdir))\n", | |
"\n", | |
" return locations" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "8edd6457-34a8-4939-a2f8-97d7cc60b96e", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_data(target, location, section):\n", | |
" rva, size = location\n", | |
" va, ptrd = section\n", | |
" offset = rva - va + ptrd\n", | |
" with open(target, 'rb') as fh:\n", | |
" fh.seek(offset)\n", | |
" data = fh.read(size)\n", | |
"\n", | |
" return data, offset" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "bf46a336-0840-4344-a511-1bd50738018b", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def format_line(offset, chunk):\n", | |
" hex_part = ' '.join(f'{byte:02x}' for byte in chunk[:8]) + ' ' + ' '.join(f'{byte:02x}' for byte in chunk[8:])\n", | |
" ascii_part = ''.join(chr(byte) if 32 <= byte < 127 else '.' for byte in chunk)\n", | |
"\n", | |
" return f'{offset:08x} {hex_part:<48} |{ascii_part}|'" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "4b5d9005-1356-49fe-9612-4ded0aaacebd", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def hexdump_data(data):\n", | |
" chunk_size = 16\n", | |
" lines = list()\n", | |
" for offset, chunk in enumerate(itertools.batched(data, chunk_size)):\n", | |
" lines.append(format_line(offset * chunk_size, chunk))\n", | |
"\n", | |
" print('\\n'.join(lines), '\\n')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "b7e092a7-1e8b-4ebd-832b-15c63aee3b26", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def dump_resources(pe, target):\n", | |
" sections = get_sections(pe)\n", | |
" first = True\n", | |
" for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:\n", | |
" if entry.id == resource_type.value:\n", | |
" locations = get_resource_location(entry)\n", | |
" for location in locations:\n", | |
" rva, size = location\n", | |
" section = find_section(rva, sections)\n", | |
" data, offset = get_data(target, location, section)\n", | |
" end = offset + size\n", | |
" print(f'Offset: {offset} {hex(offset)}, RVA: {rva} {hex(rva)}, Size: {size} {hex(size)}, End: {end} {hex(end)}\\n')\n", | |
" if first and local:\n", | |
" subprocess.run(['010editor {}'.format(f'-select:{offset}:{size}')], capture_output=True, shell=True)\n", | |
" first = False\n", | |
" sha256 = hashlib.sha256(data).hexdigest()\n", | |
" print(f'SHA256: {sha256}\\n')\n", | |
" hexdump_data(data)\n", | |
" hd = data.hex()\n", | |
" print('Hex:\\n\\n{}\\n'.format(hd))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "09036422-5e04-4975-9061-1610e192531d", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"dump_resources(pe, target)" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3 (ipykernel)", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.12.6" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For full effect, you must have 010editor and HexFiend installed.