Skip to content

Instantly share code, notes, and snippets.

@utkonos
Last active October 6, 2024 20:09
Show Gist options
  • Save utkonos/86585b85a313a2e41d33471c22cc26c6 to your computer and use it in GitHub Desktop.
Save utkonos/86585b85a313a2e41d33471c22cc26c6 to your computer and use it in GitHub Desktop.
View any resources in PE EXE
Display the source blob
Display the rendered blob
Raw
{
"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
}
@utkonos
Copy link
Author

utkonos commented Nov 27, 2022

For full effect, you must have 010editor and HexFiend installed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment