Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 107 additions & 20 deletions support/lldb/me3.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from typing import Any

import lldb
Expand All @@ -8,28 +9,107 @@ def __lldb_init_module(
) -> None:
for command in [
f"command script add -o -f {__name__}.load_wine_modules load-wine-modules",
f"command script add -o -f {__name__}.dump pe-dump",
'target stop-hook add --one-liner "load-wine-modules"'
]: debugger.HandleCommand(command)
]:
debugger.HandleCommand(command)

def load_wine_modules(
debugger: lldb.SBDebugger,
command: str,
result: lldb.SBCommandReturnObject,
internal_dict: dict[str, Any]
) -> None:

def attached_state(debugger: lldb.SBDebugger) -> tuple[lldb.SBTarget, lldb.SBProcess, lldb.SBPlatform]:
target: lldb.SBTarget = debugger.GetSelectedTarget()
if not target or not target.IsValid():
result.SetError("Invalid Target. Please attach to a process first.")
return
raise Exception("Invalid Target. Please attach to a process first.")

process: lldb.SBProcess = target.GetProcess()
if not process or not process.IsValid():
result.SetError("Invalid Process. Please attach to a process first.")
return
raise Exception("Invalid Process. Please attach to a process first.")

platform: lldb.SBPlatform = target.GetPlatform()
if not platform or not platform.IsValid():
result.SetError("Could not get a valid Platform from the target.")
raise Exception("Could not get a valid Platform from the target.")

return (target, process, platform)


def dump(
debugger: lldb.SBDebugger,
args: str,
result: lldb.SBCommandReturnObject,
internal_dict: dict[str, Any]
) -> None:
try:
target, process, platform = attached_state(debugger)
except Exception as e:
result.SetError(str(e))
return

module_name, output_path = args.split(' ', 2)
memory_regions = process.GetMemoryRegions()
start_addr = None
end_addr = None

region = lldb.SBMemoryRegionInfo()
for i in range(memory_regions.GetSize()):
if not memory_regions.GetMemoryRegionAtIndex(i, region):
continue

path: str = region.GetName()
if not path:
continue

if path.endswith(module_name):
if start_addr is None:
start_addr = region.GetRegionBase()

if end_addr is None:
end_addr = region.GetRegionEnd()

start_addr = min(start_addr, region.GetRegionBase())
end_addr = max(end_addr, region.GetRegionEnd())

result.Print(f"Dumping {module_name}@0x{start_addr:x}-{end_addr:x}")

bytes_written = 0
error = lldb.SBError()

with open(output_path, 'wb') as f:
addr = start_addr
while addr < end_addr:
read_size = min(1024, end_addr - addr)

mem = target.ReadMemory(lldb.SBAddress(
addr, target), read_size, error)

if error.Success():
f.write(mem)
else:
result.Print(str(error))
return

bytes_written += read_size
addr += read_size

result.Print(f"Success! Wrote {bytes_written} bytes.")
import pefile
pe = pefile.PE(output_path)

for section in pe.sections:
section.SizeOfRawData = section.Misc_VirtualSize
section.PointerToRawData = section.VirtualAddress

pe.write(output_path)


def load_wine_modules(
debugger: lldb.SBDebugger,
command: str,
result: lldb.SBCommandReturnObject,
internal_dict: dict[str, Any]
) -> None:
try:
target, process, platform = attached_state(debugger)
except Exception as e:
result.SetError(str(e))
return

memory_regions = process.GetMemoryRegions()
Expand All @@ -46,24 +126,31 @@ def load_wine_modules(

if path not in module_candidates:
module_candidates[path] = []
module_candidates[path].append((region.GetRegionBase(), region.GetRegionEnd()))
module_candidates[path].append(
(region.GetRegionBase(), region.GetRegionEnd()))

for path, regions in module_candidates.items():
if not path.endswith(".dll") and not path.endswith(".exe"):
continue

existing_module: lldb.SBModule = target.FindModule(lldb.SBFileSpec(path))
existing_module: lldb.SBModule = target.FindModule(
lldb.SBFileSpec(path))

if existing_module.IsValid():
continue

file_spec = lldb.SBFileSpec(path)
spec = lldb.SBModuleSpec()
spec.SetFileSpec(lldb.SBFileSpec(path))
spec.SetFileSpec(file_spec)

if path.endswith('.exe', '.dll'):
spec.SetTriple("x86_64-pc-windows-msvc")

module: lldb.SBModule = target.AddModule(spec)
module.SetPlatformFileSpec(file_spec)
module_base_address = min(start for start, end in regions)

if module.IsValid():
target.SetModuleLoadAddress(module, module_base_address)
print(f"Loaded module {path} at 0x{module_base_address:x}")
base_addr = 0 if path.endswith('.exe') else module_base_address

target.SetModuleLoadAddress(module, base_addr)
print(f"Loaded module {path} at 0x{base_addr:x}")
else:
result.AppendWarning(f"Could not create module for {path}")
Loading