├── .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 | 86 | 87 | 88 | 0 89 | 0 90 | 945 91 | 21 92 | 93 | 94 | 95 | 96 | &File 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | F&ilter 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | &Options 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | &Help 133 | 134 | 135 | 136 | 137 | 138 | &Debug 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 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 5 | 6 | #include "CommonTypes.h" 7 | 8 | namespace TED 9 | { 10 | namespace Symbols 11 | { 12 | 13 | bool EnableSymbols(std::string_view path); 14 | bool DisableSymbols(); 15 | std::string SymbolNameFromAddress(Address address); 16 | Address SymbolAddressFromName(std::string_view name); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TED/TEDCore/TEDCore.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 | {2e4fb72d-fa6b-4b09-8e27-ae577618b7a8} 18 | 19 | 20 | {731589ba-5b16-43bf-b21e-b5751f419f09} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files\Proto 44 | 45 | 46 | Source Files\Proto 47 | 48 | 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Proto 67 | 68 | 69 | Proto 70 | 71 | 72 | 73 | 74 | Proto 75 | 76 | 77 | -------------------------------------------------------------------------------- /TED/TEDCore/TEDCore.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /TED/TEDCore/TEDCore.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 | {c49f3aea-7a3c-499c-964b-416ffadaeb97} 25 | TEDCore 26 | 10.0 27 | TEDCore 28 | 29 | 30 | 31 | DynamicLibrary 32 | true 33 | v143 34 | Unicode 35 | 36 | 37 | DynamicLibrary 38 | true 39 | v143 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | false 45 | v143 46 | true 47 | Unicode 48 | 49 | 50 | DynamicLibrary 51 | false 52 | v143 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | false 76 | 77 | 78 | false 79 | 80 | 81 | false 82 | 83 | 84 | false 85 | 86 | 87 | true 88 | 89 | 90 | true 91 | 92 | 93 | true 94 | 95 | 96 | true 97 | 98 | 99 | 100 | Level3 101 | true 102 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);NOMINMAX 103 | true 104 | stdcpplatest 105 | %(AdditionalIncludeDirectories) 106 | MultiThreadedDebug 107 | 108 | 109 | Windows 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);NOMINMAX 118 | true 119 | stdcpplatest 120 | %(AdditionalIncludeDirectories) 121 | MultiThreadedDebug 122 | 123 | 124 | Windows 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | true 133 | true 134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions);NOMINMAX 135 | true 136 | stdcpplatest 137 | %(AdditionalIncludeDirectories) 138 | MultiThreaded 139 | 140 | 141 | Windows 142 | true 143 | true 144 | true 145 | 146 | 147 | 148 | 149 | Level3 150 | true 151 | true 152 | true 153 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions);NOMINMAX 154 | true 155 | stdcpplatest 156 | %(AdditionalIncludeDirectories) 157 | MultiThreaded 158 | 159 | 160 | Windows 161 | true 162 | true 163 | true 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /TED/TEDCore/TEDCore.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Source 6 | 7 | 8 | Source 9 | 10 | 11 | Source 12 | 13 | 14 | Source 15 | 16 | 17 | Source 18 | 19 | 20 | Source 21 | 22 | 23 | Source\Proto 24 | 25 | 26 | Source\Proto 27 | 28 | 29 | Source 30 | 31 | 32 | Source 33 | 34 | 35 | 36 | 37 | Headers 38 | 39 | 40 | Headers 41 | 42 | 43 | Headers 44 | 45 | 46 | Headers 47 | 48 | 49 | Headers 50 | 51 | 52 | Headers\Proto 53 | 54 | 55 | Headers\Proto 56 | 57 | 58 | Headers 59 | 60 | 61 | Headers 62 | 63 | 64 | Headers 65 | 66 | 67 | 68 | 69 | {bf030331-f9b3-4fee-bdcf-0ee3c4269ab6} 70 | 71 | 72 | {657eb249-1cd0-4eee-9b6b-50febfa04255} 73 | 74 | 75 | {cf6a94d0-3b24-44db-a7f6-95d1a3a45c72} 76 | 77 | 78 | {6dc62edf-337b-45b4-8a3e-a160e775ba19} 79 | 80 | 81 | {4a0b7a18-a669-45be-b9ab-34cd6fbf0d16} 82 | 83 | 84 | 85 | 86 | Resources 87 | 88 | 89 | -------------------------------------------------------------------------------- /TED/TEDCore/TEDCore.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /TED/TEDTestClient/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 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "Api.h" 25 | #include "Structures.h" 26 | #include "TEDClientBridge.h" 27 | 28 | #include "Breakpoint.h" 29 | #include "GrpcServer.h" 30 | 31 | #include "Proto/TED.grpc.pb.h" 32 | 33 | 34 | 35 | void TestGetModules(TED_Client* client) 36 | { 37 | auto response{ TED_GetModules(client) }; 38 | 39 | for (size_t i{ 0 }; i < response->moduleInfoCount; i++) { 40 | const auto* moduleInfo{ response->moduleInfo[i] }; 41 | std::cout << std::format("Module name: {}\tModule base address: {:X}\tModule size: {:X}", 42 | moduleInfo->name, 43 | moduleInfo->baseAddress, 44 | moduleInfo->size) 45 | << std::endl; 46 | 47 | for (size_t j{ 0 }; j < moduleInfo->executableSectionCount; j++) { 48 | const auto* executableSection{ response->moduleInfo[i]->executableSections[j] }; 49 | std::cout << std::format("Section: {}\tSection base address: {:X}\tSection size: {:X}", 50 | executableSection->name, 51 | executableSection->address, 52 | executableSection->size) 53 | << std::endl; 54 | } 55 | } 56 | 57 | TED_DestroyModules(response); 58 | } 59 | 60 | void TestEnableBreakAllCallsInModule(TED_Client* client) 61 | { 62 | auto response{ TED_EnableBreakAllCallsInModule(client, "C:\\WINDOWS\\System32\\USER32.dll") }; 63 | std::cout << "Success: " << response->success << std::endl; 64 | 65 | TED_DestroyGeneric(response); 66 | } 67 | 68 | void TestDisableBreakAllCallsInModule(TED_Client* client) 69 | { 70 | auto response{ TED_DisableBreakAllCallsInModule(client, "C:\\WINDOWS\\System32\\USER32.dll") }; 71 | std::cout << "Success: " << response->success << std::endl; 72 | 73 | TED_DestroyGeneric(response); 74 | } 75 | 76 | void TestEnableBreakCallByAddress(TED_Client* client) 77 | { 78 | auto response{ TED_EnableBreakCallByAddress(client, (uint64_t)MessageBoxA) }; 79 | std::cout << "Success: " << response->success << std::endl; 80 | 81 | TED_DestroyGeneric(response); 82 | } 83 | 84 | void TestDisableBreakCallByAddress(TED_Client* client) 85 | { 86 | auto response{ TED_DisableBreakCallByAddress(client, (uint64_t)MessageBoxA) }; 87 | std::cout << "Success: " << response->success << std::endl; 88 | 89 | TED_DestroyGeneric(response); 90 | } 91 | 92 | void TestEnableBreakCallByName(TED_Client* client) 93 | { 94 | auto response{ TED_EnableBreakCallByName(client, "IsCharLowerA") }; 95 | std::cout << "Success: " << response->success << std::endl; 96 | 97 | TED_DestroyGeneric(response); 98 | } 99 | 100 | void TestDisableBreakCallByName(TED_Client* client) 101 | { 102 | auto response{ TED_DisableBreakCallByName(client, "IsCharLowerA") }; 103 | std::cout << "Success: " << response->success << std::endl; 104 | 105 | TED_DestroyGeneric(response); 106 | } 107 | 108 | void TestEnableBreakpointByAddress(TED_Client* client) 109 | { 110 | auto response{ TED_EnableBreakpointByAddress(client, (uint64_t)MessageBoxA) }; 111 | std::cout << "Success: " << response->success << std::endl; 112 | 113 | TED_DestroyGeneric(response); 114 | } 115 | 116 | void TestDisableBreakpointByAddress(TED_Client* client) 117 | { 118 | auto response{ TED_DisableBreakpointByAddress(client, (uint64_t)MessageBoxA) }; 119 | std::cout << "Success: " << response->success << std::endl; 120 | 121 | TED_DestroyGeneric(response); 122 | } 123 | 124 | void TestEnableBreakpointByName(TED_Client* client) 125 | { 126 | auto response{ TED_EnableBreakpointByName(client, "IsCharLowerA") }; 127 | std::cout << "Success: " << response->success << std::endl; 128 | 129 | TED_DestroyGeneric(response); 130 | } 131 | 132 | void TestDisableBreakpointByName(TED_Client* client) 133 | { 134 | auto response{ TED_DisableBreakpointByName(client, "IsCharLowerA") }; 135 | std::cout << "Success: " << response->success << std::endl; 136 | 137 | TED_DestroyGeneric(response); 138 | } 139 | 140 | void TestDisassemble(TED_Client* client) 141 | { 142 | auto response{ TED_DisassembleAddress(client, (uint64_t)MessageBoxA, 40) }; 143 | 144 | for (size_t i{ 0 }; i < response->instructionsCount; i++) { 145 | const auto* instruction = response->instructions[i]; 146 | std::cout << std::format("0x{:X} ", 147 | instruction->address); 148 | 149 | for (size_t j{ 0 }; j < instruction->bytesCount; j++) { 150 | std::cout << std::format("{:x} ", 151 | (unsigned char)instruction->bytes[j]); 152 | } 153 | 154 | std::cout << std::format("{} {}", 155 | instruction->mnemonic, 156 | instruction->text) 157 | << std::endl; 158 | } 159 | 160 | TED_DestroyDisassembleAddress(response); 161 | } 162 | 163 | void TestLoadModule(TED_Client* client) 164 | { 165 | auto response{ TED_LoadModule(client, "C:\\WINDOWS\\System32\\midimap.dll") }; 166 | std::cout << "Success: " << response->success << std::endl; 167 | 168 | TED_DestroyGeneric(response); 169 | } 170 | 171 | void TestUnloadModule(TED_Client* client) 172 | { 173 | auto response{ TED_UnloadModule(client, "C:\\WINDOWS\\System32\\midimap.dll") }; 174 | std::cout << "Success: " << response->success << std::endl; 175 | 176 | TED_DestroyGeneric(response); 177 | } 178 | 179 | void TestReadMemory(TED_Client* client) 180 | { 181 | auto response{ TED_ReadMemory(client, (uint64_t)MessageBoxA, 15) }; 182 | for (size_t i{ 0 }; i < response->bytesCount; i++) { 183 | std::cout << std::format("{:x} ", 184 | (unsigned char)response->bytes[i]); 185 | } 186 | 187 | std::cout << std::endl; 188 | 189 | TED_DestroyReadMemory(response); 190 | } 191 | 192 | void TestWriteMemory(TED_Client* client, unsigned char byte) 193 | { 194 | auto response{ TED_WriteMemory(client, (uint64_t)MessageBoxA, &byte, 1) }; 195 | std::cout << "Success: " << response->success << std::endl; 196 | 197 | TED_DestroyGeneric(response); 198 | } 199 | 200 | void TestOptions(TED_Client* client) 201 | { 202 | TED_Options options{}; 203 | options.returnCallStack = true; 204 | options.returnContext = true; 205 | options.returnSymbolInfo = true; 206 | 207 | auto response{ TED_SetOptions(client, &options) }; 208 | 209 | TED_DestroyGeneric(response); 210 | } 211 | 212 | void TestCreateConsole(TED_Client* client) 213 | { 214 | auto response{ TED_CreateConsole(client) }; 215 | std::cout << "Success: " << response->success << std::endl; 216 | 217 | TED_DestroyGeneric(response); 218 | } 219 | 220 | void TestDestroyConsole(TED_Client* client) 221 | { 222 | auto response{ TED_DestroyConsole(client) }; 223 | std::cout << "Success: " << response->success << std::endl; 224 | 225 | TED_DestroyGeneric(response); 226 | } 227 | 228 | void TestEnableLogging(TED_Client* client) 229 | { 230 | auto response{ TED_EnableInternalLogging(client) }; 231 | std::cout << "Success: " << response->success << std::endl; 232 | 233 | TED_DestroyGeneric(response); 234 | } 235 | 236 | void TestDisableLogging(TED_Client* client) 237 | { 238 | auto response{ TED_DisableInternalLogging(client) }; 239 | std::cout << "Success: " << response->success << std::endl; 240 | 241 | TED_DestroyGeneric(response); 242 | } 243 | 244 | void TestFunction(TED_Client* client) 245 | { 246 | auto response{ TED_TestFunction(client) }; 247 | std::cout << "Success: " << response->success << std::endl; 248 | 249 | TED_DestroyGeneric(response); 250 | } 251 | 252 | void TestGetBreakpoints(TED_Client* client, TED_BreakpointReader* reader) 253 | { 254 | auto response{ TED_GetBreakpoint(client, reader) }; 255 | if (response != nullptr) { 256 | 257 | std::cout << "Read breakpoint event\t" 258 | << std::format("Process ID: {}\tThread ID: {}\tSource Address: {:X}\tDestination Address: {:X}", 259 | response->processId, response->threadId, response->sourceAddress, response->destinationAddress) 260 | << std::endl; 261 | 262 | std::cout << "Context: \n" 263 | << std::format("RAX:{:X} RBX:{:X} RCX:{:X} RDX:{:X}", 264 | response->context.generalRegisters.rax, 265 | response->context.generalRegisters.rbx, 266 | response->context.generalRegisters.rcx, 267 | response->context.generalRegisters.rdx) 268 | << std::format(" RSP:{:X} RBP:{:X} RSI:{:X} RDI:{:X}", 269 | response->context.generalRegisters.rsp, 270 | response->context.generalRegisters.rbp, 271 | response->context.generalRegisters.rsi, 272 | response->context.generalRegisters.rdi) 273 | << std::format(" RIP:{:X}", 274 | response->context.generalRegisters.rip) 275 | << std::format(" R8:{:X} R9:{:X} R10:{:X} R11:{:X}", 276 | response->context.generalRegistersx64.r8, 277 | response->context.generalRegistersx64.r9, 278 | response->context.generalRegistersx64.r10, 279 | response->context.generalRegistersx64.r11) 280 | << std::format(" R12:{:X} R13:{:X} R14:{:X} R15:{:X}", 281 | response->context.generalRegistersx64.r12, 282 | response->context.generalRegistersx64.r13, 283 | response->context.generalRegistersx64.r14, 284 | response->context.generalRegistersx64.r15) 285 | << std::format(" DR0:{:X} DR1:{:X} DR2:{:X} DR3:{:X}", 286 | response->context.debugRegisters.dr0, 287 | response->context.debugRegisters.dr1, 288 | response->context.debugRegisters.dr2, 289 | response->context.debugRegisters.dr3) 290 | << std::format(" DR6:{:X} DR7:{:X}", 291 | response->context.debugRegisters.dr6, 292 | response->context.debugRegisters.dr7) 293 | << std::format(" CS:{:X} DS:{:X} ES:{:X} FS:{:X}", 294 | response->context.segmentRegisters.cs, 295 | response->context.segmentRegisters.ds, 296 | response->context.segmentRegisters.es, 297 | response->context.segmentRegisters.fs) 298 | << std::format(" GS:{:X} SS:{:X}", 299 | response->context.segmentRegisters.gs, 300 | response->context.segmentRegisters.ss) 301 | << std::endl; 302 | 303 | std::cout << "Call stack: \n"; 304 | if (response->callStack.stackFramesCount > 0) { 305 | for (size_t i{ 0 }; i < response->callStack.stackFramesCount; i++) { 306 | const auto* stackFrame = response->callStack.stackFrames[i]; 307 | std::cout 308 | << std::format("RIP:{:X} Return Address:{:X} Frame Pointer:{:X} Stack Pointer:{:X}", 309 | stackFrame->rip, 310 | stackFrame->returnAddress, 311 | stackFrame->framePointer, 312 | stackFrame->stackPointer) 313 | << std::format(" Param 1:{:X} Param 2:{:X} Param 3:{:X} Param 4:{:X}", 314 | stackFrame->parameters[0], 315 | stackFrame->parameters[1], 316 | stackFrame->parameters[2], 317 | stackFrame->parameters[3]); 318 | if (stackFrame->symbols.functionNameLength > 0) { 319 | std::cout << " " << stackFrame->symbols.functionName; 320 | } 321 | 322 | std::cout << std::endl; 323 | } 324 | } 325 | } 326 | 327 | TED_DestroyBreakpoint(response); 328 | } 329 | 330 | void StartGrpcServer() { 331 | std::thread([]() { 332 | std::string server_address("0.0.0.0:50051"); 333 | TED::Communication::TEDServiceImpl service(GetCurrentThreadId()); 334 | 335 | grpc::ServerBuilder builder; 336 | builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); 337 | builder.RegisterService(&service); 338 | std::unique_ptr server = std::move(builder.BuildAndStart()); 339 | 340 | server->Wait(); 341 | }).detach(); 342 | } 343 | 344 | int main(int argc, char* argv[]) 345 | { 346 | AddVectoredExceptionHandler(0x1, TED::Breakpoint::BreakpointHandler); 347 | 348 | StartGrpcServer(); 349 | 350 | size_t count{}; 351 | auto processes{ TED_GetActiveProcessesInformation(&count) }; 352 | for (size_t i{ 0 }; i < count; i++) { 353 | const auto& process = processes[i]; 354 | std::cout << process->processId << " " 355 | << process->name << " " 356 | << process->windowTitle << " " 357 | << process->path 358 | << std::endl; 359 | } 360 | 361 | TED_DestroyActiveProcessesInformation(processes, count); 362 | 363 | auto client{ TED_CreateClient("localhost:50051") }; 364 | 365 | TestGetModules(client); 366 | TestOptions(client); 367 | TestEnableBreakAllCallsInModule(client); 368 | TestDisableBreakAllCallsInModule(client); 369 | TestEnableBreakCallByAddress(client); 370 | TestDisableBreakCallByAddress(client); 371 | TestEnableBreakCallByName(client); 372 | TestDisableBreakCallByName(client); 373 | 374 | TestDisassemble(client); 375 | 376 | TestEnableBreakpointByAddress(client); 377 | TestDisableBreakpointByAddress(client); 378 | TestEnableBreakpointByName(client); 379 | TestDisableBreakpointByName(client); 380 | 381 | TestLoadModule(client); 382 | TestUnloadModule(client); 383 | 384 | TestWriteMemory(client, 0xCC); 385 | TestReadMemory(client); 386 | TestWriteMemory(client, 0x48); 387 | TestReadMemory(client); 388 | 389 | TestCreateConsole(client); 390 | 391 | TestEnableLogging(client); 392 | 393 | TestFunction(client); 394 | TestFunction(client); 395 | 396 | TestDisableLogging(client); 397 | TestDestroyConsole(client); 398 | 399 | auto* reader{ TED_CreateBreakpointReader(client) }; 400 | 401 | while (true) { 402 | TestGetBreakpoints(client, reader); 403 | } 404 | 405 | TED_DestroyBreakpointReader(reader); 406 | TED_DestroyClient(client); 407 | 408 | std::cout << "Done!" << std::endl; 409 | 410 | return 0; 411 | } 412 | -------------------------------------------------------------------------------- /TED/TEDTestClient/TEDTestClient.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 | {0a5532bd-c990-4b55-84a5-ee54e1929e51} 18 | 19 | 20 | {583e296d-4cf5-4d3f-a7b8-8627cb7a0f0e} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files\Proto 29 | 30 | 31 | Source Files\Proto 32 | 33 | 34 | 35 | 36 | Header Files\Proto 37 | 38 | 39 | Header Files\Proto 40 | 41 | 42 | -------------------------------------------------------------------------------- /TED/TEDTestClient/TEDTestClient.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /TED/TEDTestClient/TEDTestClient.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 | {023c3308-fbb4-48b6-9712-feba3bce8ce9} 25 | TEDTestClient 26 | 10.0 27 | TEDTestClient 28 | 29 | 30 | 31 | Application 32 | true 33 | v143 34 | Unicode 35 | 36 | 37 | Application 38 | true 39 | v143 40 | Unicode 41 | 42 | 43 | Application 44 | false 45 | v143 46 | true 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v143 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | true 79 | 80 | 81 | true 82 | 83 | 84 | true 85 | 86 | 87 | 88 | Level3 89 | true 90 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | $(IncludePath);../TEDCore;../TEDClientAPI;%(AdditionalIncludeDirectories) 93 | stdcpplatest 94 | MultiThreadedDebug 95 | $(IntDir)%(RelativeDir) 96 | 97 | 98 | Console 99 | true 100 | 101 | 102 | 103 | 104 | Level3 105 | true 106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | $(IncludePath);../TEDCore;../TEDClientAPI;%(AdditionalIncludeDirectories) 109 | stdcpplatest 110 | MultiThreadedDebug 111 | $(IntDir)%(RelativeDir) 112 | 113 | 114 | Console 115 | true 116 | 117 | 118 | 119 | 120 | Level3 121 | true 122 | true 123 | true 124 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | true 126 | $(IncludePath);../TEDCore;../TEDClientAPI;%(AdditionalIncludeDirectories) 127 | stdcpplatest 128 | MultiThreaded 129 | $(IntDir)%(RelativeDir) 130 | 131 | 132 | Console 133 | true 134 | true 135 | true 136 | 137 | 138 | 139 | 140 | Level3 141 | true 142 | true 143 | true 144 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 145 | true 146 | $(IncludePath);../TEDCore;../TEDClientAPI;%(AdditionalIncludeDirectories) 147 | stdcpplatest 148 | MultiThreaded 149 | $(IntDir)%(RelativeDir) 150 | 151 | 152 | Console 153 | true 154 | true 155 | true 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /TED/TEDTestClient/TEDTestClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Source 6 | 7 | 8 | Source\Proto 9 | 10 | 11 | Source\Proto 12 | 13 | 14 | Source\Api 15 | 16 | 17 | Source\Core\Source 18 | 19 | 20 | Source\Core\Source 21 | 22 | 23 | Source\Core\Source 24 | 25 | 26 | Source\Core\Source 27 | 28 | 29 | Source\Core\Source 30 | 31 | 32 | Source\Core\Source 33 | 34 | 35 | Source\Core\Source 36 | 37 | 38 | 39 | 40 | {b6eada8d-8311-4cba-b1d7-26cceb002c6b} 41 | 42 | 43 | {1d943be6-7e92-4cf9-ab27-6b6a25882395} 44 | 45 | 46 | {7e6adec8-3c14-43a0-aed3-0800f56121e2} 47 | 48 | 49 | {62fc906c-4a06-4fd4-95fa-b7813426a45a} 50 | 51 | 52 | {03e16cb1-3510-47d6-8906-280721185b45} 53 | 54 | 55 | {6010c531-836e-418c-bd48-cc4b88437a4a} 56 | 57 | 58 | {8e098de7-bbcd-4d8d-b817-fb3929a66041} 59 | 60 | 61 | {3de7a117-9fb6-403d-a51e-1ff9126d838a} 62 | 63 | 64 | 65 | 66 | Headers\Proto 67 | 68 | 69 | Headers\Proto 70 | 71 | 72 | Source\Core\Headers 73 | 74 | 75 | Source\Core\Headers 76 | 77 | 78 | Source\Core\Headers 79 | 80 | 81 | Source\Core\Headers 82 | 83 | 84 | Source\Core\Headers 85 | 86 | 87 | Source\Core\Headers 88 | 89 | 90 | Source\Core\Headers 91 | 92 | 93 | Source\Core\Headers 94 | 95 | 96 | -------------------------------------------------------------------------------- /TED/TEDTestClient/TEDTestClient.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /TED/TEDx86InjectorBridge/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) 4 | { 5 | return reinterpret_cast(LoadLibraryA); 6 | } -------------------------------------------------------------------------------- /TED/TEDx86InjectorBridge/TEDx86InjectorBridge.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 16.0 15 | Win32Proj 16 | {734ba336-3f98-4dac-8542-b12f2b920e4a} 17 | TEDx86InjectorBridge 18 | 10.0 19 | 20 | 21 | 22 | Application 23 | true 24 | v143 25 | Unicode 26 | 27 | 28 | Application 29 | false 30 | v143 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Level3 49 | true 50 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 51 | true 52 | 53 | 54 | Windows 55 | true 56 | 57 | 58 | 59 | 60 | Level3 61 | true 62 | true 63 | true 64 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 65 | true 66 | 67 | 68 | Windows 69 | true 70 | true 71 | true 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /TED/TEDx86InjectorBridge/TEDx86InjectorBridge.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 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /TED/TEDx86InjectorBridge/TEDx86InjectorBridge.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------