{"id":19512227,"url":"https://github.com/nccgroup/pythia","last_synced_at":"2025-07-09T11:07:19.564Z","repository":{"id":136937761,"uuid":"146569304","full_name":"nccgroup/pythia","owner":"nccgroup","description":"A tool to extract RTTI information from Delphi executables, written in pure Python","archived":false,"fork":false,"pushed_at":"2020-03-11T14:28:44.000Z","size":131,"stargazers_count":23,"open_issues_count":6,"forks_count":7,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-26T04:45:31.976Z","etag":null,"topics":["delphi","malware-analysis","python","reverse-engineering"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nccgroup.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-29T08:26:55.000Z","updated_at":"2025-04-07T06:51:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"8f030261-3fcc-4577-97dc-a88e175004b0","html_url":"https://github.com/nccgroup/pythia","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nccgroup/pythia","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2Fpythia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2Fpythia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2Fpythia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2Fpythia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nccgroup","download_url":"https://codeload.github.com/nccgroup/pythia/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2Fpythia/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264446715,"owners_count":23609632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["delphi","malware-analysis","python","reverse-engineering"],"created_at":"2024-11-10T23:24:52.205Z","updated_at":"2025-07-09T11:07:19.519Z","avatar_url":"https://github.com/nccgroup.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction / tl;dr\n\nThis tool scans an executable file for Delphi data, including RTTI and virtual\nfunction tables.  It outputs a JSON file with information about identified\nclasses and functions, which can be used for additional analysis, for example:\n\n* Generate a class tree.\n* Generate names \u0026 comments for IDA.\n* Feed into further processing, e.g. automatic decompilation.\n\nAn IDAPython script that can load the output into IDA is provided.\n\nThe script was written to complement other tools for reverse engineering\nDelphi.\n\n# Author \u0026 license\n\nReleased as open source by NCC Group Plc - http://www.nccgroup.com/\n\nDeveloped by David Cannings (@edeca) david.cannings@nccgroup.com\n\nhttp://www.github.com/nccgroup/pythia\n\nThis project is released under the AGPL license. Please see LICENSE for more information.\n\n# How it works\n\nThe high level flow is:\n\n* Load a PE file and find code sections\n* Scan through each code section 4 bytes at a time\n* Identify potential vftables \u0026 validate them\n* Parse out the class name and parent relationships\n* Identify function inheritance\n\n## Idenfiying potential vftables\n\nDelphi vftables are well documented.  Information for the latest version is \n[available from Embarcadero](http://docwiki.embarcadero.com/RADStudio/Seattle/en/Internal_Data_Formats).\nUnofficial documentation is available for Delphi 2005 ([see here](http://pages.cs.wisc.edu/~rkennedy/vmt)).\n\nThe source code for Free Pascal is also useful ([Github mirror](https://github.com/graemeg/freepascal)).\n\nThe first item in a vftable is `vmtSelfPtr`, which points to the start of the\nvirtual function table.  The script scans each code segment in the PE file for\nany location pointing forward `+0x4C` bytes.  Note that the Delphi compiler aligns\nvftables to a 4 byte boundary (for optimisation).\n\nFor example, the following VA `0x0046E1C8` contains the offset `0x0046E214`, which\nis `0x4C` ahead of the current location.  As shown in IDA:\n\n    .text:0046E1C8                   ; Classes::TComponent *vftable_TDCP_misty1\n    .text:0046E1C8 14 E2 46 00       vftable_TDCP_misty1 dd offset off_46E214\n\nThis approach can generate false positives, therefore other fields in the\nvftable are checked for sensible values.  For example the `vmtInstanceSize`\nis checked to ensure it isn't excessive and function pointers are verified to\nlie in an executable section.  During testing the false positive rate was\nvery low, despite the brute force search method.\n\n## Inheritance\n\nEach function found in a vftable is checked to see if it is inherited from the \nparent or overloaded.  Delphi does not support multiple inheritance so this can\nbe achieved by checking the pointer in the parent vftable with the same offset.\n\nIf both pointers reference the same function it is inherited.  If the child has\na different pointer then it has been overloaded.\n\n# Example output\n\nThe primary output from the tool is a JSON file which can be fed into subsequent\nprocessing / tools.  However, a few other output formats are included.\n\n## Tree output\n\nUse the `--save-tree` option to generate a file like:\n\n    TObject (at 0x0040112c)\n    |-- Exception (at 0x004081f8)\n    |   |-- EAbort (at 0x00408260)\n    |   |-- EAbstractError (at 0x00408ad4)\n    |   |-- EAssertionFailed (at 0x00408a74)\n    |   |-- EBcdException (at 0x004bd110)\n    |   |   +-- EBcdOverflowException (at 0x004bd16c)\n    |   |-- EBitsError (at 0x0041ab04)\n    |   |-- EComponentError (at 0x0041abbc)\n    |   |-- EConvertError (at 0x00408850)\n    |   |-- EDCP_cipher (at 0x0046a0ac)\n    |   |   +-- EDCP_blockcipher (at 0x0046a29c)\n    |   |-- EDCP_hash (at 0x00469f20)\n    .. etc ..\n\n# Future aims\n\n* Identify the Delhi version (e.g. from `PACKAGEINFO` or `DVCLAL` resource) and adjust scanning for different vftable layouts.\n* Parse more class information, e.g. properties (a Delphi specific item) and method tables\n* Parse Delphi RTTI information (vmtTypeInfo in the vftable)\n* Disassemble code with Capstone and identify virtual calls (e.g. match `call [ecx+3Fh]` to an instance method)\n\n# Caveats\n\n* Only tested on 32-bit code at this time.  Please send me 64 bit samples.\n* Only supports Windows PE files (Delphi will compile to other formats).\n* Not designed to be a full Delphi decompiler.  Use DeDe / IDR / Hex-Rays.\n* Only useful with Delphi binaries that use objects (not all do).\n* Modern Delphi uses names like `TComparer\u003cSystem.Bindings.EvalProtocol.TPair\u003cSystem.IInterface,System.Pointer\u003e\u003e` which are fairly indecipherable in IDA.\n\nPlease send me examples of binaries where this tool doesn't work, so it can\nbe improved.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnccgroup%2Fpythia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnccgroup%2Fpythia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnccgroup%2Fpythia/lists"}