Skip to content
Open
Show file tree
Hide file tree
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
1 change: 0 additions & 1 deletion api/debuggerapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,5 @@ namespace BinaryNinjaDebuggerAPI {
bool IsWinDbgInstalled(const std::string& installPath = "");
std::string GetWinDbgInstallerPath();
std::string GetWinDbgInstalledVersion(const std::string& installPath = "");
std::string GetWinDbgLatestVersion();

}; // namespace BinaryNinjaDebuggerAPI
1 change: 0 additions & 1 deletion api/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,6 @@ extern "C"
DEBUGGER_FFI_API bool BNDebuggerIsWinDbgInstalled(const char* installPath);
DEBUGGER_FFI_API char* BNDebuggerGetWinDbgInstallerPath(void);
DEBUGGER_FFI_API char* BNDebuggerGetWinDbgInstalledVersion(const char* installPath);
DEBUGGER_FFI_API char* BNDebuggerGetWinDbgLatestVersion(void);

#ifdef __cplusplus
}
Expand Down
9 changes: 0 additions & 9 deletions api/windbginstaller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,3 @@ std::string BinaryNinjaDebuggerAPI::GetWinDbgInstalledVersion(const std::string&
BNDebuggerFreeString(version);
return result;
}


std::string BinaryNinjaDebuggerAPI::GetWinDbgLatestVersion()
{
char* version = BNDebuggerGetWinDbgLatestVersion();
std::string result = version ? version : "";
BNDebuggerFreeString(version);
return result;
}
13 changes: 0 additions & 13 deletions core/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2231,13 +2231,6 @@ char* BNDebuggerGetWinDbgInstalledVersion(const char* installPath)
return BNAllocString(version.c_str());
}


char* BNDebuggerGetWinDbgLatestVersion(void)
{
std::string version = GetLatestVersion();
return BNAllocString(version.c_str());
}

#else // !WIN32

// Stub implementations for non-Windows platforms
Expand Down Expand Up @@ -2280,10 +2273,4 @@ char* BNDebuggerGetWinDbgInstalledVersion(const char* installPath)
return BNAllocString("");
}


char* BNDebuggerGetWinDbgLatestVersion(void)
{
return BNAllocString("");
}

#endif // WIN32
91 changes: 0 additions & 91 deletions core/windbginstaller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,92 +160,6 @@ InstallResult InstallWinDbg(const std::string& installPath, bool isUpdate) {
}
}

/* Helper function to run installer CLI and capture JSON output */
static std::string RunInstallerCommand(const std::string& command, const std::string& extraArgs = "") {
std::string installerPath = GetInstallerPath();
if (installerPath.empty()) {
return "";
}

std::string cmdLine = "\"" + installerPath + "\" " + command + " --json";
if (!extraArgs.empty()) {
cmdLine += " " + extraArgs;
}

/* Create pipes for stdout */
SECURITY_ATTRIBUTES sa = {};
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;

HANDLE hReadPipe, hWritePipe;
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
return "";
}

/* Ensure read handle is not inherited */
SetHandleInformation(hReadPipe, HANDLE_FLAG_INHERIT, 0);

STARTUPINFOA si = {};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
si.wShowWindow = SW_HIDE;

PROCESS_INFORMATION pi = {};

if (!CreateProcessA(
nullptr,
const_cast<char*>(cmdLine.c_str()),
nullptr,
nullptr,
TRUE, /* Inherit handles */
CREATE_NO_WINDOW,
nullptr,
nullptr,
&si,
&pi)) {
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
return "";
}

/* Close write end in parent */
CloseHandle(hWritePipe);

/* Read output */
std::string output;
char buffer[4096];
DWORD bytesRead;
while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, nullptr) && bytesRead > 0) {
buffer[bytesRead] = '\0';
output += buffer;
}

CloseHandle(hReadPipe);

WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

return output;
}

/* Simple JSON value extractor - finds "key":"value" pattern */
static std::string ExtractJsonValue(const std::string& json, const std::string& key) {
std::string searchKey = "\"" + key + "\":\"";
size_t pos = json.find(searchKey);
if (pos == std::string::npos) {
return "";
}
pos += searchKey.length();
size_t endPos = json.find("\"", pos);
if (endPos == std::string::npos) {
return "";
}
return json.substr(pos, endPos - pos);
}

std::string GetInstalledVersion(const std::string& installPath) {
/* Read version directly from marker file (fast, no CLI call needed) */
std::string path = installPath;
Expand Down Expand Up @@ -278,11 +192,6 @@ std::string GetInstalledVersion(const std::string& installPath) {
return "";
}

std::string GetLatestVersion() {
std::string output = RunInstallerCommand("check-update");
return ExtractJsonValue(output, "latest");
}

} // namespace BinaryNinjaDebugger

#endif // WIN32
7 changes: 0 additions & 7 deletions core/windbginstaller.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,6 @@ std::string GetInstallerPath();
*/
std::string GetInstalledVersion(const std::string& installPath = "");

/*
* Get the latest available WinDbg version from Microsoft
*
* @return Version string, or empty on error
*/
std::string GetLatestVersion();

} // namespace BinaryNinjaDebugger

#endif // WIN32
18 changes: 11 additions & 7 deletions docs/guide/dbgeng-ttd.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The WinDbg installation only needs to be done once.
- Open Binary Ninja
- Click `Debugger` -> `Install WinDbg/TTD` from the menu
- A dialog will appear showing the installation progress:
- The installer automatically downloads the latest WinDbg from Microsoft
- The installer downloads a specific WinDbg version from Microsoft
- It extracts the necessary files (DbgEng DLLs and TTD components)
- WinDbg will be installed to `%APPDATA%\Binary Ninja\windbg`
- Progress and status are displayed in real-time
Expand All @@ -32,17 +32,21 @@ The WinDbg installation only needs to be done once.

The automatic installer handles all the complexity of downloading and extracting the WinDbg MSIX bundle.

### Update WinDbg/TTD
Note that the installer deliberately installs a pinned WinDbg version that has been validated against the debugger, rather than the newest release.
New WinDbg releases occasionally ship regressions that break the DbgEng/TTD adapter, so the pinned version is bumped only after it has been tested.

If you already have WinDbg/TTD installed and want to check for updates:
### Reinstall WinDbg/TTD

If you already have WinDbg/TTD installed:

- Click `Debugger` -> `Install WinDbg/TTD` from the menu
- A dialog will appear showing:
- The currently installed version
- The latest available version from Microsoft
- If a newer version is available, click "Update" to download and install it
- If you are already on the latest version, the dialog will indicate that no update is needed
- Restart Binary Ninja after updating
- The version this debugger supports
- If the two match, you can click "Reinstall" to install it again, e.g. if the installation was damaged
- If they differ, click "Install" to replace the installed version with the supported one.
Note this can be a downgrade: if you installed a newer WinDbg yourself, this replaces it with the validated version
- Restart Binary Ninja afterwards

<img src="../../img/debugger/ttd_update_windbg.png" width="600px">

Expand Down
Binary file modified docs/img/debugger/ttd_update_windbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions installer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ set(INSTALLER_LIB_HEADERS
http_downloader.h
zip_extractor.h
windbg_installer.h
windbg_version.h
signature_verifier.h
)

Expand Down
93 changes: 10 additions & 83 deletions installer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*
* Usage:
* windbg-installer install [--path <dir>] [--quiet] [--json]
* windbg-installer check-update [--path <dir>] [--json]
* windbg-installer version [--path <dir>] [--json]
* windbg-installer --help
*
Expand All @@ -17,6 +16,7 @@
#ifdef _WIN32

#include "windbg_installer.h"
#include "windbg_version.h"
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
Expand Down Expand Up @@ -222,24 +222,15 @@ void PrintJsonResult(bool success, const std::string& message, const std::string
std::cout << "}" << std::endl;
}

/* Print JSON version info */
void PrintJsonVersion(const std::string& installed, const std::string& latest, bool updateAvailable) {
std::cout << "{\"type\":\"version\",\"installed\":\"" << installed
<< "\",\"latest\":\"" << latest
<< "\",\"updateAvailable\":" << (updateAvailable ? "true" : "false")
<< "}" << std::endl;
}

void PrintUsage(const char* programName) {
std::cout << "WinDbg/TTD Installer for Binary Ninja Debugger\n"
<< "\n"
<< "Usage:\n"
<< " " << programName << " <command> [options]\n"
<< "\n"
<< "Commands:\n"
<< " install Install or update WinDbg/TTD\n"
<< " version Show installed version (local only, no network)\n"
<< " check-update Check for updates (compares local vs latest online)\n"
<< " install Install or reinstall WinDbg/TTD\n"
<< " version Show the installed and supported versions\n"
<< "\n"
<< "Options:\n"
<< " --path <dir> Specify installation directory\n"
Expand All @@ -252,15 +243,13 @@ void PrintUsage(const char* programName) {
<< "\n"
<< "Examples:\n"
<< " " << programName << " version\n"
<< " " << programName << " check-update\n"
<< " " << programName << " install\n"
<< " " << programName << " install --update\n"
<< " " << programName << " install --path C:\\Tools\\WinDbg\n"
<< "\n"
<< "Exit codes:\n"
<< " 0 Success / up to date\n"
<< " 0 Success\n"
<< " 1 Not installed / error\n"
<< " 2 Update available (for check-update)\n"
<< "\n";
}

Expand Down Expand Up @@ -410,6 +399,7 @@ int CmdVersion(const std::string& installPath, OutputMode mode) {
if (mode == OutputMode::Json) {
std::cout << "{\"type\":\"version\",\"isInstalled\":" << (installed.isInstalled ? "true" : "false")
<< ",\"installed\":\"" << installed.version
<< "\",\"supported\":\"" << kPinnedVersion
<< "\",\"installPath\":\"" << path << "\"}" << std::endl;
} else if (mode == OutputMode::Human) {
std::cout << "\n";
Expand All @@ -425,78 +415,17 @@ int CmdVersion(const std::string& installPath, OutputMode mode) {
std::cout << installed.version;
}
ResetConsoleColor();
std::cout << "\n\n";
}

return installed.isInstalled ? 0 : 1;
}

/* Command: check-update */
int CmdCheckUpdate(const std::string& installPath, OutputMode mode) {
std::string path = installPath.empty() ? GetDefaultInstallPath() : installPath;

/* Get installed version first (local, fast) */
VersionInfo installed = GetInstalledVersion(path);

if (mode == OutputMode::Human) {
std::cout << "Install path: " << path << "\n";
std::cout << "Installed: ";
if (!installed.isInstalled) {
SetConsoleColor(COLOR_YELLOW);
std::cout << "(not installed)";
ResetConsoleColor();
std::cout << "\n";
return 1; /* Exit early, no need to check latest */
} else if (installed.version.empty()) {
std::cout << "\n";
std::cout << " Supported: " << kPinnedVersion << "\n";
if (installed.isInstalled && installed.version != kPinnedVersion) {
SetConsoleColor(COLOR_YELLOW);
std::cout << "(installed, version unknown)";
std::cout << "\n The installed version is not the supported one; run 'install' to replace it.\n";
ResetConsoleColor();
std::cout << "\n";
} else {
std::cout << installed.version << "\n";
}

std::cout << "Latest: ";
std::cout << std::flush; /* Flush before network request */
}

/* Fetch latest version (network request, may take time) */
VersionInfo latest = GetLatestVersion(nullptr);
bool updateAvailable = !IsVersionUpToDate(installed, latest);

if (mode == OutputMode::Json) {
/* Include path and isInstalled in JSON output */
std::cout << "{\"type\":\"version\",\"isInstalled\":" << (installed.isInstalled ? "true" : "false")
<< ",\"installed\":\"" << installed.version
<< "\",\"latest\":\"" << latest.version
<< "\",\"updateAvailable\":" << (updateAvailable ? "true" : "false")
<< ",\"installPath\":\"" << path << "\"}" << std::endl;
} else if (mode == OutputMode::Human) {
if (latest.version.empty()) {
SetConsoleColor(COLOR_YELLOW);
std::cout << "(unable to check)";
} else {
std::cout << latest.version;
}
ResetConsoleColor();
std::cout << "\n";

if (installed.version.empty()) {
std::cout << "Recommend reinstalling with 'install --update' for version tracking.\n";
} else if (updateAvailable) {
SetConsoleColor(COLOR_GREEN);
std::cout << "Update available!\n";
ResetConsoleColor();
} else {
std::cout << "No update available.\n";
}
}

/* Exit code 2 means update available, 1 means not installed */
if (!installed.isInstalled) {
return 1;
}
return updateAvailable ? 2 : 0;
return installed.isInstalled ? 0 : 1;
}

} // anonymous namespace
Expand Down Expand Up @@ -555,8 +484,6 @@ int main(int argc, char* argv[]) {
return CmdInstall(installPath, mode, isUpdate);
} else if (command == "version") {
return CmdVersion(installPath, mode);
} else if (command == "check-update") {
return CmdCheckUpdate(installPath, mode);
} else {
std::cerr << "Error: Unknown command: " << command << "\n";
PrintUsage(argv[0]);
Expand Down
Loading