diff --git a/docs/guide/dbgeng-ttd.md b/docs/guide/dbgeng-ttd.md
index bb3ff477..7a577e59 100644
--- a/docs/guide/dbgeng-ttd.md
+++ b/docs/guide/dbgeng-ttd.md
@@ -49,8 +49,7 @@ The WinDbg installation only needs to be done once.
 ## Record a TTD Trace
 
 Once we have installed and configured WinDbg, we can start recording a TTD trace. There are two ways to do it, we can either
-do it from within Binary Ninja, or do it from WinDbg. Doing it from Binary Ninja is more convenient, though it does not support
-all types of recording supported by WinDbg (e.g., attach to a running process and start recroding).
+do it from within Binary Ninja, or do it from WinDbg. Binary Ninja now supports both launching new processes and attaching to running processes for TTD recording.
 
 ### Record a TTD Trace in Binary Ninja
 
@@ -60,13 +59,17 @@ all types of recording supported by WinDbg (e.g., attach to a running process an
 
  -- In the "TTD Record" dialog, configure the recording as you wish:
-    - Executable Path: the path of the executable to trace
-    - Working Directory: the working directory to launch the executable in
-    - Command Line Arguments: the command line arguments to pass to the executable
-    - Trace Output Directory: the directory to write the trace. By default, it is equal to the working directory, but can be changed if necessary
-- Click "Record". A UAC dialog will pop up to because the TTD recording requires Administrator privilege
-- Accept the elevation. The program will be launched and recorded. Once it exits, find the trace file in the trace output directory
+- In the "TTD Record" dialog, you can choose between two recording modes:
+    - **Launch new process**: Records a new instance of an executable from the beginning
+        - Executable Path: the path of the executable to trace
+        - Working Directory: the working directory to launch the executable in
+        - Command Line Arguments: the command line arguments to pass to the executable
+        - Start application With Recording Off: checkbox to manually control when tracing begins
+    - **Attach to running process**: Attaches to an already running process and starts recording
+        - Target Process: click "Select Process..." to choose from running processes
+    - Trace Output Directory: the directory to write the trace (applies to both modes)
+- Click "Record". A UAC dialog will pop up because TTD recording requires Administrator privilege
+- Accept the elevation. The program will be launched/attached and recorded. Once it exits, find the trace file in the trace output directory
 
 
 ### Record a TTD Trace in WinDbg
diff --git a/ui/ttdrecord.cpp b/ui/ttdrecord.cpp
index e4ed3920..fabb5905 100644
--- a/ui/ttdrecord.cpp
+++ b/ui/ttdrecord.cpp
@@ -19,13 +19,21 @@ limitations under the License.
 #include "qfiledialog.h"
 #include "fmt/format.h"
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "attachprocess.h"
 
 using namespace BinaryNinjaDebuggerAPI;
 using namespace BinaryNinja;
 using namespace std;
 
 TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
-	QDialog()
+	QDialog(), m_selectedPid(0)
 {
 	if (data)
 		m_controller = DebuggerController::GetController(data);
@@ -35,13 +43,31 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 
 	setModal(true);
 	QVBoxLayout* layout = new QVBoxLayout;
-	layout->setSpacing(0);
-
+	layout->setSpacing(10);
+
+	// Mode selection
+	m_launchModeRadio = new QRadioButton("Launch new process", this);
+	m_attachModeRadio = new QRadioButton("Attach to running process", this);
+	m_modeButtonGroup = new QButtonGroup(this);
+	m_modeButtonGroup->addButton(m_launchModeRadio, 0);
+	m_modeButtonGroup->addButton(m_attachModeRadio, 1);
+	m_launchModeRadio->setChecked(true);
+	
+	connect(m_modeButtonGroup, QOverload::of(&QButtonGroup::buttonClicked),
+		this, &TTDRecordDialog::onModeChanged);
+
+	QVBoxLayout* modeLayout = new QVBoxLayout;
+	modeLayout->addWidget(m_launchModeRadio);
+	modeLayout->addWidget(m_attachModeRadio);
+	
+	// Launch mode group
+	m_launchGroup = new QGroupBox("Launch Settings", this);
+	QVBoxLayout* launchLayout = new QVBoxLayout;
+	
 	m_pathEntry = new QLineEdit(this);
-	m_pathEntry->setMinimumWidth(800);
+	m_pathEntry->setMinimumWidth(600);
 	m_argumentsEntry = new QLineEdit(this);
 	m_workingDirectoryEntry = new QLineEdit(this);
-	m_outputDirectory = new QLineEdit(this);
 	m_launchWithoutTracing = new QCheckBox(this);
 
 	auto* pathSelector = new QPushButton("...", this);
@@ -61,6 +87,48 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 			m_workingDirectoryEntry->setText(pathName);
 	});
 
+	auto pathEntryLayout = new QHBoxLayout;
+	pathEntryLayout->addWidget(m_pathEntry);
+	pathEntryLayout->addWidget(pathSelector);
+
+	auto workingDirLayout = new QHBoxLayout;
+	workingDirLayout->addWidget(m_workingDirectoryEntry);
+	workingDirLayout->addWidget(workingDirSelector);
+
+	launchLayout->addWidget(new QLabel("Executable Path"));
+	launchLayout->addLayout(pathEntryLayout);
+	launchLayout->addWidget(new QLabel("Working Directory"));
+	launchLayout->addLayout(workingDirLayout);
+	launchLayout->addWidget(new QLabel("Command Line Arguments"));
+	launchLayout->addWidget(m_argumentsEntry);
+	launchLayout->addWidget(new QLabel("Start application With Recording Off"));
+	launchLayout->addWidget(m_launchWithoutTracing);
+	
+	m_launchGroup->setLayout(launchLayout);
+
+	// Attach mode group
+	m_attachGroup = new QGroupBox("Attach Settings", this);
+	QVBoxLayout* attachLayout = new QVBoxLayout;
+	
+	m_selectedProcessDisplay = new QLineEdit(this);
+	m_selectedProcessDisplay->setReadOnly(true);
+	m_selectedProcessDisplay->setPlaceholderText("No process selected");
+	
+	m_selectProcessButton = new QPushButton("Select Process...", this);
+	connect(m_selectProcessButton, &QPushButton::clicked, this, &TTDRecordDialog::selectProcess);
+	
+	QHBoxLayout* processLayout = new QHBoxLayout;
+	processLayout->addWidget(m_selectedProcessDisplay);
+	processLayout->addWidget(m_selectProcessButton);
+	
+	attachLayout->addWidget(new QLabel("Target Process"));
+	attachLayout->addLayout(processLayout);
+	
+	m_attachGroup->setLayout(attachLayout);
+	m_attachGroup->setEnabled(false);
+
+	// Common settings
+	m_outputDirectory = new QLineEdit(this);
 	auto* outputDirSelector = new QPushButton("...", this);
 	outputDirSelector->setMaximumWidth(30);
 	connect(outputDirSelector, &QPushButton::clicked, [&]() {
@@ -70,31 +138,11 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
             m_outputDirectory->setText(pathName);
 	});
 
-	auto pathEntryLayout = new QHBoxLayout;
-	pathEntryLayout->addWidget(m_pathEntry);
-	pathEntryLayout->addWidget(pathSelector);
-
-	auto workingDirLayout = new QHBoxLayout;
-	workingDirLayout->addWidget(m_workingDirectoryEntry);
-	workingDirLayout->addWidget(workingDirSelector);
-
 	auto outputLayout = new QHBoxLayout;
 	outputLayout->addWidget(m_outputDirectory);
 	outputLayout->addWidget(outputDirSelector);
 
-	QVBoxLayout* contentLayout = new QVBoxLayout;
-	contentLayout->setSpacing(10);
-	contentLayout->addWidget(new QLabel("Executable Path"));
-	contentLayout->addLayout(pathEntryLayout);
-	contentLayout->addWidget(new QLabel("Working Directory"));
-	contentLayout->addLayout(workingDirLayout);
-	contentLayout->addWidget(new QLabel("Command Line Arguments"));
-	contentLayout->addWidget(m_argumentsEntry);
-	contentLayout->addWidget(new QLabel("Trace Output Directory"));
-	contentLayout->addLayout(outputLayout);
-	contentLayout->addWidget(new QLabel("Start application With Recording Off"));
-	contentLayout->addWidget(m_launchWithoutTracing);
-
+	// Button layout
 	QHBoxLayout* buttonLayout = new QHBoxLayout;
 	buttonLayout->setContentsMargins(0, 0, 0, 0);
 
@@ -108,7 +156,12 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 	buttonLayout->addWidget(cancelButton);
 	buttonLayout->addWidget(acceptButton);
 
-	layout->addLayout(contentLayout);
+	// Main layout
+	layout->addLayout(modeLayout);
+	layout->addWidget(m_launchGroup);
+	layout->addWidget(m_attachGroup);
+	layout->addWidget(new QLabel("Trace Output Directory"));
+	layout->addLayout(outputLayout);
 	layout->addStretch(1);
 	layout->addSpacing(10);
 	layout->addLayout(buttonLayout);
@@ -123,16 +176,60 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 	}
 	m_launchWithoutTracing->setChecked(false);
 
-	setFixedSize(QDialog::sizeHint());
-
 	CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
 }
 
 
+void TTDRecordDialog::onModeChanged()
+{
+	bool isLaunchMode = m_launchModeRadio->isChecked();
+	m_launchGroup->setEnabled(isLaunchMode);
+	m_attachGroup->setEnabled(!isLaunchMode);
+}
+
+
+void TTDRecordDialog::selectProcess()
+{
+	AttachProcessDialog dialog(this, m_controller);
+	if (dialog.exec() == QDialog::Accepted)
+	{
+		m_selectedPid = dialog.GetSelectedPid();
+		if (m_selectedPid > 0)
+		{
+			m_selectedProcessDisplay->setText(QString("PID: %1").arg(m_selectedPid));
+		}
+	}
+}
+
+
 void TTDRecordDialog::apply()
 {
+	// Validate output directory
+	if (m_outputDirectory->text().isEmpty())
+	{
+		QMessageBox::critical(this, "Invalid Configuration", "Please specify a trace output directory.");
+		return;
+	}
+	
+	// Mode-specific validation
+	if (m_launchModeRadio->isChecked())
+	{
+		if (m_pathEntry->text().isEmpty())
+		{
+			QMessageBox::critical(this, "Invalid Configuration", "Please specify an executable path for launch mode.");
+			return;
+		}
+	}
+	else
+	{
+		if (m_selectedPid == 0)
+		{
+			QMessageBox::critical(this, "Invalid Configuration", "Please select a process to attach to.");
+			return;
+		}
+	}
+	
 	DoTTDTrace();
-
 	accept();
 }
 
@@ -197,11 +294,25 @@ void TTDRecordDialog::DoTTDTrace()
 	LogDebug("TTD Recorder in path %s", ttdPath.c_str());
 
 	auto ttdRecorder = fmt::format("\"{}\\TTD.exe\"", ttdPath);
-	auto ttdCommandLine = fmt::format("-accepteula -out \"{}\" {} -launch \"{}\" {}",
-		m_outputDirectory->text().toStdString(),
-		m_launchWithoutTracing->isChecked() ? "-tracingOff -recordMode Manual" : "",
-		m_pathEntry->text().toStdString(),
-		m_argumentsEntry->text().toStdString());
+	std::string ttdCommandLine;
+	
+	if (m_launchModeRadio->isChecked())
+	{
+		// Launch mode - existing functionality
+		ttdCommandLine = fmt::format("-accepteula -out \"{}\" {} -launch \"{}\" {}",
+			m_outputDirectory->text().toStdString(),
+			m_launchWithoutTracing->isChecked() ? "-tracingOff -recordMode Manual" : "",
+			m_pathEntry->text().toStdString(),
+			m_argumentsEntry->text().toStdString());
+	}
+	else
+	{
+		// Attach mode - new functionality
+		ttdCommandLine = fmt::format("-accepteula -out \"{}\" -attach {}",
+			m_outputDirectory->text().toStdString(),
+			m_selectedPid);
+	}
+	
 	LogWarn("TTD tracer cmd: %s %s", ttdRecorder.c_str(), ttdCommandLine.c_str());
 
 	SHELLEXECUTEINFOA info = {0};
@@ -210,7 +321,8 @@ void TTDRecordDialog::DoTTDTrace()
 	info.lpVerb = "runas";
 	info.lpFile = ttdRecorder.c_str();
 	info.lpParameters = ttdCommandLine.c_str();
-	info.lpDirectory = m_workingDirectoryEntry->text().toStdString().c_str();
+	info.lpDirectory = m_launchModeRadio->isChecked() ? 
+		m_workingDirectoryEntry->text().toStdString().c_str() : nullptr;
 	info.nShow = SW_NORMAL;
 	bool ret = ShellExecuteExA(&info);
 	if (ret == FALSE)
diff --git a/ui/ttdrecord.h b/ui/ttdrecord.h
index 7f0b85c4..24ed4b2b 100644
--- a/ui/ttdrecord.h
+++ b/ui/ttdrecord.h
@@ -22,6 +22,9 @@ limitations under the License.
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "inttypes.h"
 #include "binaryninjaapi.h"
 #include "viewframe.h"
@@ -30,6 +33,9 @@ limitations under the License.
 
 using namespace BinaryNinjaDebuggerAPI;
 
+// Forward declare the attach process dialog
+class AttachProcessDialog;
+
 class TTDRecordDialog : public QDialog
 {
 	Q_OBJECT
@@ -41,6 +47,16 @@ class TTDRecordDialog : public QDialog
 	QLineEdit* m_argumentsEntry;
 	QLineEdit* m_outputDirectory;
 	QCheckBox* m_launchWithoutTracing;
+	
+	// New UI elements for attach mode
+	QRadioButton* m_launchModeRadio;
+	QRadioButton* m_attachModeRadio;
+	QButtonGroup* m_modeButtonGroup;
+	QGroupBox* m_launchGroup;
+	QGroupBox* m_attachGroup;
+	QPushButton* m_selectProcessButton;
+	QLineEdit* m_selectedProcessDisplay;
+	uint32_t m_selectedPid;
 
 public:
 	TTDRecordDialog(QWidget* parent, BinaryView* data);
@@ -49,4 +65,6 @@ class TTDRecordDialog : public QDialog
 
 private Q_SLOTS:
 	void apply();
+	void onModeChanged();
+	void selectProcess();
 };
 
-- In the "TTD Record" dialog, configure the recording as you wish:
-    - Executable Path: the path of the executable to trace
-    - Working Directory: the working directory to launch the executable in
-    - Command Line Arguments: the command line arguments to pass to the executable
-    - Trace Output Directory: the directory to write the trace. By default, it is equal to the working directory, but can be changed if necessary
-- Click "Record". A UAC dialog will pop up to because the TTD recording requires Administrator privilege
-- Accept the elevation. The program will be launched and recorded. Once it exits, find the trace file in the trace output directory
+- In the "TTD Record" dialog, you can choose between two recording modes:
+    - **Launch new process**: Records a new instance of an executable from the beginning
+        - Executable Path: the path of the executable to trace
+        - Working Directory: the working directory to launch the executable in
+        - Command Line Arguments: the command line arguments to pass to the executable
+        - Start application With Recording Off: checkbox to manually control when tracing begins
+    - **Attach to running process**: Attaches to an already running process and starts recording
+        - Target Process: click "Select Process..." to choose from running processes
+    - Trace Output Directory: the directory to write the trace (applies to both modes)
+- Click "Record". A UAC dialog will pop up because TTD recording requires Administrator privilege
+- Accept the elevation. The program will be launched/attached and recorded. Once it exits, find the trace file in the trace output directory
 
 
 ### Record a TTD Trace in WinDbg
diff --git a/ui/ttdrecord.cpp b/ui/ttdrecord.cpp
index e4ed3920..fabb5905 100644
--- a/ui/ttdrecord.cpp
+++ b/ui/ttdrecord.cpp
@@ -19,13 +19,21 @@ limitations under the License.
 #include "qfiledialog.h"
 #include "fmt/format.h"
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "attachprocess.h"
 
 using namespace BinaryNinjaDebuggerAPI;
 using namespace BinaryNinja;
 using namespace std;
 
 TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
-	QDialog()
+	QDialog(), m_selectedPid(0)
 {
 	if (data)
 		m_controller = DebuggerController::GetController(data);
@@ -35,13 +43,31 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 
 	setModal(true);
 	QVBoxLayout* layout = new QVBoxLayout;
-	layout->setSpacing(0);
-
+	layout->setSpacing(10);
+
+	// Mode selection
+	m_launchModeRadio = new QRadioButton("Launch new process", this);
+	m_attachModeRadio = new QRadioButton("Attach to running process", this);
+	m_modeButtonGroup = new QButtonGroup(this);
+	m_modeButtonGroup->addButton(m_launchModeRadio, 0);
+	m_modeButtonGroup->addButton(m_attachModeRadio, 1);
+	m_launchModeRadio->setChecked(true);
+	
+	connect(m_modeButtonGroup, QOverload::of(&QButtonGroup::buttonClicked),
+		this, &TTDRecordDialog::onModeChanged);
+
+	QVBoxLayout* modeLayout = new QVBoxLayout;
+	modeLayout->addWidget(m_launchModeRadio);
+	modeLayout->addWidget(m_attachModeRadio);
+	
+	// Launch mode group
+	m_launchGroup = new QGroupBox("Launch Settings", this);
+	QVBoxLayout* launchLayout = new QVBoxLayout;
+	
 	m_pathEntry = new QLineEdit(this);
-	m_pathEntry->setMinimumWidth(800);
+	m_pathEntry->setMinimumWidth(600);
 	m_argumentsEntry = new QLineEdit(this);
 	m_workingDirectoryEntry = new QLineEdit(this);
-	m_outputDirectory = new QLineEdit(this);
 	m_launchWithoutTracing = new QCheckBox(this);
 
 	auto* pathSelector = new QPushButton("...", this);
@@ -61,6 +87,48 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 			m_workingDirectoryEntry->setText(pathName);
 	});
 
+	auto pathEntryLayout = new QHBoxLayout;
+	pathEntryLayout->addWidget(m_pathEntry);
+	pathEntryLayout->addWidget(pathSelector);
+
+	auto workingDirLayout = new QHBoxLayout;
+	workingDirLayout->addWidget(m_workingDirectoryEntry);
+	workingDirLayout->addWidget(workingDirSelector);
+
+	launchLayout->addWidget(new QLabel("Executable Path"));
+	launchLayout->addLayout(pathEntryLayout);
+	launchLayout->addWidget(new QLabel("Working Directory"));
+	launchLayout->addLayout(workingDirLayout);
+	launchLayout->addWidget(new QLabel("Command Line Arguments"));
+	launchLayout->addWidget(m_argumentsEntry);
+	launchLayout->addWidget(new QLabel("Start application With Recording Off"));
+	launchLayout->addWidget(m_launchWithoutTracing);
+	
+	m_launchGroup->setLayout(launchLayout);
+
+	// Attach mode group
+	m_attachGroup = new QGroupBox("Attach Settings", this);
+	QVBoxLayout* attachLayout = new QVBoxLayout;
+	
+	m_selectedProcessDisplay = new QLineEdit(this);
+	m_selectedProcessDisplay->setReadOnly(true);
+	m_selectedProcessDisplay->setPlaceholderText("No process selected");
+	
+	m_selectProcessButton = new QPushButton("Select Process...", this);
+	connect(m_selectProcessButton, &QPushButton::clicked, this, &TTDRecordDialog::selectProcess);
+	
+	QHBoxLayout* processLayout = new QHBoxLayout;
+	processLayout->addWidget(m_selectedProcessDisplay);
+	processLayout->addWidget(m_selectProcessButton);
+	
+	attachLayout->addWidget(new QLabel("Target Process"));
+	attachLayout->addLayout(processLayout);
+	
+	m_attachGroup->setLayout(attachLayout);
+	m_attachGroup->setEnabled(false);
+
+	// Common settings
+	m_outputDirectory = new QLineEdit(this);
 	auto* outputDirSelector = new QPushButton("...", this);
 	outputDirSelector->setMaximumWidth(30);
 	connect(outputDirSelector, &QPushButton::clicked, [&]() {
@@ -70,31 +138,11 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
             m_outputDirectory->setText(pathName);
 	});
 
-	auto pathEntryLayout = new QHBoxLayout;
-	pathEntryLayout->addWidget(m_pathEntry);
-	pathEntryLayout->addWidget(pathSelector);
-
-	auto workingDirLayout = new QHBoxLayout;
-	workingDirLayout->addWidget(m_workingDirectoryEntry);
-	workingDirLayout->addWidget(workingDirSelector);
-
 	auto outputLayout = new QHBoxLayout;
 	outputLayout->addWidget(m_outputDirectory);
 	outputLayout->addWidget(outputDirSelector);
 
-	QVBoxLayout* contentLayout = new QVBoxLayout;
-	contentLayout->setSpacing(10);
-	contentLayout->addWidget(new QLabel("Executable Path"));
-	contentLayout->addLayout(pathEntryLayout);
-	contentLayout->addWidget(new QLabel("Working Directory"));
-	contentLayout->addLayout(workingDirLayout);
-	contentLayout->addWidget(new QLabel("Command Line Arguments"));
-	contentLayout->addWidget(m_argumentsEntry);
-	contentLayout->addWidget(new QLabel("Trace Output Directory"));
-	contentLayout->addLayout(outputLayout);
-	contentLayout->addWidget(new QLabel("Start application With Recording Off"));
-	contentLayout->addWidget(m_launchWithoutTracing);
-
+	// Button layout
 	QHBoxLayout* buttonLayout = new QHBoxLayout;
 	buttonLayout->setContentsMargins(0, 0, 0, 0);
 
@@ -108,7 +156,12 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 	buttonLayout->addWidget(cancelButton);
 	buttonLayout->addWidget(acceptButton);
 
-	layout->addLayout(contentLayout);
+	// Main layout
+	layout->addLayout(modeLayout);
+	layout->addWidget(m_launchGroup);
+	layout->addWidget(m_attachGroup);
+	layout->addWidget(new QLabel("Trace Output Directory"));
+	layout->addLayout(outputLayout);
 	layout->addStretch(1);
 	layout->addSpacing(10);
 	layout->addLayout(buttonLayout);
@@ -123,16 +176,60 @@ TTDRecordDialog::TTDRecordDialog(QWidget* parent, BinaryView* data) :
 	}
 	m_launchWithoutTracing->setChecked(false);
 
-	setFixedSize(QDialog::sizeHint());
-
 	CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
 }
 
 
+void TTDRecordDialog::onModeChanged()
+{
+	bool isLaunchMode = m_launchModeRadio->isChecked();
+	m_launchGroup->setEnabled(isLaunchMode);
+	m_attachGroup->setEnabled(!isLaunchMode);
+}
+
+
+void TTDRecordDialog::selectProcess()
+{
+	AttachProcessDialog dialog(this, m_controller);
+	if (dialog.exec() == QDialog::Accepted)
+	{
+		m_selectedPid = dialog.GetSelectedPid();
+		if (m_selectedPid > 0)
+		{
+			m_selectedProcessDisplay->setText(QString("PID: %1").arg(m_selectedPid));
+		}
+	}
+}
+
+
 void TTDRecordDialog::apply()
 {
+	// Validate output directory
+	if (m_outputDirectory->text().isEmpty())
+	{
+		QMessageBox::critical(this, "Invalid Configuration", "Please specify a trace output directory.");
+		return;
+	}
+	
+	// Mode-specific validation
+	if (m_launchModeRadio->isChecked())
+	{
+		if (m_pathEntry->text().isEmpty())
+		{
+			QMessageBox::critical(this, "Invalid Configuration", "Please specify an executable path for launch mode.");
+			return;
+		}
+	}
+	else
+	{
+		if (m_selectedPid == 0)
+		{
+			QMessageBox::critical(this, "Invalid Configuration", "Please select a process to attach to.");
+			return;
+		}
+	}
+	
 	DoTTDTrace();
-
 	accept();
 }
 
@@ -197,11 +294,25 @@ void TTDRecordDialog::DoTTDTrace()
 	LogDebug("TTD Recorder in path %s", ttdPath.c_str());
 
 	auto ttdRecorder = fmt::format("\"{}\\TTD.exe\"", ttdPath);
-	auto ttdCommandLine = fmt::format("-accepteula -out \"{}\" {} -launch \"{}\" {}",
-		m_outputDirectory->text().toStdString(),
-		m_launchWithoutTracing->isChecked() ? "-tracingOff -recordMode Manual" : "",
-		m_pathEntry->text().toStdString(),
-		m_argumentsEntry->text().toStdString());
+	std::string ttdCommandLine;
+	
+	if (m_launchModeRadio->isChecked())
+	{
+		// Launch mode - existing functionality
+		ttdCommandLine = fmt::format("-accepteula -out \"{}\" {} -launch \"{}\" {}",
+			m_outputDirectory->text().toStdString(),
+			m_launchWithoutTracing->isChecked() ? "-tracingOff -recordMode Manual" : "",
+			m_pathEntry->text().toStdString(),
+			m_argumentsEntry->text().toStdString());
+	}
+	else
+	{
+		// Attach mode - new functionality
+		ttdCommandLine = fmt::format("-accepteula -out \"{}\" -attach {}",
+			m_outputDirectory->text().toStdString(),
+			m_selectedPid);
+	}
+	
 	LogWarn("TTD tracer cmd: %s %s", ttdRecorder.c_str(), ttdCommandLine.c_str());
 
 	SHELLEXECUTEINFOA info = {0};
@@ -210,7 +321,8 @@ void TTDRecordDialog::DoTTDTrace()
 	info.lpVerb = "runas";
 	info.lpFile = ttdRecorder.c_str();
 	info.lpParameters = ttdCommandLine.c_str();
-	info.lpDirectory = m_workingDirectoryEntry->text().toStdString().c_str();
+	info.lpDirectory = m_launchModeRadio->isChecked() ? 
+		m_workingDirectoryEntry->text().toStdString().c_str() : nullptr;
 	info.nShow = SW_NORMAL;
 	bool ret = ShellExecuteExA(&info);
 	if (ret == FALSE)
diff --git a/ui/ttdrecord.h b/ui/ttdrecord.h
index 7f0b85c4..24ed4b2b 100644
--- a/ui/ttdrecord.h
+++ b/ui/ttdrecord.h
@@ -22,6 +22,9 @@ limitations under the License.
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "inttypes.h"
 #include "binaryninjaapi.h"
 #include "viewframe.h"
@@ -30,6 +33,9 @@ limitations under the License.
 
 using namespace BinaryNinjaDebuggerAPI;
 
+// Forward declare the attach process dialog
+class AttachProcessDialog;
+
 class TTDRecordDialog : public QDialog
 {
 	Q_OBJECT
@@ -41,6 +47,16 @@ class TTDRecordDialog : public QDialog
 	QLineEdit* m_argumentsEntry;
 	QLineEdit* m_outputDirectory;
 	QCheckBox* m_launchWithoutTracing;
+	
+	// New UI elements for attach mode
+	QRadioButton* m_launchModeRadio;
+	QRadioButton* m_attachModeRadio;
+	QButtonGroup* m_modeButtonGroup;
+	QGroupBox* m_launchGroup;
+	QGroupBox* m_attachGroup;
+	QPushButton* m_selectProcessButton;
+	QLineEdit* m_selectedProcessDisplay;
+	uint32_t m_selectedPid;
 
 public:
 	TTDRecordDialog(QWidget* parent, BinaryView* data);
@@ -49,4 +65,6 @@ class TTDRecordDialog : public QDialog
 
 private Q_SLOTS:
 	void apply();
+	void onModeChanged();
+	void selectProcess();
 };