Delphi Decompiler Dede
DeDe offers several features that bridge the gap between raw binary and source code:
DeDe is a historically important, specialized tool for recovering Delphi form layouts and symbol information from older (v2–v7) 32-bit Delphi executables. It is not a full decompiler (does not produce Pascal code for logic), and it is obsolete for modern Delphi versions or packed binaries. However, for legacy software maintenance, digital forensics, or malware analysis involving classic Delphi binaries, DeDe may still be useful – though newer alternatives like IDR or Ghidra are generally preferable.
Report prepared by: [Your Name / Organization]
Date: [Current Date]
Classification: Public – Technical Reference
DeDe is a specialized decompiler for applications built with Delphi (versions 2 through 6). While it doesn't provide fully recompilable source code, it is excellent for recovering UI forms and analyzing application logic through assembly. 1. Getting Started with DeDe
To begin using DeDe, you can find it on various archives or software repositories since it is no longer actively updated.
Load the Target: Open DeDe and use the File | Open menu to load a Delphi executable (.exe), DLL, or BPL.
Analyze the File: Click the Analyze button. DeDe will scan the binary for Delphi-specific metadata, such as the Virtual Method Table (VMT) and published methods. 2. Key Features and Outputs
Once analysis is complete, DeDe provides several tabs to explore the application:
DFM Files (Forms): You can view and extract all .dfm files. These contain the UI layout and property settings (e.g., button captions, positions). You can even open and edit these directly in Delphi.
Published Methods: DeDe lists event handlers (like OnClick events). It provides these in commented ASM (Assembly) code, often including references to strings, imported functions, and class method calls.
Project Creation: Use the Make Project feature to generate a Delphi project folder containing the retrieved .dfm, .pas, and .dpr files. Note that the .pas files contain assembly code and cannot be recompiled as-is. 3. Advanced Tools in DeDe
DeDe includes several built-in utilities for deeper analysis:
Disassemble Proc: If you know a specific Relative Virtual Address (RVA), you can manually disassemble any procedure via the Tools | Disassemble Proc menu. delphi decompiler dede
Symbol Files (DSF): You can load .dsf files (DeDe Symbol Files) via File | Load Symbol File. These help DeDe identify and comment on exports from BPL libraries, similar to FLIRT signatures in other tools.
Helper Tools: The interface includes a PE Editor, RVA Converter, and DOI Builder (Delphi Offset Info) to help navigate the binary structure. 4. Limitations and Modern Alternatives Because DeDe is a legacy tool, it has specific constraints:
Version Limit: It is most effective for 32-bit executables from older Delphi versions (up to version 6 or 7).
No Logic Recovery: It does not recover high-level Pascal logic; you must be comfortable reading x86 assembly to understand "what happens" after a button click.
For more modern or complex Delphi applications, developers often use IDR (Interactive Delphi Reconstructor) for better class reconstruction or Ghidra with specialized Delphi scripts.
Are you trying to recover a specific UI form or are you looking to understand the logic of an older application? DeDe - Download - Softpedia
Introduction
Delphi Decompiler Dede is a software tool designed to reverse-engineer and decompile programs written in Delphi, a popular object-oriented programming language. Dede is a free and open-source decompiler that can help developers understand and analyze the internal workings of Delphi applications. This paper provides an overview of Dede, its features, and its uses.
What is Delphi?
Delphi is a high-level, compiled, strongly typed language developed by Embarcadero Technologies. It is widely used for building Windows desktop applications, mobile apps, and web applications. Delphi is known for its fast development capabilities, large standard library, and strong support for object-oriented programming.
What is a Decompiler?
A decompiler is a software tool that takes compiled code as input and generates source code in a high-level programming language as output. Decompilers are used to reverse-engineer software, understand its internal workings, and analyze its behavior. Decompilers can be useful for various purposes, such as: DeDe offers several features that bridge the gap
Delphi Decompiler Dede
Dede is a free and open-source decompiler for Delphi programs. It was first released in 2004 and has since become one of the most popular decompilers for Delphi. Dede can decompile Delphi programs from version 3 to the latest version, including programs compiled with the .NET framework.
Features of Dede
Some of the key features of Dede include:
How Dede Works
Dede uses a combination of disassembly and decompilation techniques to recover the source code from a compiled Delphi program. Here is a high-level overview of the decompilation process:
Uses of Dede
Dede has various uses, including:
Conclusion
Delphi Decompiler Dede is a powerful tool for reverse-engineering and decompiling Delphi programs. Its ability to decompile programs from various Delphi versions and .NET framework makes it a valuable asset for developers, researchers, and educators. Dede's features, such as syntax highlighting and support for various output formats, make it a user-friendly tool for analyzing and understanding compiled Delphi programs.
Future Work
Future work on Dede could include:
References
I'll help you develop a feature for a Delphi decompiler similar to DEDE (DeDe). This feature will extract and display form information, event handlers, and component properties from a Delphi compiled executable.
"""
Delphi Decompiler Feature - Form & Component Extractor
Inspired by DEDE (Delphi Decompiler)
"""
import struct
import re
from dataclasses import dataclass, field
from typing import List, Dict, Optional, BinaryIO
from enum import Enum
class ComponentType(Enum):
TFORM = "TForm"
TBUTTON = "TButton"
TEDIT = "TEdit"
TMEMO = "TMemo"
TLABEL = "TLabel"
TCOMBOBOX = "TComboBox"
TLISTBOX = "TListBox"
TCHECKBOX = "TCheckBox"
TRADIOBUTTON = "TRadioButton"
TPANEL = "TPanel"
TMAINMENU = "TMainMenu"
TTIMER = "TTimer"
UNKNOWN = "Unknown"
@dataclass
class RTTIProperty:
"""Represents a component property from RTTI"""
name: str
value: str
prop_type: str
@dataclass
class EventHandler:
"""Represents an event handler method"""
event_name: str
method_name: str
rva: int # Relative Virtual Address
@dataclass
class Component:
"""Represents a Delphi component/form control"""
name: str
component_type: ComponentType
parent: Optional[str]
properties: Dict[str, RTTIProperty] = field(default_factory=dict)
events: List[EventHandler] = field(default_factory=list)
children: List['Component'] = field(default_factory=list)
@dataclass
class FormInfo:
"""Represents a Delphi form"""
name: str
class_name: str
unit_name: str
components: List[Component] = field(default_factory=list)
class DelphiDecompiler:
"""Main decompiler class for Delphi executables"""
def __init__(self, file_path: str):
self.file_path = file_path
self.file_data = None
self.forms: List[FormInfo] = []
self.string_table: Dict[int, str] = {}
def load_file(self) -> bool:
"""Load the executable file"""
try:
with open(self.file_path, 'rb') as f:
self.file_data = f.read()
return True
except Exception as e:
print(f"Error loading file: e")
return False
def find_delphi_signature(self) -> bool:
"""Detect if file is a Delphi executable"""
signatures = [
b'TPF0', # Delphi 2009+
b'PACKAGEINFO', # Package info
b'System@Sysinit', # Delphi runtime
b'@System@InitUnits', # Unit initialization
]
for sig in signatures:
if sig in self.file_data:
return True
return False
def extract_strings(self) -> None:
"""Extract string table references"""
# Simple string extraction pattern
# Delphi stores strings as length-prefixed
pattern = re.compile(b'\x03([\x20-\x7E]+)\x00')
for match in pattern.finditer(self.file_data):
try:
string_val = match.group(1).decode('ascii', errors='ignore')
offset = match.start()
self.string_table[offset] = string_val
except:
pass
def find_form_resources(self) -> List[tuple]:
"""Find embedded form resource (DFM) data"""
forms = []
# Search for DFM resource patterns
dfm_patterns = [
b'OBJECT ', # DFM object declaration
b'object ', # Lowercase variant
b'POBJECT', # Pascal-style
]
for pattern in dfm_patterns:
pos = 0
while True:
found = self.file_data.find(pattern, pos)
if found == -1:
break
# Extract form name
end_of_obj = self.file_data.find(b'\n', found)
if end_of_obj != -1:
form_line = self.file_data[found:end_of_obj].decode('ascii', errors='ignore')
form_name = form_line.replace('OBJECT ', '').replace('object ', '').strip()
forms.append((found, form_name))
pos = found + 1
return forms
def parse_dfm_data(self, data: bytes) -> List[Component]:
"""Parse DFM (Delphi Form Module) binary/text data"""
components = []
# Convert to string for easier parsing
try:
dfm_text = data.decode('ascii', errors='ignore')
lines = dfm_text.split('\n')
current_component = None
indent_stack = []
for line in lines:
line = line.strip()
if not line:
continue
# Detect component start
if line.upper().startswith('OBJECT'):
# Parse component definition
parts = line.split()
if len(parts) >= 2:
comp_type = parts[1]
comp_name = parts[2] if len(parts) > 2 else "Unnamed"
component = Component(
name=comp_name,
component_type=self._parse_component_type(comp_type),
parent=None
)
components.append(component)
current_component = component
indent_stack.append(component)
# Detect component end
elif line.upper() == 'END':
if indent_stack:
indent_stack.pop()
current_component = indent_stack[-1] if indent_stack else None
# Parse properties
elif current_component and '=' in line:
self._parse_property(line, current_component)
except Exception as e:
print(f"Error parsing DFM: e")
return components
def _parse_component_type(self, type_str: str) -> ComponentType:
"""Convert Delphi type string to ComponentType enum"""
type_upper = type_str.upper()
mapping =
'TFORM': ComponentType.TFORM,
'TBUTTON': ComponentType.TBUTTON,
'TEDIT': ComponentType.TEDIT,
'TMEMO': ComponentType.TMEMO,
'TLABEL': ComponentType.TLABEL,
'TCOMBOBOX': ComponentType.TCOMBOBOX,
'TLISTBOX': ComponentType.TLISTBOX,
'TCHECKBOX': ComponentType.TCHECKBOX,
'TRADIOBUTTON': ComponentType.TRADIOBUTTON,
'TPANEL': ComponentType.TPANEL,
'TMAINMENU': ComponentType.TMAINMENU,
'TTIMER': ComponentType.TTIMER,
return mapping.get(type_upper, ComponentType.UNKNOWN)
def _parse_property(self, line: str, component: Component) -> None:
"""Parse a property line from DFM"""
try:
prop_name, prop_value = line.split('=', 1)
prop_name = prop_name.strip()
prop_value = prop_value.strip().strip('"')
# Detect event handlers
if prop_name.lower().endswith('on'):
# Event handler reference
event_handler = EventHandler(
event_name=prop_name,
method_name=prop_value,
rva=0 # Would need actual RVA calculation
)
component.events.append(event_handler)
else:
# Regular property
prop_type = self._guess_property_type(prop_value)
rtti_prop = RTTIProperty(
name=prop_name,
value=prop_value,
prop_type=prop_type
)
component.properties[prop_name] = rtti_prop
except Exception:
pass
def _guess_property_type(self, value: str) -> str:
"""Guess property type from value"""
if value.isdigit():
return 'Integer'
elif value.upper() in ['TRUE', 'FALSE']:
return 'Boolean'
elif value.startswith('$') and len(value) > 1:
return 'Hex'
else:
return 'String'
def find_event_handlers(self) -> Dict[str, List[int]]:
"""Find event handler addresses in code section"""
handlers = {}
# Pattern for Delphi method references
method_patterns = [
rb'\x68([\x00-\xFF]4)', # push address (DELPHI)
rb'\xB8([\x00-\xFF]4)', # mov eax, address
]
for pattern in method_patterns:
for match in re.finditer(pattern, self.file_data):
try:
address = struct.unpack('<I', match.group(1))[0]
# Look for method name nearby
method_name = self._find_method_name(match.start())
if method_name:
handlers.setdefault(method_name, []).append(address)
except:
pass
return handlers
def _find_method_name(self, position: int) -> Optional[str]:
"""Find method name near given position"""
# Look for Pascal string format (length byte + string)
search_range = 100
start = max(0, position - search_range)
end = min(len(self.file_data), position + search_range)
for offset in range(start, end):
if offset + 1 >= len(self.file_data):
continue
str_len = self.file_data[offset]
if 1 <= str_len <= 100: # Reasonable string length
try:
name = self.file_data[offset+1:offset+1+str_len].decode('ascii', errors='ignore')
if name and name[0].isalpha():
return name
except:
pass
return None
def decompile(self) -> bool:
"""Main decompilation process"""
print(f"[*] Loading file: self.file_path")
if not self.load_file():
return False
print("[*] Checking Delphi signature...")
if not self.find_delphi_signature():
print("[!] Warning: Delphi signature not found")
print("[*] Extracting strings...")
self.extract_strings()
print("[*] Finding form resources...")
form_resources = self.find_form_resources()
print(f"[*] Found len(form_resources) potential form(s)")
for offset, form_name in form_resources:
print(f"\n[*] Processing form: form_name")
# Extract form data (simplified)
end_offset = self.file_data.find(b'END', offset)
if end_offset != -1:
form_data = self.file_data[offset:end_offset+3]
components = self.parse_dfm_data(form_data)
form_info = FormInfo(
name=form_name,
class_name=f"Tform_name",
unit_name="", # Would need unit detection
components=components
)
self.forms.append(form_info)
print("[*] Finding event handlers...")
event_handlers = self.find_event_handlers()
print(f"[*] Found len(event_handlers) event handler(s)")
return True
def generate_report(self) -> str:
"""Generate a decompilation report"""
report = []
report.append("=" * 60)
report.append("DELPHI DECOMPILER REPORT - DEDE STYLE")
report.append("=" * 60)
report.append(f"File: self.file_path")
report.append(f"Forms Found: len(self.forms)")
report.append("")
for i, form in enumerate(self.forms):
report.append(f"\n--- FORM i+1: form.name ---")
report.append(f"Class: form.class_name")
report.append(f"Components: len(form.components)")
report.append("")
for comp in form.components:
report.append(f" [+] Component: comp.name (comp.component_type.value)")
if comp.properties:
report.append(f" Properties:")
for prop_name, prop in list(comp.properties.items())[:10]: # Limit display
report.append(f" - prop_name = prop.value")
if comp.events:
report.append(f" Events:")
for event in comp.events:
report.append(f" - event.event_name -> event.method_name")
if comp.children:
report.append(f" Children: len(comp.children)")
return "\n".join(report)
def export_to_dcr(self, output_file: str) -> None:
"""Export to DCR (DeDe format) compatible file"""
with open(output_file, 'w') as f:
f.write("[Delphi Decompiler Export]\n")
f.write(f"File: self.file_path\n\n")
for form in self.forms:
f.write(f"[Form: form.name]\n")
f.write(f"Class: form.class_name\n")
f.write("Components:\n")
for comp in form.components:
f.write(f" comp.name = comp.component_type.value\n")
for prop in comp.properties.values():
f.write(f" prop.name = prop.value\n")
f.write("\n")
Let us address the elephant in the room. Is using a Delphi decompiler DeDe illegal?
DeDe is a tool of analysis, not theft. Professional developers use it to answer the question: "What does this legacy component do because the documentation is gone?" Malicious actors use it to crack software. The legality rests entirely on intent.