├── .gitignore
├── Call Logger
├── CMakeLists.txt
├── CMakeLists.txt.user
├── Resources.qrc
├── breakpointinfowindow.cpp
├── breakpointinfowindow.h
├── breakpointinfowindow.ui
├── disassembleaddresswindow.cpp
├── disassembleaddresswindow.h
├── disassembleaddresswindow.ui
├── errormessagedialog.cpp
├── errormessagedialog.h
├── icon
│ └── icon.ico
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
├── mainwindow.ui
├── memorywindow.cpp
├── memorywindow.h
├── memorywindow.ui
├── moduleslistwindow.cpp
├── moduleslistwindow.h
├── moduleslistwindow.ui
├── numerictablewidgetitem.h
├── processelectwindow.h
├── processselectwindow.cpp
├── processselectwindow.h
├── processselectwindow.ui
└── thirdparty
│ └── include
│ ├── Api.h
│ ├── Structures.h
│ └── TEDClientBridge.h
├── LICENSE
├── README.md
└── TED
├── TED.sln
├── TEDClientAPI
├── Api.cpp
├── Api.h
├── Source.cpp
├── Structures.h
├── TEDClientAPI.vcxproj
├── TEDClientAPI.vcxproj.filters
├── TEDClientAPI.vcxproj.user
└── TEDClientBridge.h
├── TEDCore
├── Breakpoint.cpp
├── Breakpoint.h
├── CommonTypes.h
├── Console.cpp
├── Console.h
├── Disassembler.cpp
├── Disassembler.h
├── GrpcServer.cpp
├── GrpcServer.h
├── Memory.cpp
├── Memory.h
├── Process.cpp
├── Process.h
├── Proto
│ ├── TED.grpc.pb.cc
│ ├── TED.grpc.pb.h
│ ├── TED.pb.cc
│ ├── TED.pb.h
│ └── TED.proto
├── Source.cpp
├── Symbols.cpp
├── Symbols.h
├── TEDCore.filters
├── TEDCore.user
├── TEDCore.vcxproj
├── TEDCore.vcxproj.filters
└── TEDCore.vcxproj.user
├── TEDTestClient
├── Source.cpp
├── TEDTestClient.filters
├── TEDTestClient.user
├── TEDTestClient.vcxproj
├── TEDTestClient.vcxproj.filters
└── TEDTestClient.vcxproj.user
└── TEDx86InjectorBridge
├── Source.cpp
├── TEDx86InjectorBridge.vcxproj
├── TEDx86InjectorBridge.vcxproj.filters
└── TEDx86InjectorBridge.vcxproj.user
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
--------------------------------------------------------------------------------
/Call Logger/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5)
2 |
3 | project(TEDCallLoggerUI VERSION 0.1 LANGUAGES CXX)
4 |
5 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
6 |
7 | set(CMAKE_AUTOUIC ON)
8 | set(CMAKE_AUTOMOC ON)
9 | set(CMAKE_AUTORCC ON)
10 |
11 | set(CMAKE_CXX_STANDARD 17)
12 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
13 |
14 | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
15 | find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
16 |
17 | set(PROJECT_SOURCES
18 | main.cpp
19 | mainwindow.cpp
20 | mainwindow.h
21 | mainwindow.ui
22 | processselectwindow.cpp
23 | processselectwindow.h
24 | processselectwindow.ui
25 | moduleslistwindow.cpp
26 | moduleslistwindow.h
27 | moduleslistwindow.ui
28 | disassembleaddresswindow.cpp
29 | disassembleaddresswindow.h
30 | disassembleaddresswindow.ui
31 | memorywindow.cpp
32 | memorywindow.h
33 | memorywindow.ui
34 | breakpointinfowindow.cpp
35 | breakpointinfowindow.h
36 | breakpointinfowindow.ui
37 | errormessagedialog.h
38 | numerictablewidgetitem.h
39 | thirdparty/include/Api.h
40 | thirdparty/include/Structures.h
41 | thirdparty/include/TEDClientBridge.h
42 | )
43 |
44 | if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
45 | qt_add_executable(TEDCallLoggerUI
46 | MANUAL_FINALIZATION
47 | ${PROJECT_SOURCES}
48 | )
49 | # Define target properties for Android with Qt 6 as:
50 | # set_property(TARGET TEDCallLoggerUI APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
51 | # ${CMAKE_CURRENT_SOURCE_DIR}/android)
52 | # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
53 | else()
54 | if(ANDROID)
55 | add_library(TEDCallLoggerUI SHARED
56 | ${PROJECT_SOURCES}
57 | )
58 | # Define properties for Android with Qt 5 after find_package() calls as:
59 | # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
60 | else()
61 | add_executable(TEDCallLoggerUI
62 | ${PROJECT_SOURCES}
63 | )
64 | endif()
65 | endif()
66 |
67 | target_link_libraries(TEDCallLoggerUI PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
68 |
69 | set_target_properties(TEDCallLoggerUI PROPERTIES
70 | MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
71 | MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
72 | MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
73 | MACOSX_BUNDLE TRUE
74 | WIN32_EXECUTABLE TRUE
75 | )
76 |
77 | install(TARGETS TEDCallLoggerUI
78 | BUNDLE DESTINATION .
79 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
80 |
81 | if(QT_VERSION_MAJOR EQUAL 6)
82 | qt_finalize_executable(TEDCallLoggerUI)
83 | endif()
84 |
--------------------------------------------------------------------------------
/Call Logger/Resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | icon/icon.ico
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Call Logger/breakpointinfowindow.cpp:
--------------------------------------------------------------------------------
1 | #include "breakpointinfowindow.h"
2 | #include "ui_breakpointinfowindow.h"
3 |
4 | BreakpointInfoWindow::BreakpointInfoWindow(std::shared_ptr response, QWidget * parent) :
5 | QDialog(parent),
6 | ui(new Ui::BreakpointInfoWindow)
7 | {
8 | ui->setupUi(this);
9 |
10 | displayInfo(response);
11 | }
12 |
13 | BreakpointInfoWindow::~BreakpointInfoWindow()
14 | {
15 | delete ui;
16 | }
17 |
18 | void BreakpointInfoWindow::displayInfo(std::shared_ptr response)
19 | {
20 | auto text{
21 | QString("Read breakpoint event\nProcess ID: %1\nThread ID: %2\nSource Address: %3\nDestination Address: %4\n\n")
22 | .arg(response->processId)
23 | .arg(response->threadId)
24 | .arg(QString::number(response->sourceAddress, 16).toUpper())
25 | .arg(QString::number(response->destinationAddress, 16).toUpper())
26 | };
27 |
28 | text += QString("Context\nRAX: %1\nRBX: %2\nRCX: %3\nRDX: %4\nRSP: %5\nRBP: %6\nRSI: %7\nRDI: %8\n")
29 | .arg(QString::number(response->context.generalRegisters.rax, 16).toUpper())
30 | .arg(QString::number(response->context.generalRegisters.rbx, 16).toUpper())
31 | .arg(QString::number(response->context.generalRegisters.rcx, 16).toUpper())
32 | .arg(QString::number(response->context.generalRegisters.rdx, 16).toUpper())
33 | .arg(QString::number(response->context.generalRegisters.rsp, 16).toUpper())
34 | .arg(QString::number(response->context.generalRegisters.rbp, 16).toUpper())
35 | .arg(QString::number(response->context.generalRegisters.rsi, 16).toUpper())
36 | .arg(QString::number(response->context.generalRegisters.rdi, 16).toUpper());
37 |
38 | text += QString("RIP: %1\n")
39 | .arg(QString::number(response->context.generalRegisters.rip, 16).toUpper());
40 |
41 | text += QString("R8: %1\nR9: %2\nR10: %3\nR11: %4\nR12: %5\nR13: %6\nR14: %7\nR15: %8\n\n")
42 | .arg(QString::number(response->context.generalRegistersx64.r8, 16).toUpper())
43 | .arg(QString::number(response->context.generalRegistersx64.r9, 16).toUpper())
44 | .arg(QString::number(response->context.generalRegistersx64.r10, 16).toUpper())
45 | .arg(QString::number(response->context.generalRegistersx64.r11, 16).toUpper())
46 | .arg(QString::number(response->context.generalRegistersx64.r12, 16).toUpper())
47 | .arg(QString::number(response->context.generalRegistersx64.r13, 16).toUpper())
48 | .arg(QString::number(response->context.generalRegistersx64.r14, 16).toUpper())
49 | .arg(QString::number(response->context.generalRegistersx64.r15, 16).toUpper());
50 |
51 | text += QString("DR0: %1\nDR1: %2\nDR2: %3\nDR3: %4\nDR6: %5\nDR7: %6\n\n")
52 | .arg(QString::number(response->context.debugRegisters.dr0, 16).toUpper())
53 | .arg(QString::number(response->context.debugRegisters.dr1, 16).toUpper())
54 | .arg(QString::number(response->context.debugRegisters.dr2, 16).toUpper())
55 | .arg(QString::number(response->context.debugRegisters.dr3, 16).toUpper())
56 | .arg(QString::number(response->context.debugRegisters.dr6, 16).toUpper())
57 | .arg(QString::number(response->context.debugRegisters.dr7, 16).toUpper());
58 |
59 | text += QString("CS: %1\nDS: %2\nES: %3\nFS: %4\nGS: %5\nSS: %6\n\n")
60 | .arg(QString::number(response->context.segmentRegisters.cs, 16).toUpper())
61 | .arg(QString::number(response->context.segmentRegisters.ds, 16).toUpper())
62 | .arg(QString::number(response->context.segmentRegisters.es, 16).toUpper())
63 | .arg(QString::number(response->context.segmentRegisters.fs, 16).toUpper())
64 | .arg(QString::number(response->context.segmentRegisters.gs, 16).toUpper())
65 | .arg(QString::number(response->context.segmentRegisters.ss, 16).toUpper());
66 |
67 | text += "Call stack\n";
68 | if (response->callStack.stackFramesCount > 0) {
69 | for (size_t i{ 0 }; i < response->callStack.stackFramesCount; i++) {
70 | const auto * stackFrame = response->callStack.stackFrames[i];
71 | text += QString("RIP: %1\nReturn Address: %2\nFrame Pointer: %3\nStack Pointer: %4\n")
72 | .arg(QString::number(stackFrame->rip, 16).toUpper())
73 | .arg(QString::number(stackFrame->returnAddress, 16).toUpper())
74 | .arg(QString::number(stackFrame->framePointer, 16).toUpper())
75 | .arg(QString::number(stackFrame->stackPointer, 16).toUpper());
76 |
77 | text += QString("Parameters\nParam 1: %1\nParam 2: %2\nParam 3: %3\nParam 4: %4\n")
78 | .arg(QString::number(stackFrame->parameters[0], 16).toUpper())
79 | .arg(QString::number(stackFrame->parameters[1], 16).toUpper())
80 | .arg(QString::number(stackFrame->parameters[2], 16).toUpper())
81 | .arg(QString::number(stackFrame->parameters[3], 16).toUpper());
82 |
83 | if (stackFrame->symbols.functionNameLength > 0) {
84 | text += QString("Function name: %1\n")
85 | .arg(stackFrame->symbols.functionName);
86 | }
87 |
88 | text += "\n";
89 | }
90 | }
91 |
92 | this->ui->textEdit_Breakpoint_info->setText(text);
93 | }
94 |
95 | void BreakpointInfoWindow::on_pushButton_Close_clicked()
96 | {
97 | this->close();
98 | }
99 |
--------------------------------------------------------------------------------
/Call Logger/breakpointinfowindow.h:
--------------------------------------------------------------------------------
1 | #ifndef BREAKPOINTINFOWINDOW_H
2 | #define BREAKPOINTINFOWINDOW_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include "thirdparty/include/TEDClientBridge.h"
9 |
10 | namespace Ui {
11 | class BreakpointInfoWindow;
12 | }
13 |
14 | class BreakpointInfoWindow : public QDialog
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 | explicit BreakpointInfoWindow(std::shared_ptr response, QWidget * parent = nullptr);
20 | ~BreakpointInfoWindow();
21 |
22 | private slots:
23 | void on_pushButton_Close_clicked();
24 |
25 | private:
26 | Ui::BreakpointInfoWindow * ui;
27 |
28 | void displayInfo(std::shared_ptr response);
29 | };
30 |
31 | #endif // BREAKPOINTINFOWINDOW_H
32 |
--------------------------------------------------------------------------------
/Call Logger/breakpointinfowindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | BreakpointInfoWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 1004
10 | 392
11 |
12 |
13 |
14 | Breakpoint Information
15 |
16 |
17 |
18 | icon/icon.icoicon/icon.ico
19 |
20 |
21 | -
22 |
23 |
24 | true
25 |
26 |
27 | true
28 |
29 |
30 |
31 | -
32 |
33 |
-
34 |
35 |
36 | Qt::Horizontal
37 |
38 |
39 |
40 | 40
41 | 20
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 | Close
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/Call Logger/disassembleaddresswindow.cpp:
--------------------------------------------------------------------------------
1 | #include "disassembleaddresswindow.h"
2 | #include "ui_disassembleaddresswindow.h"
3 |
4 | #include
5 |
6 | #include "errormessagedialog.h"
7 |
8 | DisassembleAddressWindow::DisassembleAddressWindow(TED_Client * client, QWidget * parent) :
9 | QDialog(parent)
10 | , ui(new Ui::DisassembleAddressWindow)
11 | , m_client{client}
12 | {
13 | ui->setupUi(this);
14 | }
15 |
16 | DisassembleAddressWindow::~DisassembleAddressWindow()
17 | {
18 | delete ui;
19 | }
20 |
21 | void DisassembleAddressWindow::on_pushButton_Close_clicked()
22 | {
23 | this->close();
24 | }
25 |
26 | void DisassembleAddressWindow::on_pushButton_Disassemble_clicked()
27 | {
28 | this->ui->tableWidget_Instructions->setRowCount(0);
29 |
30 | bool validAddress{ };
31 | auto address{ this->ui->lineEdit_Address->text().toULongLong(&validAddress, 16) };
32 | if (validAddress) {
33 | std::unique_ptr response{
35 | TED_DisassembleAddressFnc(m_client, address, 1024), TED_DestroyDisassembleAddressFnc };
36 | if (response != nullptr) {
37 | for (size_t i{ 0 }; i < response->instructionsCount; i++) {
38 | const auto& instruction{ response.get()->instructions[i] };
39 | this->ui->tableWidget_Instructions->insertRow(this->ui->tableWidget_Instructions->rowCount());
40 |
41 | QString hexBytes{ QByteArray::fromRawData(
42 | reinterpret_cast(&instruction->bytes[0]),
43 | instruction->bytesCount).toHex(' ') };
44 |
45 |
46 | QString fullInstruction{ instruction->mnemonic };
47 | fullInstruction += " ";
48 | fullInstruction += instruction->text;
49 |
50 | this->ui->tableWidget_Instructions->setItem(i, 0,
51 | new QTableWidgetItem(QString::number(instruction->address, 16)));
52 | this->ui->tableWidget_Instructions->setItem(i, 1, new QTableWidgetItem(hexBytes));
53 | this->ui->tableWidget_Instructions->setItem(i, 2, new QTableWidgetItem(fullInstruction));
54 | }
55 | } else {
56 | ErrorMessageDialog::show("Could not disassmeble address");
57 | }
58 | } else {
59 | ErrorMessageDialog::show("Address is not in a valid format");
60 | }
61 |
62 | ui->tableWidget_Instructions->resizeColumnsToContents();
63 | ui->tableWidget_Instructions->horizontalHeader()->stretchLastSection();
64 | }
65 |
--------------------------------------------------------------------------------
/Call Logger/disassembleaddresswindow.h:
--------------------------------------------------------------------------------
1 | #ifndef DISASSEMBLEADDRESSWINDOW_H
2 | #define DISASSEMBLEADDRESSWINDOW_H
3 |
4 | #include
5 | #include
6 |
7 | #include "thirdparty/include/TEDClientBridge.h"
8 |
9 | namespace Ui {
10 | class DisassembleAddressWindow;
11 | }
12 |
13 | class DisassembleAddressWindow : public QDialog
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit DisassembleAddressWindow(TED_Client * client, QWidget * parent = nullptr);
19 | ~DisassembleAddressWindow();
20 |
21 | private slots:
22 | void on_pushButton_Close_clicked();
23 |
24 | void on_pushButton_Disassemble_clicked();
25 |
26 | private:
27 | Ui::DisassembleAddressWindow * ui;
28 |
29 | TED_Client * m_client;
30 | };
31 |
32 | #endif // DISASSEMBLEADDRESSWINDOW_H
33 |
--------------------------------------------------------------------------------
/Call Logger/disassembleaddresswindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | DisassembleAddressWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 500
11 |
12 |
13 |
14 | Disassembly
15 |
16 |
17 |
18 | icon/icon.icoicon/icon.ico
19 |
20 |
21 | -
22 |
23 |
24 | QAbstractScrollArea::AdjustToContents
25 |
26 |
27 | QAbstractItemView::NoEditTriggers
28 |
29 |
30 | true
31 |
32 |
33 | QAbstractItemView::SingleSelection
34 |
35 |
36 | QAbstractItemView::SelectRows
37 |
38 |
39 | true
40 |
41 |
42 | false
43 |
44 |
45 | false
46 |
47 |
48 |
49 | Address
50 |
51 |
52 |
53 |
54 | Bytes
55 |
56 |
57 |
58 |
59 | Instruction
60 |
61 |
62 |
63 |
64 | -
65 |
66 |
-
67 |
68 |
69 | Address (hex):
70 |
71 |
72 |
73 | -
74 |
75 |
76 | 18
77 |
78 |
79 |
80 | -
81 |
82 |
83 | Qt::Horizontal
84 |
85 |
86 |
87 | 40
88 | 20
89 |
90 |
91 |
92 |
93 | -
94 |
95 |
96 | Disassemble
97 |
98 |
99 |
100 | -
101 |
102 |
103 | Close
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/Call Logger/errormessagedialog.cpp:
--------------------------------------------------------------------------------
1 | #include "errormessagedialog.h"
2 |
3 | ErrorMessageDialog::ErrorMessageDialog()
4 | {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/Call Logger/errormessagedialog.h:
--------------------------------------------------------------------------------
1 | #ifndef ERRORMESSAGEDIALOG_H
2 | #define ERRORMESSAGEDIALOG_H
3 |
4 | #include
5 |
6 | class ErrorMessageDialog
7 | {
8 | public:
9 |
10 | static void show(QString message)
11 | {
12 | QMessageBox errorMessage{ };
13 |
14 | errorMessage.setText(message);
15 | errorMessage.setIcon(QMessageBox::Critical);
16 | errorMessage.exec();
17 | }
18 | };
19 |
20 | #endif // ERRORMESSAGEDIALOG_H
21 |
--------------------------------------------------------------------------------
/Call Logger/icon/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codereversing/ted_api/ff84f289f59b5432187b6c25507712b0bc4e8369/Call Logger/icon/icon.ico
--------------------------------------------------------------------------------
/Call Logger/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 |
3 | #include
4 |
5 | #include "thirdparty/include/TEDClientBridge.h"
6 |
7 | int main(int argc, char * argv[])
8 | {
9 | if (!TED_LoadClientAPI("TEDClientAPI.dll")) {
10 | MessageBoxA(nullptr, "TEDClientAPI.dll was not found!", "Error", MB_ICONEXCLAMATION);
11 | exit(-1);
12 | }
13 |
14 | TED_ResolveClientFunctions(GetModuleHandleA("TEDClientAPI.dll"));
15 |
16 | QApplication a(argc, argv);
17 | MainWindow w;
18 | w.show();
19 | return a.exec();
20 | }
21 |
--------------------------------------------------------------------------------
/Call Logger/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include "./ui_mainwindow.h"
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "breakpointinfowindow.h"
11 | #include "disassembleaddresswindow.h"
12 | #include "errormessagedialog.h"
13 | #include "memorywindow.h"
14 | #include "moduleslistwindow.h"
15 | #include "processselectwindow.h"
16 |
17 | MainWindow::MainWindow(QWidget * parent)
18 | : QMainWindow(parent)
19 | , ui(new Ui::MainWindow)
20 | , m_client{}
21 | , m_breakpointReader{}
22 | , m_symbolPath{}
23 | , m_activeModules{}
24 | , m_moduleAddressRanges{}
25 | , m_addressToRow{}
26 | , m_lastBreakpointInfo{}
27 | , m_breakpointListenThread{}
28 | , m_showOffsets{}
29 | {
30 | ui->setupUi(this);
31 |
32 | ui->tableWidget_Calls->resizeColumnsToContents();
33 | ui->tableWidget_Calls->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
34 | }
35 |
36 | MainWindow::~MainWindow()
37 | {
38 | delete ui;
39 |
40 | TED_DestroyBreakpointReaderFnc(m_client);
41 | TED_DestroyClientFnc(m_client);
42 | }
43 |
44 | void MainWindow::sendOptionsUpdate()
45 | {
46 | TED_Options options{ };
47 |
48 | options.returnContext = ui->action_Return_context->isChecked();
49 | options.returnCallStack = ui->action_Return_call_stack->isChecked();
50 | options.returnSymbolInfo = ui->action_Return_symbols->isChecked();
51 | options.useInvasiveBreakpoints = ui->action_Use_invasive_breakpoints->isChecked();
52 | options.unsafeMemoryMode = ui->action_Unsafe_memory_mode->isChecked();
53 | options.autoDisableBreakpointsMode = ui->action_Auto_disable_incoming->isChecked();
54 | options.killProcessOnDisconnect = true;
55 |
56 | strncpy_s(options.symbolPath, m_symbolPath.toStdString().c_str(), m_symbolPath.length());
57 |
58 | std::unique_ptr response{
59 | TED_SetOptionsFnc(m_client, &options), TED_DestroyGenericFnc };
60 | }
61 |
62 | void MainWindow::on_action_Exit_triggered()
63 | {
64 | QCoreApplication::quit();
65 | }
66 |
67 | void MainWindow::on_action_Return_context_triggered(bool checked)
68 | {
69 | sendOptionsUpdate();
70 | }
71 |
72 | void MainWindow::on_action_Return_call_stack_triggered(bool checked)
73 | {
74 | sendOptionsUpdate();
75 | }
76 |
77 | void MainWindow::on_action_Return_symbols_triggered(bool checked)
78 | {
79 | sendOptionsUpdate();
80 | }
81 |
82 | void MainWindow::on_action_Use_invasive_breakpoints_triggered(bool checked)
83 | {
84 | sendOptionsUpdate();
85 | }
86 |
87 | void MainWindow::on_action_Unsafe_memory_mode_triggered(bool checked)
88 | {
89 | sendOptionsUpdate();
90 | }
91 |
92 | void MainWindow::on_action_Auto_disable_incoming_triggered(bool checked)
93 | {
94 | sendOptionsUpdate();
95 | }
96 |
97 | void MainWindow::on_action_Set_symbol_path_triggered()
98 | {
99 | auto symbolsPath{ QFileDialog::getExistingDirectory(
100 | this, tr("Open Symbols Directory"),
101 | "",
102 | QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks)
103 | };
104 |
105 | if (!symbolsPath.isEmpty()) {
106 | m_symbolPath = symbolsPath;
107 | }
108 |
109 | sendOptionsUpdate();
110 | }
111 |
112 | void MainWindow::on_action_Enable_console_triggered(bool checked)
113 | {
114 | std::unique_ptr response{ { }, TED_DestroyGenericFnc };
115 |
116 | if (checked) {
117 | response.reset(TED_CreateConsoleFnc(m_client));
118 | } else {
119 | response.reset(TED_DestroyConsoleFnc(m_client));
120 | }
121 | }
122 |
123 | void MainWindow::on_action_Enable_logging_triggered(bool checked)
124 | {
125 | std::unique_ptr response{ { }, TED_DestroyGenericFnc };
126 |
127 | if (checked) {
128 | response.reset(TED_EnableInternalLoggingFnc(m_client));
129 | } else {
130 | response.reset(TED_DisableInternalLoggingFnc(m_client));
131 | }
132 | }
133 |
134 | void MainWindow::on_action_Invoke_test_function_triggered()
135 | {
136 | std::unique_ptr response{
137 | TED_TestFunctionFnc(m_client), TED_DestroyGenericFnc };
138 | }
139 |
140 | void MainWindow::on_action_Attach_triggered()
141 | {
142 | QString activeProcessName{ };
143 | QString activeProcessId{ };
144 |
145 | ProcessSelectWindow processSelectWindow{ &activeProcessName, &activeProcessId };
146 |
147 | processSelectWindow.show();
148 | processSelectWindow.exec();
149 |
150 | if (!activeProcessName.isEmpty() && !activeProcessId.isEmpty()) {
151 |
152 | this->ui->tableWidget_Calls->setRowCount(0);
153 | this->setWindowTitle("TED Call Logger - Attached to " +
154 | activeProcessName + " (" +
155 | activeProcessId + ")");
156 |
157 | m_addressToRow.clear();
158 | m_activeModules.clear();
159 | m_moduleAddressRanges.clear();
160 | m_lastBreakpointInfo.clear();
161 |
162 | m_client = TED_CreateClientFnc("localhost:50051");
163 | if (m_client != nullptr) {
164 | m_breakpointReader = TED_CreateBreakpointReaderFnc(m_client);
165 | if (m_breakpointReader != nullptr) {
166 | sendOptionsUpdate();
167 |
168 | if (m_breakpointListenThread == nullptr) {
169 | m_breakpointListenThread.reset(
170 | new BreakpointListenThread(&m_client, &m_breakpointReader));
171 | this->connect(m_breakpointListenThread.get(), &BreakpointListenThread::breakpointEventReceived,
172 | this, &MainWindow::handleBreakpointResult);
173 | m_breakpointListenThread->start();
174 |
175 | this->ui->action_Attach->setEnabled(false);
176 | } else {
177 | ErrorMessageDialog::show("Could not initialize TED breakpoint reader");
178 | }
179 | }
180 | } else {
181 | ErrorMessageDialog::show("Could not initialize TED client");
182 | }
183 | }
184 | }
185 |
186 | void MainWindow::on_action_Get_modules_triggered()
187 | {
188 | ModulesListWindow modulesListWindow{ m_client, &m_activeModules, &m_moduleAddressRanges };
189 |
190 | modulesListWindow.show();
191 | modulesListWindow.exec();
192 | }
193 |
194 | void MainWindow::on_action_Disassemble_address_triggered()
195 | {
196 | DisassembleAddressWindow disassembleAddressWindow{ m_client };
197 |
198 | disassembleAddressWindow.show();
199 | disassembleAddressWindow.exec();
200 | }
201 |
202 | void MainWindow::on_action_Memory_triggered()
203 | {
204 | MemoryWindow memoryWindow{ m_client };
205 |
206 | memoryWindow.show();
207 | memoryWindow.exec();
208 | }
209 |
210 | void MainWindow::handleBreakpointResult(std::shared_ptr response)
211 | {
212 | auto address{ QString::number(response->sourceAddress) + "," + QString::number(response->destinationAddress) };
213 |
214 | m_lastBreakpointInfo[address] = response;
215 |
216 | int count{ 1 };
217 |
218 | if (m_addressToRow.contains(address)) {
219 | if (response->callStack.stackFramesCount > 0 &&
220 | response->callStack.stackFrames[0]->symbols.functionNameLength > 0)
221 | {
222 | m_addressToRow[address].at(2)->setText(response->callStack.stackFrames[0]->symbols.functionName);
223 | }
224 |
225 | count = m_addressToRow[address].at(3)->text().toULongLong();
226 | count++;
227 | m_addressToRow[address].at(3)->setText(QString::number(count));
228 | } else {
229 | this->ui->tableWidget_Calls->insertRow(this->ui->tableWidget_Calls->rowCount());
230 |
231 | auto sourceAddress{ new NumericTableWidgetItem(
232 | QString::number(response->sourceAddress, 16), 16) };
233 | auto destinationAddress{ new NumericTableWidgetItem(
234 | QString::number(response->destinationAddress, 16), 16) };
235 | QString destinationNameStr{ "" };
236 | if (response->callStack.stackFramesCount > 0 &&
237 | response->callStack.stackFrames[0]->symbols.functionNameLength > 0)
238 | {
239 | destinationNameStr = response->callStack.stackFrames[0]->symbols.functionName;
240 | }
241 | auto destinationName{ new QTableWidgetItem(destinationNameStr) };
242 | auto hitCount{ new NumericTableWidgetItem(QString::number(count)) };
243 |
244 | auto insertRow{ this->ui->tableWidget_Calls->rowCount() - 1 };
245 | this->ui->tableWidget_Calls->setItem(insertRow, 0, sourceAddress);
246 | this->ui->tableWidget_Calls->setItem(insertRow, 1, destinationAddress);
247 | this->ui->tableWidget_Calls->setItem(insertRow, 2, destinationName);
248 | this->ui->tableWidget_Calls->setItem(insertRow, 3, hitCount);
249 |
250 | m_addressToRow[address] = QList{ {
251 | sourceAddress, destinationAddress, destinationName, hitCount } };
252 | }
253 | }
254 |
255 | void MainWindow::on_tableWidget_Calls_cellDoubleClicked(int row, int column)
256 | {
257 | bool ok1{ }, ok2{ };
258 | auto address { QString::number(this->ui->tableWidget_Calls->item(row, 0)->text().toULongLong(&ok1, 16))
259 | + ","
260 | + QString::number(this->ui->tableWidget_Calls->item(row, 1)->text().toULongLong(&ok2, 16)) };
261 |
262 | if (ok1 && ok2 && m_lastBreakpointInfo.contains(address)) {
263 | BreakpointInfoWindow breakpointInfoWindow{ m_lastBreakpointInfo[address] };
264 | breakpointInfoWindow.show();
265 | breakpointInfoWindow.exec();
266 | }
267 | }
268 |
269 | void MainWindow::on_action_Disable_all_shown_triggered()
270 | {
271 | foreach(const auto& address, m_lastBreakpointInfo.keys()){
272 | bool ok{ };
273 | auto addressValue{ address.split(",")[0].toULongLong() };
274 | std::unique_ptr response{
275 | TED_DisableBreakCallByAddressFnc(m_client, addressValue), TED_DestroyGenericFnc };
276 | }
277 | }
278 |
279 | void MainWindow::on_action_Enable_all_shown_triggered()
280 | {
281 | foreach(const auto& address, m_lastBreakpointInfo.keys()){
282 | auto addressValue{ address.split(",")[0].toULongLong() };
283 | std::unique_ptr response{
284 | TED_EnableBreakCallByAddressFnc(m_client, addressValue), TED_DestroyGenericFnc };
285 | }
286 | }
287 |
288 | void MainWindow::on_action_Disable_custom_triggered()
289 | {
290 | bool ok{ };
291 | auto address{ QInputDialog::getText(this, tr("Disable breakpoint"),
292 | tr("Address (hex):"), QLineEdit::Normal, "", &ok) };
293 |
294 | if (ok && !address.isEmpty()) {
295 | auto addressValue{ address.split(",")[0].toULongLong() };
296 | std::unique_ptr response{
297 | TED_DisableBreakCallByAddressFnc(m_client, addressValue), TED_DestroyGenericFnc };
298 | }
299 | }
300 |
301 | void MainWindow::on_action_Enable_custom_triggered()
302 | {
303 | bool ok{ };
304 | auto address{ QInputDialog::getText(this, tr("Enable breakpoint"),
305 | tr("Address (hex):"), QLineEdit::Normal, "", &ok) };
306 |
307 | if (ok && !address.isEmpty()) {
308 | auto addressValue{ address.split(",")[0].toULongLong() };
309 | std::unique_ptr response{
310 | TED_EnableBreakCallByAddressFnc(m_client, addressValue), TED_DestroyGenericFnc };
311 | }
312 | }
313 |
314 | void MainWindow::on_action_Clear_triggered()
315 | {
316 | this->ui->tableWidget_Calls->setRowCount(0);
317 | m_addressToRow.clear();
318 | }
319 |
320 | QPair MainWindow::getModuleNameAndOffsetForAddress(uint64_t address)
321 | {
322 | foreach(const auto& addressRange, this->m_moduleAddressRanges.keys()){
323 | if (address >= addressRange.first && address <= addressRange.second) {
324 | auto shortName { m_moduleAddressRanges[addressRange]
325 | .right(m_moduleAddressRanges[addressRange].length()
326 | - (m_moduleAddressRanges[addressRange].lastIndexOf("\\") + 1)) };
327 | return QPair{ shortName, address - addressRange.first };
328 | }
329 | }
330 |
331 | return QPair{ "Unknown", 0 };
332 | }
333 |
334 | void MainWindow::on_tableWidget_Calls_customContextMenuRequested(const QPoint &pos)
335 | {
336 | auto menu{ new QMenu(this) };
337 | auto copyAction{ new QAction("Copy addresses", this) };
338 | auto removeAction{ new QAction("Remove", this) };
339 |
340 | copyAction->connect(copyAction, &QAction::triggered, this, [pos, copyAction, this]() {
341 | QTableWidgetItem * selection = this->ui->tableWidget_Calls->itemAt(pos);
342 | if (selection != nullptr) {
343 | bool ok{ };
344 | auto sourceAddressText{ this->ui->tableWidget_Calls->item(selection->row(), 0)->text() };
345 | auto destinationAddressText{ this->ui->tableWidget_Calls->item(selection->row(), 1)->text() };
346 | auto sourceAddress{ sourceAddressText.toULongLong(&ok, 16) };
347 | auto sourceModuleInfo{ getModuleNameAndOffsetForAddress(sourceAddress) };
348 | auto destinationAddress{ destinationAddressText.toULongLong(&ok, 16) };
349 | auto destinationModuleInfo{ getModuleNameAndOffsetForAddress(destinationAddress) };
350 | auto text{
351 | QString("Source: 0x%1 (%2+0x%3) \t Destination: 0x%4 (%5+0x%6)")
352 | .arg(sourceAddressText)
353 | .arg(sourceModuleInfo.first)
354 | .arg(QString::number(sourceModuleInfo.second, 16))
355 | .arg(this->ui->tableWidget_Calls->item(selection->row(), 1)->text())
356 | .arg(destinationModuleInfo.first)
357 | .arg(QString::number(destinationModuleInfo.second, 16))
358 | };
359 |
360 | QApplication::clipboard()->setText(text);
361 | }
362 | });
363 |
364 | removeAction->connect(removeAction, &QAction::triggered, this, [pos, removeAction, this]() {
365 | auto selection = this->ui->tableWidget_Calls->itemAt(pos);
366 | if (selection != nullptr) {
367 | this->ui->tableWidget_Calls->removeRow(selection->row());
368 | }
369 | });
370 |
371 | menu->addAction(copyAction);
372 | menu->addAction(removeAction);
373 |
374 | menu->popup(this->ui->tableWidget_Calls->viewport()->mapToGlobal(pos));
375 | }
376 |
377 | void MainWindow::on_action_About_triggered()
378 | {
379 | QMessageBox aboutBox{ };
380 |
381 | aboutBox.setTextFormat(Qt::RichText);
382 | aboutBox.setText("Created by Alex Abramov
"
383 | "Blog: https://www.codereversing.com
"
384 | "GitHub: https://github.com/codereversing");
385 | aboutBox.setStandardButtons(QMessageBox::Ok);
386 | aboutBox.exec();
387 | }
388 |
389 |
--------------------------------------------------------------------------------
/Call Logger/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include "thirdparty/include/TEDClientBridge.h"
18 |
19 | class BreakpointListenThread : public QThread
20 | {
21 | Q_OBJECT
22 |
23 | public:
24 | BreakpointListenThread(TED_Client ** client, TED_BreakpointReader ** reader)
25 | : m_client{client}
26 | , m_reader{reader}
27 | { }
28 |
29 | void run() override
30 | {
31 | while (true) {
32 | if (m_client != nullptr && m_reader != nullptr) {
33 | std::shared_ptr response{
34 | TED_GetBreakpointFnc(*m_client, *m_reader), TED_DestroyBreakpointFnc };
35 | if (response != nullptr) {
36 | emit breakpointEventReceived(response);
37 | } else {
38 | this->msleep(100);
39 | }
40 | }
41 | }
42 | }
43 |
44 | signals:
45 | void breakpointEventReceived(std::shared_ptr response);
46 |
47 | private:
48 | TED_Client ** m_client;
49 | TED_BreakpointReader ** m_reader;
50 | };
51 |
52 | QT_BEGIN_NAMESPACE
53 | namespace Ui { class MainWindow;
54 | }
55 | QT_END_NAMESPACE
56 |
57 | class MainWindow : public QMainWindow
58 | {
59 | Q_OBJECT
60 |
61 | public:
62 | MainWindow(QWidget * parent = nullptr);
63 | ~MainWindow();
64 |
65 | private slots:
66 | void on_action_Exit_triggered();
67 | void on_action_Return_context_triggered(bool checked);
68 | void on_action_Return_call_stack_triggered(bool checked);
69 | void on_action_Return_symbols_triggered(bool checked);
70 | void on_action_Set_symbol_path_triggered();
71 | void on_action_Enable_console_triggered(bool checked);
72 | void on_action_Enable_logging_triggered(bool checked);
73 | void on_action_Invoke_test_function_triggered();
74 | void on_action_Attach_triggered();
75 | void on_action_Get_modules_triggered();
76 | void on_action_Disassemble_address_triggered();
77 | void on_action_Memory_triggered();
78 | void on_tableWidget_Calls_cellDoubleClicked(int row, int column);
79 | void on_action_Use_invasive_breakpoints_triggered(bool checked);
80 | void on_action_Unsafe_memory_mode_triggered(bool checked);
81 | void on_action_Disable_all_shown_triggered();
82 | void on_action_Disable_custom_triggered();
83 | void on_action_Enable_all_shown_triggered();
84 | void on_action_Enable_custom_triggered();
85 | void on_action_Clear_triggered();
86 | void on_action_Auto_disable_incoming_triggered(bool checked);
87 | void on_tableWidget_Calls_customContextMenuRequested(const QPoint &pos);
88 | void on_action_About_triggered();
89 |
90 | public slots:
91 | void handleBreakpointResult(std::shared_ptr response);
92 |
93 | private:
94 | Ui::MainWindow * ui;
95 |
96 | void sendOptionsUpdate();
97 |
98 | QPair getModuleNameAndOffsetForAddress(uint64_t address);
99 |
100 | TED_Client * m_client;
101 | TED_BreakpointReader * m_breakpointReader;
102 |
103 | QSet m_activeModules;
104 | QMap, QString> m_moduleAddressRanges;
105 |
106 | QString m_symbolPath;
107 | QMap > m_addressToRow;
108 | QMap > m_lastBreakpointInfo;
109 |
110 | std::unique_ptr m_breakpointListenThread;
111 |
112 | bool m_showOffsets;
113 | };
114 | #endif // MAINWINDOW_H
115 |
--------------------------------------------------------------------------------
/Call Logger/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 945
10 | 360
11 |
12 |
13 |
14 | TED Call Logger
15 |
16 |
17 |
18 | icon/icon.icoicon/icon.ico
19 |
20 |
21 |
22 | -
23 |
24 |
-
25 |
26 |
27 | Qt::CustomContextMenu
28 |
29 |
30 | Qt::ScrollBarAlwaysOff
31 |
32 |
33 | QAbstractScrollArea::AdjustToContents
34 |
35 |
36 | QAbstractItemView::NoEditTriggers
37 |
38 |
39 | true
40 |
41 |
42 | QAbstractItemView::SingleSelection
43 |
44 |
45 | QAbstractItemView::SelectRows
46 |
47 |
48 | true
49 |
50 |
51 | true
52 |
53 |
54 | true
55 |
56 |
57 | false
58 |
59 |
60 |
61 | Source Address
62 |
63 |
64 |
65 |
66 | Destination Address
67 |
68 |
69 |
70 |
71 | Destination Name
72 |
73 |
74 |
75 |
76 | Count
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
157 |
158 |
159 |
160 | toolBar
161 |
162 |
163 | TopToolBarArea
164 |
165 |
166 | false
167 |
168 |
169 |
170 |
171 | Exit
172 |
173 |
174 |
175 |
176 | Disable custom
177 |
178 |
179 |
180 |
181 | false
182 |
183 |
184 | Disable all shown
185 |
186 |
187 |
188 |
189 | Attach
190 |
191 |
192 |
193 |
194 | true
195 |
196 |
197 | true
198 |
199 |
200 | Return context
201 |
202 |
203 |
204 |
205 | true
206 |
207 |
208 | true
209 |
210 |
211 | Return call stack
212 |
213 |
214 |
215 |
216 | true
217 |
218 |
219 | true
220 |
221 |
222 | Return symbols
223 |
224 |
225 |
226 |
227 | Set symbol path
228 |
229 |
230 |
231 |
232 | Modules
233 |
234 |
235 |
236 |
237 | Disassemble address
238 |
239 |
240 |
241 |
242 | Invoke test function
243 |
244 |
245 |
246 |
247 | true
248 |
249 |
250 | Enable console
251 |
252 |
253 |
254 |
255 | true
256 |
257 |
258 | Enable logging
259 |
260 |
261 |
262 |
263 | Memory
264 |
265 |
266 |
267 |
268 | true
269 |
270 |
271 | true
272 |
273 |
274 | Use invasive breakpoints (faster)
275 |
276 |
277 |
278 |
279 | Enable all shown
280 |
281 |
282 |
283 |
284 | Enable custom
285 |
286 |
287 |
288 |
289 | Clear
290 |
291 |
292 |
293 |
294 | true
295 |
296 |
297 | Unsafe memory mode
298 |
299 |
300 |
301 |
302 | true
303 |
304 |
305 | Auto-disable incoming
306 |
307 |
308 |
309 |
310 | About
311 |
312 |
313 |
314 |
315 |
316 |
317 |
--------------------------------------------------------------------------------
/Call Logger/memorywindow.cpp:
--------------------------------------------------------------------------------
1 | #include "memorywindow.h"
2 | #include "thirdparty/include/Structures.h"
3 | #include "ui_memorywindow.h"
4 |
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | #include "errormessagedialog.h"
11 |
12 | MemoryWindow::MemoryWindow(TED_Client * client, QWidget * parent) :
13 | QDialog(parent),
14 | ui(new Ui::MemoryWindow)
15 | , m_client{client}
16 | , m_previousByteValues{}
17 | {
18 | ui->setupUi(this);
19 |
20 | ui->tableWidget_Bytes->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
21 | ui->tableWidget_Bytes->resizeColumnsToContents();
22 | }
23 |
24 | MemoryWindow::~MemoryWindow()
25 | {
26 | delete ui;
27 | }
28 |
29 | void MemoryWindow::on_pushButton_Close_clicked()
30 | {
31 | this->close();
32 | }
33 |
34 | void MemoryWindow::on_pushButton_Save_clicked()
35 | {
36 | bool validAddress{ };
37 | auto address{ this->ui->lineEdit_Address->text().toULongLong(&validAddress, 16) };
38 |
39 | if (validAddress) {
40 | QMap writeBytesMap{ };
41 | uint64_t writeOffset{ };
42 | for (auto i{ 0 }; i < this->ui->tableWidget_Bytes->rowCount(); i++) {
43 | for (auto j{ 1 }; j < this->ui->tableWidget_Bytes->columnCount(); j++) {
44 | auto currentByte{ this->ui->tableWidget_Bytes->item(i, j) };
45 | if (currentByte->background() == Qt::red) {
46 | auto byteArray{ QByteArray::fromHex(
47 | this->ui->tableWidget_Bytes->item(i, j)->text().toUtf8()) };
48 | writeBytesMap[address + writeOffset] = static_cast(byteArray.at(0));
49 | }
50 |
51 | writeOffset++;
52 | }
53 | }
54 |
55 | foreach(const auto& writeAddress, writeBytesMap.keys()){
56 | std::unique_ptr response{
57 | TED_WriteMemoryFnc(m_client, writeAddress, &writeBytesMap[writeAddress], 1),
58 | TED_DestroyGenericFnc };
59 | }
60 | } else {
61 | ErrorMessageDialog::show("Address to write to is not valid");
62 | }
63 | }
64 |
65 | void MemoryWindow::on_pushButton_Read_clicked()
66 | {
67 | this->ui->tableWidget_Bytes->setRowCount(0);
68 |
69 | m_previousByteValues.clear();
70 |
71 | bool validAddress{ };
72 | auto address{ this->ui->lineEdit_Address->text().toULongLong(&validAddress, 16) };
73 | if (validAddress) {
74 | std::unique_ptr response{
75 | TED_ReadMemoryFnc(m_client, address, 512), TED_DestroyReadMemoryFnc };
76 | if (response != nullptr) {
77 | QString hexBytes{ QByteArray::fromRawData(
78 | reinterpret_cast(&response->bytes[0]),
79 | response->bytesCount).toHex(' ') };
80 | auto hexBytesSplit{ hexBytes.split(' ') };
81 |
82 | int i{ };
83 | int column{ };
84 | while (i < hexBytesSplit.size()) {
85 | int row{ i / (this->ui->tableWidget_Bytes->columnCount() - 1) };
86 | if (column == 0 || column == this->ui->tableWidget_Bytes->columnCount()) {
87 | this->ui->tableWidget_Bytes->insertRow(this->ui->tableWidget_Bytes->rowCount());
88 | auto newItem{ new QTableWidgetItem(QString::number(address, 16)) };
89 | newItem->setFlags(newItem->flags() ^ Qt::ItemIsEditable);
90 | this->ui->tableWidget_Bytes->setItem(row, 0, newItem);
91 | address += (this->ui->tableWidget_Bytes->columnCount() - 1);
92 | column = 1;
93 | } else {
94 | this->ui->tableWidget_Bytes->setItem(row, column,
95 | new QTableWidgetItem(hexBytesSplit[i].toUpper()));
96 | column++;
97 | i++;
98 | }
99 | }
100 | } else {
101 | ErrorMessageDialog::show("Error reading memory");
102 | }
103 | } else {
104 | ErrorMessageDialog::show("Address to read from is not valid");
105 | }
106 |
107 | ui->tableWidget_Bytes->resizeColumnsToContents();
108 | ui->tableWidget_Bytes->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
109 | }
110 |
111 | void MemoryWindow::on_tableWidget_Bytes_itemChanged(QTableWidgetItem * item)
112 | {
113 | ui->tableWidget_Bytes->blockSignals(true);
114 |
115 | auto selection{ this->ui->tableWidget_Bytes->selectedItems() };
116 | if (selection.size() > 0) {
117 | auto key{ QString::number(selection.at(0)->row(), 10) + QString{ "," }
118 | + QString::number(selection.at(0)->column()) };
119 | auto currentByteValue{ selection.at(0)->text().toUpper() };
120 | if (m_previousByteValues[key] != currentByteValue) {
121 | item->setBackground(Qt::red);
122 | } else {
123 | item->setBackground(Qt::white);
124 | }
125 |
126 | item->setText(item->text().toUpper());
127 | }
128 |
129 | ui->tableWidget_Bytes->blockSignals(false);
130 | }
131 |
132 | void MemoryWindow::on_tableWidget_Bytes_itemSelectionChanged()
133 | {
134 | auto selection{ this->ui->tableWidget_Bytes->selectedItems() };
135 |
136 | if (selection.size() > 0) {
137 | auto key{ QString::number(selection.at(0)->row(), 10) + QString{ "," }
138 | + QString::number(selection.at(0)->column()) };
139 | if (!m_previousByteValues.contains(key)) {
140 | m_previousByteValues[key] = selection.at(0)->text().toUpper();
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/Call Logger/memorywindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MEMORYWINDOW_H
2 | #define MEMORYWINDOW_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "thirdparty/include/TEDClientBridge.h"
9 |
10 | namespace Ui {
11 | class MemoryWindow;
12 | }
13 |
14 | class MemoryWindow : public QDialog
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 | explicit MemoryWindow(TED_Client * client, QWidget * parent = nullptr);
20 | ~MemoryWindow();
21 |
22 | private slots:
23 | void on_pushButton_Close_clicked();
24 | void on_pushButton_Save_clicked();
25 | void on_pushButton_Read_clicked();
26 | void on_tableWidget_Bytes_itemChanged(QTableWidgetItem * item);
27 | void on_tableWidget_Bytes_itemSelectionChanged();
28 |
29 | private:
30 | Ui::MemoryWindow * ui;
31 |
32 | TED_Client * m_client;
33 |
34 | QMap m_previousByteValues;
35 | };
36 |
37 | #endif // MEMORYWINDOW_H
38 |
--------------------------------------------------------------------------------
/Call Logger/memorywindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MemoryWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 500
11 |
12 |
13 |
14 | Dialog
15 |
16 |
17 |
18 | icon/icon.icoicon/icon.ico
19 |
20 |
21 | -
22 |
23 |
-
24 |
25 |
26 | QAbstractScrollArea::AdjustToContents
27 |
28 |
29 | QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed
30 |
31 |
32 | QAbstractItemView::SingleSelection
33 |
34 |
35 | false
36 |
37 |
38 |
39 | Base address
40 |
41 |
42 |
43 |
44 | +0
45 |
46 |
47 |
48 |
49 | +1
50 |
51 |
52 |
53 |
54 | +2
55 |
56 |
57 |
58 |
59 | +3
60 |
61 |
62 |
63 |
64 | +4
65 |
66 |
67 |
68 |
69 | +5
70 |
71 |
72 |
73 |
74 | +6
75 |
76 |
77 |
78 |
79 | +7
80 |
81 |
82 |
83 |
84 | +8
85 |
86 |
87 |
88 |
89 | +9
90 |
91 |
92 |
93 |
94 | +A
95 |
96 |
97 |
98 |
99 | +B
100 |
101 |
102 |
103 |
104 | +C
105 |
106 |
107 |
108 |
109 | +D
110 |
111 |
112 |
113 |
114 | +E
115 |
116 |
117 |
118 |
119 | +F
120 |
121 |
122 |
123 |
124 |
125 |
126 | -
127 |
128 |
-
129 |
130 |
131 | Address (hex):
132 |
133 |
134 |
135 | -
136 |
137 |
138 | 18
139 |
140 |
141 |
142 | -
143 |
144 |
145 | Qt::Horizontal
146 |
147 |
148 |
149 | 40
150 | 20
151 |
152 |
153 |
154 |
155 | -
156 |
157 |
158 | Read
159 |
160 |
161 |
162 | -
163 |
164 |
165 | Save
166 |
167 |
168 |
169 | -
170 |
171 |
172 | Close
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/Call Logger/moduleslistwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "moduleslistwindow.h"
2 | #include "ui_moduleslistwindow.h"
3 |
4 | #include "errormessagedialog.h"
5 | #include "numerictablewidgetitem.h"
6 |
7 | #include "thirdparty/include/TEDClientBridge.h"
8 |
9 | ModulesListWindow::ModulesListWindow(TED_Client * client,
10 | QSet * activeModules,
11 | QMap, QString> * moduleAddressRanges,
12 | QWidget * parent) :
13 | QDialog(parent)
14 | , ui(new Ui::ModulesListWindow)
15 | , m_client{client}
16 | , m_activeModules{activeModules}
17 | , m_moduleAddressRanges{moduleAddressRanges}
18 | , m_moduleNamesMap{}
19 | {
20 | ui->setupUi(this);
21 |
22 | refreshModules();
23 | }
24 |
25 | ModulesListWindow::~ModulesListWindow()
26 | {
27 | delete ui;
28 | }
29 |
30 | void ModulesListWindow::on_pushButton_Close_clicked()
31 | {
32 | this->close();
33 | }
34 |
35 | void ModulesListWindow::refreshModules()
36 | {
37 | this->ui->tableWidget_Modules->setRowCount(0);
38 |
39 | std::unique_ptr response{ TED_GetModulesFnc(m_client), TED_DestroyModulesFnc };
41 | if (response != nullptr) {
42 | m_moduleAddressRanges->clear();
43 |
44 | for (size_t i{ 0 }; i < response->moduleInfoCount; i++) {
45 | const auto& module{ response.get()->moduleInfo[i] };
46 | this->ui->tableWidget_Modules->insertRow(this->ui->tableWidget_Modules->rowCount());
47 |
48 | QString moduleName{ module->name };
49 | moduleName = moduleName.right(moduleName.length() - (moduleName.lastIndexOf("\\") + 1));
50 | m_moduleNamesMap[moduleName] = module->name;
51 |
52 | this->ui->tableWidget_Modules->setItem(i, 0, new QTableWidgetItem(moduleName));
53 | this->ui->tableWidget_Modules->setItem(i, 1,
54 | new NumericTableWidgetItem(QString::number(module->baseAddress, 16), 16));
55 | this->ui->tableWidget_Modules->setItem(i, 2,
56 | new NumericTableWidgetItem(QString::number(module->size, 16), 16));
57 |
58 | QString isActive = m_activeModules->contains(moduleName) ? "Yes" : "No";
59 | this->ui->tableWidget_Modules->setItem(i, 3, new QTableWidgetItem(isActive));
60 |
61 | auto newKey{ QPair(
62 | module->baseAddress, module->baseAddress + module->size) };
63 | m_moduleAddressRanges->insert(newKey, QString{ module->name });
64 | }
65 | } else {
66 | ErrorMessageDialog::show("Error getting module list");
67 | }
68 |
69 | ui->tableWidget_Modules->resizeColumnsToContents();
70 | ui->tableWidget_Modules->horizontalHeader()->stretchLastSection();
71 | }
72 |
73 | void ModulesListWindow::on_pushButton_Log_calls_clicked()
74 | {
75 | auto selection{ this->ui->tableWidget_Modules->selectedItems() };
76 |
77 | if (selection.size() > 0) {
78 | auto moduleName{ selection.at(0)->text() };
79 | if (!m_activeModules->contains(moduleName)) {
80 | auto fullModuleName{ m_moduleNamesMap[moduleName] };
81 | std::unique_ptr response{
82 | TED_EnableBreakAllCallsInModuleFnc(m_client, fullModuleName.toStdString().c_str()),
83 | TED_DestroyGenericFnc };
84 | if (response != nullptr) {
85 | this->ui->tableWidget_Modules->item(selection.at(0)->row(), 3)->setText("Yes");
86 | m_activeModules->insert(moduleName);
87 | }
88 | }
89 | }
90 | }
91 |
92 | void ModulesListWindow::on_pushButton_Stop_logging_calls_clicked()
93 | {
94 | auto selection{ this->ui->tableWidget_Modules->selectedItems() };
95 |
96 | if (selection.size() > 0) {
97 | auto moduleName{ selection.at(0)->text() };
98 | if (m_activeModules->contains(moduleName)) {
99 | auto fullModuleName{ m_moduleNamesMap[moduleName] };
100 | std::unique_ptr response{
101 | TED_DisableBreakAllCallsInModuleFnc(m_client, fullModuleName.toStdString().c_str()),
102 | TED_DestroyGenericFnc };
103 | if (response != nullptr) {
104 | this->ui->tableWidget_Modules->item(selection.at(0)->row(), 3)->setText("No");
105 | m_activeModules->remove(moduleName);
106 | }
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/Call Logger/moduleslistwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MODULESLISTWINDOW_H
2 | #define MODULESLISTWINDOW_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "numerictablewidgetitem.h"
12 |
13 | #include "thirdparty/include/TEDClientBridge.h"
14 |
15 | namespace Ui {
16 | class ModulesListWindow;
17 | }
18 |
19 | class ModulesListWindow : public QDialog
20 | {
21 | Q_OBJECT
22 |
23 | public:
24 | explicit ModulesListWindow(TED_Client * client,
25 | QSet * activeModules,
26 | QMap, QString> * moduleAddressRanges,
27 | QWidget * parent = nullptr);
28 |
29 | ~ModulesListWindow();
30 |
31 | private slots:
32 | void on_pushButton_Close_clicked();
33 | void on_pushButton_Log_calls_clicked();
34 | void on_pushButton_Stop_logging_calls_clicked();
35 |
36 | private:
37 | Ui::ModulesListWindow * ui;
38 |
39 | void refreshModules();
40 |
41 | TED_Client * m_client;
42 |
43 | QSet * m_activeModules;
44 | QMap, QString> * m_moduleAddressRanges;
45 |
46 | QMap m_moduleNamesMap;
47 | };
48 |
49 | #endif // MODULESLISTWINDOW_H
50 |
--------------------------------------------------------------------------------
/Call Logger/moduleslistwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | ModulesListWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 700
10 | 300
11 |
12 |
13 |
14 | Modules
15 |
16 |
17 |
18 | icon/icon.icoicon/icon.ico
19 |
20 |
21 | -
22 |
23 |
-
24 |
25 |
26 | QAbstractScrollArea::AdjustToContents
27 |
28 |
29 | QAbstractItemView::NoEditTriggers
30 |
31 |
32 | true
33 |
34 |
35 | QAbstractItemView::SingleSelection
36 |
37 |
38 | QAbstractItemView::SelectRows
39 |
40 |
41 | true
42 |
43 |
44 | true
45 |
46 |
47 | false
48 |
49 |
50 |
51 | Module name
52 |
53 |
54 |
55 |
56 | Base address
57 |
58 |
59 |
60 |
61 | Size
62 |
63 |
64 |
65 |
66 | Being traced
67 |
68 |
69 |
70 |
71 |
72 |
73 | -
74 |
75 |
-
76 |
77 |
78 | Qt::Horizontal
79 |
80 |
81 |
82 | 40
83 | 20
84 |
85 |
86 |
87 |
88 | -
89 |
90 |
91 | Log calls
92 |
93 |
94 |
95 | -
96 |
97 |
98 | Stop logging calls
99 |
100 |
101 |
102 | -
103 |
104 |
105 | Close
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/Call Logger/numerictablewidgetitem.h:
--------------------------------------------------------------------------------
1 | #ifndef NUMERICTABLEWIDGETITEM_H
2 | #define NUMERICTABLEWIDGETITEM_H
3 |
4 | #include
5 |
6 | class NumericTableWidgetItem : public QTableWidgetItem
7 | {
8 | public:
9 | NumericTableWidgetItem(const QString text, int base = 10)
10 | : QTableWidgetItem(text)
11 | , m_base{base}
12 | { }
13 |
14 | bool operator < (const QTableWidgetItem &other) const
15 | {
16 | bool ok{ };
17 |
18 | return text().toULongLong(&ok, m_base) < other.text().toULongLong(&ok, m_base);
19 | }
20 |
21 | private:
22 | int m_base;
23 | };
24 |
25 | #endif // NUMERICTABLEWIDGETITEM_H
26 |
--------------------------------------------------------------------------------
/Call Logger/processelectwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef PROCESSELECTWINDOW_H
2 | #define PROCESSELECTWINDOW_H
3 |
4 | #include
5 |
6 | namespace Ui {
7 | class ProcessSelectWindow;
8 | }
9 |
10 | class ProcessSelectWindow : public QDialog
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit ProcessSelectWindow(QWidget *parent = nullptr);
16 | ~ProcessSelectWindow();
17 |
18 | private slots:
19 | void on_pushButton_close_clicked();
20 |
21 | void on_pushButton_attach_clicked();
22 |
23 | void on_pushButton_refresh_clicked();
24 |
25 | private:
26 | Ui::ProcessSelectWindow *ui;
27 |
28 | void refreshActiveProcesses();
29 | };
30 |
31 | #endif // PROCESSELECTWINDOW_H
32 |
--------------------------------------------------------------------------------
/Call Logger/processselectwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "processselectwindow.h"
2 | #include "ui_processselectwindow.h"
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "errormessagedialog.h"
11 | #include "numerictablewidgetitem.h"
12 |
13 | #include "thirdparty/include/TEDClientBridge.h"
14 |
15 | ProcessSelectWindow::ProcessSelectWindow(QString * activeProcessName,
16 | QString * activeProcessId,
17 | QWidget * parent) :
18 | QDialog(parent)
19 | , ui(new Ui::ProcessSelectWindow)
20 | , m_activeProcessName{activeProcessName}
21 | , m_activeProcessId{activeProcessId}
22 | {
23 | ui->setupUi(this);
24 |
25 | QFileInfo maybeDllPath{ QDir::currentPath() + QDir::separator() + "tedcore.dll" };
26 | if (maybeDllPath.exists() && maybeDllPath.isFile()) {
27 | this->ui->lineEdit_Server_dll_path->setText(maybeDllPath.absoluteFilePath());
28 | }
29 |
30 | refreshActiveProcesses();
31 | }
32 |
33 | ProcessSelectWindow::~ProcessSelectWindow()
34 | {
35 | delete ui;
36 | }
37 |
38 | void ProcessSelectWindow::on_pushButton_Close_clicked()
39 | {
40 | this->close();
41 | }
42 |
43 | void ProcessSelectWindow::on_pushButton_Attach_clicked()
44 | {
45 | attachToProcessAndClose();
46 | }
47 |
48 | void ProcessSelectWindow::on_tableWidget_Processes_itemDoubleClicked(QTableWidgetItem * item)
49 | {
50 | attachToProcessAndClose();
51 | }
52 |
53 | void ProcessSelectWindow::on_pushButton_Refresh_clicked()
54 | {
55 | refreshActiveProcesses();
56 | }
57 |
58 | void ProcessSelectWindow::on_pushButton_Find_server_dll_clicked()
59 | {
60 | auto serverDllPath{ QFileDialog::getOpenFileName(this,
61 | tr("Find TED Server Dll"), "", tr("Dll Files (*.dll)")) };
62 |
63 | if (!serverDllPath.isEmpty()) {
64 | this->ui->lineEdit_Server_dll_path->setText(serverDllPath);
65 | }
66 | }
67 |
68 | void ProcessSelectWindow::refreshActiveProcesses()
69 | {
70 | this->ui->tableWidget_Processes->setRowCount(0);
71 |
72 | size_t processCount{ };
73 | auto deleter = [&](auto ** ptr){
74 | TED_DestroyActiveProcessesInformationFnc(ptr, processCount);
75 | };
76 | std::unique_ptr response{
77 | TED_GetActiveProcessesInformation(&processCount), deleter };
78 |
79 | int insertIndex{};
80 | for (size_t i{ 0 }; i < processCount; i++) {
81 | const auto& process{ response.get()[i] };
82 |
83 | if (m_activeProcessId->isEmpty() || (process->processId != m_activeProcessId->toULong())) {
84 | this->ui->tableWidget_Processes->insertRow(this->ui->tableWidget_Processes->rowCount());
85 |
86 | this->ui->tableWidget_Processes->setItem(insertIndex, 0, new NumericTableWidgetItem(QString::number(process->processId)));
87 | this->ui->tableWidget_Processes->setItem(insertIndex, 1, new QTableWidgetItem(process->name));
88 | this->ui->tableWidget_Processes->setItem(insertIndex, 2, new QTableWidgetItem(process->windowTitle));
89 | this->ui->tableWidget_Processes->setItem(insertIndex, 3, new QTableWidgetItem(process->path));
90 | insertIndex++;
91 | }
92 | }
93 |
94 | ui->tableWidget_Processes->resizeColumnsToContents();
95 | ui->tableWidget_Processes->horizontalHeader()->stretchLastSection();
96 | }
97 |
98 | void ProcessSelectWindow::attachToProcessAndClose()
99 | {
100 | auto selection{ this->ui->tableWidget_Processes->selectedItems() };
101 |
102 | if (selection.size() > 0) {
103 | auto serverDllPath{ this->ui->lineEdit_Server_dll_path->text() };
104 | if (!serverDllPath.isEmpty()) {
105 | auto selectedProcessId = selection.at(0)->text();
106 | auto selectedProcessName = selection.at(1)->text();
107 |
108 | if (!selectedProcessId.isEmpty()) {
109 | TED_TerminateProcess(m_activeProcessId->toULong());
110 | }
111 |
112 | auto injected{ TED_InjectIntoProcess(selection.at(0)->text().toULong(),
113 | serverDllPath.toStdString().c_str()) };
114 | if (injected) {
115 | *m_activeProcessId = selectedProcessId;
116 | *m_activeProcessName = selectedProcessName;
117 | } else {
118 | ErrorMessageDialog::show("Could not inject TED dll to target");
119 | }
120 |
121 | this->close();
122 | } else {
123 | ErrorMessageDialog::show("Server dll path is not valid");
124 | }
125 | } else {
126 | ErrorMessageDialog::show("Process to inject to is not selected");
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/Call Logger/processselectwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef PROCESSELECTWINDOW_H
2 | #define PROCESSELECTWINDOW_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | namespace Ui {
10 | class ProcessSelectWindow;
11 | }
12 |
13 | class ProcessSelectWindow : public QDialog
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit ProcessSelectWindow(QString * activeProcessName,
19 | QString * activeProcessId,
20 | QWidget * parent = nullptr);
21 | ~ProcessSelectWindow();
22 |
23 | private slots:
24 | void on_pushButton_Close_clicked();
25 | void on_pushButton_Attach_clicked();
26 | void on_pushButton_Refresh_clicked();
27 | void on_tableWidget_Processes_itemDoubleClicked(QTableWidgetItem * item);
28 | void on_pushButton_Find_server_dll_clicked();
29 |
30 | private:
31 | Ui::ProcessSelectWindow * ui;
32 |
33 | void refreshActiveProcesses();
34 | void attachToProcessAndClose();
35 |
36 | QString * m_activeProcessName;
37 | QString * m_activeProcessId;
38 | };
39 |
40 | #endif // PROCESSELECTWINDOW_H
41 |
--------------------------------------------------------------------------------
/Call Logger/processselectwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | ProcessSelectWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 1200
10 | 360
11 |
12 |
13 |
14 | Select target process
15 |
16 |
17 |
18 | icon/icon.icoicon/icon.ico
19 |
20 |
21 | -
22 |
23 |
24 | QAbstractScrollArea::AdjustToContents
25 |
26 |
27 | QAbstractItemView::NoEditTriggers
28 |
29 |
30 | true
31 |
32 |
33 | QAbstractItemView::SingleSelection
34 |
35 |
36 | QAbstractItemView::SelectRows
37 |
38 |
39 | true
40 |
41 |
42 | 100
43 |
44 |
45 | true
46 |
47 |
48 | false
49 |
50 |
51 |
52 | ID
53 |
54 |
55 |
56 |
57 | Name
58 |
59 |
60 |
61 |
62 | Window Title
63 |
64 |
65 |
66 |
67 | Path
68 |
69 |
70 |
71 |
72 | -
73 |
74 |
-
75 |
76 |
77 | Server DLL Path:
78 |
79 |
80 |
81 | -
82 |
83 |
84 | true
85 |
86 |
87 |
88 | -
89 |
90 |
91 | ...
92 |
93 |
94 |
95 | -
96 |
97 |
98 | Refresh
99 |
100 |
101 |
102 | -
103 |
104 |
105 | Attach
106 |
107 |
108 |
109 | -
110 |
111 |
112 | Close
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/Call Logger/thirdparty/include/Api.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef TED_API_H
4 | #define TED_API_H
5 |
6 | #include
7 |
8 | #include "Structures.h"
9 |
10 | extern "C"
11 | {
12 |
13 | #define SYMBOL_MAX_PATH 255
14 |
15 | typedef struct
16 | {
17 | bool returnCallStack;
18 | bool returnContext;
19 | bool returnSymbolInfo;
20 | bool useInvasiveBreakpoints;
21 | bool unsafeMemoryMode;
22 | bool autoDisableBreakpointsMode;
23 | bool killProcessOnDisconnect;
24 | char symbolPath[SYMBOL_MAX_PATH];
25 | } TED_Options;
26 |
27 | __declspec(dllexport) TED_Client* TED_CreateClient(const char* uri);
28 | __declspec(dllexport) void TED_DestroyClient(TED_Client* client);
29 |
30 | __declspec(dllexport) TED_BreakpointReader* TED_CreateBreakpointReader(TED_Client* client);
31 | __declspec(dllexport) void TED_DestroyBreakpointReader(TED_BreakpointReader* reader);
32 |
33 | __declspec(dllexport) TED_BreakpointResponse* TED_GetBreakpoint(TED_Client* client, TED_BreakpointReader* reader);
34 | __declspec(dllexport) void TED_DestroyBreakpoint(TED_BreakpointResponse* response);
35 |
36 | __declspec(dllexport) TED_GetModulesResponse* TED_GetModules(TED_Client* client);
37 | __declspec(dllexport) void TED_DestroyModules(TED_GetModulesResponse* response);
38 |
39 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakAllCallsInModule(TED_Client* client, const char* name);
40 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakAllCallsInModule(TED_Client* client, const char* name);
41 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakCallByAddress(TED_Client* client, uint64_t address);
42 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakCallByAddress(TED_Client* client, uint64_t address);
43 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakCallByName(TED_Client* client, const char* name);
44 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakCallByName(TED_Client* client, const char* name);
45 |
46 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakpointByAddress(TED_Client* client, uint64_t address);
47 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakpointByAddress(TED_Client* client, uint64_t address);
48 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakpointByName(TED_Client* client, const char* name);
49 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakpointByName(TED_Client* client, const char* name);
50 |
51 | __declspec(dllexport) TED_DisassembleAddressResponse* TED_DisassembleAddress(TED_Client* client, uint64_t address, uint32_t size);
52 | __declspec(dllexport) void TED_DestroyDisassembleAddress(TED_DisassembleAddressResponse* response);
53 |
54 | __declspec(dllexport) TED_GenericResponse* TED_LoadModule(TED_Client* client, const char* path);
55 | __declspec(dllexport) TED_GenericResponse* TED_UnloadModule(TED_Client* client, const char* path);
56 |
57 | __declspec(dllexport) TED_ReadMemoryResponse* TED_ReadMemory(TED_Client* client, uint64_t address, uint32_t size);
58 | __declspec(dllexport) void TED_DestroyReadMemory(TED_ReadMemoryResponse* response);
59 | __declspec(dllexport) TED_GenericResponse* TED_WriteMemory(TED_Client* client, uint64_t address, const unsigned char* bytes, uint32_t size);
60 |
61 | __declspec(dllexport) TED_GenericResponse* TED_CreateConsole(TED_Client* client);
62 | __declspec(dllexport) TED_GenericResponse* TED_DestroyConsole(TED_Client* client);
63 |
64 | __declspec(dllexport) TED_GenericResponse* TED_EnableInternalLogging(TED_Client* client);
65 | __declspec(dllexport) TED_GenericResponse* TED_DisableInternalLogging(TED_Client* client);
66 |
67 | __declspec(dllexport) TED_GenericResponse* TED_SetOptions(TED_Client* client, TED_Options* options);
68 |
69 | __declspec(dllexport) TED_GenericResponse* TED_TestFunction(TED_Client* client);
70 |
71 | __declspec(dllexport) void TED_DestroyGeneric(TED_GenericResponse* response);
72 |
73 | }
74 |
75 | #endif
76 |
--------------------------------------------------------------------------------
/Call Logger/thirdparty/include/Structures.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef TED_STRUCTURES_H
4 | #define TED_STRUCTURES_H
5 |
6 | #include
7 |
8 | #define MODULE_MAX_PATH 255
9 |
10 | extern "C"
11 | {
12 |
13 | using TED_Client = void*;
14 | using TED_BreakpointReader = void*;
15 |
16 | typedef struct
17 | {
18 | uint32_t cs;
19 | uint32_t ds;
20 | uint32_t es;
21 | uint32_t fs;
22 | uint32_t gs;
23 | uint32_t ss;
24 | } TED_SegmentRegisters;
25 |
26 | typedef struct
27 | {
28 | uint64_t dr0;
29 | uint64_t dr1;
30 | uint64_t dr2;
31 | uint64_t dr3;
32 | uint64_t dr6;
33 | uint64_t dr7;
34 | } TED_DebugRegisters;
35 |
36 | typedef struct
37 | {
38 | uint64_t rax;
39 | uint64_t rcx;
40 | uint64_t rdx;
41 | uint64_t rbx;
42 | uint64_t rsp;
43 | uint64_t rbp;
44 | uint64_t rsi;
45 | uint64_t rdi;
46 | uint64_t rip;
47 | } TED_GeneralRegisters;
48 |
49 | typedef struct
50 | {
51 | uint64_t r8;
52 | uint64_t r9;
53 | uint64_t r10;
54 | uint64_t r11;
55 | uint64_t r12;
56 | uint64_t r13;
57 | uint64_t r14;
58 | uint64_t r15;
59 | } TED_GeneralRegistersX64;
60 |
61 | typedef struct
62 | {
63 | TED_SegmentRegisters segmentRegisters;
64 | TED_DebugRegisters debugRegisters;
65 | TED_GeneralRegisters generalRegisters;
66 | TED_GeneralRegistersX64 generalRegistersx64;
67 | uint32_t processorFlags;
68 | } TED_Context;
69 |
70 | typedef struct
71 | {
72 | char* functionName;
73 | size_t functionNameLength;
74 | } TED_Symbols;
75 |
76 | typedef struct
77 | {
78 | uint64_t rip;
79 | uint64_t returnAddress;
80 | uint64_t framePointer;
81 | uint64_t stackPointer;
82 | uint64_t parameters[4];
83 | TED_Symbols symbols;
84 | } TED_StackFrame;
85 |
86 | typedef struct
87 | {
88 | TED_StackFrame** stackFrames;
89 | size_t stackFramesCount;
90 | } TED_CallStack;
91 |
92 | typedef struct
93 | {
94 | uint32_t processId;
95 | uint32_t threadId;
96 | uint64_t sourceAddress;
97 | uint64_t destinationAddress;
98 |
99 | TED_Context context;
100 | TED_CallStack callStack;
101 | } TED_BreakpointResponse;
102 |
103 | typedef struct
104 | {
105 | char name[9];
106 | uint64_t address;
107 | uint64_t size;
108 | } TED_ExecutableSection;
109 |
110 | typedef struct
111 | {
112 | char name[MODULE_MAX_PATH];
113 | uint64_t baseAddress;
114 | uint64_t size;
115 | TED_ExecutableSection** executableSections;
116 | size_t executableSectionCount;
117 | } TED_ModuleInfo;
118 |
119 | typedef struct
120 | {
121 | TED_ModuleInfo** moduleInfo;
122 | size_t moduleInfoCount;
123 | } TED_GetModulesResponse;
124 |
125 | typedef struct
126 | {
127 | unsigned char* bytes;
128 | size_t bytesCount;
129 | } TED_ReadMemoryResponse;
130 |
131 | typedef struct
132 | {
133 | uint64_t address;
134 | char mnemonic[32];
135 | char text[64];
136 | unsigned char bytes[32];
137 | size_t bytesCount;
138 | } TED_Instruction;
139 |
140 | typedef struct
141 | {
142 | TED_Instruction** instructions;
143 | size_t instructionsCount;
144 | } TED_DisassembleAddressResponse;
145 |
146 | typedef struct
147 | {
148 | bool success;
149 | unsigned int* errorCodes;
150 | size_t errorCodesCount;
151 | char** errorMessages;
152 | size_t errorMessagesCount;
153 | } TED_GenericResponse;
154 |
155 | }
156 |
157 | #endif
158 |
--------------------------------------------------------------------------------
/TED/TED.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.2.32630.192
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEDCore", "TEDCore\TEDCore.vcxproj", "{C49F3AEA-7A3C-499C-964B-416FFADAEB97}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEDTestClient", "TEDTestClient\TEDTestClient.vcxproj", "{023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEDClientAPI", "TEDClientAPI\TEDClientAPI.vcxproj", "{0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}"
11 | EndProject
12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEDx86InjectorBridge", "TEDx86InjectorBridge\TEDx86InjectorBridge.vcxproj", "{734BA336-3F98-4DAC-8542-B12F2B920E4A}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Win32 = Debug|Win32
17 | Debug|x64 = Debug|x64
18 | Release|Win32 = Release|Win32
19 | Release|x64 = Release|x64
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Debug|Win32.ActiveCfg = Debug|Win32
23 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Debug|Win32.Build.0 = Debug|Win32
24 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Debug|x64.ActiveCfg = Debug|x64
25 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Debug|x64.Build.0 = Debug|x64
26 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Release|Win32.ActiveCfg = Release|Win32
27 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Release|Win32.Build.0 = Release|Win32
28 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Release|x64.ActiveCfg = Release|x64
29 | {C49F3AEA-7A3C-499C-964B-416FFADAEB97}.Release|x64.Build.0 = Release|x64
30 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Debug|Win32.ActiveCfg = Debug|Win32
31 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Debug|Win32.Build.0 = Debug|Win32
32 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Debug|x64.ActiveCfg = Debug|x64
33 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Debug|x64.Build.0 = Debug|x64
34 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Release|Win32.ActiveCfg = Release|Win32
35 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Release|Win32.Build.0 = Release|Win32
36 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Release|x64.ActiveCfg = Release|x64
37 | {023C3308-FBB4-48B6-9712-FEBA3BCE8CE9}.Release|x64.Build.0 = Release|x64
38 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Debug|Win32.ActiveCfg = Debug|Win32
39 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Debug|Win32.Build.0 = Debug|Win32
40 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Debug|x64.ActiveCfg = Debug|x64
41 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Debug|x64.Build.0 = Debug|x64
42 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Release|Win32.ActiveCfg = Release|Win32
43 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Release|Win32.Build.0 = Release|Win32
44 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Release|x64.ActiveCfg = Release|x64
45 | {0C9F4058-246A-4E9E-825E-DB2C4FC3EDEB}.Release|x64.Build.0 = Release|x64
46 | {734BA336-3F98-4DAC-8542-B12F2B920E4A}.Debug|Win32.ActiveCfg = Debug|Win32
47 | {734BA336-3F98-4DAC-8542-B12F2B920E4A}.Debug|Win32.Build.0 = Debug|Win32
48 | {734BA336-3F98-4DAC-8542-B12F2B920E4A}.Debug|x64.ActiveCfg = Debug|Win32
49 | {734BA336-3F98-4DAC-8542-B12F2B920E4A}.Debug|x64.Build.0 = Debug|Win32
50 | {734BA336-3F98-4DAC-8542-B12F2B920E4A}.Release|Win32.ActiveCfg = Release|Win32
51 | {734BA336-3F98-4DAC-8542-B12F2B920E4A}.Release|Win32.Build.0 = Release|Win32
52 | {734BA336-3F98-4DAC-8542-B12F2B920E4A}.Release|x64.ActiveCfg = Release|Win32
53 | EndGlobalSection
54 | GlobalSection(SolutionProperties) = preSolution
55 | HideSolutionNode = FALSE
56 | EndGlobalSection
57 | GlobalSection(ExtensibilityGlobals) = postSolution
58 | SolutionGuid = {8CB898A8-FDC9-4F46-8EBE-C280724FF0FD}
59 | EndGlobalSection
60 | EndGlobal
61 |
--------------------------------------------------------------------------------
/TED/TEDClientAPI/Api.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef TED_API_H
4 | #define TED_API_H
5 |
6 | #include
7 |
8 | #include "Structures.h"
9 |
10 | extern "C"
11 | {
12 |
13 | #define SYMBOL_MAX_PATH 255
14 |
15 | typedef struct
16 | {
17 | bool returnCallStack;
18 | bool returnContext;
19 | bool returnSymbolInfo;
20 | bool useInvasiveBreakpoints;
21 | bool unsafeMemoryMode;
22 | bool autoDisableBreakpointsMode;
23 | bool killProcessOnDisconnect;
24 | char symbolPath[SYMBOL_MAX_PATH];
25 | } TED_Options;
26 |
27 | __declspec(dllexport) TED_Client* TED_CreateClient(const char* uri);
28 | __declspec(dllexport) void TED_DestroyClient(TED_Client* client);
29 |
30 | __declspec(dllexport) TED_BreakpointReader* TED_CreateBreakpointReader(TED_Client* client);
31 | __declspec(dllexport) void TED_DestroyBreakpointReader(TED_BreakpointReader* reader);
32 |
33 | __declspec(dllexport) TED_BreakpointResponse* TED_GetBreakpoint(TED_Client* client, TED_BreakpointReader* reader);
34 | __declspec(dllexport) void TED_DestroyBreakpoint(TED_BreakpointResponse* response);
35 |
36 | __declspec(dllexport) TED_GetModulesResponse* TED_GetModules(TED_Client* client);
37 | __declspec(dllexport) void TED_DestroyModules(TED_GetModulesResponse* response);
38 |
39 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakAllCallsInModule(TED_Client* client, const char* name);
40 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakAllCallsInModule(TED_Client* client, const char* name);
41 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakCallByAddress(TED_Client* client, uint64_t address);
42 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakCallByAddress(TED_Client* client, uint64_t address);
43 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakCallByName(TED_Client* client, const char* name);
44 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakCallByName(TED_Client* client, const char* name);
45 |
46 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakpointByAddress(TED_Client* client, uint64_t address);
47 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakpointByAddress(TED_Client* client, uint64_t address);
48 | __declspec(dllexport) TED_GenericResponse* TED_EnableBreakpointByName(TED_Client* client, const char* name);
49 | __declspec(dllexport) TED_GenericResponse* TED_DisableBreakpointByName(TED_Client* client, const char* name);
50 |
51 | __declspec(dllexport) TED_DisassembleAddressResponse* TED_DisassembleAddress(TED_Client* client, uint64_t address, uint32_t size);
52 | __declspec(dllexport) void TED_DestroyDisassembleAddress(TED_DisassembleAddressResponse* response);
53 |
54 | __declspec(dllexport) TED_GenericResponse* TED_LoadModule(TED_Client* client, const char* path);
55 | __declspec(dllexport) TED_GenericResponse* TED_UnloadModule(TED_Client* client, const char* path);
56 |
57 | __declspec(dllexport) TED_ReadMemoryResponse* TED_ReadMemory(TED_Client* client, uint64_t address, uint32_t size);
58 | __declspec(dllexport) void TED_DestroyReadMemory(TED_ReadMemoryResponse* response);
59 | __declspec(dllexport) TED_GenericResponse* TED_WriteMemory(TED_Client* client, uint64_t address, const unsigned char* bytes, uint32_t size);
60 |
61 | __declspec(dllexport) TED_GenericResponse* TED_CreateConsole(TED_Client* client);
62 | __declspec(dllexport) TED_GenericResponse* TED_DestroyConsole(TED_Client* client);
63 |
64 | __declspec(dllexport) TED_GenericResponse* TED_EnableInternalLogging(TED_Client* client);
65 | __declspec(dllexport) TED_GenericResponse* TED_DisableInternalLogging(TED_Client* client);
66 |
67 | __declspec(dllexport) TED_GenericResponse* TED_SetOptions(TED_Client* client, TED_Options* options);
68 |
69 | __declspec(dllexport) TED_GenericResponse* TED_TestFunction(TED_Client* client);
70 |
71 | __declspec(dllexport) void TED_DestroyGeneric(TED_GenericResponse* response);
72 |
73 | }
74 |
75 | #endif
76 |
--------------------------------------------------------------------------------
/TED/TEDClientAPI/Source.cpp:
--------------------------------------------------------------------------------
1 | #pragma comment(lib, "crypt32.lib")
2 | #pragma comment(lib, "iphlpapi.lib")
3 |
4 | #include
5 |
6 | #include "Api.h"
7 | #include "TEDClientBridge.h"
8 |
9 | __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID reserved)
10 | {
11 | return TRUE;
12 | }
--------------------------------------------------------------------------------
/TED/TEDClientAPI/Structures.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef TED_STRUCTURES_H
4 | #define TED_STRUCTURES_H
5 |
6 | #include
7 |
8 | #define MODULE_MAX_PATH 255
9 |
10 | extern "C"
11 | {
12 |
13 | using TED_Client = void*;
14 | using TED_BreakpointReader = void*;
15 |
16 | typedef struct
17 | {
18 | uint32_t cs;
19 | uint32_t ds;
20 | uint32_t es;
21 | uint32_t fs;
22 | uint32_t gs;
23 | uint32_t ss;
24 | } TED_SegmentRegisters;
25 |
26 | typedef struct
27 | {
28 | uint64_t dr0;
29 | uint64_t dr1;
30 | uint64_t dr2;
31 | uint64_t dr3;
32 | uint64_t dr6;
33 | uint64_t dr7;
34 | } TED_DebugRegisters;
35 |
36 | typedef struct
37 | {
38 | uint64_t rax;
39 | uint64_t rcx;
40 | uint64_t rdx;
41 | uint64_t rbx;
42 | uint64_t rsp;
43 | uint64_t rbp;
44 | uint64_t rsi;
45 | uint64_t rdi;
46 | uint64_t rip;
47 | } TED_GeneralRegisters;
48 |
49 | typedef struct
50 | {
51 | uint64_t r8;
52 | uint64_t r9;
53 | uint64_t r10;
54 | uint64_t r11;
55 | uint64_t r12;
56 | uint64_t r13;
57 | uint64_t r14;
58 | uint64_t r15;
59 | } TED_GeneralRegistersX64;
60 |
61 | typedef struct
62 | {
63 | TED_SegmentRegisters segmentRegisters;
64 | TED_DebugRegisters debugRegisters;
65 | TED_GeneralRegisters generalRegisters;
66 | TED_GeneralRegistersX64 generalRegistersx64;
67 | uint32_t processorFlags;
68 | } TED_Context;
69 |
70 | typedef struct
71 | {
72 | char* functionName;
73 | size_t functionNameLength;
74 | } TED_Symbols;
75 |
76 | typedef struct
77 | {
78 | uint64_t rip;
79 | uint64_t returnAddress;
80 | uint64_t framePointer;
81 | uint64_t stackPointer;
82 | uint64_t parameters[4];
83 | TED_Symbols symbols;
84 | } TED_StackFrame;
85 |
86 | typedef struct
87 | {
88 | TED_StackFrame** stackFrames;
89 | size_t stackFramesCount;
90 | } TED_CallStack;
91 |
92 | typedef struct
93 | {
94 | uint32_t processId;
95 | uint32_t threadId;
96 | uint64_t sourceAddress;
97 | uint64_t destinationAddress;
98 |
99 | TED_Context context;
100 | TED_CallStack callStack;
101 | } TED_BreakpointResponse;
102 |
103 | typedef struct
104 | {
105 | char name[9];
106 | uint64_t address;
107 | uint64_t size;
108 | } TED_ExecutableSection;
109 |
110 | typedef struct
111 | {
112 | char name[MODULE_MAX_PATH];
113 | uint64_t baseAddress;
114 | uint64_t size;
115 | TED_ExecutableSection** executableSections;
116 | size_t executableSectionCount;
117 | } TED_ModuleInfo;
118 |
119 | typedef struct
120 | {
121 | TED_ModuleInfo** moduleInfo;
122 | size_t moduleInfoCount;
123 | } TED_GetModulesResponse;
124 |
125 | typedef struct
126 | {
127 | unsigned char* bytes;
128 | size_t bytesCount;
129 | } TED_ReadMemoryResponse;
130 |
131 | typedef struct
132 | {
133 | uint64_t address;
134 | char mnemonic[32];
135 | char text[64];
136 | unsigned char bytes[32];
137 | size_t bytesCount;
138 | } TED_Instruction;
139 |
140 | typedef struct
141 | {
142 | TED_Instruction** instructions;
143 | size_t instructionsCount;
144 | } TED_DisassembleAddressResponse;
145 |
146 | typedef struct
147 | {
148 | bool success;
149 | unsigned int* errorCodes;
150 | size_t errorCodesCount;
151 | char** errorMessages;
152 | size_t errorMessagesCount;
153 | } TED_GenericResponse;
154 |
155 | }
156 |
157 | #endif
158 |
--------------------------------------------------------------------------------
/TED/TEDClientAPI/TEDClientAPI.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {0c9f4058-246a-4e9e-825e-db2c4fc3edeb}
25 | TEDClientAPI
26 | 10.0
27 |
28 |
29 |
30 | DynamicLibrary
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | DynamicLibrary
37 | true
38 | v143
39 | Unicode
40 |
41 |
42 | DynamicLibrary
43 | false
44 | v143
45 | true
46 | Unicode
47 |
48 |
49 | DynamicLibrary
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | true
78 |
79 |
80 | true
81 |
82 |
83 | true
84 |
85 |
86 |
87 | Level3
88 | true
89 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
90 | true
91 | ../TEDCore;%(AdditionalIncludeDirectories)
92 | stdcpplatest
93 | MultiThreadedDebug
94 |
95 |
96 | Windows
97 | true
98 |
99 |
100 |
101 |
102 | Level3
103 | true
104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
105 | true
106 | ../TEDCore;%(AdditionalIncludeDirectories)
107 | stdcpplatest
108 | MultiThreadedDebug
109 |
110 |
111 | Windows
112 | true
113 |
114 |
115 |
116 |
117 | Level3
118 | true
119 | true
120 | true
121 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
122 | true
123 | ../TEDCore;%(AdditionalIncludeDirectories)
124 | stdcpplatest
125 | MultiThreaded
126 |
127 |
128 | Windows
129 | true
130 | true
131 | true
132 |
133 |
134 |
135 |
136 | Level3
137 | true
138 | true
139 | true
140 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
141 | true
142 | ../TEDCore;%(AdditionalIncludeDirectories)
143 | stdcpplatest
144 | MultiThreaded
145 |
146 |
147 | Windows
148 | true
149 | true
150 | true
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
--------------------------------------------------------------------------------
/TED/TEDClientAPI/TEDClientAPI.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {3c22c5b7-1e7a-4d1f-be3c-152f2f4004b2}
18 |
19 |
20 | {9f802af0-150b-4187-a7d3-17adf258c57e}
21 |
22 |
23 | {46ec77c7-bf28-4388-8dec-c6ef6e6e8e88}
24 |
25 |
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files\Proto
35 |
36 |
37 | Source Files\Proto
38 |
39 |
40 |
41 |
42 | Header Files\Include
43 |
44 |
45 | Header Files\Include
46 |
47 |
48 | Header Files\Proto
49 |
50 |
51 | Header Files\Proto
52 |
53 |
54 | Header Files\Include
55 |
56 |
57 |
--------------------------------------------------------------------------------
/TED/TEDClientAPI/TEDClientAPI.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/TED/TEDCore/Breakpoint.cpp:
--------------------------------------------------------------------------------
1 | #pragma comment(lib, "DbgHelp.lib")
2 |
3 | #include "Breakpoint.h"
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "Memory.h"
14 | #include "Process.h"
15 |
16 | namespace TED
17 | {
18 | namespace Breakpoint
19 | {
20 |
21 | #ifdef _M_IX86
22 |
23 | static std::unordered_map threadsTls{};
24 | static std::mutex mapMutex{};
25 |
26 | Address* brokenAddress()
27 | {
28 | // thread_local storage seems to have some issues properly
29 | // initializing on x86 builds. Manually creating a TLS index
30 | // as a workaround. The allocated index isn't getting freed
31 | // but not really expecting it to be an issue since most
32 | // applications don't create and kill gigantic amounts of threads.
33 | auto currentThreadId{ GetCurrentThreadId() };
34 |
35 | if (!threadsTls.contains(currentThreadId)) {
36 | auto newTlsIndex{ TlsAlloc() };
37 | if (newTlsIndex != TLS_OUT_OF_INDEXES) {
38 | TlsSetValue(newTlsIndex, new Address{});
39 |
40 | std::scoped_lock{ mapMutex };
41 | threadsTls.insert({ currentThreadId, newTlsIndex });
42 | }
43 | else {
44 | assert("Out of TLS indexes");
45 | }
46 | }
47 |
48 | std::scoped_lock{ mapMutex };
49 | return reinterpret_cast(TlsGetValue(threadsTls[currentThreadId]));
50 | }
51 | #define brokenAddress *brokenAddress()
52 |
53 | #elif defined _M_AMD64
54 | thread_local Address brokenAddress{};
55 | #endif
56 |
57 | static std::unordered_map> breakpointRanges{};
58 |
59 | static std::unordered_map int3ToOriginalByte{};
60 | static std::unordered_set int3Breakpoints{};
61 |
62 | static std::unordered_set callStackBreakpoints{};
63 | static std::unordered_set immediateBreakpoints{};
64 |
65 | static bool autoDisableMode{};
66 |
67 | moodycamel::ConcurrentQueue breakpointEvents{};
68 |
69 | bool AddImmediateBreakpoint(Address address)
70 | {
71 | return immediateBreakpoints.insert(address).second;
72 | }
73 |
74 | bool RemoveImmediateBreakpoint(Address address)
75 | {
76 | return immediateBreakpoints.erase(address) != 0;
77 | }
78 |
79 | bool IsImmediateBreakpoint(Address address)
80 | {
81 | return immediateBreakpoints.contains(address);
82 | }
83 |
84 | bool EnableCallStack(Address address)
85 | {
86 | return callStackBreakpoints.insert(address).second;
87 | }
88 |
89 | bool DisableCallStack(Address address)
90 | {
91 | return callStackBreakpoints.erase(address) != 0;
92 | }
93 |
94 | bool IsCallStackBreakpoint(Address address)
95 | {
96 | return callStackBreakpoints.contains(address);
97 | }
98 |
99 | bool AddInt3BreakpointInternal(Address address)
100 | {
101 | return int3Breakpoints.insert(address).second;
102 | }
103 |
104 | bool RemoveInt3BreakpointInternal(Address address)
105 | {
106 | return int3Breakpoints.erase(address) != 0;
107 | }
108 |
109 | bool IsInt3BreakpointAddress(Address address)
110 | {
111 | return int3Breakpoints.contains(address);
112 | }
113 |
114 | bool IsKnownBreakpointAddress(Address address)
115 | {
116 | return int3ToOriginalByte.contains(address);
117 | }
118 |
119 | bool IsMemoryBreakpointAddress(Address address)
120 | {
121 | auto alignedAddress{ TED::Memory::AlignToPage(address) };
122 | if (breakpointRanges.empty() || !breakpointRanges.contains(alignedAddress)) {
123 | return false;
124 | }
125 |
126 | auto& range{ breakpointRanges[alignedAddress] };
127 | return std::find(range.begin(), range.end(), address) != range.end();
128 | }
129 |
130 | bool IsBreakpointAddress(Address address)
131 | {
132 | return IsMemoryBreakpointAddress(address) || IsInt3BreakpointAddress(address);
133 | }
134 |
135 | void AddMemoryBreakpointAddressInternal(Address address)
136 | {
137 | auto pageAlignedAddress{ TED::Memory::AlignToPage(address) };
138 |
139 | if (breakpointRanges.find(pageAlignedAddress) == breakpointRanges.end()) {
140 | breakpointRanges.insert({ pageAlignedAddress, std::vector() });
141 | }
142 |
143 | breakpointRanges[pageAlignedAddress].push_back(address);
144 | }
145 |
146 | void RemoveMemoryBreakpointAddressInternal(Address address)
147 | {
148 | auto pageAlignedAddress{ TED::Memory::AlignToPage(address) };
149 |
150 | breakpointRanges[pageAlignedAddress].erase(std::remove(
151 | breakpointRanges[pageAlignedAddress].begin(), breakpointRanges[pageAlignedAddress].end(), address),
152 | breakpointRanges[pageAlignedAddress].end());
153 | if (breakpointRanges[pageAlignedAddress].size() == 0) {
154 | breakpointRanges.erase(pageAlignedAddress);
155 | }
156 | }
157 |
158 | const std::vector& GetMemoryBreakpointAddressesForPage(Address address)
159 | {
160 | auto alignedAddress{ TED::Memory::AlignToPage(address) };
161 | auto range{ breakpointRanges.find(alignedAddress) };
162 | if (range == breakpointRanges.end()) {
163 | static std::vector emptyRange{};
164 | return emptyRange;
165 | }
166 |
167 | return range->second;
168 | }
169 |
170 | bool EnableMemoryBreakpoint(Address address)
171 | {
172 | MEMORY_BASIC_INFORMATION memoryInfo{};
173 |
174 | VirtualQuery(reinterpret_cast(address), &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION));
175 | return TED::Memory::SetPagePermissions(reinterpret_cast(memoryInfo.BaseAddress),
176 | memoryInfo.RegionSize, memoryInfo.AllocationProtect | PAGE_GUARD);
177 | }
178 |
179 | bool DisableMemoryBreakpoint(Address address)
180 | {
181 | MEMORY_BASIC_INFORMATION memoryInfo{};
182 |
183 | VirtualQuery(reinterpret_cast(address), &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION));
184 | return TED::Memory::SetPagePermissions(reinterpret_cast(memoryInfo.BaseAddress),
185 | memoryInfo.RegionSize, memoryInfo.AllocationProtect & ~PAGE_GUARD);
186 | }
187 |
188 | bool SetMemoryBreakpoint(Address address, bool withCallStack, bool isImmediate)
189 | {
190 | if (IsBreakpointAddress(address)) {
191 | return true;
192 | }
193 |
194 | AddMemoryBreakpointAddressInternal(address);
195 | if (withCallStack) {
196 | EnableCallStack(address);
197 | }
198 | if (isImmediate) {
199 | AddImmediateBreakpoint(address);
200 | }
201 |
202 | auto result{ EnableMemoryBreakpoint(address) };
203 | if (!result) {
204 | UnsetMemoryBreakpoint(address, withCallStack, isImmediate);
205 | }
206 |
207 | return result;
208 | }
209 |
210 | bool UnsetMemoryBreakpoint(Address address, bool withCallStack, bool isImmediate)
211 | {
212 | if (!IsMemoryBreakpointAddress(address)) {
213 | return true;
214 | }
215 |
216 | auto result{ DisableMemoryBreakpoint(address) };
217 | if (result) {
218 | RemoveMemoryBreakpointAddressInternal(address);
219 | DisableCallStack(address);
220 | RemoveImmediateBreakpoint(address);
221 | }
222 |
223 | return result;
224 | }
225 |
226 | bool WriteOriginalInstuction(Address address)
227 | {
228 | std::vector originalByte{ {int3ToOriginalByte[address]} };
229 | auto result = TED::Memory::WriteMemory(address, originalByte);
230 |
231 | return result;
232 | }
233 |
234 | bool EnableInt3Breakpoint(Address address)
235 | {
236 | if (!TED::Memory::IsMemoryCommitted(address, sizeof(unsigned char))) {
237 | return false;
238 | }
239 |
240 | auto readBytes{ TED::Memory::ReadMemory(address, sizeof(unsigned char)) };
241 | if (readBytes.size() == 0) {
242 | return false;
243 | }
244 |
245 | unsigned char originalByte{ readBytes[0] };;
246 | int3ToOriginalByte[address] = originalByte;
247 |
248 | std::vector int3{ {0xCC} };
249 | auto result{ TED::Memory::WriteMemory(address, int3) };
250 |
251 | return result;
252 | }
253 |
254 | bool DisableInt3Breakpoint(Address address)
255 | {
256 | auto result{ WriteOriginalInstuction(address) };
257 |
258 | // Keep the original byte in case another thread is calling the
259 | // function when the breakpoint gets disabled.
260 |
261 | // int3ToOriginalByte.erase(address);
262 |
263 | return result;
264 | }
265 |
266 | bool SetInt3Breakpoint(Address address, bool withCallStack, bool isImmediate)
267 | {
268 | if (IsBreakpointAddress(address)) {
269 | return true;
270 | }
271 |
272 | AddInt3BreakpointInternal(address);
273 | if (withCallStack) {
274 | EnableCallStack(address);
275 | }
276 | if (isImmediate) {
277 | AddImmediateBreakpoint(address);
278 | }
279 |
280 | auto result{ EnableInt3Breakpoint(address) };
281 | if (!result) {
282 | UnsetInt3Breakpoint(address, withCallStack, isImmediate);
283 | }
284 |
285 | return result;
286 | }
287 |
288 | bool UnsetInt3Breakpoint(Address address, bool withCallStack, bool isImmediate)
289 | {
290 | if (!IsInt3BreakpointAddress(address)) {
291 | return true;
292 | }
293 |
294 | auto result{ DisableInt3Breakpoint(address) };
295 | if (result) {
296 | RemoveInt3BreakpointInternal(address);
297 | DisableCallStack(address);
298 | RemoveImmediateBreakpoint(address);
299 | }
300 |
301 | return result;
302 | }
303 |
304 | bool UnsetBreakpoint(Address address, bool withCallStack, bool isImmediate)
305 | {
306 | if (IsMemoryBreakpointAddress(address)) {
307 | return UnsetMemoryBreakpoint(address, withCallStack, isImmediate);
308 | }
309 | if (IsInt3BreakpointAddress(address)) {
310 | return UnsetInt3Breakpoint(address, withCallStack, isImmediate);
311 | }
312 |
313 | return false;
314 | }
315 |
316 | bool UnsetAllBreakpointsInModule(std::string moduleName)
317 | {
318 | std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(),
319 | [](unsigned char c) { return std::tolower(c); });
320 |
321 | auto modules{ TED::Process::GetModules() };
322 | auto moduleInfo = std::find_if(modules.begin(), modules.end(),
323 | [&](TED::Process::Module& info) {
324 | std::transform(info.name.begin(), info.name.end(), info.name.begin(),
325 | [](unsigned char c) { return std::tolower(c); });
326 | return moduleName == info.name;
327 | });
328 |
329 | if (moduleInfo == modules.end()) {
330 | return false;
331 | }
332 |
333 | auto startAddress = moduleInfo->baseAddress;
334 | auto endAddress = static_cast(startAddress + moduleInfo->size);
335 |
336 | for (const auto& int3Breakpoint : int3Breakpoints) {
337 | if (int3Breakpoint >= startAddress && int3Breakpoint <= endAddress) {
338 | UnsetInt3Breakpoint(int3Breakpoint, true, true);
339 | }
340 | }
341 |
342 | auto alignedAddress = TED::Memory::AlignToPage(startAddress);
343 | while (startAddress < endAddress) {
344 | if (breakpointRanges.contains(alignedAddress)) {
345 | auto memoryBreakpoints = breakpointRanges[alignedAddress];
346 | for (const auto& memoryBreakpoint : memoryBreakpoints) {
347 | UnsetMemoryBreakpoint(memoryBreakpoint, true, true);
348 | }
349 | }
350 |
351 | startAddress += TED::Memory::PAGE_SIZE;
352 | alignedAddress = TED::Memory::AlignToPage(startAddress);
353 | }
354 |
355 |
356 | return true;
357 | }
358 |
359 | std::vector GetCallStack(Address address, CONTEXT* context)
360 | {
361 | if (!IsCallStackBreakpoint(brokenAddress)) {
362 | return std::vector{};
363 | }
364 |
365 | CONTEXT localContext = *context;
366 |
367 | std::vector stackFrames{};
368 | STACKFRAME64 stackFrame{};
369 | auto maxFrames{ 16 };
370 |
371 | stackFrame.AddrPC.Mode = AddrModeFlat;
372 | stackFrame.AddrFrame.Mode = AddrModeFlat;
373 | stackFrame.AddrStack.Mode = AddrModeFlat;
374 |
375 | #ifdef _M_IX86
376 | auto machineType{ IMAGE_FILE_MACHINE_I386 };
377 | stackFrame.AddrPC.Offset = context->Eip;
378 | stackFrame.AddrFrame.Offset = context->Ebp;
379 | stackFrame.AddrStack.Offset = context->Esp;
380 | #elif defined _M_AMD64
381 | auto machineType{ IMAGE_FILE_MACHINE_AMD64 };
382 | stackFrame.AddrPC.Offset = context->Rip;
383 | stackFrame.AddrFrame.Offset = context->Rbp;
384 | stackFrame.AddrStack.Offset = context->Rsp;
385 | #else
386 | #error "Unsupported platform"
387 | #endif
388 |
389 | for (auto i{ 0 }; i < maxFrames; i++)
390 | {
391 | auto result{ StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame,
392 | (machineType == IMAGE_FILE_MACHINE_I386 ? nullptr : &localContext),
393 | nullptr, SymFunctionTableAccess64, SymGetModuleBase64, nullptr) };
394 |
395 | if (!result)
396 | {
397 | break;
398 | }
399 |
400 | stackFrames.push_back(stackFrame);
401 | }
402 |
403 | return stackFrames;
404 | }
405 |
406 | void EnqueueBreakpointEvent(EXCEPTION_POINTERS* exceptionInfo)
407 | {
408 | constexpr size_t MAX_QUEUE_SIZE = (2 << 22);
409 |
410 | if (breakpointEvents.size_approx() < MAX_QUEUE_SIZE) {
411 | auto callStack{ GetCallStack(brokenAddress, exceptionInfo->ContextRecord) };
412 | breakpointEvents.enqueue({ *exceptionInfo->ContextRecord, brokenAddress,
413 | reinterpret_cast(exceptionInfo->ExceptionRecord->ExceptionAddress),
414 | callStack, GetCurrentProcessId(), GetCurrentThreadId() });
415 | }
416 | }
417 |
418 | void ReenableMemoryBreakpoints()
419 | {
420 | if (!breakpointRanges.empty()) {
421 | auto breakpoints{ GetMemoryBreakpointAddressesForPage(brokenAddress) };
422 | for (const auto& breakpoint : breakpoints) {
423 | EnableMemoryBreakpoint(breakpoint);
424 | }
425 | }
426 | }
427 |
428 | bool IsInAutoDisableBreakpointMode()
429 | {
430 | return autoDisableMode;
431 | }
432 |
433 | void EnableAutoDisableBreakpointMode()
434 | {
435 | autoDisableMode = true;
436 | }
437 |
438 | void DisableAutoDisableBreakpointMode()
439 | {
440 | autoDisableMode = false;
441 | }
442 |
443 | LONG WINAPI BreakpointHandler(EXCEPTION_POINTERS* exceptionInfo)
444 | {
445 | if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) {
446 |
447 | auto exceptionAddress = reinterpret_cast(
448 | exceptionInfo->ExceptionRecord->ExceptionAddress);
449 |
450 | if ((exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) &&
451 | !IsInt3BreakpointAddress(exceptionAddress)) {
452 |
453 | ReenableMemoryBreakpoints();
454 |
455 | if (IsKnownBreakpointAddress(exceptionAddress)) {
456 |
457 | WriteOriginalInstuction(brokenAddress);
458 |
459 | return EXCEPTION_CONTINUE_EXECUTION;
460 | }
461 |
462 | return EXCEPTION_CONTINUE_SEARCH;
463 | }
464 |
465 | if (IsImmediateBreakpoint(exceptionAddress)) {
466 | EnqueueBreakpointEvent(exceptionInfo);
467 | }
468 |
469 | WriteOriginalInstuction(exceptionAddress);
470 |
471 | exceptionInfo->ContextRecord->EFlags |= 0x100;
472 | brokenAddress = exceptionAddress;
473 |
474 | return EXCEPTION_CONTINUE_EXECUTION;
475 | }
476 |
477 | if (exceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) {
478 |
479 | exceptionInfo->ContextRecord->EFlags |= 0x100;
480 | brokenAddress = reinterpret_cast(exceptionInfo->ExceptionRecord->ExceptionAddress);
481 |
482 | if (IsImmediateBreakpoint(brokenAddress)) {
483 | EnqueueBreakpointEvent(exceptionInfo);
484 | }
485 |
486 | return EXCEPTION_CONTINUE_EXECUTION;
487 | }
488 |
489 | if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) {
490 |
491 | if (!IsImmediateBreakpoint(brokenAddress)) {
492 | if (IsMemoryBreakpointAddress(brokenAddress) || IsInt3BreakpointAddress(brokenAddress)) {
493 | EnqueueBreakpointEvent(exceptionInfo);
494 | }
495 |
496 | if (IsInAutoDisableBreakpointMode()) {
497 | UnsetBreakpoint(brokenAddress, true, true);
498 | }
499 | else if (IsInt3BreakpointAddress(brokenAddress)) {
500 | EnableInt3Breakpoint(brokenAddress);
501 | }
502 | }
503 |
504 | ReenableMemoryBreakpoints();
505 |
506 | return EXCEPTION_CONTINUE_EXECUTION;
507 | }
508 |
509 | return EXCEPTION_CONTINUE_SEARCH;
510 | }
511 |
512 | }
513 | }
--------------------------------------------------------------------------------
/TED/TEDCore/Breakpoint.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | #include "CommonTypes.h"
10 |
11 | #include
12 |
13 | namespace TED
14 | {
15 | namespace Breakpoint
16 | {
17 |
18 | typedef struct {
19 | CONTEXT context;
20 | Address source_address;
21 | Address destination_address;
22 | std::vector stackFrames;
23 | unsigned int processId;
24 | unsigned int threadId;
25 | } BreakpointEvent;
26 |
27 | extern moodycamel::ConcurrentQueue breakpointEvents;
28 |
29 | bool SetMemoryBreakpoint(Address address, bool withCallStack, bool isImmediate);
30 | bool UnsetMemoryBreakpoint(Address address, bool withCallStack, bool isImmediate);
31 |
32 | bool SetInt3Breakpoint(Address address, bool withCallStack, bool isImmediate);
33 | bool UnsetInt3Breakpoint(Address address, bool withCallStack, bool isImmediate);
34 |
35 | bool UnsetBreakpoint(Address address, bool withCallStack, bool isImmediate);
36 | bool UnsetAllBreakpointsInModule(std::string moduleName);
37 |
38 | void EnableAutoDisableBreakpointMode();
39 | void DisableAutoDisableBreakpointMode();
40 |
41 | LONG WINAPI BreakpointHandler(EXCEPTION_POINTERS* exceptionInfo);
42 |
43 | }
44 | }
--------------------------------------------------------------------------------
/TED/TEDCore/CommonTypes.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace TED
4 | {
5 |
6 | using Address = unsigned long long;
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/TED/TEDCore/Console.cpp:
--------------------------------------------------------------------------------
1 | #include "Console.h"
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace TED
8 | {
9 | namespace Console
10 | {
11 |
12 | static bool loggingEnabled{};
13 | static bool consoleAllocated{};
14 |
15 | bool CreateConsole()
16 | {
17 | auto result{ AllocConsole() };
18 | if (result) {
19 | FILE* stream{};
20 | (void)freopen_s(&stream, "CONOUT$", "w", stdout);
21 | (void)freopen_s(&stream, "CONOUT$", "w", stderr);
22 | SetConsoleTitle(L"Console");
23 | SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
24 | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
25 | consoleAllocated = true;
26 | }
27 | else if (GetLastError() == ERROR_ACCESS_DENIED) {
28 | result = true;
29 | }
30 |
31 |
32 | return result;
33 | }
34 |
35 | bool DestroyConsole()
36 | {
37 | if (!consoleAllocated) {
38 | return true;
39 | }
40 |
41 | return FreeConsole();
42 | }
43 |
44 | void EnableLogging()
45 | {
46 | loggingEnabled = true;
47 | }
48 |
49 | void DisableLogging()
50 | {
51 | loggingEnabled = false;
52 | }
53 |
54 | bool IsLoggingEnabled()
55 | {
56 | return loggingEnabled;
57 | }
58 |
59 | void LogInternal(std::string_view message)
60 | {
61 | if (IsLoggingEnabled()) {
62 | std::cerr << message << std::endl;
63 | }
64 | }
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/TED/TEDCore/Console.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace TED
6 | {
7 | namespace Console
8 | {
9 |
10 | bool CreateConsole();
11 | bool DestroyConsole();
12 |
13 | void EnableLogging();
14 | void DisableLogging();
15 | bool IsLoggingEnabled();
16 |
17 | void LogInternal(std::string_view message);
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/TED/TEDCore/Disassembler.cpp:
--------------------------------------------------------------------------------
1 | #include "Disassembler.h"
2 |
3 | #include
4 | #include
5 |
6 | namespace TED
7 | {
8 | namespace Disassembler
9 | {
10 |
11 | #ifdef _M_IX86
12 | static cs_mode Mode = CS_MODE_32;
13 | #elif defined(_M_AMD64)
14 | static cs_mode Mode = CS_MODE_64;
15 | #else
16 | #error "Unsupported architecture"
17 | #endif
18 |
19 | Disassembler::Disassembler()
20 | : m_handle{}
21 | {
22 | auto result{ cs_open(CS_ARCH_X86, Mode, &m_handle) };
23 | if (result != CS_ERR_OK) {
24 | throw std::runtime_error(
25 | std::format("Could not initialize disassembly engine: {}", static_cast(result)));
26 | }
27 |
28 | cs_option(m_handle, CS_OPT_DETAIL, CS_OPT_ON);
29 | cs_option(m_handle, CS_OPT_SKIPDATA, CS_OPT_ON);
30 | }
31 |
32 | Disassembler::~Disassembler()
33 | {
34 | cs_close(&m_handle);
35 | }
36 |
37 | std::vector Disassembler::GetCallInstructions(Address startAddress, size_t size) const
38 | {
39 | std::vector callInstructions{};
40 |
41 | auto call{ std::string{"call"} };
42 |
43 | cs_insn* instructions{};
44 |
45 | size_t disassembleSize{ 0x10000 };
46 | const auto endAddress{ startAddress + size };
47 | while (startAddress < endAddress) {
48 | size_t disassembledBytesSize{};
49 |
50 | auto count{ cs_disasm(m_handle, reinterpret_cast(startAddress), disassembleSize, 0, 0, &instructions) };
51 | if (count > 0) {
52 | for (size_t j{ 0 }; j < count; j++) {
53 | if (call == instructions[j].mnemonic) {
54 | callInstructions.push_back(startAddress + instructions[j].address);
55 | }
56 | disassembledBytesSize += instructions[j].size;
57 | }
58 |
59 | cs_free(instructions, count);
60 | }
61 |
62 | startAddress += disassembledBytesSize;
63 | disassembleSize = std::min(disassembleSize, static_cast(endAddress - startAddress));
64 | }
65 |
66 | return callInstructions;
67 | }
68 |
69 | std::vector Disassembler::GetInstructions(Address startAddress, size_t size) const
70 | {
71 | std::vector callInstructions{};
72 |
73 | cs_insn* instructions{};
74 | auto count{ cs_disasm(m_handle, reinterpret_cast(startAddress), size, 0, 0, &instructions) };
75 | if (count > 0) {
76 | for (size_t i{ 0 }; i < count; i++) {
77 | InstructionInfo instructionInfo{};
78 | instructionInfo.address = startAddress + instructions[i].address;
79 | instructionInfo.mnemonic.assign(instructions[i].mnemonic);
80 | instructionInfo.opcodes.assign(instructions[i].op_str);
81 | instructionInfo.bytes.assign(instructions[i].bytes, std::begin(instructions[i].bytes) + instructions[i].size);
82 |
83 | callInstructions.push_back(instructionInfo);
84 | }
85 |
86 | cs_free(instructions, count);
87 | }
88 |
89 | return callInstructions;
90 | }
91 |
92 | size_t Disassembler::GetFunctionSize(Address startAddress) const
93 | {
94 | size_t functionSize{};
95 |
96 | auto ret{ std::string{"ret"} };
97 | size_t offset{};
98 |
99 | do {
100 | cs_insn* instructions{};
101 | auto count{ cs_disasm(m_handle, reinterpret_cast(startAddress + functionSize), 0x20, 0, 1, &instructions) };
102 | if (count > 0) {
103 | functionSize += instructions[0].size;
104 | if (ret == instructions[0].mnemonic) {
105 | break;
106 | }
107 | cs_free(instructions, count);
108 | }
109 | } while (functionSize < 0x1000);
110 |
111 | return functionSize;
112 | }
113 |
114 | }
115 | }
--------------------------------------------------------------------------------
/TED/TEDCore/Disassembler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "CommonTypes.h"
7 |
8 | #include
9 |
10 | namespace TED
11 | {
12 | namespace Disassembler
13 | {
14 |
15 | typedef struct {
16 | Address address;
17 | std::string mnemonic;
18 | std::string opcodes;
19 | std::vector bytes;
20 | } InstructionInfo;
21 |
22 | class Disassembler
23 | {
24 | public:
25 | Disassembler();
26 | virtual ~Disassembler();
27 |
28 | std::vector GetCallInstructions(Address startAddress, size_t size) const;
29 | std::vector GetInstructions(Address startAddress, size_t size) const;
30 |
31 | size_t GetFunctionSize(Address startAddress) const;
32 |
33 | private:
34 | csh m_handle;
35 | };
36 |
37 | }
38 | }
--------------------------------------------------------------------------------
/TED/TEDCore/GrpcServer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | #include "Proto/TED.pb.h"
15 | #include "Proto/TED.grpc.pb.h"
16 |
17 | #include "Memory.h"
18 | #include "Process.h"
19 |
20 | namespace TED
21 | {
22 | namespace Communication
23 | {
24 |
25 | class TEDServiceImpl final : public TED::Grpc::TEDService::Service
26 | {
27 | public:
28 | TEDServiceImpl(unsigned long listenThreadId);
29 | ~TEDServiceImpl();
30 |
31 | grpc::Status GetBreakpoints(grpc::ServerContext* context,
32 | const TED::Grpc::Empty* request,
33 | grpc::ServerWriter* writer) override;
34 |
35 | grpc::Status GetModules(grpc::ServerContext* context,
36 | const TED::Grpc::Empty* request,
37 | TED::Grpc::GetModulesResponse* response) override;
38 |
39 | grpc::Status EnableBreakAllCallsInModule(grpc::ServerContext* context,
40 | const TED::Grpc::EnableBreakAllCallsInModuleRequest* request,
41 | TED::Grpc::GenericResponse* response) override;
42 | grpc::Status DisableBreakAllCallsInModule(grpc::ServerContext* context,
43 | const TED::Grpc::DisableBreakAllCallsInModuleRequest* request,
44 | TED::Grpc::GenericResponse* response) override;
45 | grpc::Status EnableBreakCallByAddress(grpc::ServerContext* context,
46 | const TED::Grpc::EnableBreakCallByAddressRequest* request,
47 | TED::Grpc::GenericResponse* response) override;
48 | grpc::Status DisableBreakCallByAddress(grpc::ServerContext* context,
49 | const TED::Grpc::DisableBreakCallByAddressRequest* request,
50 | TED::Grpc::GenericResponse* response) override;
51 | grpc::Status EnableBreakCallByName(grpc::ServerContext* context,
52 | const TED::Grpc::EnableBreakCallByNameRequest* request,
53 | TED::Grpc::GenericResponse* response) override;
54 | grpc::Status DisableBreakCallByName(grpc::ServerContext* context,
55 | const TED::Grpc::DisableBreakCallByNameRequest* request,
56 | TED::Grpc::GenericResponse* response) override;
57 |
58 | grpc::Status EnableBreakpointByAddress(grpc::ServerContext* context,
59 | const TED::Grpc::EnableBreakpointByAddressRequest* request,
60 | TED::Grpc::GenericResponse* response) override;
61 | grpc::Status DisableBreakpointByAddress(grpc::ServerContext* context,
62 | const TED::Grpc::DisableBreakpointByAddressRequest* request,
63 | TED::Grpc::GenericResponse* response) override;
64 | grpc::Status EnableBreakpointByName(grpc::ServerContext* context,
65 | const TED::Grpc::EnableBreakpointByNameRequest* request,
66 | TED::Grpc::GenericResponse* response) override;
67 | grpc::Status DisableBreakpointByName(grpc::ServerContext* context,
68 | const TED::Grpc::DisableBreakpointByNameRequest* request,
69 | TED::Grpc::GenericResponse* response) override;
70 |
71 | grpc::Status DisassembleAddress(grpc::ServerContext* context,
72 | const TED::Grpc::DisassembleAddressRequest* request,
73 | TED::Grpc::DisassembleAddressResponse* response) override;
74 |
75 | grpc::Status LoadModule(grpc::ServerContext* context,
76 | const TED::Grpc::LoadModuleRequest* request,
77 | TED::Grpc::GenericResponse* response) override;
78 | grpc::Status UnloadModule(grpc::ServerContext* context,
79 | const TED::Grpc::UnloadModuleRequest* request,
80 | TED::Grpc::GenericResponse* response) override;
81 |
82 | grpc::Status ReadMemory(grpc::ServerContext* context,
83 | const TED::Grpc::ReadMemoryRequest* request,
84 | TED::Grpc::ReadMemoryResponse* response) override;
85 | grpc::Status WriteMemory(grpc::ServerContext* context,
86 | const TED::Grpc::WriteMemoryRequest* request,
87 | TED::Grpc::GenericResponse* response) override;
88 |
89 | grpc::Status CreateConsole(grpc::ServerContext* context,
90 | const TED::Grpc::Empty* request,
91 | TED::Grpc::GenericResponse* response) override;
92 | grpc::Status DestroyConsole(grpc::ServerContext* context,
93 | const TED::Grpc::Empty* request,
94 | TED::Grpc::GenericResponse* response) override;
95 |
96 | grpc::Status EnableInternalLogging(grpc::ServerContext* context,
97 | const TED::Grpc::Empty* request,
98 | TED::Grpc::GenericResponse* response) override;
99 | grpc::Status DisableInternalLogging(grpc::ServerContext* context,
100 | const TED::Grpc::Empty* request,
101 | TED::Grpc::GenericResponse* response) override;
102 |
103 | grpc::Status Options(grpc::ServerContext* context,
104 | const TED::Grpc::OptionsRequest* request,
105 | TED::Grpc::GenericResponse* response) override;
106 |
107 | grpc::Status TestFunction(grpc::ServerContext* context,
108 | const TED::Grpc::Empty* request,
109 | TED::Grpc::GenericResponse* response) override;
110 |
111 | private:
112 | grpc::Status GenericResult(bool result, TED::Grpc::GenericResponse* response) const;
113 |
114 | grpc::Status ModifyModuleBreakpoints(grpc::ServerContext* context,
115 | const std::string& moduleName,
116 | const std::function,
117 | bool isImmediateBreakpoint,
118 | TED::Grpc::GenericResponse* response) const;
119 |
120 | const std::function GetSetBreakpointFunction() const;
121 |
122 | std::vector::iterator FindModule(std::vector& modules, std::string moduleName) const;
123 | std::vector GetCallInstructions(std::vector::iterator moduleIter) const;
124 | std::vector GetApplicationThreadIds() const;
125 |
126 | TED::Grpc::Context BuildContext(const CONTEXT& context) const;
127 | std::vector BuildCallStack(const std::vector& stackFrames) const;
128 |
129 | void StartSendBreakpointEventLoop();
130 |
131 | unsigned long m_listenThreadId;
132 | unsigned long m_breakpointThreadId;
133 |
134 | bool m_returnCallStack;
135 | bool m_returnContext;
136 | bool m_returnSymbolInfo;
137 | bool m_useInvasiveBreakpoints;
138 | bool m_unsafeMemoryMode;
139 | bool m_autoDisableBreakpointsMode;
140 | bool m_killProcessOnDisconnect;
141 |
142 | std::atomic_bool m_running;
143 | std::vector*, std::condition_variable*>> m_subscribers;
144 | };
145 |
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/TED/TEDCore/Memory.cpp:
--------------------------------------------------------------------------------
1 | #include "Memory.h"
2 |
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | namespace TED
9 | {
10 | namespace Memory
11 | {
12 |
13 | static bool unsafeMemoryMode{};
14 |
15 | Address AlignToPage(Address address)
16 | {
17 | return ((address)+PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
18 | }
19 |
20 | bool IsMemoryCommitted(Address address, size_t size)
21 | {
22 | if (unsafeMemoryMode) {
23 | return true;
24 | }
25 |
26 | MEMORY_BASIC_INFORMATION memoryInfo{};
27 | auto result{ VirtualQuery(reinterpret_cast(address), &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION)) };
28 |
29 | return (memoryInfo.RegionSize >= size) && (memoryInfo.State & MEM_COMMIT);
30 | }
31 |
32 | unsigned long GetPagePermissions(Address address)
33 | {
34 | MEMORY_BASIC_INFORMATION memoryInfo{};
35 | VirtualQuery(reinterpret_cast(address), &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION));
36 |
37 | return static_cast(memoryInfo.AllocationProtect);
38 | }
39 |
40 | bool SetPagePermissions(Address address, size_t size, unsigned long newProtections, unsigned long& oldProtections)
41 | {
42 | if (unsafeMemoryMode) {
43 | return true;
44 | }
45 |
46 | auto result{ VirtualProtect(reinterpret_cast(address), size, newProtections,
47 | &oldProtections) };
48 |
49 | return result;
50 |
51 | }
52 |
53 | bool SetPagePermissions(Address address, size_t size, unsigned long newProtections)
54 | {
55 | DWORD oldProtections{};
56 | return SetPagePermissions(address, size, newProtections, oldProtections);
57 | }
58 |
59 | std::vector ReadMemory(Address address, size_t size)
60 | {
61 | if (!IsMemoryCommitted(address, size)) {
62 | return std::vector{};
63 | }
64 |
65 | std::vector bytes(size);
66 | std::memcpy(bytes.data(), reinterpret_cast(address), size);
67 |
68 | return bytes;
69 | }
70 |
71 | bool FlushInstructionCache(Address address)
72 | {
73 | if (unsafeMemoryMode) {
74 | return true;
75 | }
76 |
77 | return ::FlushInstructionCache(GetCurrentProcess(), reinterpret_cast(address), PAGE_SIZE);
78 | }
79 |
80 | bool WriteMemory(Address address, std::vector& bytes)
81 | {
82 | if (!IsMemoryCommitted(address, bytes.size())) {
83 | return false;
84 | }
85 |
86 | DWORD oldProtections{};
87 | auto result{ SetPagePermissions(address, bytes.size(), PAGE_EXECUTE_READWRITE, oldProtections) };
88 | if (result) {
89 |
90 | std::memcpy(reinterpret_cast(address), bytes.data(), bytes.size());
91 |
92 | // Multiple threads can set the page permission simlutaneously, so don't set it back to prevent
93 | // access violations.
94 |
95 | //result &= SetPagePermissions(address, bytes.size(), oldProtections);
96 |
97 | #if !defined(_M_IX86) && !defined(_M_AMD64)
98 | FlushInstructionCache(address);
99 | #endif
100 |
101 | }
102 |
103 | return result;
104 | }
105 |
106 | void EnableUnsafeMemoryMode()
107 | {
108 | unsafeMemoryMode = true;
109 | }
110 |
111 | void DisableUnsafeMemoryMode()
112 | {
113 | unsafeMemoryMode = false;
114 | }
115 |
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/TED/TEDCore/Memory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "CommonTypes.h"
6 |
7 | namespace TED
8 | {
9 | namespace Memory
10 | {
11 |
12 | constexpr unsigned long long PAGE_SIZE = 4096;
13 |
14 | Address AlignToPage(Address address);
15 |
16 | bool IsMemoryCommitted(Address address, size_t size);
17 | unsigned long GetPagePermissions(Address address);
18 | bool SetPagePermissions(Address address, size_t size, unsigned long newProtections, unsigned long& oldProtections);
19 | bool SetPagePermissions(Address address, size_t size, unsigned long newProtections);
20 |
21 | std::vector ReadMemory(Address address, size_t size);
22 | bool WriteMemory(Address address, std::vector& bytes);
23 |
24 | void EnableUnsafeMemoryMode();
25 | void DisableUnsafeMemoryMode();
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/TED/TEDCore/Process.cpp:
--------------------------------------------------------------------------------
1 | #pragma comment(lib, "Dbghelp.lib")
2 | #pragma comment(lib, "psapi.lib")
3 |
4 | #include "Process.h"
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | namespace TED
16 | {
17 | namespace Process
18 | {
19 |
20 | ThreadId CurrentThreadId()
21 | {
22 | return static_cast(GetCurrentThreadId());
23 | }
24 |
25 | std::vector GetThreadIds()
26 | {
27 | return GetThreadIds(GetCurrentProcessId());
28 | }
29 |
30 | std::vector GetThreadIds(const ProcessId processId)
31 | {
32 | std::vector threadIds{};
33 |
34 | auto snapshot{ CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, processId) };
35 | if (snapshot == INVALID_HANDLE_VALUE) {
36 | return threadIds;
37 | }
38 |
39 | THREADENTRY32 threadEntry{};
40 | threadEntry.dwSize = sizeof(THREADENTRY32);
41 | if (Thread32First(snapshot, &threadEntry)) {
42 | do {
43 | if (threadEntry.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
44 | sizeof(threadEntry.th32OwnerProcessID)) {
45 | if (threadEntry.th32OwnerProcessID == processId) {
46 | threadIds.push_back(threadEntry.th32ThreadID);
47 | }
48 | }
49 | threadEntry.dwSize = sizeof(THREADENTRY32);
50 | } while (Thread32Next(snapshot, &threadEntry));
51 | }
52 |
53 | CloseHandle(snapshot);
54 |
55 | return threadIds;
56 | }
57 |
58 | static std::vector InvokeOnThreadHandle(const std::vector& threadIds, std::function operation)
59 | {
60 | std::vector failed{};
61 |
62 | for (const auto& threadId : threadIds) {
63 | auto handle{ OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadId) };
64 | if (handle == INVALID_HANDLE_VALUE) {
65 | failed.push_back(threadId);
66 | }
67 | else {
68 | if (operation(handle) == static_cast(-1)) {
69 | failed.push_back(threadId);
70 | }
71 |
72 | CloseHandle(handle);
73 | }
74 |
75 | }
76 |
77 | return failed;
78 | }
79 |
80 | std::vector SuspendThreads(const std::vector& threadIds)
81 | {
82 | return InvokeOnThreadHandle(threadIds, SuspendThread);
83 | }
84 |
85 | std::vector ResumeThreads(const std::vector& threadIds)
86 | {
87 | return InvokeOnThreadHandle(threadIds, ResumeThread);
88 | }
89 |
90 | HANDLE GetProcessHandle(const ProcessId processId)
91 | {
92 | HANDLE processHandle{ GetCurrentProcess() };
93 | if (processId != GetCurrentProcessId()) {
94 | processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
95 | FALSE, processId);
96 | if (processHandle == NULL) {
97 | return nullptr;
98 | }
99 | }
100 |
101 | return processHandle;
102 | }
103 |
104 | std::vector GetModuleHandles(HANDLE processHandle)
105 | {
106 | std::array handles{};
107 | DWORD modulesNeeded{};
108 | if (EnumProcessModules(processHandle, handles.data(), sizeof(HMODULE) * static_cast(handles.size()), &modulesNeeded)) {
109 | return std::vector{handles.begin(), handles.begin() + (modulesNeeded / sizeof(HMODULE))};
110 | }
111 |
112 | return std::vector{};
113 | }
114 |
115 | std::vector GetModules()
116 | {
117 | return GetModules(GetCurrentProcessId());
118 | }
119 |
120 | std::vector GetModules(const ProcessId processId)
121 | {
122 | std::vector modules{};
123 |
124 | auto processHandle{ GetProcessHandle(processId) };
125 |
126 | auto moduleHandles{ GetModuleHandles(processHandle) };
127 | for (const auto& moduleHandle : moduleHandles)
128 | {
129 | Module module{};
130 |
131 | std::array moduleName{};
132 | auto result{ GetModuleFileNameExA(processHandle, moduleHandle, moduleName.data(), static_cast(moduleName.size())) };
133 | if (result) {
134 | module.name = moduleName.data();
135 | }
136 |
137 | MODULEINFO moduleInfo{};
138 | result = GetModuleInformation(GetCurrentProcess(), moduleHandle, &moduleInfo,
139 | sizeof(MODULEINFO));
140 | if (result) {
141 | module.baseAddress = reinterpret_cast(moduleInfo.lpBaseOfDll);
142 | module.size = moduleInfo.SizeOfImage;
143 | }
144 |
145 | auto ntHeader{ ImageNtHeader(moduleHandle) };
146 | auto section{ IMAGE_FIRST_SECTION(ntHeader) };
147 | for (auto j{ 0 }; j < ntHeader->FileHeader.NumberOfSections; j++)
148 | {
149 | if (section->Characteristics & (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE)) {
150 | module.executableSectionNames.push_back({ reinterpret_cast(section->Name),
151 | sizeof(section->Name) });
152 | module.executableSectionBaseAddresses.push_back(
153 | reinterpret_cast(moduleInfo.lpBaseOfDll) + section->VirtualAddress);
154 | module.executableSectionSizes.push_back(section->SizeOfRawData);
155 | }
156 |
157 | section++;
158 | }
159 |
160 | modules.push_back(module);
161 | }
162 |
163 | CloseHandle(processHandle);
164 |
165 | return modules;
166 | }
167 |
168 | bool LoadModule(std::string_view moduleName)
169 | {
170 | return LoadLibraryA(moduleName.data());
171 | }
172 |
173 | bool UnloadModule(std::string moduleName)
174 | {
175 | std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(),
176 | [](unsigned char c) { return std::tolower(c); });
177 |
178 | auto processHandle{ GetProcessHandle(GetCurrentProcessId()) };
179 |
180 | auto moduleHandles{ GetModuleHandles(processHandle) };
181 | for (const auto& moduleHandle : moduleHandles) {
182 |
183 | std::array currentModuleName{};
184 | auto result{ GetModuleFileNameExA(processHandle, moduleHandle, currentModuleName.data(), static_cast(currentModuleName.size())) };
185 | if (result) {
186 | std::transform(currentModuleName.begin(), currentModuleName.end(), currentModuleName.begin(),
187 | [](unsigned char c) { return std::tolower(c); });
188 | if (moduleName == currentModuleName.data()) {
189 | return FreeLibrary(moduleHandle);
190 | }
191 | }
192 | }
193 |
194 | return false;
195 | }
196 |
197 | void Terminate()
198 | {
199 | TerminateProcess(GetCurrentProcess(), 0);
200 | }
201 |
202 | }
203 | }
--------------------------------------------------------------------------------
/TED/TEDCore/Process.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "CommonTypes.h"
8 |
9 | namespace TED
10 | {
11 | namespace Process
12 | {
13 |
14 | using ProcessId = unsigned long;
15 | using ThreadId = unsigned long;
16 |
17 | typedef struct {
18 | std::string name;
19 | Address baseAddress;
20 | unsigned long size;
21 | std::vector executableSectionNames;
22 | std::vector executableSectionBaseAddresses;
23 | std::vector executableSectionSizes;
24 | } Module;
25 |
26 | ThreadId CurrentThreadId();
27 | std::vector GetThreadIds();
28 | std::vector GetThreadIds(const ProcessId processId);
29 | std::vector SuspendThreads(const std::vector& threadIds);
30 | std::vector ResumeThreads(const std::vector& threadIds);
31 |
32 | std::vector GetModules();
33 | std::vector GetModules(const ProcessId processId);
34 |
35 | bool LoadModule(std::string_view moduleName);
36 | bool UnloadModule(std::string moduleName);
37 |
38 | void Terminate();
39 |
40 | }
41 | }
--------------------------------------------------------------------------------
/TED/TEDCore/Proto/TED.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option java_multiple_files = true;
4 | option java_package = "io.grpc.ted.service";
5 | option java_outer_classname = "TEDProto";
6 |
7 | package TED.Grpc;
8 |
9 | service TEDService {
10 |
11 | rpc GetBreakpoints(Empty) returns (stream BreakpointResponse) {}
12 | rpc GetModules(Empty) returns (GetModulesResponse) {}
13 |
14 | rpc EnableBreakAllCallsInModule(EnableBreakAllCallsInModuleRequest) returns (GenericResponse) {}
15 | rpc DisableBreakAllCallsInModule(DisableBreakAllCallsInModuleRequest) returns (GenericResponse) {}
16 | rpc EnableBreakCallByAddress(EnableBreakCallByAddressRequest) returns (GenericResponse) {}
17 | rpc DisableBreakCallByAddress(DisableBreakCallByAddressRequest) returns (GenericResponse) {}
18 | rpc EnableBreakCallByName(EnableBreakCallByNameRequest) returns (GenericResponse) {}
19 | rpc DisableBreakCallByName(DisableBreakCallByNameRequest) returns (GenericResponse) {}
20 |
21 | rpc EnableBreakpointByAddress(EnableBreakpointByAddressRequest) returns (GenericResponse) {}
22 | rpc DisableBreakpointByAddress(DisableBreakpointByAddressRequest) returns (GenericResponse) {}
23 | rpc EnableBreakpointByName(EnableBreakpointByNameRequest) returns (GenericResponse) {}
24 | rpc DisableBreakpointByName(DisableBreakpointByNameRequest) returns (GenericResponse) {}
25 |
26 | rpc DisassembleAddress(DisassembleAddressRequest) returns (DisassembleAddressResponse) {}
27 |
28 | rpc LoadModule(LoadModuleRequest) returns (GenericResponse) {}
29 | rpc UnloadModule(UnloadModuleRequest) returns (GenericResponse) {}
30 |
31 | rpc ReadMemory(ReadMemoryRequest) returns (ReadMemoryResponse) {}
32 | rpc WriteMemory(WriteMemoryRequest) returns (GenericResponse) {}
33 |
34 | rpc CreateConsole(Empty) returns (GenericResponse) {}
35 | rpc DestroyConsole(Empty) returns (GenericResponse) {}
36 |
37 | rpc EnableInternalLogging(Empty) returns (GenericResponse) {}
38 | rpc DisableInternalLogging(Empty) returns (GenericResponse) {}
39 |
40 | rpc Options(OptionsRequest) returns (GenericResponse) {}
41 |
42 | rpc TestFunction(Empty) returns (GenericResponse) {}
43 | }
44 |
45 | message Empty {}
46 |
47 | message SegmentRegisters {
48 | uint32 cs = 1;
49 | uint32 ds = 2;
50 | uint32 es = 3;
51 | uint32 fs = 4;
52 | uint32 gs = 5;
53 | uint32 ss = 6;
54 | }
55 |
56 | message DebugRegisters {
57 | uint64 dr0 = 1;
58 | uint64 dr1 = 2;
59 | uint64 dr2 = 3;
60 | uint64 dr3 = 4;
61 | uint64 dr6 = 5;
62 | uint64 dr7 = 6;
63 | }
64 |
65 | message GeneralRegisters {
66 | uint64 rax = 1;
67 | uint64 rcx = 2;
68 | uint64 rdx = 3;
69 | uint64 rbx = 4;
70 | uint64 rsp = 5;
71 | uint64 rbp = 6;
72 | uint64 rsi = 7;
73 | uint64 rdi = 8;
74 | uint64 rip = 9;
75 | }
76 |
77 | message GeneralRegistersX64 {
78 | uint64 r8 = 1;
79 | uint64 r9 = 2;
80 | uint64 r10 = 3;
81 | uint64 r11 = 4;
82 | uint64 r12 = 5;
83 | uint64 r13 = 6;
84 | uint64 r14 = 7;
85 | uint64 r15 = 8;
86 | }
87 |
88 | message Context {
89 | SegmentRegisters segment_registers = 1;
90 | DebugRegisters debug_registers = 2;
91 | GeneralRegisters general_registers = 3;
92 | GeneralRegistersX64 general_registers_x64 = 4;
93 | int32 processor_flags = 5;
94 | }
95 |
96 | message Symbols {
97 | string function_name = 1;
98 | }
99 |
100 | message StackFrame {
101 | uint64 rip = 1;
102 | uint64 return_address = 2;
103 | uint64 frame_pointer = 3;
104 | uint64 stack_pointer = 4;
105 | repeated uint64 parameters = 5;
106 | Symbols symbols = 6;
107 | }
108 |
109 | message CallStack {
110 | repeated StackFrame stack_frame = 1;
111 | }
112 |
113 | message BreakpointResponse {
114 | uint32 process_id = 1;
115 | uint32 thread_id = 2;
116 | uint64 source_address = 3;
117 | uint64 destination_address = 4;
118 |
119 | Context context = 5;
120 | CallStack call_stack = 6;
121 | }
122 |
123 | message ExecutableSection {
124 | string name = 1;
125 | uint64 address = 2;
126 | uint64 size = 3;
127 | }
128 |
129 | message ModuleInfo {
130 | string name = 1;
131 | uint64 base_address = 2;
132 | uint64 size = 3;
133 | repeated ExecutableSection executable_sections = 4;
134 | }
135 |
136 | message GetModulesResponse {
137 | repeated ModuleInfo module_info = 1;
138 | }
139 |
140 | message EnableBreakAllCallsInModuleRequest {
141 | string module_name = 1;
142 | }
143 |
144 | message DisableBreakAllCallsInModuleRequest {
145 | string module_name = 1;
146 | }
147 |
148 | message EnableBreakCallByAddressRequest {
149 | uint64 address = 1;
150 | }
151 |
152 | message DisableBreakCallByAddressRequest {
153 | uint64 address = 1;
154 | }
155 |
156 | message EnableBreakCallByNameRequest {
157 | string name = 1;
158 | }
159 |
160 | message DisableBreakCallByNameRequest {
161 | string name = 1;
162 | }
163 |
164 | message EnableBreakpointByAddressRequest {
165 | uint64 address = 1;
166 | }
167 |
168 | message DisableBreakpointByAddressRequest {
169 | uint64 address = 1;
170 | }
171 |
172 | message EnableBreakpointByNameRequest {
173 | string name = 1;
174 | }
175 |
176 | message DisableBreakpointByNameRequest {
177 | string name = 1;
178 | }
179 |
180 | message LoadModuleRequest {
181 | string path = 1;
182 | }
183 |
184 | message UnloadModuleRequest {
185 | string path = 1;
186 | }
187 |
188 | message ReadMemoryRequest {
189 | uint64 address = 1;
190 | uint32 size = 2;
191 | }
192 |
193 | message ReadMemoryResponse {
194 | bytes bytes = 1;
195 | }
196 |
197 | message WriteMemoryRequest {
198 | uint64 address = 1;
199 | bytes bytes = 2;
200 | }
201 |
202 | message OptionsRequest {
203 | bool return_call_stack = 1;
204 | bool return_context = 2;
205 | bool return_symbol_info = 3;
206 | bool use_invasive_breakpoints = 4;
207 | bool unsafe_memory_mode = 5;
208 | bool auto_disable_breakpoints_mode = 6;
209 | bool kill_process_on_disconnect = 7;
210 | string symbol_path = 8;
211 | }
212 |
213 | message DisassembleAddressRequest {
214 | uint64 address = 1;
215 | uint32 size = 2;
216 | }
217 |
218 | message Instruction {
219 | uint64 address = 1;
220 | string mnemonic = 2;
221 | string text = 3;
222 | bytes bytes = 4;
223 | }
224 |
225 | message DisassembleAddressResponse {
226 | repeated Instruction instructions = 1;
227 | }
228 |
229 | message GenericResponse {
230 | bool success = 1;
231 | repeated uint32 last_error_code = 2;
232 | repeated string error_message = 3;
233 | }
234 |
--------------------------------------------------------------------------------
/TED/TEDCore/Source.cpp:
--------------------------------------------------------------------------------
1 | #pragma comment(lib, "Ws2_32.lib")
2 |
3 | #pragma comment(lib, "crypt32.lib")
4 | #pragma comment(lib, "iphlpapi.lib")
5 |
6 | #define WIN32_LEAN_AND_MEAN
7 |
8 | #include
9 |
10 | #include "Breakpoint.h"
11 | #include "Console.h"
12 | #include "GrpcServer.h"
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "Proto/TED.grpc.pb.h"
23 |
24 | static PVOID exceptionHandler{};
25 | static std::unique_ptr server{};
26 |
27 | void StartGrpcServer() {
28 | std::thread([]() {
29 | std::string server_address("0.0.0.0:50051");
30 | TED::Communication::TEDServiceImpl service(GetCurrentThreadId());
31 |
32 | grpc::ServerBuilder builder;
33 | builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
34 | builder.RegisterService(&service);
35 | server = std::move(builder.BuildAndStart());
36 |
37 | server->Wait();
38 | }).detach();
39 | }
40 |
41 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID reserved)
42 | {
43 | if (dwReason == DLL_PROCESS_ATTACH) {
44 | exceptionHandler = AddVectoredExceptionHandler(1, TED::Breakpoint::BreakpointHandler);
45 |
46 | StartGrpcServer();
47 | }
48 |
49 | return TRUE;
50 | }
51 |
--------------------------------------------------------------------------------
/TED/TEDCore/Symbols.cpp:
--------------------------------------------------------------------------------
1 | #pragma comment(lib, "Dbghelp.lib")
2 |
3 | #include "Symbols.h"
4 |
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | namespace TED
12 | {
13 | namespace Symbols
14 | {
15 |
16 | static std::atomic_bool symbolsEnabled{};
17 |
18 | bool EnableSymbols(std::string_view path)
19 | {
20 | if (symbolsEnabled) {
21 | return true;
22 | }
23 |
24 | SymSetOptions(SYMOPT_UNDNAME);
25 |
26 | auto result{ SymInitialize(GetCurrentProcess(), nullptr, TRUE) };
27 |
28 | if (!path.empty()) {
29 | std::array symbolPaths{};
30 | result &=
31 | SymGetSearchPath(GetCurrentProcess(), symbolPaths.data(), static_cast(symbolPaths.size()));
32 | if (result) {
33 | std::string foundPathsStr{ symbolPaths.data() };
34 | if (!foundPathsStr.ends_with(";")) {
35 | foundPathsStr += ";";
36 | }
37 |
38 | foundPathsStr += path;
39 | result &= SymSetSearchPath(GetCurrentProcess(), foundPathsStr.c_str());
40 | }
41 | }
42 |
43 | symbolsEnabled = result;
44 |
45 | return result;
46 | }
47 |
48 | bool DisableSymbols()
49 | {
50 | if (!symbolsEnabled) {
51 | return true;
52 | }
53 |
54 | auto result{ SymCleanup(GetCurrentProcess()) };
55 | symbolsEnabled = !result;
56 |
57 | return result;
58 | }
59 |
60 | std::string SymbolNameFromAddress(Address address)
61 | {
62 | if (!symbolsEnabled) {
63 | return std::string{};
64 | }
65 |
66 | std::array pBuffer{};
67 | auto symbolInfo{ reinterpret_cast(pBuffer.data()) };
68 |
69 | symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
70 | symbolInfo->MaxNameLen = MAX_SYM_NAME;
71 |
72 | DWORD64 dwDisplacement{};
73 | auto result{ SymFromAddr(GetCurrentProcess(), address, &dwDisplacement, symbolInfo) };
74 | if (!result) {
75 | return std::string{};
76 | }
77 |
78 | return std::string{ symbolInfo->Name, symbolInfo->NameLen };
79 | }
80 |
81 | Address SymbolAddressFromName(std::string_view name)
82 | {
83 | if (!symbolsEnabled) {
84 | return 0;
85 | }
86 |
87 | std::array pBuffer{};
88 | auto symbolInfo{ reinterpret_cast(pBuffer.data()) };
89 |
90 | symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
91 | symbolInfo->MaxNameLen = MAX_SYM_NAME;
92 |
93 | auto result{ SymFromName(GetCurrentProcess(), name.data(), symbolInfo) };
94 | if (!result) {
95 | return 0;
96 | }
97 |
98 | return symbolInfo->Address;
99 | }
100 |
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/TED/TEDCore/Symbols.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include