├── SampleDebuggerPart1 ├── SampleDebuggerPart1 │ ├── Common.h │ ├── Source.cpp │ ├── Debugger.h │ ├── DebugEventHandler.h │ ├── DebugExceptionHandler.h │ ├── SampleDebuggerPart1.vcxproj.filters │ ├── Observable.h │ ├── Debugger.cpp │ ├── SampleDebuggerPart1.vcxproj │ ├── DebugExceptionHandler.cpp │ └── DebugEventHandler.cpp └── SampleDebuggerPart1.sln ├── SampleDebuggerPart2 ├── SampleDebuggerPart2 │ ├── Common.h │ ├── InterruptBreakpoint.h │ ├── Breakpoint.h │ ├── Breakpoint.cpp │ ├── DebugEventHandler.h │ ├── InterruptBreakpoint.cpp │ ├── Source.cpp │ ├── Debugger.h │ ├── DebugExceptionHandler.h │ ├── Observable.h │ ├── SampleDebuggerPart2.vcxproj.filters │ ├── SampleDebuggerPart2.vcxproj │ ├── DebugEventHandler.cpp │ └── Debugger.cpp └── SampleDebuggerPart2.sln ├── SampleDebuggerPart3 ├── SampleDebuggerPart3 │ ├── Common.h │ ├── InterruptBreakpoint.h │ ├── Breakpoint.h │ ├── Breakpoint.cpp │ ├── DebugEventHandler.h │ ├── InterruptBreakpoint.cpp │ ├── SafeHandle.h │ ├── DebugExceptionHandler.h │ ├── Debugger.h │ ├── Observable.h │ ├── SampleDebuggerPart3.vcxproj.filters │ ├── Source.cpp │ ├── SampleDebuggerPart3.vcxproj │ ├── DebugEventHandler.cpp │ └── DebugExceptionHandler.cpp └── SampleDebuggerPart3.sln ├── SampleDebuggerPart4 ├── SampleDebuggerPart4 │ ├── Common.h │ ├── InterruptBreakpoint.h │ ├── Breakpoint.h │ ├── Breakpoint.cpp │ ├── DebugEventHandler.h │ ├── InterruptBreakpoint.cpp │ ├── SafeHandle.h │ ├── DebugExceptionHandler.h │ ├── Observable.h │ ├── Debugger.h │ ├── SampleDebuggerPart4.vcxproj.filters │ ├── Symbols.h │ ├── SampleDebuggerPart4.vcxproj │ ├── Source.cpp │ ├── DebugEventHandler.cpp │ └── DebugExceptionHandler.cpp └── SampleDebuggerPart4.sln ├── SampleDebuggerPart5 ├── SampleDebuggerPart5 │ ├── Common.h │ ├── InterruptBreakpoint.h │ ├── Disassembler.h │ ├── Breakpoint.h │ ├── Breakpoint.cpp │ ├── DebugEventHandler.h │ ├── SafeHandle.h │ ├── InterruptBreakpoint.cpp │ ├── DebugExceptionHandler.h │ ├── Observable.h │ ├── SampleDebuggerPart5.vcxproj.filters │ ├── Debugger.h │ ├── Disassembler.cpp │ ├── Symbols.h │ ├── DebugEventHandler.cpp │ ├── Source.cpp │ └── DebugExceptionHandler.cpp ├── dlls │ ├── BeaEngine_x64.dll │ └── BeaEngine_x86.dll ├── Debug │ ├── BeaEngine_x64.dll │ └── BeaEngine_x86.dll ├── x64 │ └── Debug │ │ ├── BeaEngine_x64.dll │ │ └── BeaEngine_x86.dll ├── SampleDebuggerPart5.sln └── beaengine │ ├── Includes │ └── export.h │ └── BeaEngine.h └── README.md /SampleDebuggerPart1/SampleDebuggerPart1/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BOOLIFY(x) !!(x) -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BOOLIFY(x) !!(x) -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BOOLIFY(x) !!(x) -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BOOLIFY(x) !!(x) -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BOOLIFY(x) !!(x) -------------------------------------------------------------------------------- /SampleDebuggerPart5/dlls/BeaEngine_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codereversing/debugger/HEAD/SampleDebuggerPart5/dlls/BeaEngine_x64.dll -------------------------------------------------------------------------------- /SampleDebuggerPart5/dlls/BeaEngine_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codereversing/debugger/HEAD/SampleDebuggerPart5/dlls/BeaEngine_x86.dll -------------------------------------------------------------------------------- /SampleDebuggerPart5/Debug/BeaEngine_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codereversing/debugger/HEAD/SampleDebuggerPart5/Debug/BeaEngine_x64.dll -------------------------------------------------------------------------------- /SampleDebuggerPart5/Debug/BeaEngine_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codereversing/debugger/HEAD/SampleDebuggerPart5/Debug/BeaEngine_x86.dll -------------------------------------------------------------------------------- /SampleDebuggerPart5/x64/Debug/BeaEngine_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codereversing/debugger/HEAD/SampleDebuggerPart5/x64/Debug/BeaEngine_x64.dll -------------------------------------------------------------------------------- /SampleDebuggerPart5/x64/Debug/BeaEngine_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codereversing/debugger/HEAD/SampleDebuggerPart5/x64/Debug/BeaEngine_x86.dll -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Debugger.h" 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | CodeReversing::Debugger dbg(1234); 7 | 8 | return dbg.Start(); 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # debugger 2 | Sample debugger for x86 and x64 3 | 4 | From November 2014 - December 2014 5 | 6 | http://www.codereversing.com/archives/168 7 | 8 | http://www.codereversing.com/archives/169 9 | 10 | http://www.codereversing.com/archives/170 11 | 12 | http://www.codereversing.com/archives/176 13 | 14 | http://www.codereversing.com/archives/178 15 | -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/InterruptBreakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Breakpoint.h" 5 | 6 | namespace CodeReversing 7 | { 8 | 9 | class InterruptBreakpoint final : public Breakpoint 10 | { 11 | public: 12 | InterruptBreakpoint() = delete; 13 | InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress); 14 | 15 | InterruptBreakpoint(const InterruptBreakpoint ©) = delete; 16 | InterruptBreakpoint &operator=(const InterruptBreakpoint ©) = delete; 17 | 18 | ~InterruptBreakpoint() = default; 19 | 20 | const bool EnableBreakpoint(); 21 | const bool DisableBreakpoint(); 22 | 23 | private: 24 | const static unsigned char m_breakpointOpcode = 0xCC; 25 | unsigned char m_originalByte; 26 | 27 | }; 28 | 29 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/InterruptBreakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Breakpoint.h" 5 | 6 | namespace CodeReversing 7 | { 8 | 9 | class InterruptBreakpoint final : public Breakpoint 10 | { 11 | public: 12 | InterruptBreakpoint() = delete; 13 | InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress); 14 | 15 | InterruptBreakpoint(const InterruptBreakpoint ©) = delete; 16 | InterruptBreakpoint &operator=(const InterruptBreakpoint ©) = delete; 17 | 18 | ~InterruptBreakpoint() = default; 19 | 20 | const bool EnableBreakpoint(); 21 | const bool DisableBreakpoint(); 22 | 23 | private: 24 | const static unsigned char m_breakpointOpcode = 0xCC; 25 | unsigned char m_originalByte; 26 | 27 | }; 28 | 29 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/InterruptBreakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Breakpoint.h" 5 | 6 | namespace CodeReversing 7 | { 8 | 9 | class InterruptBreakpoint final : public Breakpoint 10 | { 11 | public: 12 | InterruptBreakpoint() = delete; 13 | InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress); 14 | 15 | InterruptBreakpoint(const InterruptBreakpoint ©) = delete; 16 | InterruptBreakpoint &operator=(const InterruptBreakpoint ©) = delete; 17 | 18 | ~InterruptBreakpoint() = default; 19 | 20 | const bool EnableBreakpoint(); 21 | const bool DisableBreakpoint(); 22 | 23 | private: 24 | const static unsigned char m_breakpointOpcode = 0xCC; 25 | unsigned char m_originalByte; 26 | 27 | }; 28 | 29 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/InterruptBreakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Breakpoint.h" 5 | 6 | namespace CodeReversing 7 | { 8 | 9 | class InterruptBreakpoint final : public Breakpoint 10 | { 11 | public: 12 | InterruptBreakpoint() = delete; 13 | InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress); 14 | 15 | InterruptBreakpoint(const InterruptBreakpoint ©) = delete; 16 | InterruptBreakpoint &operator=(const InterruptBreakpoint ©) = delete; 17 | 18 | ~InterruptBreakpoint() = default; 19 | 20 | const bool EnableBreakpoint(); 21 | const bool DisableBreakpoint(); 22 | 23 | void ChangeAddress(const DWORD_PTR dwNewAddress); 24 | 25 | private: 26 | const static unsigned char m_breakpointOpcode = 0xCC; 27 | unsigned char m_originalByte; 28 | 29 | }; 30 | 31 | } -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/Debugger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "DebugEventHandler.h" 11 | 12 | namespace CodeReversing 13 | { 14 | 15 | class Debugger final 16 | { 17 | public: 18 | Debugger() = delete; 19 | Debugger(const DWORD dwProcessId, const bool bKillOnExit = false); 20 | 21 | Debugger(const Debugger ©) = delete; 22 | Debugger &operator=(const Debugger ©) = delete; 23 | 24 | ~Debugger() = default; 25 | 26 | const bool Start(); 27 | const bool Stop(); 28 | 29 | const bool IsActive() const; 30 | 31 | private: 32 | bool m_bIsActive; 33 | bool m_bKillOnExit; 34 | DWORD m_dwProcessId; 35 | HANDLE m_hProcess; 36 | 37 | const bool DebuggerLoop(); 38 | 39 | std::unique_ptr m_pEventHandler; 40 | }; 41 | 42 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDebuggerPart5", "SampleDebuggerPart5\SampleDebuggerPart5.vcxproj", "{2862A32D-C7A8-4AAB-B16C-E4A6FA789AE4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {2862A32D-C7A8-4AAB-B16C-E4A6FA789AE4}.Debug|Win32.ActiveCfg = Debug|x64 15 | {2862A32D-C7A8-4AAB-B16C-E4A6FA789AE4}.Debug|Win32.Build.0 = Debug|x64 16 | {2862A32D-C7A8-4AAB-B16C-E4A6FA789AE4}.Release|Win32.ActiveCfg = Release|Win32 17 | {2862A32D-C7A8-4AAB-B16C-E4A6FA789AE4}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDebuggerPart1", "SampleDebuggerPart1\SampleDebuggerPart1.vcxproj", "{88A92DD3-FE5F-4B75-BDF2-E4FE9CF5ADEF}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {88A92DD3-FE5F-4B75-BDF2-E4FE9CF5ADEF}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {88A92DD3-FE5F-4B75-BDF2-E4FE9CF5ADEF}.Debug|Win32.Build.0 = Debug|Win32 16 | {88A92DD3-FE5F-4B75-BDF2-E4FE9CF5ADEF}.Release|Win32.ActiveCfg = Release|Win32 17 | {88A92DD3-FE5F-4B75-BDF2-E4FE9CF5ADEF}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDebuggerPart2", "SampleDebuggerPart2\SampleDebuggerPart2.vcxproj", "{8619AF7D-E3EA-4AFF-A043-F360A72B4D78}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {8619AF7D-E3EA-4AFF-A043-F360A72B4D78}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {8619AF7D-E3EA-4AFF-A043-F360A72B4D78}.Debug|Win32.Build.0 = Debug|Win32 16 | {8619AF7D-E3EA-4AFF-A043-F360A72B4D78}.Release|Win32.ActiveCfg = Release|Win32 17 | {8619AF7D-E3EA-4AFF-A043-F360A72B4D78}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDebuggerPart3", "SampleDebuggerPart3\SampleDebuggerPart3.vcxproj", "{616FC782-491B-4FAB-B5C5-3C2FAFFFD215}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {616FC782-491B-4FAB-B5C5-3C2FAFFFD215}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {616FC782-491B-4FAB-B5C5-3C2FAFFFD215}.Debug|Win32.Build.0 = Debug|Win32 16 | {616FC782-491B-4FAB-B5C5-3C2FAFFFD215}.Release|Win32.ActiveCfg = Release|Win32 17 | {616FC782-491B-4FAB-B5C5-3C2FAFFFD215}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDebuggerPart4", "SampleDebuggerPart4\SampleDebuggerPart4.vcxproj", "{C94AEC4E-B027-4F2B-A65B-5AC5AA6F2488}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C94AEC4E-B027-4F2B-A65B-5AC5AA6F2488}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {C94AEC4E-B027-4F2B-A65B-5AC5AA6F2488}.Debug|Win32.Build.0 = Debug|Win32 16 | {C94AEC4E-B027-4F2B-A65B-5AC5AA6F2488}.Release|Win32.ActiveCfg = Release|Win32 17 | {C94AEC4E-B027-4F2B-A65B-5AC5AA6F2488}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Disassembler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BeaEngine.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace CodeReversing 10 | { 11 | typedef int(__stdcall *pDisasm)(LPDISASM pDisAsm); 12 | 13 | class Disassembler final 14 | { 15 | public: 16 | Disassembler() = delete; 17 | 18 | Disassembler(HANDLE hProcess); 19 | 20 | Disassembler(const Disassembler ©) = delete; 21 | Disassembler &operator=(const Disassembler ©) = delete; 22 | 23 | ~Disassembler(); 24 | 25 | const bool BytesAtAddress(DWORD_PTR dwAddress, size_t ulInstructionsToDisassemble = 15); 26 | DWORD_PTR GetNextInstruction(const DWORD_PTR dwAddress, bool &bIsUnconditionalBranch); 27 | 28 | private: 29 | static HMODULE m_hDll; 30 | static pDisasm m_pDisasm; 31 | 32 | static const bool IsInitialized(); 33 | 34 | void SetDisassembler(const DWORD_PTR dwAddress); 35 | const bool TransferBytes(const DWORD_PTR dwAddress); 36 | 37 | HANDLE m_hProcess; 38 | DISASM m_disassembler; 39 | 40 | DWORD_PTR m_dwStartAddress; 41 | std::array m_bytes; 42 | }; 43 | 44 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/Breakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CodeReversing 6 | { 7 | 8 | class Breakpoint 9 | { 10 | public: 11 | enum class eType 12 | { 13 | eHardware = 1, 14 | eSoftware = 2, 15 | eInterrupt = 3 16 | }; 17 | 18 | Breakpoint() = delete; 19 | Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType); 20 | 21 | Breakpoint(const Breakpoint ©) = delete; 22 | Breakpoint &operator=(const Breakpoint ©) = delete; 23 | 24 | virtual ~Breakpoint() = default; 25 | 26 | const eType Type() const; 27 | const DWORD_PTR Address() const; 28 | const bool IsEnabled() const; 29 | 30 | const bool Enable(); 31 | const bool Disable(); 32 | 33 | bool operator==(const Breakpoint &rhs) const; 34 | 35 | private: 36 | enum class eState 37 | { 38 | eDisabled = 0, 39 | eEnabled = 1 40 | }; 41 | 42 | virtual const bool EnableBreakpoint() = 0; 43 | virtual const bool DisableBreakpoint() = 0; 44 | 45 | eType m_eType; 46 | eState m_eState; 47 | 48 | protected: 49 | HANDLE m_hProcess; 50 | DWORD_PTR m_dwAddress; 51 | 52 | }; 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/Breakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CodeReversing 6 | { 7 | 8 | class Breakpoint 9 | { 10 | public: 11 | enum class eType 12 | { 13 | eHardware = 1, 14 | eSoftware = 2, 15 | eInterrupt = 3 16 | }; 17 | 18 | Breakpoint() = delete; 19 | Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType); 20 | 21 | Breakpoint(const Breakpoint ©) = delete; 22 | Breakpoint &operator=(const Breakpoint ©) = delete; 23 | 24 | virtual ~Breakpoint() = default; 25 | 26 | const eType Type() const; 27 | const DWORD_PTR Address() const; 28 | const bool IsEnabled() const; 29 | 30 | const bool Enable(); 31 | const bool Disable(); 32 | 33 | bool operator==(const Breakpoint &rhs) const; 34 | 35 | private: 36 | enum class eState 37 | { 38 | eDisabled = 0, 39 | eEnabled = 1 40 | }; 41 | 42 | virtual const bool EnableBreakpoint() = 0; 43 | virtual const bool DisableBreakpoint() = 0; 44 | 45 | eType m_eType; 46 | eState m_eState; 47 | 48 | protected: 49 | HANDLE m_hProcess; 50 | DWORD_PTR m_dwAddress; 51 | 52 | }; 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/Breakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CodeReversing 6 | { 7 | 8 | class Breakpoint 9 | { 10 | public: 11 | enum class eType 12 | { 13 | eHardware = 1, 14 | eSoftware = 2, 15 | eInterrupt = 3 16 | }; 17 | 18 | Breakpoint() = delete; 19 | Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType); 20 | 21 | Breakpoint(const Breakpoint ©) = delete; 22 | Breakpoint &operator=(const Breakpoint ©) = delete; 23 | 24 | virtual ~Breakpoint() = default; 25 | 26 | const eType Type() const; 27 | const DWORD_PTR Address() const; 28 | const bool IsEnabled() const; 29 | 30 | const bool Enable(); 31 | const bool Disable(); 32 | 33 | bool operator==(const Breakpoint &rhs) const; 34 | 35 | private: 36 | enum class eState 37 | { 38 | eDisabled = 0, 39 | eEnabled = 1 40 | }; 41 | 42 | virtual const bool EnableBreakpoint() = 0; 43 | virtual const bool DisableBreakpoint() = 0; 44 | 45 | eType m_eType; 46 | eState m_eState; 47 | 48 | protected: 49 | HANDLE m_hProcess; 50 | DWORD_PTR m_dwAddress; 51 | 52 | }; 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/Breakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "Breakpoint.h" 2 | 3 | namespace CodeReversing 4 | { 5 | 6 | Breakpoint::Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType) 7 | : m_hProcess{ hProcess }, m_dwAddress{ dwAddress }, m_eType{ eBreakpointType }, 8 | m_eState{Breakpoint::eState::eDisabled} 9 | { 10 | } 11 | 12 | const bool Breakpoint::Enable() 13 | { 14 | if (EnableBreakpoint()) 15 | { 16 | m_eState = Breakpoint::eState::eEnabled; 17 | return true; 18 | } 19 | return false; 20 | } 21 | 22 | const bool Breakpoint::Disable() 23 | { 24 | if (DisableBreakpoint()) 25 | { 26 | m_eState = Breakpoint::eState::eDisabled; 27 | return true; 28 | } 29 | return false; 30 | } 31 | 32 | const Breakpoint::eType Breakpoint::Type() const 33 | { 34 | return m_eType; 35 | } 36 | 37 | const DWORD_PTR Breakpoint::Address() const 38 | { 39 | return m_dwAddress; 40 | } 41 | 42 | const bool Breakpoint::IsEnabled() const 43 | { 44 | return m_eState == Breakpoint::eState::eEnabled; 45 | } 46 | 47 | bool Breakpoint::operator==(const Breakpoint &rhs) const 48 | { 49 | return (m_eType == rhs.m_eType) && (m_dwAddress == rhs.m_dwAddress); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/Breakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "Breakpoint.h" 2 | 3 | namespace CodeReversing 4 | { 5 | 6 | Breakpoint::Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType) 7 | : m_hProcess{ hProcess }, m_dwAddress{ dwAddress }, m_eType{ eBreakpointType }, 8 | m_eState{Breakpoint::eState::eDisabled} 9 | { 10 | } 11 | 12 | const bool Breakpoint::Enable() 13 | { 14 | if (EnableBreakpoint()) 15 | { 16 | m_eState = Breakpoint::eState::eEnabled; 17 | return true; 18 | } 19 | return false; 20 | } 21 | 22 | const bool Breakpoint::Disable() 23 | { 24 | if (DisableBreakpoint()) 25 | { 26 | m_eState = Breakpoint::eState::eDisabled; 27 | return true; 28 | } 29 | return false; 30 | } 31 | 32 | const Breakpoint::eType Breakpoint::Type() const 33 | { 34 | return m_eType; 35 | } 36 | 37 | const DWORD_PTR Breakpoint::Address() const 38 | { 39 | return m_dwAddress; 40 | } 41 | 42 | const bool Breakpoint::IsEnabled() const 43 | { 44 | return m_eState == Breakpoint::eState::eEnabled; 45 | } 46 | 47 | bool Breakpoint::operator==(const Breakpoint &rhs) const 48 | { 49 | return (m_eType == rhs.m_eType) && (m_dwAddress == rhs.m_dwAddress); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/Breakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "Breakpoint.h" 2 | 3 | namespace CodeReversing 4 | { 5 | 6 | Breakpoint::Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType) 7 | : m_hProcess{ hProcess }, m_dwAddress{ dwAddress }, m_eType{ eBreakpointType }, 8 | m_eState{Breakpoint::eState::eDisabled} 9 | { 10 | } 11 | 12 | const bool Breakpoint::Enable() 13 | { 14 | if (EnableBreakpoint()) 15 | { 16 | m_eState = Breakpoint::eState::eEnabled; 17 | return true; 18 | } 19 | return false; 20 | } 21 | 22 | const bool Breakpoint::Disable() 23 | { 24 | if (DisableBreakpoint()) 25 | { 26 | m_eState = Breakpoint::eState::eDisabled; 27 | return true; 28 | } 29 | return false; 30 | } 31 | 32 | const Breakpoint::eType Breakpoint::Type() const 33 | { 34 | return m_eType; 35 | } 36 | 37 | const DWORD_PTR Breakpoint::Address() const 38 | { 39 | return m_dwAddress; 40 | } 41 | 42 | const bool Breakpoint::IsEnabled() const 43 | { 44 | return m_eState == Breakpoint::eState::eEnabled; 45 | } 46 | 47 | bool Breakpoint::operator==(const Breakpoint &rhs) const 48 | { 49 | return (m_eType == rhs.m_eType) && (m_dwAddress == rhs.m_dwAddress); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Breakpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CodeReversing 6 | { 7 | 8 | class Breakpoint 9 | { 10 | public: 11 | enum class eType 12 | { 13 | eHardware = 1, 14 | eSoftware = 2, 15 | eInterrupt = 3 16 | }; 17 | 18 | Breakpoint() = delete; 19 | Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType); 20 | 21 | Breakpoint(const Breakpoint ©) = delete; 22 | Breakpoint &operator=(const Breakpoint ©) = delete; 23 | 24 | virtual ~Breakpoint() = default; 25 | 26 | const eType Type() const; 27 | const DWORD_PTR Address() const; 28 | const bool IsEnabled() const; 29 | 30 | const bool Enable(); 31 | const bool Disable(); 32 | 33 | bool operator==(const Breakpoint &rhs) const; 34 | bool operator!=(const Breakpoint &rhs) const; 35 | 36 | private: 37 | enum class eState 38 | { 39 | eDisabled = 0, 40 | eEnabled = 1 41 | }; 42 | 43 | virtual const bool EnableBreakpoint() = 0; 44 | virtual const bool DisableBreakpoint() = 0; 45 | 46 | eType m_eType; 47 | eState m_eState; 48 | 49 | protected: 50 | HANDLE m_hProcess; 51 | DWORD_PTR m_dwAddress; 52 | 53 | }; 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Breakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "Breakpoint.h" 2 | 3 | namespace CodeReversing 4 | { 5 | 6 | Breakpoint::Breakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress, const eType eBreakpointType) 7 | : m_hProcess{ hProcess }, m_dwAddress{ dwAddress }, m_eType{ eBreakpointType }, 8 | m_eState{Breakpoint::eState::eDisabled} 9 | { 10 | } 11 | 12 | const bool Breakpoint::Enable() 13 | { 14 | if (EnableBreakpoint()) 15 | { 16 | m_eState = Breakpoint::eState::eEnabled; 17 | return true; 18 | } 19 | return false; 20 | } 21 | 22 | const bool Breakpoint::Disable() 23 | { 24 | if (DisableBreakpoint()) 25 | { 26 | m_eState = Breakpoint::eState::eDisabled; 27 | return true; 28 | } 29 | return false; 30 | } 31 | 32 | const Breakpoint::eType Breakpoint::Type() const 33 | { 34 | return m_eType; 35 | } 36 | 37 | const DWORD_PTR Breakpoint::Address() const 38 | { 39 | return m_dwAddress; 40 | } 41 | 42 | const bool Breakpoint::IsEnabled() const 43 | { 44 | return m_eState == Breakpoint::eState::eEnabled; 45 | } 46 | 47 | bool Breakpoint::operator==(const Breakpoint &rhs) const 48 | { 49 | return (m_eType == rhs.m_eType) && (m_dwAddress == rhs.m_dwAddress); 50 | } 51 | 52 | bool Breakpoint::operator!=(const Breakpoint &rhs) const 53 | { 54 | return !(*this == rhs); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/DebugEventHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "Observable.h" 9 | #include "DebugExceptionHandler.h" 10 | 11 | namespace CodeReversing 12 | { 13 | 14 | enum DebugEvents 15 | { 16 | //General events 17 | eException = EXCEPTION_DEBUG_EVENT, 18 | eCreateThread = CREATE_THREAD_DEBUG_EVENT, 19 | eCreateProcess = CREATE_PROCESS_DEBUG_EVENT, 20 | eExitThread = EXIT_THREAD_DEBUG_EVENT, 21 | eExitProcess = EXIT_PROCESS_DEBUG_EVENT, 22 | eLoadDll = LOAD_DLL_DEBUG_EVENT, 23 | eUnloadDll = UNLOAD_DLL_DEBUG_EVENT, 24 | eDebugString = OUTPUT_DEBUG_STRING_EVENT, 25 | eRipEvent = RIP_EVENT, 26 | }; 27 | 28 | class DebugEventHandler final : public Observable 29 | { 30 | public: 31 | DebugEventHandler(); 32 | 33 | DebugEventHandler(const DebugEventHandler ©) = delete; 34 | DebugEventHandler &operator=(const DebugEventHandler ©) = delete; 35 | 36 | ~DebugEventHandler() = default; 37 | 38 | const DWORD ContinueStatus() const; 39 | 40 | private: 41 | void Initialize(); 42 | void SetContinueStatus(const DWORD dwContinueStatus); 43 | 44 | DWORD m_dwContinueStatus; 45 | HANDLE m_hProcess; 46 | std::unique_ptr m_pExceptionHandler; 47 | }; 48 | 49 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/DebugEventHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "Observable.h" 9 | #include "DebugExceptionHandler.h" 10 | 11 | namespace CodeReversing 12 | { 13 | 14 | class Debugger; 15 | 16 | enum DebugEvents 17 | { 18 | //General events 19 | eException = EXCEPTION_DEBUG_EVENT, 20 | eCreateThread = CREATE_THREAD_DEBUG_EVENT, 21 | eCreateProcess = CREATE_PROCESS_DEBUG_EVENT, 22 | eExitThread = EXIT_THREAD_DEBUG_EVENT, 23 | eExitProcess = EXIT_PROCESS_DEBUG_EVENT, 24 | eLoadDll = LOAD_DLL_DEBUG_EVENT, 25 | eUnloadDll = UNLOAD_DLL_DEBUG_EVENT, 26 | eDebugString = OUTPUT_DEBUG_STRING_EVENT, 27 | eRipEvent = RIP_EVENT, 28 | }; 29 | 30 | class DebugEventHandler final : public Observable 31 | { 32 | public: 33 | DebugEventHandler() = delete; 34 | DebugEventHandler(Debugger *pDebugger); 35 | 36 | DebugEventHandler(const DebugEventHandler ©) = delete; 37 | DebugEventHandler &operator=(const DebugEventHandler ©) = delete; 38 | 39 | ~DebugEventHandler() = default; 40 | 41 | const DWORD ContinueStatus() const; 42 | 43 | private: 44 | void Initialize(); 45 | void SetContinueStatus(const DWORD dwContinueStatus); 46 | 47 | Debugger * const m_pDebugger; 48 | DWORD m_dwContinueStatus; 49 | }; 50 | 51 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/DebugEventHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "Observable.h" 9 | #include "DebugExceptionHandler.h" 10 | 11 | namespace CodeReversing 12 | { 13 | 14 | class Debugger; 15 | 16 | enum DebugEvents 17 | { 18 | //General events 19 | eException = EXCEPTION_DEBUG_EVENT, 20 | eCreateThread = CREATE_THREAD_DEBUG_EVENT, 21 | eCreateProcess = CREATE_PROCESS_DEBUG_EVENT, 22 | eExitThread = EXIT_THREAD_DEBUG_EVENT, 23 | eExitProcess = EXIT_PROCESS_DEBUG_EVENT, 24 | eLoadDll = LOAD_DLL_DEBUG_EVENT, 25 | eUnloadDll = UNLOAD_DLL_DEBUG_EVENT, 26 | eDebugString = OUTPUT_DEBUG_STRING_EVENT, 27 | eRipEvent = RIP_EVENT, 28 | }; 29 | 30 | class DebugEventHandler final : public Observable 31 | { 32 | public: 33 | DebugEventHandler() = delete; 34 | DebugEventHandler(Debugger *pDebugger); 35 | 36 | DebugEventHandler(const DebugEventHandler ©) = delete; 37 | DebugEventHandler &operator=(const DebugEventHandler ©) = delete; 38 | 39 | ~DebugEventHandler() = default; 40 | 41 | const DWORD ContinueStatus() const; 42 | 43 | private: 44 | void Initialize(); 45 | void SetContinueStatus(const DWORD dwContinueStatus); 46 | 47 | Debugger * const m_pDebugger; 48 | DWORD m_dwContinueStatus; 49 | }; 50 | 51 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/DebugEventHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "Observable.h" 9 | #include "DebugExceptionHandler.h" 10 | 11 | namespace CodeReversing 12 | { 13 | 14 | class Debugger; 15 | 16 | enum DebugEvents 17 | { 18 | //General events 19 | eException = EXCEPTION_DEBUG_EVENT, 20 | eCreateThread = CREATE_THREAD_DEBUG_EVENT, 21 | eCreateProcess = CREATE_PROCESS_DEBUG_EVENT, 22 | eExitThread = EXIT_THREAD_DEBUG_EVENT, 23 | eExitProcess = EXIT_PROCESS_DEBUG_EVENT, 24 | eLoadDll = LOAD_DLL_DEBUG_EVENT, 25 | eUnloadDll = UNLOAD_DLL_DEBUG_EVENT, 26 | eDebugString = OUTPUT_DEBUG_STRING_EVENT, 27 | eRipEvent = RIP_EVENT, 28 | }; 29 | 30 | class DebugEventHandler final : public Observable 31 | { 32 | public: 33 | DebugEventHandler() = delete; 34 | DebugEventHandler(Debugger *pDebugger); 35 | 36 | DebugEventHandler(const DebugEventHandler ©) = delete; 37 | DebugEventHandler &operator=(const DebugEventHandler ©) = delete; 38 | 39 | ~DebugEventHandler() = default; 40 | 41 | const DWORD ContinueStatus() const; 42 | 43 | private: 44 | void Initialize(); 45 | void SetContinueStatus(const DWORD dwContinueStatus); 46 | 47 | Debugger * const m_pDebugger; 48 | DWORD m_dwContinueStatus; 49 | }; 50 | 51 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/DebugEventHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "Observable.h" 9 | #include "DebugExceptionHandler.h" 10 | 11 | namespace CodeReversing 12 | { 13 | 14 | class Debugger; 15 | 16 | enum DebugEvents 17 | { 18 | //General events 19 | eException = EXCEPTION_DEBUG_EVENT, 20 | eCreateThread = CREATE_THREAD_DEBUG_EVENT, 21 | eCreateProcess = CREATE_PROCESS_DEBUG_EVENT, 22 | eExitThread = EXIT_THREAD_DEBUG_EVENT, 23 | eExitProcess = EXIT_PROCESS_DEBUG_EVENT, 24 | eLoadDll = LOAD_DLL_DEBUG_EVENT, 25 | eUnloadDll = UNLOAD_DLL_DEBUG_EVENT, 26 | eDebugString = OUTPUT_DEBUG_STRING_EVENT, 27 | eRipEvent = RIP_EVENT, 28 | }; 29 | 30 | class DebugEventHandler final : public Observable 31 | { 32 | public: 33 | DebugEventHandler() = delete; 34 | DebugEventHandler(Debugger *pDebugger); 35 | 36 | DebugEventHandler(const DebugEventHandler ©) = delete; 37 | DebugEventHandler &operator=(const DebugEventHandler ©) = delete; 38 | 39 | ~DebugEventHandler() = default; 40 | 41 | const DWORD ContinueStatus() const; 42 | 43 | private: 44 | void Initialize(); 45 | void SetContinueStatus(const DWORD dwContinueStatus); 46 | 47 | Debugger * const m_pDebugger; 48 | DWORD m_dwContinueStatus; 49 | }; 50 | 51 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/InterruptBreakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "InterruptBreakpoint.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | InterruptBreakpoint::InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress) 11 | : Breakpoint(hProcess, dwAddress, Breakpoint::eType::eInterrupt), 12 | m_originalByte{ 0 } 13 | { 14 | } 15 | 16 | const bool InterruptBreakpoint::EnableBreakpoint() 17 | { 18 | SIZE_T ulBytes = 0; 19 | bool bSuccess = BOOLIFY(ReadProcessMemory(m_hProcess, (LPCVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 20 | if (bSuccess && ulBytes == sizeof(unsigned char)) 21 | { 22 | bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_breakpointOpcode, sizeof(unsigned char), &ulBytes)); 23 | return bSuccess && (ulBytes == sizeof(unsigned char)); 24 | } 25 | else 26 | { 27 | fprintf(stderr, "Could not read from address %p. Error = %X\n", m_dwAddress, GetLastError()); 28 | } 29 | 30 | return false; 31 | } 32 | 33 | const bool InterruptBreakpoint::DisableBreakpoint() 34 | { 35 | SIZE_T ulBytes = 0; 36 | const bool bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 37 | if (bSuccess && ulBytes == sizeof(unsigned char)) 38 | { 39 | return true; 40 | } 41 | fprintf(stderr, "Could not write back original opcode to address %p. Error = %X\n", m_dwAddress, GetLastError()); 42 | 43 | return false; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/InterruptBreakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "InterruptBreakpoint.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | InterruptBreakpoint::InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress) 11 | : Breakpoint(hProcess, dwAddress, Breakpoint::eType::eInterrupt), 12 | m_originalByte{ 0 } 13 | { 14 | } 15 | 16 | const bool InterruptBreakpoint::EnableBreakpoint() 17 | { 18 | SIZE_T ulBytes = 0; 19 | bool bSuccess = BOOLIFY(ReadProcessMemory(m_hProcess, (LPCVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 20 | if (bSuccess && ulBytes == sizeof(unsigned char)) 21 | { 22 | bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_breakpointOpcode, sizeof(unsigned char), &ulBytes)); 23 | return bSuccess && (ulBytes == sizeof(unsigned char)); 24 | } 25 | else 26 | { 27 | fprintf(stderr, "Could not read from address %p. Error = %X\n", m_dwAddress, GetLastError()); 28 | } 29 | 30 | return false; 31 | } 32 | 33 | const bool InterruptBreakpoint::DisableBreakpoint() 34 | { 35 | SIZE_T ulBytes = 0; 36 | const bool bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 37 | if (bSuccess && ulBytes == sizeof(unsigned char)) 38 | { 39 | return true; 40 | } 41 | fprintf(stderr, "Could not write back original opcode to address %p. Error = %X\n", m_dwAddress, GetLastError()); 42 | 43 | return false; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/InterruptBreakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "InterruptBreakpoint.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | InterruptBreakpoint::InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress) 11 | : Breakpoint(hProcess, dwAddress, Breakpoint::eType::eInterrupt), 12 | m_originalByte{ 0 } 13 | { 14 | } 15 | 16 | const bool InterruptBreakpoint::EnableBreakpoint() 17 | { 18 | SIZE_T ulBytes = 0; 19 | bool bSuccess = BOOLIFY(ReadProcessMemory(m_hProcess, (LPCVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 20 | if (bSuccess && ulBytes == sizeof(unsigned char)) 21 | { 22 | bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_breakpointOpcode, sizeof(unsigned char), &ulBytes)); 23 | return bSuccess && (ulBytes == sizeof(unsigned char)); 24 | } 25 | else 26 | { 27 | fprintf(stderr, "Could not read from address %p. Error = %X\n", m_dwAddress, GetLastError()); 28 | } 29 | 30 | return false; 31 | } 32 | 33 | const bool InterruptBreakpoint::DisableBreakpoint() 34 | { 35 | SIZE_T ulBytes = 0; 36 | const bool bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 37 | if (bSuccess && ulBytes == sizeof(unsigned char)) 38 | { 39 | return true; 40 | } 41 | fprintf(stderr, "Could not write back original opcode to address %p. Error = %X\n", m_dwAddress, GetLastError()); 42 | 43 | return false; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/SafeHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CodeReversing 6 | { 7 | //An extremely incomplete RAII wrapper around the HANDLE object 8 | class SafeHandle 9 | { 10 | public: 11 | SafeHandle() : m_handle{ INVALID_HANDLE_VALUE } 12 | { 13 | } 14 | 15 | SafeHandle(HANDLE handle) : m_handle{ handle } 16 | { 17 | } 18 | 19 | SafeHandle(const SafeHandle ©) = delete; 20 | SafeHandle &operator=(const SafeHandle ©) = delete; 21 | 22 | SafeHandle(SafeHandle &&obj) 23 | { 24 | m_handle = obj.m_handle; 25 | obj.m_handle = INVALID_HANDLE_VALUE; 26 | } 27 | 28 | SafeHandle &operator=(SafeHandle &&obj) 29 | { 30 | m_handle = obj.m_handle; 31 | obj.m_handle = INVALID_HANDLE_VALUE; 32 | return *this; 33 | } 34 | 35 | SafeHandle &operator=(const HANDLE handle) 36 | { 37 | m_handle = handle; 38 | return *this; 39 | } 40 | 41 | ~SafeHandle() 42 | { 43 | if (IsValid()) 44 | { 45 | (void)CloseHandle(m_handle); 46 | } 47 | } 48 | 49 | const bool IsValid() const 50 | { 51 | return (m_handle != INVALID_HANDLE_VALUE) || (m_handle != nullptr); 52 | } 53 | 54 | HANDLE operator()() const 55 | { 56 | return m_handle; 57 | } 58 | 59 | private: 60 | HANDLE m_handle; 61 | }; 62 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/SafeHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CodeReversing 6 | { 7 | //An extremely incomplete RAII wrapper around the HANDLE object 8 | class SafeHandle 9 | { 10 | public: 11 | SafeHandle() : m_handle{ INVALID_HANDLE_VALUE } 12 | { 13 | } 14 | 15 | SafeHandle(HANDLE handle) : m_handle{ handle } 16 | { 17 | } 18 | 19 | SafeHandle(const SafeHandle ©) = delete; 20 | SafeHandle &operator=(const SafeHandle ©) = delete; 21 | 22 | SafeHandle(SafeHandle &&obj) 23 | { 24 | m_handle = obj.m_handle; 25 | obj.m_handle = INVALID_HANDLE_VALUE; 26 | } 27 | 28 | SafeHandle &operator=(SafeHandle &&obj) 29 | { 30 | m_handle = obj.m_handle; 31 | obj.m_handle = INVALID_HANDLE_VALUE; 32 | return *this; 33 | } 34 | 35 | SafeHandle &operator=(const HANDLE handle) 36 | { 37 | m_handle = handle; 38 | return *this; 39 | } 40 | 41 | ~SafeHandle() 42 | { 43 | if (IsValid()) 44 | { 45 | (void)CloseHandle(m_handle); 46 | } 47 | } 48 | 49 | const bool IsValid() const 50 | { 51 | return (m_handle != INVALID_HANDLE_VALUE) || (m_handle != nullptr); 52 | } 53 | 54 | HANDLE operator()() const 55 | { 56 | return m_handle; 57 | } 58 | 59 | private: 60 | HANDLE m_handle; 61 | }; 62 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/SafeHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CodeReversing 6 | { 7 | //An extremely incomplete RAII wrapper around the HANDLE object 8 | class SafeHandle 9 | { 10 | public: 11 | SafeHandle() : m_handle{ INVALID_HANDLE_VALUE } 12 | { 13 | } 14 | 15 | SafeHandle(HANDLE handle) : m_handle{ handle } 16 | { 17 | } 18 | 19 | SafeHandle(const SafeHandle ©) = delete; 20 | SafeHandle &operator=(const SafeHandle ©) = delete; 21 | 22 | SafeHandle(SafeHandle &&obj) 23 | { 24 | m_handle = obj.m_handle; 25 | obj.m_handle = INVALID_HANDLE_VALUE; 26 | } 27 | 28 | SafeHandle &operator=(SafeHandle &&obj) 29 | { 30 | m_handle = obj.m_handle; 31 | obj.m_handle = INVALID_HANDLE_VALUE; 32 | return *this; 33 | } 34 | 35 | SafeHandle &operator=(const HANDLE handle) 36 | { 37 | m_handle = handle; 38 | return *this; 39 | } 40 | 41 | ~SafeHandle() 42 | { 43 | if (IsValid()) 44 | { 45 | (void)CloseHandle(m_handle); 46 | } 47 | } 48 | 49 | const bool IsValid() const 50 | { 51 | return (m_handle != INVALID_HANDLE_VALUE) || (m_handle != nullptr); 52 | } 53 | 54 | HANDLE operator()() const 55 | { 56 | return m_handle; 57 | } 58 | 59 | private: 60 | HANDLE m_handle; 61 | }; 62 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/InterruptBreakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "InterruptBreakpoint.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | InterruptBreakpoint::InterruptBreakpoint(const HANDLE hProcess, const DWORD_PTR dwAddress) 11 | : Breakpoint(hProcess, dwAddress, Breakpoint::eType::eInterrupt), 12 | m_originalByte{ 0 } 13 | { 14 | } 15 | 16 | const bool InterruptBreakpoint::EnableBreakpoint() 17 | { 18 | SIZE_T ulBytes = 0; 19 | bool bSuccess = BOOLIFY(ReadProcessMemory(m_hProcess, (LPCVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 20 | if (bSuccess && ulBytes == sizeof(unsigned char)) 21 | { 22 | bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_breakpointOpcode, sizeof(unsigned char), &ulBytes)); 23 | return bSuccess && (ulBytes == sizeof(unsigned char)); 24 | } 25 | else 26 | { 27 | fprintf(stderr, "Could not read from address %p. Error = %X\n", m_dwAddress, GetLastError()); 28 | } 29 | 30 | return false; 31 | } 32 | 33 | const bool InterruptBreakpoint::DisableBreakpoint() 34 | { 35 | SIZE_T ulBytes = 0; 36 | const bool bSuccess = BOOLIFY(WriteProcessMemory(m_hProcess, (LPVOID)m_dwAddress, &m_originalByte, sizeof(unsigned char), &ulBytes)); 37 | if (bSuccess && ulBytes == sizeof(unsigned char)) 38 | { 39 | return true; 40 | } 41 | fprintf(stderr, "Could not write back original opcode to address %p. Error = %X\n", m_dwAddress, GetLastError()); 42 | 43 | return false; 44 | } 45 | 46 | void InterruptBreakpoint::ChangeAddress(const DWORD_PTR dwNewAddress) 47 | { 48 | m_dwAddress = dwNewAddress; 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/Source.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | 3 | #include 4 | #include "Debugger.h" 5 | 6 | DWORD WINAPI DebuggingThread(LPVOID lpParameters) 7 | { 8 | CodeReversing::Debugger *pDebugger = (CodeReversing::Debugger *)lpParameters; 9 | 10 | return pDebugger->Start(); 11 | } 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | DWORD dwPid = 0; 16 | fprintf(stderr, "Enter target process id to attach to: "); 17 | fscanf(stdin, "%i", &dwPid); 18 | 19 | CodeReversing::Debugger dbg(dwPid); 20 | DWORD dwThreadId = 0; 21 | 22 | HANDLE hDebugThread = CreateThread(nullptr, 0, DebuggingThread, &dbg, 0, &dwThreadId); 23 | 24 | printf("[A]dd breakpoint.\n" 25 | "[R]emove breakpoint.\n" 26 | "[S]tep instruction.\n" 27 | "[C]ontinue.\n" 28 | "[Q]uit.\n"); 29 | 30 | char cInput = 0; 31 | DWORD_PTR dwTargetAddress = 0; 32 | 33 | do 34 | { 35 | cInput = getchar(); 36 | switch (cInput) 37 | { 38 | case 'A': 39 | case 'a': 40 | printf("Target address: 0x"); 41 | fscanf(stdin, "%p", &dwTargetAddress); 42 | (void)dbg.AddBreakpoint(dwTargetAddress); 43 | break; 44 | case 'R': 45 | case 'r': 46 | printf("Target address: 0x"); 47 | fscanf(stdin, "%p", &dwTargetAddress); 48 | (void)dbg.RemoveBreakpoint(dwTargetAddress); 49 | break; 50 | case 'S': 51 | case 's': 52 | (void)dbg.StepInto(); 53 | break; 54 | case 'C': 55 | case 'c': 56 | (void)dbg.Continue(); 57 | break; 58 | } 59 | 60 | } while (cInput != 'Q' || cInput != 'q'); 61 | 62 | return 0; 63 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/Debugger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "DebugEventHandler.h" 12 | #include "DebugExceptionHandler.h" 13 | #include "Breakpoint.h" 14 | 15 | namespace CodeReversing 16 | { 17 | 18 | class Debugger final 19 | { 20 | public: 21 | friend class DebugEventHandler; 22 | friend class DebugExceptionHandler; 23 | 24 | Debugger() = delete; 25 | Debugger(const DWORD dwProcessId, const bool bKillOnExit = false); 26 | 27 | Debugger(const Debugger ©) = delete; 28 | Debugger &operator=(const Debugger ©) = delete; 29 | 30 | ~Debugger(); 31 | 32 | const bool Start(); 33 | const bool Stop(); 34 | const bool StepInto(); 35 | const bool Continue(); 36 | 37 | const volatile bool IsActive() const; 38 | 39 | const bool AddBreakpoint(const DWORD_PTR dwAddress); 40 | const bool RemoveBreakpoint(const DWORD_PTR dwAddress); 41 | Breakpoint * FindBreakpoint(const DWORD_PTR dwAddress); 42 | 43 | const HANDLE Handle() const; 44 | 45 | private: 46 | volatile bool m_bIsActive; 47 | bool m_bKillOnExit; 48 | DWORD m_dwProcessId; 49 | HANDLE m_hProcess; 50 | HANDLE m_hContinueEvent; 51 | 52 | Breakpoint *m_pLastBreakpoint; 53 | DWORD m_dwExecutingThreadId; 54 | volatile bool m_bIsStepping; 55 | 56 | const bool DebuggerLoop(); 57 | 58 | const bool Continue(const bool bIsStepping); 59 | const bool WaitForContinue() const; 60 | 61 | const DWORD ChangeMemoryPermissions(const DWORD_PTR dwAddress, const size_t ulSize, DWORD dwNewPermissions); 62 | 63 | std::unique_ptr m_pEventHandler; 64 | std::unique_ptr m_pExceptionHandler; 65 | 66 | std::list> m_lstBreakpoints; 67 | 68 | }; 69 | 70 | } -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/DebugExceptionHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Observable.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | enum DebugExceptions 11 | { 12 | eAccessViolation = EXCEPTION_ACCESS_VIOLATION, 13 | eDataTypeMisalignment = EXCEPTION_DATATYPE_MISALIGNMENT, 14 | eBreakpoint = EXCEPTION_BREAKPOINT, 15 | eSingleStep = EXCEPTION_SINGLE_STEP, 16 | eArrayBoundsExceeded = EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 17 | eFltDenormal = EXCEPTION_FLT_DENORMAL_OPERAND, 18 | eFltDivideByZero = EXCEPTION_FLT_DIVIDE_BY_ZERO, 19 | eFltInexactResult = EXCEPTION_FLT_INEXACT_RESULT, 20 | eFltInvalidOperation = EXCEPTION_FLT_INVALID_OPERATION, 21 | eFltOverflow = EXCEPTION_FLT_OVERFLOW, 22 | eFltStackCheck = EXCEPTION_FLT_STACK_CHECK, 23 | eFltUnderflow = EXCEPTION_FLT_UNDERFLOW, 24 | eIntDivideByZero = EXCEPTION_INT_DIVIDE_BY_ZERO, 25 | eIntOverflow = EXCEPTION_INT_OVERFLOW, 26 | ePrivilegedInstruction = EXCEPTION_PRIV_INSTRUCTION, 27 | ePageError = EXCEPTION_IN_PAGE_ERROR, 28 | eIllegalInstruction = EXCEPTION_ILLEGAL_INSTRUCTION, 29 | eNoncontinuableException = EXCEPTION_NONCONTINUABLE_EXCEPTION, 30 | eStackOverflow = EXCEPTION_STACK_OVERFLOW, 31 | eInvalidDisposition = EXCEPTION_INVALID_DISPOSITION, 32 | eGuardPage = EXCEPTION_GUARD_PAGE, 33 | eInvalidHandle = EXCEPTION_INVALID_HANDLE, 34 | }; 35 | 36 | class DebugExceptionHandler final : public Observable 37 | { 38 | public: 39 | DebugExceptionHandler() = delete; 40 | DebugExceptionHandler(const HANDLE &m_hProcess); 41 | 42 | ~DebugExceptionHandler() = default; 43 | 44 | const DWORD ContinueStatus() const; 45 | 46 | private: 47 | void Initialize(); 48 | void SetContinueStatus(const DWORD dwContinueStatus); 49 | 50 | const HANDLE &m_hProcess; 51 | DWORD m_dwContinueStatus; 52 | }; 53 | 54 | } -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/SampleDebuggerPart1.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;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 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/DebugExceptionHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Observable.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | class Debugger; 11 | 12 | enum DebugExceptions 13 | { 14 | eAccessViolation = EXCEPTION_ACCESS_VIOLATION, 15 | eDataTypeMisalignment = EXCEPTION_DATATYPE_MISALIGNMENT, 16 | eBreakpoint = EXCEPTION_BREAKPOINT, 17 | eSingleStep = EXCEPTION_SINGLE_STEP, 18 | eArrayBoundsExceeded = EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 19 | eFltDenormal = EXCEPTION_FLT_DENORMAL_OPERAND, 20 | eFltDivideByZero = EXCEPTION_FLT_DIVIDE_BY_ZERO, 21 | eFltInexactResult = EXCEPTION_FLT_INEXACT_RESULT, 22 | eFltInvalidOperation = EXCEPTION_FLT_INVALID_OPERATION, 23 | eFltOverflow = EXCEPTION_FLT_OVERFLOW, 24 | eFltStackCheck = EXCEPTION_FLT_STACK_CHECK, 25 | eFltUnderflow = EXCEPTION_FLT_UNDERFLOW, 26 | eIntDivideByZero = EXCEPTION_INT_DIVIDE_BY_ZERO, 27 | eIntOverflow = EXCEPTION_INT_OVERFLOW, 28 | ePrivilegedInstruction = EXCEPTION_PRIV_INSTRUCTION, 29 | ePageError = EXCEPTION_IN_PAGE_ERROR, 30 | eIllegalInstruction = EXCEPTION_ILLEGAL_INSTRUCTION, 31 | eNoncontinuableException = EXCEPTION_NONCONTINUABLE_EXCEPTION, 32 | eStackOverflow = EXCEPTION_STACK_OVERFLOW, 33 | eInvalidDisposition = EXCEPTION_INVALID_DISPOSITION, 34 | eGuardPage = EXCEPTION_GUARD_PAGE, 35 | eInvalidHandle = EXCEPTION_INVALID_HANDLE, 36 | }; 37 | 38 | class DebugExceptionHandler final : public Observable 39 | { 40 | public: 41 | DebugExceptionHandler() = delete; 42 | DebugExceptionHandler(Debugger *pDebugger); 43 | 44 | ~DebugExceptionHandler() = default; 45 | 46 | const DWORD ContinueStatus() const; 47 | 48 | private: 49 | void Initialize(); 50 | void SetContinueStatus(const DWORD dwContinueStatus); 51 | 52 | Debugger * const m_pDebugger; 53 | DWORD m_dwContinueStatus; 54 | }; 55 | 56 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/DebugExceptionHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Observable.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | class Debugger; 11 | 12 | enum DebugExceptions 13 | { 14 | eAccessViolation = EXCEPTION_ACCESS_VIOLATION, 15 | eDataTypeMisalignment = EXCEPTION_DATATYPE_MISALIGNMENT, 16 | eBreakpoint = EXCEPTION_BREAKPOINT, 17 | eSingleStep = EXCEPTION_SINGLE_STEP, 18 | eArrayBoundsExceeded = EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 19 | eFltDenormal = EXCEPTION_FLT_DENORMAL_OPERAND, 20 | eFltDivideByZero = EXCEPTION_FLT_DIVIDE_BY_ZERO, 21 | eFltInexactResult = EXCEPTION_FLT_INEXACT_RESULT, 22 | eFltInvalidOperation = EXCEPTION_FLT_INVALID_OPERATION, 23 | eFltOverflow = EXCEPTION_FLT_OVERFLOW, 24 | eFltStackCheck = EXCEPTION_FLT_STACK_CHECK, 25 | eFltUnderflow = EXCEPTION_FLT_UNDERFLOW, 26 | eIntDivideByZero = EXCEPTION_INT_DIVIDE_BY_ZERO, 27 | eIntOverflow = EXCEPTION_INT_OVERFLOW, 28 | ePrivilegedInstruction = EXCEPTION_PRIV_INSTRUCTION, 29 | ePageError = EXCEPTION_IN_PAGE_ERROR, 30 | eIllegalInstruction = EXCEPTION_ILLEGAL_INSTRUCTION, 31 | eNoncontinuableException = EXCEPTION_NONCONTINUABLE_EXCEPTION, 32 | eStackOverflow = EXCEPTION_STACK_OVERFLOW, 33 | eInvalidDisposition = EXCEPTION_INVALID_DISPOSITION, 34 | eGuardPage = EXCEPTION_GUARD_PAGE, 35 | eInvalidHandle = EXCEPTION_INVALID_HANDLE, 36 | }; 37 | 38 | class DebugExceptionHandler final : public Observable 39 | { 40 | public: 41 | DebugExceptionHandler() = delete; 42 | DebugExceptionHandler(Debugger *pDebugger); 43 | 44 | ~DebugExceptionHandler() = default; 45 | 46 | const DWORD ContinueStatus() const; 47 | 48 | private: 49 | void Initialize(); 50 | void SetContinueStatus(const DWORD dwContinueStatus); 51 | 52 | Debugger * const m_pDebugger; 53 | DWORD m_dwContinueStatus; 54 | }; 55 | 56 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/DebugExceptionHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Observable.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | class Debugger; 11 | 12 | enum DebugExceptions 13 | { 14 | eAccessViolation = EXCEPTION_ACCESS_VIOLATION, 15 | eDataTypeMisalignment = EXCEPTION_DATATYPE_MISALIGNMENT, 16 | eBreakpoint = EXCEPTION_BREAKPOINT, 17 | eSingleStep = EXCEPTION_SINGLE_STEP, 18 | eArrayBoundsExceeded = EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 19 | eFltDenormal = EXCEPTION_FLT_DENORMAL_OPERAND, 20 | eFltDivideByZero = EXCEPTION_FLT_DIVIDE_BY_ZERO, 21 | eFltInexactResult = EXCEPTION_FLT_INEXACT_RESULT, 22 | eFltInvalidOperation = EXCEPTION_FLT_INVALID_OPERATION, 23 | eFltOverflow = EXCEPTION_FLT_OVERFLOW, 24 | eFltStackCheck = EXCEPTION_FLT_STACK_CHECK, 25 | eFltUnderflow = EXCEPTION_FLT_UNDERFLOW, 26 | eIntDivideByZero = EXCEPTION_INT_DIVIDE_BY_ZERO, 27 | eIntOverflow = EXCEPTION_INT_OVERFLOW, 28 | ePrivilegedInstruction = EXCEPTION_PRIV_INSTRUCTION, 29 | ePageError = EXCEPTION_IN_PAGE_ERROR, 30 | eIllegalInstruction = EXCEPTION_ILLEGAL_INSTRUCTION, 31 | eNoncontinuableException = EXCEPTION_NONCONTINUABLE_EXCEPTION, 32 | eStackOverflow = EXCEPTION_STACK_OVERFLOW, 33 | eInvalidDisposition = EXCEPTION_INVALID_DISPOSITION, 34 | eGuardPage = EXCEPTION_GUARD_PAGE, 35 | eInvalidHandle = EXCEPTION_INVALID_HANDLE, 36 | }; 37 | 38 | class DebugExceptionHandler final : public Observable 39 | { 40 | public: 41 | DebugExceptionHandler() = delete; 42 | DebugExceptionHandler(Debugger *pDebugger); 43 | 44 | ~DebugExceptionHandler() = default; 45 | 46 | const DWORD ContinueStatus() const; 47 | 48 | private: 49 | void Initialize(); 50 | void SetContinueStatus(const DWORD dwContinueStatus); 51 | 52 | Debugger * const m_pDebugger; 53 | DWORD m_dwContinueStatus; 54 | }; 55 | 56 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/DebugExceptionHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Observable.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | class Debugger; 11 | 12 | enum DebugExceptions 13 | { 14 | eAccessViolation = EXCEPTION_ACCESS_VIOLATION, 15 | eDataTypeMisalignment = EXCEPTION_DATATYPE_MISALIGNMENT, 16 | eBreakpoint = EXCEPTION_BREAKPOINT, 17 | eSingleStep = EXCEPTION_SINGLE_STEP, 18 | eArrayBoundsExceeded = EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 19 | eFltDenormal = EXCEPTION_FLT_DENORMAL_OPERAND, 20 | eFltDivideByZero = EXCEPTION_FLT_DIVIDE_BY_ZERO, 21 | eFltInexactResult = EXCEPTION_FLT_INEXACT_RESULT, 22 | eFltInvalidOperation = EXCEPTION_FLT_INVALID_OPERATION, 23 | eFltOverflow = EXCEPTION_FLT_OVERFLOW, 24 | eFltStackCheck = EXCEPTION_FLT_STACK_CHECK, 25 | eFltUnderflow = EXCEPTION_FLT_UNDERFLOW, 26 | eIntDivideByZero = EXCEPTION_INT_DIVIDE_BY_ZERO, 27 | eIntOverflow = EXCEPTION_INT_OVERFLOW, 28 | ePrivilegedInstruction = EXCEPTION_PRIV_INSTRUCTION, 29 | ePageError = EXCEPTION_IN_PAGE_ERROR, 30 | eIllegalInstruction = EXCEPTION_ILLEGAL_INSTRUCTION, 31 | eNoncontinuableException = EXCEPTION_NONCONTINUABLE_EXCEPTION, 32 | eStackOverflow = EXCEPTION_STACK_OVERFLOW, 33 | eInvalidDisposition = EXCEPTION_INVALID_DISPOSITION, 34 | eGuardPage = EXCEPTION_GUARD_PAGE, 35 | eInvalidHandle = EXCEPTION_INVALID_HANDLE, 36 | }; 37 | 38 | class DebugExceptionHandler final : public Observable 39 | { 40 | public: 41 | DebugExceptionHandler() = delete; 42 | DebugExceptionHandler(Debugger *pDebugger); 43 | 44 | ~DebugExceptionHandler() = default; 45 | 46 | const DWORD ContinueStatus() const; 47 | 48 | private: 49 | void Initialize(); 50 | void SetContinueStatus(const DWORD dwContinueStatus); 51 | 52 | Debugger * const m_pDebugger; 53 | DWORD m_dwContinueStatus; 54 | }; 55 | 56 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/Debugger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "DebugEventHandler.h" 12 | #include "DebugExceptionHandler.h" 13 | #include "Breakpoint.h" 14 | #include "SafeHandle.h" 15 | 16 | namespace CodeReversing 17 | { 18 | 19 | class Debugger final 20 | { 21 | public: 22 | friend class DebugEventHandler; 23 | friend class DebugExceptionHandler; 24 | 25 | Debugger() = delete; 26 | Debugger(const DWORD dwProcessId, const bool bKillOnExit = false); 27 | 28 | Debugger(const Debugger ©) = delete; 29 | Debugger &operator=(const Debugger ©) = delete; 30 | 31 | ~Debugger(); 32 | 33 | const bool Start(); 34 | const bool Stop(); 35 | const bool StepInto(); 36 | const bool Continue(); 37 | 38 | void PrintCallStack(); 39 | 40 | void PrintContext(); 41 | const bool SetExecutingContext(const CONTEXT &ctx); 42 | const CONTEXT GetExecutingContext(); 43 | 44 | const volatile bool IsActive() const; 45 | 46 | const bool AddBreakpoint(const DWORD_PTR dwAddress); 47 | const bool RemoveBreakpoint(const DWORD_PTR dwAddress); 48 | Breakpoint * FindBreakpoint(const DWORD_PTR dwAddress); 49 | 50 | const HANDLE Handle() const; 51 | 52 | private: 53 | volatile bool m_bIsActive; 54 | bool m_bKillOnExit; 55 | DWORD m_dwProcessId; 56 | SafeHandle m_hProcess; 57 | SafeHandle m_hContinueEvent; 58 | 59 | Breakpoint *m_pLastBreakpoint; 60 | DWORD m_dwExecutingThreadId; 61 | CONTEXT m_lastContext; 62 | volatile bool m_bIsStepping; 63 | 64 | const bool DebuggerLoop(); 65 | 66 | const bool Continue(const bool bIsStepping); 67 | const bool WaitForContinue() const; 68 | 69 | const DWORD ChangeMemoryPermissions(const DWORD_PTR dwAddress, const size_t ulSize, DWORD dwNewPermissions); 70 | SafeHandle OpenCurrentThread(); 71 | 72 | std::unique_ptr m_pEventHandler; 73 | std::unique_ptr m_pExceptionHandler; 74 | 75 | std::list> m_lstBreakpoints; 76 | 77 | }; 78 | 79 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/Observable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | struct FunctionInfo 10 | { 11 | Event m_event; 12 | size_t m_vectorIndex; 13 | }; 14 | 15 | template 16 | class Observable 17 | { 18 | 19 | public: 20 | Observable() = default; 21 | virtual ~Observable() = default; 22 | 23 | template 24 | const FunctionInfo Register(const Event &event, Observer &&observer) 25 | { 26 | m_observers[event].push_back(std::forward(observer)); 27 | 28 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 29 | return FunctionInfo; 30 | } 31 | 32 | template 33 | const FunctionInfo Register(const Event &&event, Observer &&observer) 34 | { 35 | m_observers[std::move(event)].push_back(std::forward(observer)); 36 | 37 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 38 | return FunctionInfo; 39 | } 40 | 41 | template 42 | void Notify(const Event &event, Parameters... Params) const 43 | { 44 | if (m_observers.size() > 0 && m_observers.find(event) != m_observers.end()) 45 | { 46 | for (const auto &observer : m_observers.at(event)) 47 | { 48 | observer(Params...); 49 | } 50 | } 51 | } 52 | 53 | const bool Remove(const FunctionInfo &functionInfo) 54 | { 55 | auto callbackVectorIter = m_observers.find(functionInfo.m_event); 56 | if (callbackVectorIter != m_observers.end()) 57 | { 58 | auto callbackVectors = m_observers[functionInfo.m_event]; 59 | auto callbackRemove = callbackVectors.begin() + functionInfo.m_vectorIndex; 60 | callbackVectors.erase(callbackRemove); 61 | m_observers[functionInfo.m_event] = callbackVectors; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | Observable(const Observable &) = delete; 68 | Observable &operator=(const Observable &) = delete; 69 | 70 | private: 71 | std::map>> m_observers; 72 | 73 | }; -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/Observable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | struct FunctionInfo 10 | { 11 | Event m_event; 12 | size_t m_vectorIndex; 13 | }; 14 | 15 | template 16 | class Observable 17 | { 18 | 19 | public: 20 | Observable() = default; 21 | virtual ~Observable() = default; 22 | 23 | template 24 | const FunctionInfo Register(const Event &event, Observer &&observer) 25 | { 26 | m_observers[event].push_back(std::forward(observer)); 27 | 28 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 29 | return FunctionInfo; 30 | } 31 | 32 | template 33 | const FunctionInfo Register(const Event &&event, Observer &&observer) 34 | { 35 | m_observers[std::move(event)].push_back(std::forward(observer)); 36 | 37 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 38 | return FunctionInfo; 39 | } 40 | 41 | template 42 | void Notify(const Event &event, Parameters... Params) const 43 | { 44 | if (m_observers.size() > 0 && m_observers.find(event) != m_observers.end()) 45 | { 46 | for (const auto &observer : m_observers.at(event)) 47 | { 48 | observer(Params...); 49 | } 50 | } 51 | } 52 | 53 | const bool Remove(const FunctionInfo &functionInfo) 54 | { 55 | auto callbackVectorIter = m_observers.find(functionInfo.m_event); 56 | if (callbackVectorIter != m_observers.end()) 57 | { 58 | auto callbackVectors = m_observers[functionInfo.m_event]; 59 | auto callbackRemove = callbackVectors.begin() + functionInfo.m_vectorIndex; 60 | callbackVectors.erase(callbackRemove); 61 | m_observers[functionInfo.m_event] = callbackVectors; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | Observable(const Observable &) = delete; 68 | Observable &operator=(const Observable &) = delete; 69 | 70 | private: 71 | std::map>> m_observers; 72 | 73 | }; -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/Observable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | struct FunctionInfo 10 | { 11 | Event m_event; 12 | size_t m_vectorIndex; 13 | }; 14 | 15 | template 16 | class Observable 17 | { 18 | 19 | public: 20 | Observable() = default; 21 | virtual ~Observable() = default; 22 | 23 | template 24 | const FunctionInfo Register(const Event &event, Observer &&observer) 25 | { 26 | m_observers[event].push_back(std::forward(observer)); 27 | 28 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 29 | return FunctionInfo; 30 | } 31 | 32 | template 33 | const FunctionInfo Register(const Event &&event, Observer &&observer) 34 | { 35 | m_observers[std::move(event)].push_back(std::forward(observer)); 36 | 37 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 38 | return FunctionInfo; 39 | } 40 | 41 | template 42 | void Notify(const Event &event, Parameters... Params) const 43 | { 44 | if (m_observers.size() > 0 && m_observers.find(event) != m_observers.end()) 45 | { 46 | for (const auto &observer : m_observers.at(event)) 47 | { 48 | observer(Params...); 49 | } 50 | } 51 | } 52 | 53 | const bool Remove(const FunctionInfo &functionInfo) 54 | { 55 | auto callbackVectorIter = m_observers.find(functionInfo.m_event); 56 | if (callbackVectorIter != m_observers.end()) 57 | { 58 | auto callbackVectors = m_observers[functionInfo.m_event]; 59 | auto callbackRemove = callbackVectors.begin() + functionInfo.m_vectorIndex; 60 | callbackVectors.erase(callbackRemove); 61 | m_observers[functionInfo.m_event] = callbackVectors; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | Observable(const Observable &) = delete; 68 | Observable &operator=(const Observable &) = delete; 69 | 70 | private: 71 | std::map>> m_observers; 72 | 73 | }; -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Observable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | struct FunctionInfo 10 | { 11 | Event m_event; 12 | size_t m_vectorIndex; 13 | }; 14 | 15 | template 16 | class Observable 17 | { 18 | 19 | public: 20 | Observable() = default; 21 | virtual ~Observable() = default; 22 | 23 | template 24 | const FunctionInfo Register(const Event &event, Observer &&observer) 25 | { 26 | m_observers[event].push_back(std::forward(observer)); 27 | 28 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 29 | return FunctionInfo; 30 | } 31 | 32 | template 33 | const FunctionInfo Register(const Event &&event, Observer &&observer) 34 | { 35 | m_observers[std::move(event)].push_back(std::forward(observer)); 36 | 37 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 38 | return FunctionInfo; 39 | } 40 | 41 | template 42 | void Notify(const Event &event, Parameters... Params) const 43 | { 44 | if (m_observers.size() > 0 && m_observers.find(event) != m_observers.end()) 45 | { 46 | for (const auto &observer : m_observers.at(event)) 47 | { 48 | observer(Params...); 49 | } 50 | } 51 | } 52 | 53 | const bool Remove(const FunctionInfo &functionInfo) 54 | { 55 | auto callbackVectorIter = m_observers.find(functionInfo.m_event); 56 | if (callbackVectorIter != m_observers.end()) 57 | { 58 | auto callbackVectors = m_observers[functionInfo.m_event]; 59 | auto callbackRemove = callbackVectors.begin() + functionInfo.m_vectorIndex; 60 | callbackVectors.erase(callbackRemove); 61 | m_observers[functionInfo.m_event] = callbackVectors; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | Observable(const Observable &) = delete; 68 | Observable &operator=(const Observable &) = delete; 69 | 70 | private: 71 | std::map>> m_observers; 72 | 73 | }; -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/Observable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | struct FunctionInfo 10 | { 11 | Event m_event; 12 | unsigned int m_vectorIndex; 13 | }; 14 | 15 | template 16 | class Observable 17 | { 18 | 19 | public: 20 | Observable() = default; 21 | virtual ~Observable() = default; 22 | 23 | template 24 | const FunctionInfo Register(const Event &event, Observer &&observer) 25 | { 26 | m_observers[event].push_back(std::forward(observer)); 27 | 28 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 29 | return FunctionInfo; 30 | } 31 | 32 | template 33 | const FunctionInfo Register(const Event &&event, Observer &&observer) 34 | { 35 | m_observers[std::move(event)].push_back(std::forward(observer)); 36 | 37 | FunctionInfo FunctionInfo{ event, m_observers[event].size() - 1 }; 38 | return FunctionInfo; 39 | } 40 | 41 | template 42 | void Notify(const Event &event, Parameters... Params) const 43 | { 44 | if (m_observers.size() > 0 && m_observers.find(event) != m_observers.end()) 45 | { 46 | for (const auto &observer : m_observers.at(event)) 47 | { 48 | observer(Params...); 49 | } 50 | } 51 | } 52 | 53 | const bool Remove(const FunctionInfo &functionInfo) 54 | { 55 | auto callbackVectorIter = m_observers.find(functionInfo.m_event); 56 | if (callbackVectorIter != m_observers.end()) 57 | { 58 | auto callbackVectors = m_observers[functionInfo.m_event]; 59 | auto callbackRemove = callbackVectors.begin() + functionInfo.m_vectorIndex; 60 | callbackVectors.erase(callbackRemove); 61 | m_observers[functionInfo.m_event] = callbackVectors; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | Observable(const Observable &) = delete; 68 | Observable &operator=(const Observable &) = delete; 69 | 70 | private: 71 | std::map>> m_observers; 72 | 73 | }; -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/SampleDebuggerPart2.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;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 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Resource Files 40 | 41 | 42 | Resource Files 43 | 44 | 45 | Resource Files 46 | 47 | 48 | Resource Files 49 | 50 | 51 | Resource Files 52 | 53 | 54 | Resource Files 55 | 56 | 57 | Resource Files 58 | 59 | 60 | -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/Debugger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "DebugEventHandler.h" 12 | #include "DebugExceptionHandler.h" 13 | #include "Breakpoint.h" 14 | #include "SafeHandle.h" 15 | #include "Symbols.h" 16 | 17 | namespace CodeReversing 18 | { 19 | 20 | class Debugger final 21 | { 22 | public: 23 | friend class DebugEventHandler; 24 | friend class DebugExceptionHandler; 25 | 26 | Debugger() = delete; 27 | Debugger(const DWORD dwProcessId, const bool bKillOnExit = false); 28 | 29 | Debugger(const Debugger ©) = delete; 30 | Debugger &operator=(const Debugger ©) = delete; 31 | 32 | ~Debugger(); 33 | 34 | const bool Start(); 35 | const bool Stop(); 36 | const bool StepInto(); 37 | const bool Continue(); 38 | 39 | void PrintCallStack(); 40 | 41 | void PrintContext(); 42 | const bool SetExecutingContext(const CONTEXT &ctx); 43 | const CONTEXT GetExecutingContext(); 44 | 45 | const volatile bool IsActive() const; 46 | 47 | const bool AddBreakpoint(const DWORD_PTR dwAddress); 48 | const bool RemoveBreakpoint(const DWORD_PTR dwAddress); 49 | Breakpoint * FindBreakpoint(const DWORD_PTR dwAddress); 50 | 51 | const bool AddBreakpoint(const char * const pSymbolName); 52 | const bool RemoveBreakpoint(const char * const pSymbolName); 53 | 54 | const HANDLE Handle() const; 55 | const Symbols * const ProcessSymbols() const; 56 | 57 | private: 58 | volatile bool m_bIsActive; 59 | bool m_bKillOnExit; 60 | DWORD m_dwProcessId; 61 | SafeHandle m_hProcess; 62 | SafeHandle m_hFile; 63 | SafeHandle m_hContinueEvent; 64 | 65 | Breakpoint *m_pLastBreakpoint; 66 | DWORD m_dwExecutingThreadId; 67 | CONTEXT m_lastContext; 68 | volatile bool m_bIsStepping; 69 | 70 | const bool DebuggerLoop(); 71 | 72 | const bool Continue(const bool bIsStepping); 73 | const bool WaitForContinue() const; 74 | 75 | const DWORD ChangeMemoryPermissions(const DWORD_PTR dwAddress, const size_t ulSize, DWORD dwNewPermissions); 76 | SafeHandle OpenCurrentThread(); 77 | 78 | std::unique_ptr m_pEventHandler; 79 | std::unique_ptr m_pExceptionHandler; 80 | std::unique_ptr m_pSymbols; 81 | 82 | std::list> m_lstBreakpoints; 83 | 84 | }; 85 | 86 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/SampleDebuggerPart3.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;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 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/Debugger.cpp: -------------------------------------------------------------------------------- 1 | #include "Debugger.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | Debugger::Debugger(const DWORD dwProcessId, const bool bKillOnExit /*= false*/) : m_bIsActive{ false }, 11 | m_dwProcessId{ dwProcessId }, m_bKillOnExit{ bKillOnExit }, m_hProcess{ INVALID_HANDLE_VALUE } 12 | { 13 | m_pEventHandler = std::unique_ptr(new DebugEventHandler); 14 | } 15 | 16 | const bool Debugger::Start() 17 | { 18 | m_bIsActive = BOOLIFY(DebugActiveProcess(m_dwProcessId)); 19 | if (m_bIsActive) 20 | { 21 | const bool bIsSuccess = BOOLIFY(DebugSetProcessKillOnExit(m_bKillOnExit)); 22 | if (!bIsSuccess) 23 | { 24 | fprintf(stderr, "Could not set process kill on exit policy. Error = %X\n", GetLastError()); 25 | } 26 | return DebuggerLoop(); 27 | } 28 | else 29 | { 30 | fprintf(stderr, "Could not debug process %X. Error = %X\n", m_dwProcessId, GetLastError()); 31 | } 32 | 33 | return false; 34 | } 35 | 36 | const bool Debugger::Stop() 37 | { 38 | m_bIsActive = BOOLIFY(DebugActiveProcessStop(m_dwProcessId)); 39 | if (!m_bIsActive) 40 | { 41 | fprintf(stderr, "Could not stop debugging process %X. Error = %X\n", m_dwProcessId, GetLastError()); 42 | } 43 | 44 | return m_bIsActive; 45 | } 46 | 47 | const bool Debugger::IsActive() const 48 | { 49 | return m_bIsActive; 50 | } 51 | 52 | const bool Debugger::DebuggerLoop() 53 | { 54 | DEBUG_EVENT dbgEvent = { 0 }; 55 | DWORD dwContinueStatus = 0; 56 | bool bSuccess = false; 57 | 58 | while (m_bIsActive) 59 | { 60 | bSuccess = BOOLIFY(WaitForDebugEvent(&dbgEvent, INFINITE)); 61 | if (!bSuccess) 62 | { 63 | fprintf(stderr, "WaitForDebugEvent returned failure. Error = %X\n", GetLastError()); 64 | return false; 65 | } 66 | 67 | fprintf(stderr, "Debug event raised in process %X -- thread %X.\n", dbgEvent.dwProcessId, dbgEvent.dwThreadId); 68 | 69 | m_pEventHandler->Notify((DebugEvents)dbgEvent.dwDebugEventCode, dbgEvent); 70 | dwContinueStatus = m_pEventHandler->ContinueStatus(); 71 | 72 | bSuccess = BOOLIFY(ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, dwContinueStatus)); 73 | if (!bSuccess) 74 | { 75 | fprintf(stderr, "ContinueDebugEvent returned failure. Error = %X\n", GetLastError()); 76 | return false; 77 | } 78 | } 79 | 80 | return true; 81 | } 82 | 83 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/SampleDebuggerPart4.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;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 | Source Files 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 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 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 | Header Files 67 | 68 | 69 | -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/SampleDebuggerPart5.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;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 | Source Files 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 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 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 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Debugger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "DebugEventHandler.h" 12 | #include "DebugExceptionHandler.h" 13 | #include "Breakpoint.h" 14 | #include "InterruptBreakpoint.h" 15 | #include "SafeHandle.h" 16 | #include "Symbols.h" 17 | #include "Disassembler.h" 18 | 19 | namespace CodeReversing 20 | { 21 | 22 | class Debugger final 23 | { 24 | public: 25 | friend class DebugEventHandler; 26 | friend class DebugExceptionHandler; 27 | 28 | Debugger() = delete; 29 | Debugger(const DWORD dwProcessId, const bool bKillOnExit = false); 30 | 31 | Debugger(const Debugger ©) = delete; 32 | Debugger &operator=(const Debugger ©) = delete; 33 | 34 | ~Debugger(); 35 | 36 | const bool Start(); 37 | const bool Stop(); 38 | const bool StepInto(); 39 | const bool StepOver(); 40 | const bool Continue(); 41 | 42 | void PrintCallStack(); 43 | void PrintDisassembly(const DWORD_PTR dwAddress); 44 | void PrintContext(); 45 | 46 | const bool SetExecutingContext(const CONTEXT &ctx); 47 | const CONTEXT GetExecutingContext(); 48 | 49 | const bool ChangeByteAt(const DWORD_PTR dwAddress, const unsigned char cNewByte); 50 | const bool PrintBytesAt(const DWORD_PTR dwAddress, size_t ulNumBytes = 40); 51 | 52 | const volatile bool IsActive() const; 53 | 54 | const bool AddBreakpoint(const DWORD_PTR dwAddress); 55 | const bool RemoveBreakpoint(const DWORD_PTR dwAddress); 56 | Breakpoint * FindBreakpoint(const DWORD_PTR dwAddress); 57 | 58 | const bool AddBreakpoint(const char * const pSymbolName); 59 | const bool RemoveBreakpoint(const char * const pSymbolName); 60 | 61 | const HANDLE Handle() const; 62 | const Symbols * const ProcessSymbols() const; 63 | 64 | private: 65 | volatile bool m_bIsActive; 66 | bool m_bKillOnExit; 67 | DWORD m_dwProcessId; 68 | SafeHandle m_hProcess; 69 | SafeHandle m_hFile; 70 | SafeHandle m_hContinueEvent; 71 | 72 | Breakpoint *m_pLastBreakpoint; 73 | DWORD m_dwExecutingThreadId; 74 | CONTEXT m_lastContext; 75 | volatile bool m_bIsStepping; 76 | 77 | const bool DebuggerLoop(); 78 | 79 | const bool Continue(const bool bIsStepping); 80 | const bool WaitForContinue() const; 81 | 82 | const DWORD ChangeMemoryPermissions(const DWORD_PTR dwAddress, const size_t ulSize, DWORD dwNewPermissions); 83 | SafeHandle OpenCurrentThread(); 84 | 85 | std::unique_ptr m_pEventHandler; 86 | std::unique_ptr m_pExceptionHandler; 87 | std::unique_ptr m_pSymbols; 88 | 89 | std::unique_ptr m_pStepPoint; 90 | std::unique_ptr m_pDisassembler; 91 | 92 | std::list> m_lstBreakpoints; 93 | 94 | }; 95 | 96 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Disassembler.cpp: -------------------------------------------------------------------------------- 1 | #include "Disassembler.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "Common.h" 7 | 8 | namespace CodeReversing 9 | { 10 | 11 | HMODULE Disassembler::m_hDll = nullptr; 12 | pDisasm Disassembler::m_pDisasm = nullptr; 13 | 14 | Disassembler::Disassembler(HANDLE hProcess) : m_hProcess{ hProcess } 15 | { 16 | memset(&m_disassembler, 0, sizeof(DISASM)); 17 | #ifdef _M_IX86 18 | m_disassembler.Archi = 0; 19 | if (m_hDll == nullptr) 20 | { 21 | m_hDll = LoadLibrary(L"BeaEngine_x86.dll"); 22 | m_pDisasm = (pDisasm)GetProcAddress(m_hDll, "_Disasm@4"); 23 | } 24 | #elif defined _M_AMD64 25 | m_disassembler.Archi = 64; 26 | if(m_hDll == nullptr) 27 | { 28 | m_hDll = LoadLibrary(L"BeaEngine_x64.dll"); 29 | m_pDisasm = (pDisasm)GetProcAddress(m_hDll, "Disasm"); 30 | } 31 | #else 32 | #error "Unsupported architecture" 33 | #endif 34 | } 35 | 36 | Disassembler::~Disassembler() 37 | { 38 | if (m_hDll != nullptr) 39 | { 40 | FreeLibrary(m_hDll); 41 | } 42 | } 43 | 44 | const bool Disassembler::BytesAtAddress(DWORD_PTR dwAddress, size_t ulInstructionsToDisassemble /*= 15*/) 45 | { 46 | if (IsInitialized()) 47 | { 48 | SetDisassembler(dwAddress); 49 | bool bFailed = false; 50 | while (!bFailed && ulInstructionsToDisassemble-- > 0) 51 | { 52 | int iDisasmLength = m_pDisasm(&m_disassembler); 53 | if (iDisasmLength != UNKNOWN_OPCODE) 54 | { 55 | fprintf(stderr, "0x%p - %s\n", dwAddress, m_disassembler.CompleteInstr); 56 | m_disassembler.EIP += iDisasmLength; 57 | dwAddress += iDisasmLength; 58 | } 59 | else 60 | { 61 | fprintf(stderr, "Error: Reached unknown opcode in disassembly.\n"); 62 | bFailed = true; 63 | } 64 | } 65 | } 66 | else 67 | { 68 | fprintf(stderr, "Could not show disassembly at address. Disassembler Dll was not loaded properly.\n"); 69 | return false; 70 | } 71 | 72 | return true; 73 | } 74 | 75 | DWORD_PTR Disassembler::GetNextInstruction(const DWORD_PTR dwAddress, bool &bIsUnconditionalBranch) 76 | { 77 | DWORD_PTR dwNextAddress = 0; 78 | if (IsInitialized()) 79 | { 80 | SetDisassembler(dwAddress); 81 | int iDisasmLength = m_pDisasm(&m_disassembler); 82 | if (iDisasmLength != UNKNOWN_OPCODE) 83 | { 84 | if (m_disassembler.Instruction.BranchType == RetType || m_disassembler.Instruction.BranchType == JmpType) 85 | { 86 | bIsUnconditionalBranch = true; 87 | } 88 | else 89 | { 90 | dwNextAddress = (dwAddress + iDisasmLength); 91 | } 92 | } 93 | else 94 | { 95 | fprintf(stderr, "Could not get next instruction. Unknown opcode at %p.\n"); 96 | } 97 | } 98 | else 99 | { 100 | fprintf(stderr, "Could not get next instruction. Disassembler Dll was not loaded propertly.\n"); 101 | } 102 | 103 | return dwNextAddress; 104 | } 105 | 106 | void Disassembler::SetDisassembler(const DWORD_PTR dwAddress) 107 | { 108 | bool bIsCached = ((dwAddress - m_dwStartAddress) < m_bytes.size()); 109 | bIsCached &= (dwAddress < m_dwStartAddress); 110 | if (!bIsCached) 111 | { 112 | (void)TransferBytes(dwAddress); 113 | m_disassembler.EIP = (UIntPtr)m_bytes.data(); 114 | m_dwStartAddress = dwAddress; 115 | } 116 | else 117 | { 118 | m_disassembler.EIP = (UIntPtr)&m_bytes.data()[dwAddress - m_dwStartAddress]; 119 | } 120 | } 121 | 122 | const bool Disassembler::TransferBytes(const DWORD_PTR dwAddress) 123 | { 124 | SIZE_T ulBytesRead = 0; 125 | bool bSuccess = BOOLIFY(ReadProcessMemory(m_hProcess, (LPCVOID)dwAddress, m_bytes.data(), m_bytes.size(), &ulBytesRead)); 126 | if (bSuccess && ulBytesRead == m_bytes.size()) 127 | { 128 | return true; 129 | } 130 | else 131 | { 132 | fprintf(stderr, "Could not read from %p. Error = %X\n", dwAddress, GetLastError()); 133 | } 134 | 135 | return false; 136 | } 137 | 138 | const bool Disassembler::IsInitialized() 139 | { 140 | return (m_hDll != nullptr) && (m_pDisasm != nullptr); 141 | } 142 | 143 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/Source.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | 3 | #include 4 | #include "Debugger.h" 5 | 6 | DWORD WINAPI DebuggingThread(LPVOID lpParameters) 7 | { 8 | CodeReversing::Debugger *pDebugger = (CodeReversing::Debugger *)lpParameters; 9 | 10 | return pDebugger->Start(); 11 | } 12 | 13 | CONTEXT PromptModifyContext(CodeReversing::Debugger *dbg) 14 | { 15 | CONTEXT ctx = dbg->GetExecutingContext(); 16 | char strRegister[8] = { 0 }; 17 | 18 | #ifdef _M_IX86 19 | char *pRegisters[] = { 20 | "EAX", "EBX", "ECX", "EDX", 21 | "ESP", "EBP", "ESI", "EDI", 22 | "EIP", "EFlags" 23 | }; 24 | DWORD_PTR *pdwRegisters[] = { 25 | &ctx.Eax, &ctx.Ebx, &ctx.Ecx, &ctx.Edx, 26 | &ctx.Esp, &ctx.Ebp, &ctx.Esi, &ctx.Edi, 27 | &ctx.Eip, &ctx.EFlags 28 | }; 29 | 30 | #elif defined _M_AMD64 31 | char *pRegisters[] = { 32 | "RAX", "RBX", "RCX", "RDX", 33 | "RSP", "RBP", "RSI", "RDI", 34 | "R8", "R9", "R10", "R11", 35 | "R12", "R13", "R14", "R15", 36 | "RIP", "EFlags" 37 | }; 38 | DWORD_PTR *pdwRegisters[] = { 39 | &ctx.Rax, &ctx.Rbx, &ctx.Rcx, &ctx.Rdx, 40 | &ctx.Rsp, &ctx.Rbp, &ctx.Rsi, &ctx.Rdi, 41 | &ctx.R8, &ctx.R9, &ctx.R10, &ctx.R11, 42 | &ctx.R12, &ctx.R13, &ctx.R14, &ctx.R15, 43 | &ctx.Rip 44 | }; 45 | 46 | #else 47 | #error "Unsupported platform" 48 | #endif 49 | 50 | fprintf(stderr, "Enter register to change: "); 51 | fscanf(stdin, "%7s", strRegister); 52 | 53 | for (size_t i = 0; i < sizeof(pRegisters) / sizeof(pRegisters[0]); ++i) 54 | { 55 | if (_stricmp(pRegisters[i], strRegister) == 0) 56 | { 57 | DWORD_PTR dwNewValue = 0; 58 | fprintf(stderr, "Enter new value for register %s: 0x", pRegisters[i]); 59 | fscanf(stdin, "%p", &dwNewValue); 60 | #ifdef _M_AMD64 61 | //Annoying workaround since EFlags is 32-bit on x64 62 | if (_stricmp("EFlags", strRegister) == 0) 63 | { 64 | DWORD *pdwEFlags = &ctx.EFlags; 65 | *pdwEFlags = (DWORD)dwNewValue; 66 | } 67 | else 68 | { 69 | *pdwRegisters[i] = dwNewValue; 70 | } 71 | #else 72 | *pdwRegisters[i] = dwNewValue; 73 | #endif 74 | break; 75 | } 76 | 77 | } 78 | 79 | return ctx; 80 | } 81 | 82 | int main(int argc, char *argv[]) 83 | { 84 | DWORD dwPid = 0; 85 | fprintf(stderr, "Enter target process id to attach to: "); 86 | fscanf(stdin, "%i", &dwPid); 87 | 88 | CodeReversing::Debugger dbg(dwPid); 89 | DWORD dwThreadId = 0; 90 | 91 | HANDLE hDebugThread = CreateThread(nullptr, 0, DebuggingThread, &dbg, 0, &dwThreadId); 92 | 93 | printf("[A]dd breakpoint.\n" 94 | "[R]emove breakpoint.\n" 95 | "[S]tep instruction.\n" 96 | "[C]ontinue.\n" 97 | "[P]rint context\n" 98 | "[M]odify context" 99 | "Ca[l]l Stack\n" 100 | "[Q]uit.\n"); 101 | 102 | char cInput = 0; 103 | DWORD_PTR dwTargetAddress = 0; 104 | 105 | do 106 | { 107 | cInput = getchar(); 108 | switch (cInput) 109 | { 110 | case 'A': 111 | case 'a': 112 | printf("Target address: 0x"); 113 | fscanf(stdin, "%p", &dwTargetAddress); 114 | (void)dbg.AddBreakpoint(dwTargetAddress); 115 | break; 116 | case 'R': 117 | case 'r': 118 | printf("Target address: 0x"); 119 | fscanf(stdin, "%p", &dwTargetAddress); 120 | (void)dbg.RemoveBreakpoint(dwTargetAddress); 121 | break; 122 | case 'S': 123 | case 's': 124 | (void)dbg.StepInto(); 125 | break; 126 | case 'C': 127 | case 'c': 128 | (void)dbg.Continue(); 129 | break; 130 | case 'P': 131 | case 'p': 132 | dbg.PrintContext(); 133 | break; 134 | case 'M': 135 | case 'm': 136 | { 137 | CONTEXT ctx = PromptModifyContext(&dbg); 138 | (void)dbg.SetExecutingContext(ctx); 139 | } 140 | break; 141 | case 'L': 142 | case 'l': 143 | dbg.PrintCallStack(); 144 | break; 145 | } 146 | 147 | } while (cInput != 'Q' || cInput != 'q'); 148 | 149 | return 0; 150 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/Symbols.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace CodeReversing 12 | { 13 | 14 | struct SymbolInfo 15 | { 16 | SymbolInfo() : dwAddress{ 0 }, dwLineNumber{ 0 }, dwDisplacement{ 0 } 17 | { 18 | strName.clear(); 19 | strSourceFile.clear(); 20 | } 21 | 22 | SymbolInfo(const SymbolInfo ©) = delete; 23 | SymbolInfo &operator=(const SymbolInfo ©) = delete; 24 | 25 | SymbolInfo(SymbolInfo &&obj) 26 | { 27 | *this = std::move(obj); 28 | } 29 | 30 | SymbolInfo &operator=(SymbolInfo &&obj) 31 | { 32 | strName = std::move(obj.strName); 33 | dwAddress = obj.dwAddress; 34 | dwLineNumber = obj.dwLineNumber; 35 | dwDisplacement = obj.dwDisplacement; 36 | strSourceFile = std::move(obj.strSourceFile); 37 | return *this; 38 | } 39 | 40 | ~SymbolInfo() = default; 41 | 42 | std::vector strName; 43 | DWORD_PTR dwAddress; 44 | DWORD dwLineNumber; 45 | DWORD dwDisplacement; 46 | std::vector strSourceFile; 47 | }; 48 | 49 | struct ModuleSymbolInfo 50 | { 51 | ModuleSymbolInfo() : dwModuleBaseAddress{ 0 } 52 | { 53 | strName.clear(); 54 | } 55 | 56 | ModuleSymbolInfo(const ModuleSymbolInfo ©) = delete; 57 | ModuleSymbolInfo &operator=(const ModuleSymbolInfo ©) = delete; 58 | 59 | ModuleSymbolInfo(ModuleSymbolInfo &&obj) 60 | { 61 | *this = std::move(obj); 62 | } 63 | 64 | ModuleSymbolInfo &operator=(ModuleSymbolInfo &&obj) 65 | { 66 | dwModuleBaseAddress = obj.dwModuleBaseAddress; 67 | strName = std::move(obj.strName); 68 | symbolInfo = std::move(obj.symbolInfo); 69 | return *this; 70 | } 71 | 72 | ~ModuleSymbolInfo() = default; 73 | 74 | DWORD_PTR dwModuleBaseAddress; 75 | std::vector strName; 76 | SymbolInfo symbolInfo; 77 | }; 78 | 79 | class Symbols final 80 | { 81 | public: 82 | Symbols() = delete; 83 | Symbols(const HANDLE hProcess, const HANDLE hFile, const bool bLoadAll = false); 84 | 85 | Symbols(const Symbols ©) = delete; 86 | Symbols &operator=(const Symbols ©) = delete; 87 | 88 | ~Symbols(); 89 | 90 | const bool EnumerateAllModulesWithSymbols(); 91 | const bool EnumerateModuleSymbols(const char * const pModulePath, const DWORD64 dwBaseAddress); 92 | 93 | const bool SymbolFromAddress(const DWORD64 dwAddress, const SymbolInfo **pFullSymbolInfo); 94 | const bool SymbolFromName(const char * const pName, const SymbolInfo **pFullSymbolInfo); 95 | 96 | const bool SymbolLineFromAddress(const DWORD64 dwAddress); 97 | const bool SymbolAddressFromLine(const char * const pName, const char * const pFileName, 98 | const DWORD dwLineNumber); 99 | 100 | const bool ListSourceFiles(); 101 | const bool DumpSourceFileInfo(const DWORD64 dwBaseAddress, const char * const pFilePath); 102 | 103 | const std::multimap &SymbolList() const; 104 | const SymbolInfo * const FindSymbolByName(const char * const pName) const; 105 | const SymbolInfo * const FindSymbolByAddress(const DWORD_PTR dwAddress) const; 106 | 107 | void PrintSymbolsForModule(const char * const pModuleName) const; 108 | void PrintSymbol(const SymbolInfo * const pSymbol) const; 109 | 110 | private: 111 | 112 | struct UserContext 113 | { 114 | Symbols *pThis; 115 | const char *pName; 116 | }; 117 | 118 | static BOOL CALLBACK SymEnumCallback(PCSTR strModuleName, DWORD64 dwBaseOfDll, PVOID pUserContext); 119 | static BOOL CALLBACK SymEnumCallback(PSYMBOL_INFO pSymInfo, ULONG ulSymbolSize, PVOID pUserContext); 120 | 121 | static BOOL CALLBACK SymEnumSourceFilesCallback(PSOURCEFILE pSourceFile, PVOID pUserContext); 122 | static BOOL CALLBACK SymEnumLinesCallback(PSRCCODEINFO pLineInfo, PVOID pUserContext); 123 | 124 | const IMAGEHLP_LINE64 GetSymbolLineInfo(const DWORD64 dwAddress, DWORD &dwDisplacement, bool &bSuccess); 125 | const IMAGEHLP_LINE64 GetSymbolLineInfo(const char * const pName, const char * const pFileName, 126 | const DWORD dwLineNumber, LONG &lDisplacement, bool &bSuccess); 127 | 128 | const bool SymbolModuleExists(const DWORD_PTR dwAddress) const; 129 | 130 | HANDLE m_hProcess; 131 | HANDLE m_hFile; 132 | 133 | std::multimap m_mapSymbols; 134 | }; 135 | 136 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Symbols.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace CodeReversing 12 | { 13 | 14 | struct SymbolInfo 15 | { 16 | SymbolInfo() : dwAddress{ 0 }, dwLineNumber{ 0 }, dwDisplacement{ 0 } 17 | { 18 | strName.clear(); 19 | strSourceFile.clear(); 20 | } 21 | 22 | SymbolInfo(const SymbolInfo ©) = delete; 23 | SymbolInfo &operator=(const SymbolInfo ©) = delete; 24 | 25 | SymbolInfo(SymbolInfo &&obj) 26 | { 27 | *this = std::move(obj); 28 | } 29 | 30 | SymbolInfo &operator=(SymbolInfo &&obj) 31 | { 32 | strName = std::move(obj.strName); 33 | dwAddress = obj.dwAddress; 34 | dwLineNumber = obj.dwLineNumber; 35 | dwDisplacement = obj.dwDisplacement; 36 | strSourceFile = std::move(obj.strSourceFile); 37 | return *this; 38 | } 39 | 40 | ~SymbolInfo() = default; 41 | 42 | std::vector strName; 43 | DWORD_PTR dwAddress; 44 | DWORD dwLineNumber; 45 | DWORD dwDisplacement; 46 | std::vector strSourceFile; 47 | }; 48 | 49 | struct ModuleSymbolInfo 50 | { 51 | ModuleSymbolInfo() : dwModuleBaseAddress{ 0 } 52 | { 53 | strName.clear(); 54 | } 55 | 56 | ModuleSymbolInfo(const ModuleSymbolInfo ©) = delete; 57 | ModuleSymbolInfo &operator=(const ModuleSymbolInfo ©) = delete; 58 | 59 | ModuleSymbolInfo(ModuleSymbolInfo &&obj) 60 | { 61 | *this = std::move(obj); 62 | } 63 | 64 | ModuleSymbolInfo &operator=(ModuleSymbolInfo &&obj) 65 | { 66 | dwModuleBaseAddress = obj.dwModuleBaseAddress; 67 | strName = std::move(obj.strName); 68 | symbolInfo = std::move(obj.symbolInfo); 69 | return *this; 70 | } 71 | 72 | ~ModuleSymbolInfo() = default; 73 | 74 | DWORD_PTR dwModuleBaseAddress; 75 | std::vector strName; 76 | SymbolInfo symbolInfo; 77 | }; 78 | 79 | class Symbols final 80 | { 81 | public: 82 | Symbols() = delete; 83 | Symbols(const HANDLE hProcess, const HANDLE hFile, const bool bLoadAll = false); 84 | 85 | Symbols(const Symbols ©) = delete; 86 | Symbols &operator=(const Symbols ©) = delete; 87 | 88 | ~Symbols(); 89 | 90 | const bool EnumerateAllModulesWithSymbols(); 91 | const bool EnumerateModuleSymbols(const char * const pModulePath, const DWORD64 dwBaseAddress); 92 | 93 | const bool SymbolFromAddress(const DWORD64 dwAddress, const SymbolInfo **pFullSymbolInfo); 94 | const bool SymbolFromName(const char * const pName, const SymbolInfo **pFullSymbolInfo); 95 | 96 | const bool SymbolLineFromAddress(const DWORD64 dwAddress); 97 | const bool SymbolAddressFromLine(const char * const pName, const char * const pFileName, 98 | const DWORD dwLineNumber); 99 | 100 | const bool ListSourceFiles(); 101 | const bool DumpSourceFileInfo(const DWORD64 dwBaseAddress, const char * const pFilePath); 102 | 103 | const std::multimap &SymbolList() const; 104 | const SymbolInfo * const FindSymbolByName(const char * const pName) const; 105 | const SymbolInfo * const FindSymbolByAddress(const DWORD_PTR dwAddress) const; 106 | 107 | void PrintSymbolsForModule(const char * const pModuleName) const; 108 | void PrintSymbol(const SymbolInfo * const pSymbol) const; 109 | 110 | private: 111 | 112 | struct UserContext 113 | { 114 | Symbols *pThis; 115 | const char *pName; 116 | }; 117 | 118 | static BOOL CALLBACK SymEnumCallback(PCSTR strModuleName, DWORD64 dwBaseOfDll, PVOID pUserContext); 119 | static BOOL CALLBACK SymEnumCallback(PSYMBOL_INFO pSymInfo, ULONG ulSymbolSize, PVOID pUserContext); 120 | 121 | static BOOL CALLBACK SymEnumSourceFilesCallback(PSOURCEFILE pSourceFile, PVOID pUserContext); 122 | static BOOL CALLBACK SymEnumLinesCallback(PSRCCODEINFO pLineInfo, PVOID pUserContext); 123 | 124 | const IMAGEHLP_LINE64 GetSymbolLineInfo(const DWORD64 dwAddress, DWORD &dwDisplacement, bool &bSuccess); 125 | const IMAGEHLP_LINE64 GetSymbolLineInfo(const char * const pName, const char * const pFileName, 126 | const DWORD dwLineNumber, LONG &lDisplacement, bool &bSuccess); 127 | 128 | const bool SymbolModuleExists(const DWORD_PTR dwAddress) const; 129 | 130 | HANDLE m_hProcess; 131 | HANDLE m_hFile; 132 | 133 | std::multimap m_mapSymbols; 134 | }; 135 | 136 | } -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/SampleDebuggerPart1.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {88A92DD3-FE5F-4B75-BDF2-E4FE9CF5ADEF} 15 | Win32Proj 16 | SampleDebuggerPart1 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | true 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 71 | true 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/SampleDebuggerPart2.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {8619AF7D-E3EA-4AFF-A043-F360A72B4D78} 15 | Win32Proj 16 | SampleDebuggerPart2 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | true 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 71 | true 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/SampleDebuggerPart3.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {616FC782-491B-4FAB-B5C5-3C2FAFFFD215} 15 | Win32Proj 16 | SampleDebuggerPart3 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | true 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 71 | true 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/SampleDebuggerPart4.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {C94AEC4E-B027-4F2B-A65B-5AC5AA6F2488} 15 | Win32Proj 16 | SampleDebuggerPart4 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | true 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 71 | true 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /SampleDebuggerPart5/beaengine/Includes/export.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file export.h 3 | * @author igor.gutnik@gmail.com 4 | * @date Mon Sep 22 09:28:54 2008 5 | * 6 | * @brief This file sets things up for C dynamic library function definitions and 7 | * static inlined functions 8 | * 9 | * This file is part of BeaEngine. 10 | * 11 | * BeaEngine is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Lesser General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * BeaEngine is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Lesser General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public License 22 | * along with BeaEngine. If not, see . */ 23 | 24 | #ifndef __BEA_EXPORT_H__ 25 | #define __BEA_EXPORT_H__ 26 | 27 | 28 | /* Set up for C function definitions, even when using C++ */ 29 | 30 | #ifdef __cplusplus 31 | #define CPP_VISIBLE_BEGIN extern "C" { 32 | #define CPP_VISIBLE_END } 33 | #else 34 | #define CPP_VISIBLE_BEGIN 35 | #define CPP_VISIBLE_END 36 | #endif 37 | 38 | #if defined(_MSC_VER) 39 | #pragma warning( disable: 4251 ) 40 | #endif 41 | 42 | /* Some compilers use a special export keyword */ 43 | #ifndef bea__api_export__ 44 | # if defined(__BEOS__) 45 | # if defined(__GNUC__) 46 | # define bea__api_export__ __declspec(dllexport) 47 | # else 48 | # define bea__api_export__ __declspec(export) 49 | # endif 50 | # elif defined(_WIN32) || defined(_WIN64) 51 | # ifdef __BORLANDC__ 52 | # define bea__api_export__ __declspec(dllexport) 53 | # define bea__api_import__ __declspec(dllimport) 54 | # elif defined(__WATCOMC__) 55 | # define bea__api_export__ __declspec(dllexport) 56 | # define bea__api_import__ 57 | # else 58 | # define bea__api_export__ __declspec(dllexport) 59 | # define bea__api_import__ __declspec(dllimport) 60 | # endif 61 | # elif defined(__OS2__) 62 | # ifdef __WATCOMC__ 63 | # define bea__api_export__ __declspec(dllexport) 64 | # define bea__api_import__ 65 | # else 66 | # define bea__api_export__ 67 | # define bea__api_import__ 68 | # endif 69 | # else 70 | # if defined(_WIN32) && defined(__GNUC__) && __GNUC__ >= 4 71 | # define bea__api_export__ __attribubea__ ((visibility("default"))) 72 | # define bea__api_import__ __attribubea__ ((visibility("default"))) 73 | # else 74 | # define bea__api_export__ 75 | # define bea__api_import__ 76 | # endif 77 | # endif 78 | #endif 79 | 80 | /* Use C calling convention by default*/ 81 | 82 | #ifndef __bea_callspec__ 83 | #if defined(BEA_USE_STDCALL) 84 | #if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64) 85 | #if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__POCC__) 86 | #define __bea_callspec__ __stdcall 87 | #else 88 | #define __bea_callspec__ 89 | #endif 90 | #else 91 | #ifdef __OS2__ 92 | #define __bea_callspec__ _System 93 | #else 94 | #define __bea_callspec__ 95 | #endif 96 | #endif 97 | #else 98 | #define __bea_callspec__ 99 | #endif 100 | #endif 101 | 102 | #ifdef __SYMBIAN32__ 103 | # ifndef EKA2 104 | # undef bea__api_export__ 105 | # undef bea__api_import__ 106 | # define bea__api_export__ 107 | # define bea__api_import__ 108 | # elif !defined(__WINS__) 109 | # undef bea__api_export__ 110 | # undef bea__api_import__ 111 | # define bea__api_export__ __declspec(dllexport) 112 | # define bea__api_import__ __declspec(dllexport) 113 | # endif /* !EKA2 */ 114 | #endif /* __SYMBIAN32__ */ 115 | 116 | 117 | #if defined(__GNUC__) && (__GNUC__ > 2) 118 | #define BEA_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) 119 | #define BEA_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) 120 | #else 121 | #define BEA_EXPECT_CONDITIONAL(c) (c) 122 | #define BEA_UNEXPECT_CONDITIONAL(c) (c) 123 | #endif 124 | 125 | 126 | /* Set up compiler-specific options for inlining functions */ 127 | #ifndef BEA_HAS_INLINE 128 | #if defined(__GNUC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C) 129 | #define BEA_HAS_INLINE 130 | #else 131 | /* Add any special compiler-specific cases here */ 132 | #if defined(_MSC_VER) || defined(__BORLANDC__) || \ 133 | defined(__DMC__) || defined(__SC__) || \ 134 | defined(__WATCOMC__) || defined(__LCC__) || \ 135 | defined(__DECC) || defined(__EABI__) 136 | #ifndef __inline__ 137 | #define __inline__ __inline 138 | #endif 139 | #define BEA_HAS_INLINE 140 | #else 141 | #if !defined(__MRC__) && !defined(_SGI_SOURCE) 142 | #ifndef __inline__ 143 | #define __inline__ inline 144 | #endif 145 | #define BEA_HAS_INLINE 146 | #endif /* Not a funky compiler */ 147 | #endif /* Visual C++ */ 148 | #endif /* GNU C */ 149 | #endif /* CACHE_HAS_INLINE */ 150 | 151 | /* If inlining isn't supported, remove "__inline__", turning static 152 | inlined functions into static functions (resulting in code bloat 153 | in all files which include the offending header files) 154 | */ 155 | #ifndef BEA_HAS_INLINE 156 | #define __inline__ 157 | #endif 158 | 159 | /* fix a bug with gcc under windows */ 160 | 161 | #if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64) 162 | #if defined(__MINGW32__) 163 | #define const__ 164 | #else 165 | #define const__ const 166 | #endif 167 | #else 168 | #define const__ const 169 | #endif 170 | 171 | 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/DebugExceptionHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugExceptionHandler.h" 2 | 3 | namespace CodeReversing 4 | { 5 | 6 | DebugExceptionHandler::DebugExceptionHandler(const HANDLE &hProcess) : m_hProcess{ hProcess } 7 | { 8 | Initialize(); 9 | } 10 | 11 | void DebugExceptionHandler::Initialize() 12 | { 13 | Register(DebugExceptions::eAccessViolation, [&](const DEBUG_EVENT &dbgEvent) 14 | { 15 | fprintf(stderr, "Received access violation\n"); 16 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 17 | }); 18 | 19 | Register(DebugExceptions::eDataTypeMisalignment, [&](const DEBUG_EVENT &dbgEvent) 20 | { 21 | fprintf(stderr, "Received datatype misalignment\n"); 22 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 23 | }); 24 | 25 | Register(DebugExceptions::eBreakpoint, [&](const DEBUG_EVENT &dbgEvent) 26 | { 27 | fprintf(stderr, "Received breakpoint\n"); 28 | SetContinueStatus(DBG_CONTINUE); 29 | }); 30 | 31 | Register(DebugExceptions::eSingleStep, [&](const DEBUG_EVENT &dbgEvent) 32 | { 33 | fprintf(stderr, "Received single step\n"); 34 | SetContinueStatus(DBG_CONTINUE); 35 | }); 36 | 37 | Register(DebugExceptions::eArrayBoundsExceeded, [&](const DEBUG_EVENT &dbgEvent) 38 | { 39 | fprintf(stderr, "Received array bounds exceeded\n"); 40 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 41 | }); 42 | 43 | Register(DebugExceptions::eFltDenormal, [&](const DEBUG_EVENT &dbgEvent) 44 | { 45 | fprintf(stderr, "Received floating point denormal\n"); 46 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 47 | }); 48 | 49 | Register(DebugExceptions::eFltDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 50 | { 51 | fprintf(stderr, "Received floating point divide by zero\n"); 52 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 53 | }); 54 | 55 | Register(DebugExceptions::eFltInexactResult, [&](const DEBUG_EVENT &dbgEvent) 56 | { 57 | fprintf(stderr, "Received floating point inexact result\n"); 58 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 59 | }); 60 | 61 | Register(DebugExceptions::eFltInvalidOperation, [&](const DEBUG_EVENT &dbgEvent) 62 | { 63 | fprintf(stderr, "Received floating point invalid operation\n"); 64 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 65 | }); 66 | 67 | Register(DebugExceptions::eFltOverflow, [&](const DEBUG_EVENT &dbgEvent) 68 | { 69 | fprintf(stderr, "Received floating point overflow\n"); 70 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 71 | }); 72 | 73 | Register(DebugExceptions::eFltStackCheck, [&](const DEBUG_EVENT &dbgEvent) 74 | { 75 | fprintf(stderr, "Received floating point stack check\n"); 76 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 77 | }); 78 | 79 | Register(DebugExceptions::eFltUnderflow, [&](const DEBUG_EVENT &dbgEvent) 80 | { 81 | fprintf(stderr, "Received floating point underflow\n"); 82 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 83 | }); 84 | 85 | Register(DebugExceptions::eIntDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 86 | { 87 | fprintf(stderr, "Received integer divide by zero\n"); 88 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 89 | }); 90 | 91 | Register(DebugExceptions::eIntOverflow, [&](const DEBUG_EVENT &dbgEvent) 92 | { 93 | fprintf(stderr, "Received integer overflow\n"); 94 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 95 | }); 96 | 97 | Register(DebugExceptions::ePrivilegedInstruction, [&](const DEBUG_EVENT &dbgEvent) 98 | { 99 | fprintf(stderr, "Received privileged instruction\n"); 100 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 101 | }); 102 | 103 | Register(DebugExceptions::ePageError, [&](const DEBUG_EVENT &dbgEvent) 104 | { 105 | fprintf(stderr, "Received page error\n"); 106 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 107 | }); 108 | 109 | Register(DebugExceptions::eIllegalInstruction, [&](const DEBUG_EVENT &dbgEvent) 110 | { 111 | fprintf(stderr, "Received illegal instruction\n"); 112 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 113 | }); 114 | 115 | Register(DebugExceptions::eNoncontinuableException, [&](const DEBUG_EVENT &dbgEvent) 116 | { 117 | fprintf(stderr, "Received non-continuable exception\n"); 118 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 119 | }); 120 | 121 | Register(DebugExceptions::eStackOverflow, [&](const DEBUG_EVENT &dbgEvent) 122 | { 123 | fprintf(stderr, "Received stack overflow\n"); 124 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 125 | }); 126 | 127 | Register(DebugExceptions::eInvalidDisposition, [&](const DEBUG_EVENT &dbgEvent) 128 | { 129 | fprintf(stderr, "Received invalid disposition\n"); 130 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 131 | }); 132 | 133 | Register(DebugExceptions::eGuardPage, [&](const DEBUG_EVENT &dbgEvent) 134 | { 135 | fprintf(stderr, "Received guard page\n"); 136 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 137 | }); 138 | 139 | Register(DebugExceptions::eInvalidHandle, [&](const DEBUG_EVENT &dbgEvent) 140 | { 141 | fprintf(stderr, "Received invalid handle\n"); 142 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 143 | }); 144 | } 145 | 146 | const DWORD DebugExceptionHandler::ContinueStatus() const 147 | { 148 | return m_dwContinueStatus; 149 | } 150 | 151 | void DebugExceptionHandler::SetContinueStatus(const DWORD dwContinueStatus) 152 | { 153 | m_dwContinueStatus = dwContinueStatus; 154 | } 155 | 156 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/Source.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | 3 | #include 4 | #include "Debugger.h" 5 | 6 | DWORD WINAPI DebuggingThread(LPVOID lpParameters) 7 | { 8 | CodeReversing::Debugger *pDebugger = (CodeReversing::Debugger *)lpParameters; 9 | 10 | return pDebugger->Start(); 11 | } 12 | 13 | CONTEXT PromptModifyContext(CodeReversing::Debugger *dbg) 14 | { 15 | CONTEXT ctx = dbg->GetExecutingContext(); 16 | char strRegister[8] = { 0 }; 17 | 18 | #ifdef _M_IX86 19 | char *pRegisters[] = { 20 | "EAX", "EBX", "ECX", "EDX", 21 | "ESP", "EBP", "ESI", "EDI", 22 | "EIP", "EFlags" 23 | }; 24 | DWORD_PTR *pdwRegisters[] = { 25 | &ctx.Eax, &ctx.Ebx, &ctx.Ecx, &ctx.Edx, 26 | &ctx.Esp, &ctx.Ebp, &ctx.Esi, &ctx.Edi, 27 | &ctx.Eip, &ctx.EFlags 28 | }; 29 | 30 | #elif defined _M_AMD64 31 | char *pRegisters[] = { 32 | "RAX", "RBX", "RCX", "RDX", 33 | "RSP", "RBP", "RSI", "RDI", 34 | "R8", "R9", "R10", "R11", 35 | "R12", "R13", "R14", "R15", 36 | "RIP", "EFlags" 37 | }; 38 | DWORD_PTR *pdwRegisters[] = { 39 | &ctx.Rax, &ctx.Rbx, &ctx.Rcx, &ctx.Rdx, 40 | &ctx.Rsp, &ctx.Rbp, &ctx.Rsi, &ctx.Rdi, 41 | &ctx.R8, &ctx.R9, &ctx.R10, &ctx.R11, 42 | &ctx.R12, &ctx.R13, &ctx.R14, &ctx.R15, 43 | &ctx.Rip 44 | }; 45 | 46 | #else 47 | #error "Unsupported platform" 48 | #endif 49 | 50 | fprintf(stderr, "Enter register to change: "); 51 | fscanf(stdin, "%7s", strRegister); 52 | 53 | for (size_t i = 0; i < sizeof(pRegisters) / sizeof(pRegisters[0]); ++i) 54 | { 55 | if (_stricmp(pRegisters[i], strRegister) == 0) 56 | { 57 | DWORD_PTR dwNewValue = 0; 58 | fprintf(stderr, "Enter new value for register %s: 0x", pRegisters[i]); 59 | fscanf(stdin, "%p", &dwNewValue); 60 | #ifdef _M_AMD64 61 | //Annoying workaround since EFlags is 32-bit on x64 62 | if (_stricmp("EFlags", strRegister) == 0) 63 | { 64 | DWORD *pdwEFlags = &ctx.EFlags; 65 | *pdwEFlags = (DWORD)dwNewValue; 66 | } 67 | else 68 | { 69 | *pdwRegisters[i] = dwNewValue; 70 | } 71 | #else 72 | *pdwRegisters[i] = dwNewValue; 73 | #endif 74 | break; 75 | } 76 | 77 | } 78 | 79 | return ctx; 80 | } 81 | 82 | const DWORD_PTR PromptBreakpointAddress(CodeReversing::Debugger *dbg) 83 | { 84 | DWORD_PTR dwAddress = 0; 85 | char cChoice = 0; 86 | fprintf(stderr, "[A]ddress or [s]ymbol name? "); 87 | cChoice = getchar(); 88 | fflush(stdin); 89 | if (cChoice == 'A' || cChoice == 'a') 90 | { 91 | fprintf(stderr, "Breakpoint address: 0x"); 92 | fscanf(stdin, "%p", &dwAddress); 93 | } 94 | else if (cChoice == 'S' || cChoice == 's') 95 | { 96 | char strSymbolName[64] = { 0 }; 97 | fprintf(stderr, "Name: "); 98 | fscanf(stdin, "%63s", strSymbolName); 99 | auto symbol = dbg->ProcessSymbols()->FindSymbolByName(strSymbolName); 100 | dwAddress = (symbol == nullptr ? 0 : symbol->dwAddress); 101 | } 102 | 103 | return dwAddress; 104 | } 105 | 106 | int main(int argc, char *argv[]) 107 | { 108 | DWORD dwPid = 0; 109 | fprintf(stderr, "Enter target process id to attach to: "); 110 | fscanf(stdin, "%i", &dwPid); 111 | 112 | CodeReversing::Debugger dbg(dwPid); 113 | DWORD dwThreadId = 0; 114 | 115 | HANDLE hDebugThread = CreateThread(nullptr, 0, DebuggingThread, &dbg, 0, &dwThreadId); 116 | 117 | printf("[A]dd breakpoint.\n" 118 | "[R]emove breakpoint.\n" 119 | "[S]tep instruction.\n" 120 | "[C]ontinue.\n" 121 | "[P]rint context\n" 122 | "[M]odify context" 123 | "Ca[l]l Stack\n" 124 | "List S[y]mbols for Module" 125 | "[Q]uit.\n"); 126 | 127 | char cInput = 0; 128 | DWORD_PTR dwTargetAddress = 0; 129 | 130 | do 131 | { 132 | cInput = getchar(); 133 | fflush(stdin); 134 | 135 | switch (cInput) 136 | { 137 | case 'A': 138 | case 'a': 139 | dwTargetAddress = PromptBreakpointAddress(&dbg); 140 | if (dwTargetAddress != 0) 141 | { 142 | (void)dbg.AddBreakpoint(dwTargetAddress); 143 | } 144 | break; 145 | case 'R': 146 | case 'r': 147 | dwTargetAddress = PromptBreakpointAddress(&dbg); 148 | if (dwTargetAddress != 0) 149 | { 150 | (void)dbg.RemoveBreakpoint(dwTargetAddress); 151 | } 152 | break; 153 | case 'S': 154 | case 's': 155 | (void)dbg.StepInto(); 156 | break; 157 | case 'C': 158 | case 'c': 159 | (void)dbg.Continue(); 160 | break; 161 | case 'P': 162 | case 'p': 163 | dbg.PrintContext(); 164 | break; 165 | case 'M': 166 | case 'm': 167 | { 168 | CONTEXT ctx = PromptModifyContext(&dbg); 169 | (void)dbg.SetExecutingContext(ctx); 170 | } 171 | break; 172 | case 'L': 173 | case 'l': 174 | dbg.PrintCallStack(); 175 | break; 176 | case 'Y': 177 | case 'y': 178 | { 179 | char strModuleName[MAX_PATH] = { 0 }; 180 | fprintf(stderr, "Enter in module name to dump symbols for: "); 181 | fscanf(stdin, "%259s", strModuleName); 182 | dbg.ProcessSymbols()->PrintSymbolsForModule(strModuleName); 183 | } 184 | break; 185 | } 186 | 187 | } while (cInput != 'Q' || cInput != 'q'); 188 | 189 | return 0; 190 | } -------------------------------------------------------------------------------- /SampleDebuggerPart1/SampleDebuggerPart1/DebugEventHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugEventHandler.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | 7 | namespace CodeReversing 8 | { 9 | 10 | DebugEventHandler::DebugEventHandler() 11 | { 12 | m_pExceptionHandler = std::unique_ptr(new DebugExceptionHandler(m_hProcess)); 13 | Initialize(); 14 | } 15 | 16 | void DebugEventHandler::Initialize() 17 | { 18 | Register(DebugEvents::eCreateThread, [&](const DEBUG_EVENT &dbgEvent) 19 | { 20 | auto &info = dbgEvent.u.CreateThread; 21 | fprintf(stderr, "CREATE_THREAD_DEBUG_EVENT received.\n" 22 | "Handle: %X\n" 23 | "TLS base: %X\n" 24 | "Start address: %X\n", 25 | info.hThread, info.lpThreadLocalBase, info.lpStartAddress); 26 | SetContinueStatus(DBG_CONTINUE); 27 | }); 28 | 29 | Register(DebugEvents::eCreateProcess, [&](const DEBUG_EVENT &dbgEvent) 30 | { 31 | auto &info = dbgEvent.u.CreateProcessInfo; 32 | fprintf(stderr, "CREATE_PROCESS_DEBUG_EVENT received.\n" 33 | "Handle (image file): %X\n" 34 | "Handle (process): %X\n" 35 | "Handle (main thread): %X\n" 36 | "Image base address: %X\n" 37 | "Debug info file offset: %X\n" 38 | "Debug info size: %X\n" 39 | "TLS base: %X\n" 40 | "Start address: %X\n", 41 | info.hFile, info.hProcess, info.hThread, info.lpBaseOfImage, 42 | info.dwDebugInfoFileOffset, info.nDebugInfoSize, info.lpThreadLocalBase, 43 | info.lpStartAddress); 44 | 45 | m_hProcess = info.hProcess; 46 | 47 | SetContinueStatus(DBG_CONTINUE); 48 | }); 49 | 50 | Register(DebugEvents::eExitThread, [&](const DEBUG_EVENT &dbgEvent) 51 | { 52 | fprintf(stderr, "EXIT_THREAD_DEBUG_EVENT received.\n" 53 | "Thread %X exited with code %X.\n", 54 | dbgEvent.dwThreadId, dbgEvent.u.ExitThread.dwExitCode); 55 | SetContinueStatus(DBG_CONTINUE); 56 | }); 57 | 58 | Register(DebugEvents::eExitProcess, [&](const DEBUG_EVENT &dbgEvent) 59 | { 60 | fprintf(stderr, "EXIT_PROCESS_DEBUG_EVENT received.\n" 61 | "Process %X exited with code %X.\n", 62 | dbgEvent.dwProcessId, dbgEvent.u.ExitProcess.dwExitCode); 63 | SetContinueStatus(DBG_CONTINUE); 64 | }); 65 | 66 | Register(DebugEvents::eLoadDll, [&](const DEBUG_EVENT &dbgEvent) 67 | { 68 | auto &info = dbgEvent.u.LoadDll; 69 | fprintf(stderr, "LOAD_DLL_DEBUG_EVENT received.\n" 70 | "Handle: %X\n" 71 | "Base address: %X\n" 72 | "Debug info file offset: %X\n" 73 | "Debug info size: %X\n", 74 | info.hFile, info.lpBaseOfDll, info.dwDebugInfoFileOffset, 75 | info.nDebugInfoSize); 76 | char strName[MAX_PATH] = { 0 }; 77 | (void)GetFinalPathNameByHandleA(info.hFile, strName, sizeof(strName), FILE_NAME_NORMALIZED); 78 | fprintf(stderr, "Name: %s\n", strName); 79 | 80 | m_dwContinueStatus = DBG_CONTINUE; 81 | }); 82 | 83 | Register(DebugEvents::eUnloadDll, [&](const DEBUG_EVENT &dbgEvent) 84 | { 85 | fprintf(stderr, "UNLOAD_DLL_DEBUG_EVENT received.\n" 86 | "Dll at %X has unloaded.\n", dbgEvent.u.UnloadDll.lpBaseOfDll); 87 | SetContinueStatus(DBG_CONTINUE); 88 | }); 89 | 90 | Register(DebugEvents::eDebugString, [&](const DEBUG_EVENT &dbgEvent) 91 | { 92 | auto &info = dbgEvent.u.DebugString; 93 | fprintf(stderr, "OUTPUT_DEBUG_STRING_EVENT received.\n"); 94 | std::unique_ptr pBuffer = std::unique_ptr(new char[info.nDebugStringLength]); 95 | DWORD dwBytesRead = 0; 96 | 97 | const bool bSuccess = BOOLIFY(ReadProcessMemory(m_hProcess, info.lpDebugStringData, pBuffer.get(), info.nDebugStringLength, &dwBytesRead)); 98 | if (bSuccess) 99 | { 100 | if (info.fUnicode) 101 | { 102 | fwprintf(stderr, L"Debug string: %s\n", (wchar_t *)pBuffer.get()); 103 | } 104 | else 105 | { 106 | fprintf(stderr, "Debug string: %s\n", pBuffer.get()); 107 | } 108 | } 109 | else 110 | { 111 | fprintf(stderr, "Could not read debug string. Error = %X\n", GetLastError()); 112 | } 113 | 114 | SetContinueStatus(DBG_CONTINUE); 115 | }); 116 | 117 | Register(DebugEvents::eRipEvent, [&](const DEBUG_EVENT &dbgEvent) 118 | { 119 | fprintf(stderr, "Received RIP event.\n"); 120 | SetContinueStatus(DBG_CONTINUE); 121 | }); 122 | 123 | Register(DebugEvents::eException, [&](const DEBUG_EVENT &dbgEvent) 124 | { 125 | auto &exception = dbgEvent.u.Exception; 126 | fprintf(stderr, "Received exception event.\n" 127 | "First chance exception: %X\n" 128 | "Exception code: %X\n" 129 | "Exception flags: %X\n" 130 | "Exception address: %X\n" 131 | "Number parameters (associated with exception): %X\n", 132 | exception.dwFirstChance, exception.ExceptionRecord.ExceptionCode, 133 | exception.ExceptionRecord.ExceptionFlags, exception.ExceptionRecord.ExceptionAddress, 134 | exception.ExceptionRecord.NumberParameters); 135 | 136 | m_pExceptionHandler->Notify((DebugExceptions)dbgEvent.u.Exception.ExceptionRecord.ExceptionCode, dbgEvent); 137 | SetContinueStatus(m_pExceptionHandler->ContinueStatus()); 138 | }); 139 | } 140 | 141 | const DWORD DebugEventHandler::ContinueStatus() const 142 | { 143 | return m_dwContinueStatus; 144 | } 145 | 146 | void DebugEventHandler::SetContinueStatus(const DWORD dwContinueStatus) 147 | { 148 | m_dwContinueStatus = dwContinueStatus; 149 | } 150 | 151 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/DebugEventHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugEventHandler.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | #include "Debugger.h" 7 | 8 | namespace CodeReversing 9 | { 10 | 11 | DebugEventHandler::DebugEventHandler(Debugger *pDebugger) : m_pDebugger{ pDebugger } 12 | { 13 | Initialize(); 14 | } 15 | 16 | void DebugEventHandler::Initialize() 17 | { 18 | Register(DebugEvents::eCreateThread, [&](const DEBUG_EVENT &dbgEvent) 19 | { 20 | auto &info = dbgEvent.u.CreateThread; 21 | fprintf(stderr, "CREATE_THREAD_DEBUG_EVENT received.\n" 22 | "Handle: %p\n" 23 | "TLS base: %p\n" 24 | "Start address: %p\n", 25 | info.hThread, info.lpThreadLocalBase, info.lpStartAddress); 26 | SetContinueStatus(DBG_CONTINUE); 27 | }); 28 | 29 | Register(DebugEvents::eCreateProcess, [&](const DEBUG_EVENT &dbgEvent) 30 | { 31 | auto &info = dbgEvent.u.CreateProcessInfo; 32 | fprintf(stderr, "CREATE_PROCESS_DEBUG_EVENT received.\n" 33 | "Handle (image file): %p\n" 34 | "Handle (process): %p\n" 35 | "Handle (main thread): %p\n" 36 | "Image base address: %p\n" 37 | "Debug info file offset: %X\n" 38 | "Debug info size: %X\n" 39 | "TLS base: %p\n" 40 | "Start address: %p\n", 41 | info.hFile, info.hProcess, info.hThread, info.lpBaseOfImage, 42 | info.dwDebugInfoFileOffset, info.nDebugInfoSize, info.lpThreadLocalBase, 43 | info.lpStartAddress); 44 | 45 | m_pDebugger->m_hProcess = info.hProcess; 46 | 47 | SetContinueStatus(DBG_CONTINUE); 48 | }); 49 | 50 | Register(DebugEvents::eExitThread, [&](const DEBUG_EVENT &dbgEvent) 51 | { 52 | fprintf(stderr, "EXIT_THREAD_DEBUG_EVENT received.\n" 53 | "Thread %X exited with code %X.\n", 54 | dbgEvent.dwThreadId, dbgEvent.u.ExitThread.dwExitCode); 55 | SetContinueStatus(DBG_CONTINUE); 56 | }); 57 | 58 | Register(DebugEvents::eExitProcess, [&](const DEBUG_EVENT &dbgEvent) 59 | { 60 | fprintf(stderr, "EXIT_PROCESS_DEBUG_EVENT received.\n" 61 | "Process %X exited with code %X.\n", 62 | dbgEvent.dwProcessId, dbgEvent.u.ExitProcess.dwExitCode); 63 | SetContinueStatus(DBG_CONTINUE); 64 | }); 65 | 66 | Register(DebugEvents::eLoadDll, [&](const DEBUG_EVENT &dbgEvent) 67 | { 68 | auto &info = dbgEvent.u.LoadDll; 69 | fprintf(stderr, "LOAD_DLL_DEBUG_EVENT received.\n" 70 | "Handle: %p\n" 71 | "Base address: %p\n" 72 | "Debug info file offset: %X\n" 73 | "Debug info size: %X\n", 74 | info.hFile, info.lpBaseOfDll, info.dwDebugInfoFileOffset, 75 | info.nDebugInfoSize); 76 | char strName[MAX_PATH] = { 0 }; 77 | (void)GetFinalPathNameByHandleA(info.hFile, strName, sizeof(strName), FILE_NAME_NORMALIZED); 78 | fprintf(stderr, "Name: %s\n", strName); 79 | 80 | m_dwContinueStatus = DBG_CONTINUE; 81 | }); 82 | 83 | Register(DebugEvents::eUnloadDll, [&](const DEBUG_EVENT &dbgEvent) 84 | { 85 | fprintf(stderr, "UNLOAD_DLL_DEBUG_EVENT received.\n" 86 | "Dll at %p has unloaded.\n", dbgEvent.u.UnloadDll.lpBaseOfDll); 87 | SetContinueStatus(DBG_CONTINUE); 88 | }); 89 | 90 | Register(DebugEvents::eDebugString, [&](const DEBUG_EVENT &dbgEvent) 91 | { 92 | auto &info = dbgEvent.u.DebugString; 93 | fprintf(stderr, "OUTPUT_DEBUG_STRING_EVENT received.\n"); 94 | std::unique_ptr pBuffer = std::unique_ptr(new char[info.nDebugStringLength]); 95 | SIZE_T ulBytesRead = 0; 96 | 97 | const bool bSuccess = BOOLIFY(ReadProcessMemory(m_pDebugger->m_hProcess, info.lpDebugStringData, pBuffer.get(), info.nDebugStringLength, &ulBytesRead)); 98 | if (bSuccess) 99 | { 100 | if (info.fUnicode) 101 | { 102 | fwprintf(stderr, L"Debug string: %s\n", (wchar_t *)pBuffer.get()); 103 | } 104 | else 105 | { 106 | fprintf(stderr, "Debug string: %s\n", pBuffer.get()); 107 | } 108 | } 109 | else 110 | { 111 | fprintf(stderr, "Could not read debug string. Error = %X\n", GetLastError()); 112 | } 113 | 114 | SetContinueStatus(DBG_CONTINUE); 115 | }); 116 | 117 | Register(DebugEvents::eRipEvent, [&](const DEBUG_EVENT &dbgEvent) 118 | { 119 | fprintf(stderr, "Received RIP event.\n"); 120 | SetContinueStatus(DBG_CONTINUE); 121 | }); 122 | 123 | Register(DebugEvents::eException, [&](const DEBUG_EVENT &dbgEvent) 124 | { 125 | /* 126 | auto &exception = dbgEvent.u.Exception; 127 | fprintf(stderr, "Received exception event.\n" 128 | "First chance exception: %X\n" 129 | "Exception code: %X\n" 130 | "Exception flags: %X\n" 131 | "Exception address: %p\n" 132 | "Number parameters (associated with exception): %X\n", 133 | exception.dwFirstChance, exception.ExceptionRecord.ExceptionCode, 134 | exception.ExceptionRecord.ExceptionFlags, exception.ExceptionRecord.ExceptionAddress, 135 | exception.ExceptionRecord.NumberParameters); 136 | */ 137 | m_pDebugger->m_pExceptionHandler->Notify((DebugExceptions)dbgEvent.u.Exception.ExceptionRecord.ExceptionCode, dbgEvent); 138 | SetContinueStatus(m_pDebugger->m_pExceptionHandler->ContinueStatus()); 139 | }); 140 | } 141 | 142 | const DWORD DebugEventHandler::ContinueStatus() const 143 | { 144 | return m_dwContinueStatus; 145 | } 146 | 147 | void DebugEventHandler::SetContinueStatus(const DWORD dwContinueStatus) 148 | { 149 | m_dwContinueStatus = dwContinueStatus; 150 | } 151 | 152 | } -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/DebugEventHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugEventHandler.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | #include "Debugger.h" 7 | 8 | namespace CodeReversing 9 | { 10 | 11 | DebugEventHandler::DebugEventHandler(Debugger *pDebugger) : m_pDebugger{ pDebugger } 12 | { 13 | Initialize(); 14 | } 15 | 16 | void DebugEventHandler::Initialize() 17 | { 18 | Register(DebugEvents::eCreateThread, [&](const DEBUG_EVENT &dbgEvent) 19 | { 20 | auto &info = dbgEvent.u.CreateThread; 21 | fprintf(stderr, "CREATE_THREAD_DEBUG_EVENT received.\n" 22 | "Handle: %p\n" 23 | "TLS base: %p\n" 24 | "Start address: %p\n", 25 | info.hThread, info.lpThreadLocalBase, info.lpStartAddress); 26 | SetContinueStatus(DBG_CONTINUE); 27 | }); 28 | 29 | Register(DebugEvents::eCreateProcess, [&](const DEBUG_EVENT &dbgEvent) 30 | { 31 | auto &info = dbgEvent.u.CreateProcessInfo; 32 | fprintf(stderr, "CREATE_PROCESS_DEBUG_EVENT received.\n" 33 | "Handle (image file): %p\n" 34 | "Handle (process): %p\n" 35 | "Handle (main thread): %p\n" 36 | "Image base address: %p\n" 37 | "Debug info file offset: %X\n" 38 | "Debug info size: %X\n" 39 | "TLS base: %p\n" 40 | "Start address: %p\n", 41 | info.hFile, info.hProcess, info.hThread, info.lpBaseOfImage, 42 | info.dwDebugInfoFileOffset, info.nDebugInfoSize, info.lpThreadLocalBase, 43 | info.lpStartAddress); 44 | 45 | m_pDebugger->m_hProcess = info.hProcess; 46 | 47 | SetContinueStatus(DBG_CONTINUE); 48 | }); 49 | 50 | Register(DebugEvents::eExitThread, [&](const DEBUG_EVENT &dbgEvent) 51 | { 52 | fprintf(stderr, "EXIT_THREAD_DEBUG_EVENT received.\n" 53 | "Thread %X exited with code %X.\n", 54 | dbgEvent.dwThreadId, dbgEvent.u.ExitThread.dwExitCode); 55 | SetContinueStatus(DBG_CONTINUE); 56 | }); 57 | 58 | Register(DebugEvents::eExitProcess, [&](const DEBUG_EVENT &dbgEvent) 59 | { 60 | fprintf(stderr, "EXIT_PROCESS_DEBUG_EVENT received.\n" 61 | "Process %X exited with code %X.\n", 62 | dbgEvent.dwProcessId, dbgEvent.u.ExitProcess.dwExitCode); 63 | SetContinueStatus(DBG_CONTINUE); 64 | }); 65 | 66 | Register(DebugEvents::eLoadDll, [&](const DEBUG_EVENT &dbgEvent) 67 | { 68 | auto &info = dbgEvent.u.LoadDll; 69 | fprintf(stderr, "LOAD_DLL_DEBUG_EVENT received.\n" 70 | "Handle: %p\n" 71 | "Base address: %p\n" 72 | "Debug info file offset: %X\n" 73 | "Debug info size: %X\n", 74 | info.hFile, info.lpBaseOfDll, info.dwDebugInfoFileOffset, 75 | info.nDebugInfoSize); 76 | char strName[MAX_PATH] = { 0 }; 77 | (void)GetFinalPathNameByHandleA(info.hFile, strName, sizeof(strName), FILE_NAME_NORMALIZED); 78 | fprintf(stderr, "Name: %s\n", strName); 79 | 80 | m_dwContinueStatus = DBG_CONTINUE; 81 | }); 82 | 83 | Register(DebugEvents::eUnloadDll, [&](const DEBUG_EVENT &dbgEvent) 84 | { 85 | fprintf(stderr, "UNLOAD_DLL_DEBUG_EVENT received.\n" 86 | "Dll at %p has unloaded.\n", dbgEvent.u.UnloadDll.lpBaseOfDll); 87 | SetContinueStatus(DBG_CONTINUE); 88 | }); 89 | 90 | Register(DebugEvents::eDebugString, [&](const DEBUG_EVENT &dbgEvent) 91 | { 92 | auto &info = dbgEvent.u.DebugString; 93 | fprintf(stderr, "OUTPUT_DEBUG_STRING_EVENT received.\n"); 94 | std::unique_ptr pBuffer = std::unique_ptr(new char[info.nDebugStringLength]); 95 | SIZE_T ulBytesRead = 0; 96 | 97 | const bool bSuccess = BOOLIFY(ReadProcessMemory(m_pDebugger->m_hProcess(), info.lpDebugStringData, pBuffer.get(), info.nDebugStringLength, &ulBytesRead)); 98 | if (bSuccess) 99 | { 100 | if (info.fUnicode) 101 | { 102 | fwprintf(stderr, L"Debug string: %s\n", (wchar_t *)pBuffer.get()); 103 | } 104 | else 105 | { 106 | fprintf(stderr, "Debug string: %s\n", pBuffer.get()); 107 | } 108 | } 109 | else 110 | { 111 | fprintf(stderr, "Could not read debug string. Error = %X\n", GetLastError()); 112 | } 113 | 114 | SetContinueStatus(DBG_CONTINUE); 115 | }); 116 | 117 | Register(DebugEvents::eRipEvent, [&](const DEBUG_EVENT &dbgEvent) 118 | { 119 | fprintf(stderr, "Received RIP event.\n"); 120 | SetContinueStatus(DBG_CONTINUE); 121 | }); 122 | 123 | Register(DebugEvents::eException, [&](const DEBUG_EVENT &dbgEvent) 124 | { 125 | /* 126 | auto &exception = dbgEvent.u.Exception; 127 | fprintf(stderr, "Received exception event.\n" 128 | "First chance exception: %X\n" 129 | "Exception code: %X\n" 130 | "Exception flags: %X\n" 131 | "Exception address: %p\n" 132 | "Number parameters (associated with exception): %X\n", 133 | exception.dwFirstChance, exception.ExceptionRecord.ExceptionCode, 134 | exception.ExceptionRecord.ExceptionFlags, exception.ExceptionRecord.ExceptionAddress, 135 | exception.ExceptionRecord.NumberParameters); 136 | */ 137 | m_pDebugger->m_pExceptionHandler->Notify((DebugExceptions)dbgEvent.u.Exception.ExceptionRecord.ExceptionCode, dbgEvent); 138 | SetContinueStatus(m_pDebugger->m_pExceptionHandler->ContinueStatus()); 139 | }); 140 | } 141 | 142 | const DWORD DebugEventHandler::ContinueStatus() const 143 | { 144 | return m_dwContinueStatus; 145 | } 146 | 147 | void DebugEventHandler::SetContinueStatus(const DWORD dwContinueStatus) 148 | { 149 | m_dwContinueStatus = dwContinueStatus; 150 | } 151 | 152 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/DebugEventHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugEventHandler.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | #include "Debugger.h" 7 | 8 | namespace CodeReversing 9 | { 10 | 11 | DebugEventHandler::DebugEventHandler(Debugger *pDebugger) : m_pDebugger{ pDebugger } 12 | { 13 | Initialize(); 14 | } 15 | 16 | void DebugEventHandler::Initialize() 17 | { 18 | Register(DebugEvents::eCreateThread, [&](const DEBUG_EVENT &dbgEvent) 19 | { 20 | auto &info = dbgEvent.u.CreateThread; 21 | fprintf(stderr, "CREATE_THREAD_DEBUG_EVENT received.\n" 22 | "Handle: %p\n" 23 | "TLS base: %p\n" 24 | "Start address: %p\n", 25 | info.hThread, info.lpThreadLocalBase, info.lpStartAddress); 26 | SetContinueStatus(DBG_CONTINUE); 27 | }); 28 | 29 | Register(DebugEvents::eCreateProcess, [&](const DEBUG_EVENT &dbgEvent) 30 | { 31 | auto &info = dbgEvent.u.CreateProcessInfo; 32 | fprintf(stderr, "CREATE_PROCESS_DEBUG_EVENT received.\n" 33 | "Handle (image file): %p\n" 34 | "Handle (process): %p\n" 35 | "Handle (main thread): %p\n" 36 | "Image base address: %p\n" 37 | "Debug info file offset: %X\n" 38 | "Debug info size: %X\n" 39 | "TLS base: %p\n" 40 | "Start address: %p\n", 41 | info.hFile, info.hProcess, info.hThread, info.lpBaseOfImage, 42 | info.dwDebugInfoFileOffset, info.nDebugInfoSize, info.lpThreadLocalBase, 43 | info.lpStartAddress); 44 | 45 | char strName[MAX_PATH] = { 0 }; 46 | (void)GetFinalPathNameByHandleA(info.hFile, strName, sizeof(strName), FILE_NAME_NORMALIZED); 47 | 48 | m_pDebugger->m_hProcess = info.hProcess; 49 | m_pDebugger->m_hFile = info.hFile; 50 | m_pDebugger->m_pSymbols = std::unique_ptr(new Symbols(m_pDebugger->m_hProcess(), 51 | m_pDebugger->m_hFile())); 52 | m_pDebugger->m_pSymbols->EnumerateModuleSymbols(strName, (DWORD64)info.lpBaseOfImage); 53 | 54 | SetContinueStatus(DBG_CONTINUE); 55 | }); 56 | 57 | Register(DebugEvents::eExitThread, [&](const DEBUG_EVENT &dbgEvent) 58 | { 59 | fprintf(stderr, "EXIT_THREAD_DEBUG_EVENT received.\n" 60 | "Thread %X exited with code %X.\n", 61 | dbgEvent.dwThreadId, dbgEvent.u.ExitThread.dwExitCode); 62 | SetContinueStatus(DBG_CONTINUE); 63 | }); 64 | 65 | Register(DebugEvents::eExitProcess, [&](const DEBUG_EVENT &dbgEvent) 66 | { 67 | fprintf(stderr, "EXIT_PROCESS_DEBUG_EVENT received.\n" 68 | "Process %X exited with code %X.\n", 69 | dbgEvent.dwProcessId, dbgEvent.u.ExitProcess.dwExitCode); 70 | SetContinueStatus(DBG_CONTINUE); 71 | }); 72 | 73 | Register(DebugEvents::eLoadDll, [&](const DEBUG_EVENT &dbgEvent) 74 | { 75 | auto &info = dbgEvent.u.LoadDll; 76 | fprintf(stderr, "LOAD_DLL_DEBUG_EVENT received.\n" 77 | "Handle: %p\n" 78 | "Base address: %p\n" 79 | "Debug info file offset: %X\n" 80 | "Debug info size: %X\n", 81 | info.hFile, info.lpBaseOfDll, info.dwDebugInfoFileOffset, 82 | info.nDebugInfoSize); 83 | char strName[MAX_PATH] = { 0 }; 84 | (void)GetFinalPathNameByHandleA(info.hFile, strName, sizeof(strName), FILE_NAME_NORMALIZED); 85 | fprintf(stderr, "Name: %s\n", strName); 86 | m_pDebugger->m_pSymbols->EnumerateModuleSymbols(strName, (DWORD64)info.lpBaseOfDll); 87 | 88 | m_dwContinueStatus = DBG_CONTINUE; 89 | }); 90 | 91 | Register(DebugEvents::eUnloadDll, [&](const DEBUG_EVENT &dbgEvent) 92 | { 93 | fprintf(stderr, "UNLOAD_DLL_DEBUG_EVENT received.\n" 94 | "Dll at %p has unloaded.\n", dbgEvent.u.UnloadDll.lpBaseOfDll); 95 | SetContinueStatus(DBG_CONTINUE); 96 | }); 97 | 98 | Register(DebugEvents::eDebugString, [&](const DEBUG_EVENT &dbgEvent) 99 | { 100 | auto &info = dbgEvent.u.DebugString; 101 | fprintf(stderr, "OUTPUT_DEBUG_STRING_EVENT received.\n"); 102 | std::unique_ptr pBuffer = std::unique_ptr(new char[info.nDebugStringLength]); 103 | SIZE_T ulBytesRead = 0; 104 | 105 | const bool bSuccess = BOOLIFY(ReadProcessMemory(m_pDebugger->m_hProcess(), info.lpDebugStringData, pBuffer.get(), info.nDebugStringLength, &ulBytesRead)); 106 | if (bSuccess) 107 | { 108 | if (info.fUnicode) 109 | { 110 | fwprintf(stderr, L"Debug string: %s\n", (wchar_t *)pBuffer.get()); 111 | } 112 | else 113 | { 114 | fprintf(stderr, "Debug string: %s\n", pBuffer.get()); 115 | } 116 | } 117 | else 118 | { 119 | fprintf(stderr, "Could not read debug string. Error = %X\n", GetLastError()); 120 | } 121 | 122 | SetContinueStatus(DBG_CONTINUE); 123 | }); 124 | 125 | Register(DebugEvents::eRipEvent, [&](const DEBUG_EVENT &dbgEvent) 126 | { 127 | fprintf(stderr, "Received RIP event.\n"); 128 | SetContinueStatus(DBG_CONTINUE); 129 | }); 130 | 131 | Register(DebugEvents::eException, [&](const DEBUG_EVENT &dbgEvent) 132 | { 133 | /* 134 | auto &exception = dbgEvent.u.Exception; 135 | fprintf(stderr, "Received exception event.\n" 136 | "First chance exception: %X\n" 137 | "Exception code: %X\n" 138 | "Exception flags: %X\n" 139 | "Exception address: %p\n" 140 | "Number parameters (associated with exception): %X\n", 141 | exception.dwFirstChance, exception.ExceptionRecord.ExceptionCode, 142 | exception.ExceptionRecord.ExceptionFlags, exception.ExceptionRecord.ExceptionAddress, 143 | exception.ExceptionRecord.NumberParameters); 144 | */ 145 | m_pDebugger->m_pExceptionHandler->Notify((DebugExceptions)dbgEvent.u.Exception.ExceptionRecord.ExceptionCode, dbgEvent); 146 | SetContinueStatus(m_pDebugger->m_pExceptionHandler->ContinueStatus()); 147 | }); 148 | } 149 | 150 | const DWORD DebugEventHandler::ContinueStatus() const 151 | { 152 | return m_dwContinueStatus; 153 | } 154 | 155 | void DebugEventHandler::SetContinueStatus(const DWORD dwContinueStatus) 156 | { 157 | m_dwContinueStatus = dwContinueStatus; 158 | } 159 | 160 | } -------------------------------------------------------------------------------- /SampleDebuggerPart2/SampleDebuggerPart2/Debugger.cpp: -------------------------------------------------------------------------------- 1 | #include "Debugger.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "Common.h" 7 | #include "InterruptBreakpoint.h" 8 | 9 | namespace CodeReversing 10 | { 11 | 12 | Debugger::Debugger(const DWORD dwProcessId, const bool bKillOnExit /*= false*/) : m_bIsActive{ false }, 13 | m_dwProcessId{ dwProcessId }, m_bKillOnExit{ bKillOnExit }, m_hProcess{ INVALID_HANDLE_VALUE }, 14 | m_pLastBreakpoint{ nullptr }, m_dwExecutingThreadId{ 0 }, m_bIsStepping{ false } 15 | { 16 | m_pEventHandler = std::unique_ptr(new DebugEventHandler(this)); 17 | m_pExceptionHandler = std::unique_ptr(new DebugExceptionHandler(this)); 18 | m_hContinueEvent = CreateEvent(nullptr, false, false, L"Continue event"); 19 | } 20 | 21 | Debugger::~Debugger() 22 | { 23 | (void)CloseHandle(m_hContinueEvent); 24 | (void)CloseHandle(m_hProcess); 25 | } 26 | 27 | const bool Debugger::Start() 28 | { 29 | m_bIsActive = BOOLIFY(DebugActiveProcess(m_dwProcessId)); 30 | if (m_bIsActive) 31 | { 32 | const bool bIsSuccess = BOOLIFY(DebugSetProcessKillOnExit(m_bKillOnExit)); 33 | if (!bIsSuccess) 34 | { 35 | fprintf(stderr, "Could not set process kill on exit policy. Error = %X\n", GetLastError()); 36 | } 37 | return DebuggerLoop(); 38 | } 39 | else 40 | { 41 | fprintf(stderr, "Could not debug process %X. Error = %X\n", m_dwProcessId, GetLastError()); 42 | } 43 | 44 | return false; 45 | } 46 | 47 | const bool Debugger::Stop() 48 | { 49 | m_bIsActive = BOOLIFY(DebugActiveProcessStop(m_dwProcessId)); 50 | if (!m_bIsActive) 51 | { 52 | fprintf(stderr, "Could not stop debugging process %X. Error = %X\n", m_dwProcessId, GetLastError()); 53 | } 54 | 55 | return m_bIsActive; 56 | } 57 | 58 | const volatile bool Debugger::IsActive() const 59 | { 60 | return m_bIsActive; 61 | } 62 | 63 | const bool Debugger::DebuggerLoop() 64 | { 65 | DEBUG_EVENT dbgEvent = { 0 }; 66 | DWORD dwContinueStatus = 0; 67 | bool bSuccess = false; 68 | 69 | while (m_bIsActive) 70 | { 71 | bSuccess = BOOLIFY(WaitForDebugEvent(&dbgEvent, INFINITE)); 72 | if (!bSuccess) 73 | { 74 | fprintf(stderr, "WaitForDebugEvent returned failure. Error = %X\n", GetLastError()); 75 | return false; 76 | } 77 | 78 | //fprintf(stderr, "Debug event raised in process %X -- thread %X.\n", dbgEvent.dwProcessId, dbgEvent.dwThreadId); 79 | 80 | m_pEventHandler->Notify((DebugEvents)dbgEvent.dwDebugEventCode, dbgEvent); 81 | dwContinueStatus = m_pEventHandler->ContinueStatus(); 82 | 83 | bSuccess = BOOLIFY(ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, dwContinueStatus)); 84 | if (!bSuccess) 85 | { 86 | fprintf(stderr, "ContinueDebugEvent returned failure. Error = %X\n", GetLastError()); 87 | return false; 88 | } 89 | } 90 | 91 | return true; 92 | } 93 | 94 | const bool Debugger::AddBreakpoint(const DWORD_PTR dwAddress) 95 | { 96 | bool bSuccess = false; 97 | DWORD dwOldProtect = ChangeMemoryPermissions(dwAddress, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE); 98 | 99 | std::unique_ptr pNewBreakpoint(new InterruptBreakpoint(m_hProcess, dwAddress)); 100 | if (pNewBreakpoint->EnableBreakpoint()) 101 | { 102 | m_lstBreakpoints.emplace_back(std::move(pNewBreakpoint)); 103 | bSuccess = true; 104 | } 105 | 106 | (void)ChangeMemoryPermissions(dwAddress, sizeof(DWORD_PTR), dwOldProtect); 107 | 108 | return bSuccess; 109 | } 110 | 111 | const bool Debugger::RemoveBreakpoint(const DWORD_PTR dwAddress) 112 | { 113 | bool bSuccess = false; 114 | DWORD dwOldProtect = ChangeMemoryPermissions(dwAddress, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE); 115 | 116 | auto breakpoint = std::find_if(m_lstBreakpoints.begin(), m_lstBreakpoints.end(), [=](const std::unique_ptr &breakpoint) 117 | { 118 | return breakpoint->Address() == dwAddress; 119 | }); 120 | if (breakpoint != m_lstBreakpoints.end()) 121 | { 122 | (void)(*breakpoint)->Disable(); 123 | m_lstBreakpoints.remove(*breakpoint); 124 | bSuccess = true; 125 | } 126 | 127 | (void)ChangeMemoryPermissions(dwAddress, sizeof(DWORD_PTR), dwOldProtect); 128 | 129 | return bSuccess; 130 | } 131 | 132 | Breakpoint * Debugger::FindBreakpoint(const DWORD_PTR dwAddress) 133 | { 134 | auto breakpoint = std::find_if(m_lstBreakpoints.begin(), m_lstBreakpoints.end(), [=](const std::unique_ptr &breakpoint) 135 | { 136 | return breakpoint->Address() == dwAddress; 137 | }); 138 | 139 | return breakpoint == m_lstBreakpoints.end() ? nullptr : breakpoint->get(); 140 | } 141 | 142 | const bool Debugger::StepInto() 143 | { 144 | CONTEXT ctx = { 0 }; 145 | ctx.ContextFlags = CONTEXT_ALL; 146 | HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, m_dwExecutingThreadId); 147 | if (hThread != NULL) 148 | { 149 | bool bSuccess = BOOLIFY(GetThreadContext(hThread, &ctx)); 150 | ctx.EFlags |= 0x100; 151 | bSuccess &= BOOLIFY(SetThreadContext(hThread, &ctx)); 152 | CloseHandle(hThread); 153 | (void)Continue(true); 154 | 155 | return bSuccess; 156 | } 157 | 158 | return false; 159 | } 160 | 161 | const bool Debugger::Continue() 162 | { 163 | return Continue(false); 164 | } 165 | 166 | const bool Debugger::Continue(const bool bIsStepping) 167 | { 168 | m_bIsStepping = bIsStepping; 169 | return BOOLIFY(SetEvent(m_hContinueEvent)); 170 | } 171 | 172 | const DWORD Debugger::ChangeMemoryPermissions(const DWORD_PTR dwAddress, const size_t ulSize, DWORD dwNewPermissions) 173 | { 174 | DWORD dwOldProtect = 0; 175 | const bool bSuccess = BOOLIFY(VirtualProtectEx(m_hProcess, (LPVOID)dwAddress, ulSize, dwNewPermissions, &dwOldProtect)); 176 | if (!bSuccess) 177 | { 178 | fprintf(stderr, "Could not change memory permissions at address %X. Error = %X\n", dwAddress, GetLastError()); 179 | } 180 | return dwOldProtect; 181 | } 182 | 183 | const bool Debugger::WaitForContinue() const 184 | { 185 | return (WaitForSingleObject(m_hContinueEvent, INFINITE) == WAIT_OBJECT_0); 186 | } 187 | 188 | const HANDLE Debugger::Handle() const 189 | { 190 | return m_hProcess; 191 | } 192 | 193 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/DebugEventHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugEventHandler.h" 2 | 3 | #include 4 | 5 | #include "Common.h" 6 | #include "Debugger.h" 7 | #include "InterruptBreakpoint.h" 8 | 9 | namespace CodeReversing 10 | { 11 | 12 | DebugEventHandler::DebugEventHandler(Debugger *pDebugger) : m_pDebugger{ pDebugger } 13 | { 14 | Initialize(); 15 | } 16 | 17 | void DebugEventHandler::Initialize() 18 | { 19 | Register(DebugEvents::eCreateThread, [&](const DEBUG_EVENT &dbgEvent) 20 | { 21 | auto &info = dbgEvent.u.CreateThread; 22 | fprintf(stderr, "CREATE_THREAD_DEBUG_EVENT received.\n" 23 | "Handle: %p\n" 24 | "TLS base: %p\n" 25 | "Start address: %p\n", 26 | info.hThread, info.lpThreadLocalBase, info.lpStartAddress); 27 | SetContinueStatus(DBG_CONTINUE); 28 | }); 29 | 30 | Register(DebugEvents::eCreateProcess, [&](const DEBUG_EVENT &dbgEvent) 31 | { 32 | auto &info = dbgEvent.u.CreateProcessInfo; 33 | fprintf(stderr, "CREATE_PROCESS_DEBUG_EVENT received.\n" 34 | "Handle (image file): %p\n" 35 | "Handle (process): %p\n" 36 | "Handle (main thread): %p\n" 37 | "Image base address: %p\n" 38 | "Debug info file offset: %X\n" 39 | "Debug info size: %X\n" 40 | "TLS base: %p\n" 41 | "Start address: %p\n", 42 | info.hFile, info.hProcess, info.hThread, info.lpBaseOfImage, 43 | info.dwDebugInfoFileOffset, info.nDebugInfoSize, info.lpThreadLocalBase, 44 | info.lpStartAddress); 45 | 46 | char strName[MAX_PATH] = { 0 }; 47 | (void)GetFinalPathNameByHandleA(info.hFile, strName, sizeof(strName), FILE_NAME_NORMALIZED); 48 | 49 | m_pDebugger->m_hProcess = info.hProcess; 50 | m_pDebugger->m_hFile = info.hFile; 51 | m_pDebugger->m_pSymbols = std::unique_ptr(new Symbols(m_pDebugger->m_hProcess(), 52 | m_pDebugger->m_hFile())); 53 | m_pDebugger->m_pSymbols->EnumerateModuleSymbols(strName, (DWORD64)info.lpBaseOfImage); 54 | m_pDebugger->m_pStepPoint = std::unique_ptr(new InterruptBreakpoint(info.hProcess, 0)); 55 | m_pDebugger->m_pDisassembler = std::unique_ptr(new Disassembler(info.hProcess)); 56 | 57 | SetContinueStatus(DBG_CONTINUE); 58 | }); 59 | 60 | Register(DebugEvents::eExitThread, [&](const DEBUG_EVENT &dbgEvent) 61 | { 62 | fprintf(stderr, "EXIT_THREAD_DEBUG_EVENT received.\n" 63 | "Thread %X exited with code %X.\n", 64 | dbgEvent.dwThreadId, dbgEvent.u.ExitThread.dwExitCode); 65 | SetContinueStatus(DBG_CONTINUE); 66 | }); 67 | 68 | Register(DebugEvents::eExitProcess, [&](const DEBUG_EVENT &dbgEvent) 69 | { 70 | fprintf(stderr, "EXIT_PROCESS_DEBUG_EVENT received.\n" 71 | "Process %X exited with code %X.\n", 72 | dbgEvent.dwProcessId, dbgEvent.u.ExitProcess.dwExitCode); 73 | SetContinueStatus(DBG_CONTINUE); 74 | }); 75 | 76 | Register(DebugEvents::eLoadDll, [&](const DEBUG_EVENT &dbgEvent) 77 | { 78 | auto &info = dbgEvent.u.LoadDll; 79 | fprintf(stderr, "LOAD_DLL_DEBUG_EVENT received.\n" 80 | "Handle: %p\n" 81 | "Base address: %p\n" 82 | "Debug info file offset: %X\n" 83 | "Debug info size: %X\n", 84 | info.hFile, info.lpBaseOfDll, info.dwDebugInfoFileOffset, 85 | info.nDebugInfoSize); 86 | char strName[MAX_PATH] = { 0 }; 87 | (void)GetFinalPathNameByHandleA(info.hFile, strName, sizeof(strName), FILE_NAME_NORMALIZED); 88 | fprintf(stderr, "Name: %s\n", strName); 89 | m_pDebugger->m_pSymbols->EnumerateModuleSymbols(strName, (DWORD64)info.lpBaseOfDll); 90 | 91 | m_dwContinueStatus = DBG_CONTINUE; 92 | }); 93 | 94 | Register(DebugEvents::eUnloadDll, [&](const DEBUG_EVENT &dbgEvent) 95 | { 96 | fprintf(stderr, "UNLOAD_DLL_DEBUG_EVENT received.\n" 97 | "Dll at %p has unloaded.\n", dbgEvent.u.UnloadDll.lpBaseOfDll); 98 | SetContinueStatus(DBG_CONTINUE); 99 | }); 100 | 101 | Register(DebugEvents::eDebugString, [&](const DEBUG_EVENT &dbgEvent) 102 | { 103 | auto &info = dbgEvent.u.DebugString; 104 | fprintf(stderr, "OUTPUT_DEBUG_STRING_EVENT received.\n"); 105 | std::unique_ptr pBuffer = std::unique_ptr(new char[info.nDebugStringLength]); 106 | SIZE_T ulBytesRead = 0; 107 | 108 | const bool bSuccess = BOOLIFY(ReadProcessMemory(m_pDebugger->m_hProcess(), info.lpDebugStringData, pBuffer.get(), info.nDebugStringLength, &ulBytesRead)); 109 | if (bSuccess) 110 | { 111 | if (info.fUnicode) 112 | { 113 | fwprintf(stderr, L"Debug string: %s\n", (wchar_t *)pBuffer.get()); 114 | } 115 | else 116 | { 117 | fprintf(stderr, "Debug string: %s\n", pBuffer.get()); 118 | } 119 | } 120 | else 121 | { 122 | fprintf(stderr, "Could not read debug string. Error = %X\n", GetLastError()); 123 | } 124 | 125 | SetContinueStatus(DBG_CONTINUE); 126 | }); 127 | 128 | Register(DebugEvents::eRipEvent, [&](const DEBUG_EVENT &dbgEvent) 129 | { 130 | fprintf(stderr, "Received RIP event.\n"); 131 | SetContinueStatus(DBG_CONTINUE); 132 | }); 133 | 134 | Register(DebugEvents::eException, [&](const DEBUG_EVENT &dbgEvent) 135 | { 136 | /* 137 | auto &exception = dbgEvent.u.Exception; 138 | fprintf(stderr, "Received exception event.\n" 139 | "First chance exception: %X\n" 140 | "Exception code: %X\n" 141 | "Exception flags: %X\n" 142 | "Exception address: %p\n" 143 | "Number parameters (associated with exception): %X\n", 144 | exception.dwFirstChance, exception.ExceptionRecord.ExceptionCode, 145 | exception.ExceptionRecord.ExceptionFlags, exception.ExceptionRecord.ExceptionAddress, 146 | exception.ExceptionRecord.NumberParameters); 147 | */ 148 | m_pDebugger->m_pExceptionHandler->Notify((DebugExceptions)dbgEvent.u.Exception.ExceptionRecord.ExceptionCode, dbgEvent); 149 | SetContinueStatus(m_pDebugger->m_pExceptionHandler->ContinueStatus()); 150 | }); 151 | } 152 | 153 | const DWORD DebugEventHandler::ContinueStatus() const 154 | { 155 | return m_dwContinueStatus; 156 | } 157 | 158 | void DebugEventHandler::SetContinueStatus(const DWORD dwContinueStatus) 159 | { 160 | m_dwContinueStatus = dwContinueStatus; 161 | } 162 | 163 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/Source.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | 3 | #include 4 | #include "Debugger.h" 5 | #include "Disassembler.h" 6 | 7 | DWORD WINAPI DebuggingThread(LPVOID lpParameters) 8 | { 9 | CodeReversing::Debugger *pDebugger = (CodeReversing::Debugger *)lpParameters; 10 | 11 | return pDebugger->Start(); 12 | } 13 | 14 | CONTEXT PromptModifyContext(CodeReversing::Debugger *dbg) 15 | { 16 | CONTEXT ctx = dbg->GetExecutingContext(); 17 | char strRegister[8] = { 0 }; 18 | 19 | #ifdef _M_IX86 20 | char *pRegisters[] = { 21 | "EAX", "EBX", "ECX", "EDX", 22 | "ESP", "EBP", "ESI", "EDI", 23 | "EIP", "EFlags" 24 | }; 25 | DWORD_PTR *pdwRegisters[] = { 26 | &ctx.Eax, &ctx.Ebx, &ctx.Ecx, &ctx.Edx, 27 | &ctx.Esp, &ctx.Ebp, &ctx.Esi, &ctx.Edi, 28 | &ctx.Eip, &ctx.EFlags 29 | }; 30 | 31 | #elif defined _M_AMD64 32 | char *pRegisters[] = { 33 | "RAX", "RBX", "RCX", "RDX", 34 | "RSP", "RBP", "RSI", "RDI", 35 | "R8", "R9", "R10", "R11", 36 | "R12", "R13", "R14", "R15", 37 | "RIP", "EFlags" 38 | }; 39 | DWORD_PTR *pdwRegisters[] = { 40 | &ctx.Rax, &ctx.Rbx, &ctx.Rcx, &ctx.Rdx, 41 | &ctx.Rsp, &ctx.Rbp, &ctx.Rsi, &ctx.Rdi, 42 | &ctx.R8, &ctx.R9, &ctx.R10, &ctx.R11, 43 | &ctx.R12, &ctx.R13, &ctx.R14, &ctx.R15, 44 | &ctx.Rip 45 | }; 46 | 47 | #else 48 | #error "Unsupported platform" 49 | #endif 50 | 51 | fprintf(stderr, "Enter register to change: "); 52 | fscanf(stdin, "%7s", strRegister); 53 | 54 | for (size_t i = 0; i < sizeof(pRegisters) / sizeof(pRegisters[0]); ++i) 55 | { 56 | if (_stricmp(pRegisters[i], strRegister) == 0) 57 | { 58 | DWORD_PTR dwNewValue = 0; 59 | fprintf(stderr, "Enter new value for register %s: 0x", pRegisters[i]); 60 | fscanf(stdin, "%p", &dwNewValue); 61 | #ifdef _M_AMD64 62 | //Annoying workaround since EFlags is 32-bit on x64 63 | if (_stricmp("EFlags", strRegister) == 0) 64 | { 65 | DWORD *pdwEFlags = &ctx.EFlags; 66 | *pdwEFlags = (DWORD)dwNewValue; 67 | } 68 | else 69 | { 70 | *pdwRegisters[i] = dwNewValue; 71 | } 72 | #else 73 | *pdwRegisters[i] = dwNewValue; 74 | #endif 75 | break; 76 | } 77 | 78 | } 79 | 80 | return ctx; 81 | } 82 | 83 | const DWORD_PTR PromptBreakpointAddress(CodeReversing::Debugger *dbg) 84 | { 85 | DWORD_PTR dwAddress = 0; 86 | char cChoice = 0; 87 | fprintf(stderr, "[A]ddress or [s]ymbol name? "); 88 | cChoice = getchar(); 89 | fflush(stdin); 90 | if (cChoice == 'A' || cChoice == 'a') 91 | { 92 | fprintf(stderr, "Breakpoint address: 0x"); 93 | fscanf(stdin, "%p", &dwAddress); 94 | } 95 | else if (cChoice == 'S' || cChoice == 's') 96 | { 97 | char strSymbolName[64] = { 0 }; 98 | fprintf(stderr, "Name: "); 99 | fscanf(stdin, "%63s", strSymbolName); 100 | auto symbol = dbg->ProcessSymbols()->FindSymbolByName(strSymbolName); 101 | dwAddress = (symbol == nullptr ? 0 : symbol->dwAddress); 102 | } 103 | 104 | return dwAddress; 105 | } 106 | 107 | int main(int argc, char *argv[]) 108 | { 109 | DWORD dwPid = 0; 110 | fprintf(stderr, "Enter target process id to attach to: "); 111 | fscanf(stdin, "%i", &dwPid); 112 | 113 | CodeReversing::Debugger dbg(dwPid); 114 | DWORD dwThreadId = 0; 115 | 116 | HANDLE hDebugThread = CreateThread(nullptr, 0, DebuggingThread, &dbg, 0, &dwThreadId); 117 | 118 | printf("[A]dd breakpoint.\n" 119 | "[R]emove breakpoint.\n" 120 | "[S]tep into instruction.\n" 121 | "Step [o]ver instruction.\n" 122 | "[C]ontinue.\n" 123 | "[P]rint context.\n" 124 | "[M]odify context.\n" 125 | "Ca[l]l Stack.\n" 126 | "List S[y]mbols for Module.\n" 127 | "[D]isassemble at address.\n" 128 | "Modify at m[e]mory.\n" 129 | "Pr[i]nt at memory.\n" 130 | "[Q]uit.\n"); 131 | 132 | char cInput = 0; 133 | DWORD_PTR dwTargetAddress = 0; 134 | 135 | do 136 | { 137 | cInput = getchar(); 138 | fflush(stdin); 139 | 140 | switch (cInput) 141 | { 142 | case 'A': 143 | case 'a': 144 | dwTargetAddress = PromptBreakpointAddress(&dbg); 145 | if (dwTargetAddress != 0) 146 | { 147 | (void)dbg.AddBreakpoint(dwTargetAddress); 148 | } 149 | break; 150 | case 'R': 151 | case 'r': 152 | dwTargetAddress = PromptBreakpointAddress(&dbg); 153 | if (dwTargetAddress != 0) 154 | { 155 | (void)dbg.RemoveBreakpoint(dwTargetAddress); 156 | } 157 | break; 158 | case 'S': 159 | case 's': 160 | (void)dbg.StepInto(); 161 | break; 162 | case 'O': 163 | case 'o': 164 | (void)dbg.StepOver(); 165 | break; 166 | case 'C': 167 | case 'c': 168 | (void)dbg.Continue(); 169 | break; 170 | case 'P': 171 | case 'p': 172 | dbg.PrintContext(); 173 | break; 174 | case 'M': 175 | case 'm': 176 | { 177 | CONTEXT ctx = PromptModifyContext(&dbg); 178 | (void)dbg.SetExecutingContext(ctx); 179 | } 180 | break; 181 | case 'L': 182 | case 'l': 183 | dbg.PrintCallStack(); 184 | break; 185 | case 'Y': 186 | case 'y': 187 | { 188 | char strModuleName[MAX_PATH] = { 0 }; 189 | fprintf(stderr, "Enter in module name to dump symbols for: "); 190 | fscanf(stdin, "%259s", strModuleName); 191 | dbg.ProcessSymbols()->PrintSymbolsForModule(strModuleName); 192 | } 193 | break; 194 | case 'D': 195 | case 'd': 196 | { 197 | fprintf(stderr, "Enter address to print disassembly at: 0x"); 198 | fscanf(stdin, "%p", &dwTargetAddress); 199 | dbg.PrintDisassembly(dwTargetAddress); 200 | } 201 | break; 202 | case 'I': 203 | case 'i': 204 | { 205 | fprintf(stderr, "Enter address to print bytes at: 0x"); 206 | fscanf(stdin, "%p", &dwTargetAddress); 207 | dbg.PrintBytesAt(dwTargetAddress); 208 | } 209 | break; 210 | case 'E': 211 | case 'e': 212 | { 213 | char iNewChar = 0; 214 | fprintf(stderr, "Enter address to change byte at: 0x"); 215 | fscanf(stdin, "%p", &dwTargetAddress); 216 | fprintf(stderr, "Enter new byte: 0x"); 217 | fscanf(stdin, "%X", &iNewChar); 218 | (void)dbg.ChangeByteAt(dwTargetAddress, (unsigned char)(iNewChar & 0xFF)); 219 | } 220 | break; 221 | } 222 | 223 | } while (cInput != 'Q' || cInput != 'q'); 224 | 225 | return 0; 226 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/beaengine/BeaEngine.h: -------------------------------------------------------------------------------- 1 | /* Header for BeaEngine 4.x */ 2 | #ifndef _BEA_ENGINE_ 3 | #define _BEA_ENGINE_ 4 | 5 | #include "Includes/export.h" 6 | #include "Includes/basic_types.h" 7 | 8 | #if !defined(BEA_ENGINE_STATIC) 9 | #if defined(BUILD_BEA_ENGINE_DLL) 10 | #define BEA_API bea__api_export__ 11 | #else 12 | #define BEA_API bea__api_import__ 13 | #endif 14 | #else 15 | #define BEA_API 16 | #endif 17 | 18 | 19 | #define INSTRUCT_LENGTH 64 20 | 21 | #pragma pack(1) 22 | typedef struct { 23 | UInt8 W_; 24 | UInt8 R_; 25 | UInt8 X_; 26 | UInt8 B_; 27 | UInt8 state; 28 | } REX_Struct ; 29 | #pragma pack() 30 | 31 | #pragma pack(1) 32 | typedef struct { 33 | int Number; 34 | int NbUndefined; 35 | UInt8 LockPrefix; 36 | UInt8 OperandSize; 37 | UInt8 AddressSize; 38 | UInt8 RepnePrefix; 39 | UInt8 RepPrefix; 40 | UInt8 FSPrefix; 41 | UInt8 SSPrefix; 42 | UInt8 GSPrefix; 43 | UInt8 ESPrefix; 44 | UInt8 CSPrefix; 45 | UInt8 DSPrefix; 46 | UInt8 BranchTaken; 47 | UInt8 BranchNotTaken; 48 | REX_Struct REX; 49 | char alignment[2]; 50 | } PREFIXINFO ; 51 | #pragma pack() 52 | 53 | #pragma pack(1) 54 | typedef struct { 55 | UInt8 OF_; 56 | UInt8 SF_; 57 | UInt8 ZF_; 58 | UInt8 AF_; 59 | UInt8 PF_; 60 | UInt8 CF_; 61 | UInt8 TF_; 62 | UInt8 IF_; 63 | UInt8 DF_; 64 | UInt8 NT_; 65 | UInt8 RF_; 66 | UInt8 alignment; 67 | } EFLStruct ; 68 | #pragma pack() 69 | 70 | #pragma pack(4) 71 | typedef struct { 72 | Int32 BaseRegister; 73 | Int32 IndexRegister; 74 | Int32 Scale; 75 | Int64 Displacement; 76 | } MEMORYTYPE ; 77 | #pragma pack() 78 | 79 | 80 | #pragma pack(1) 81 | typedef struct { 82 | Int32 Category; 83 | Int32 Opcode; 84 | char Mnemonic[16]; 85 | Int32 BranchType; 86 | EFLStruct Flags; 87 | UInt64 AddrValue; 88 | Int64 Immediat; 89 | UInt32 ImplicitModifiedRegs; 90 | } INSTRTYPE; 91 | #pragma pack() 92 | 93 | #pragma pack(1) 94 | typedef struct { 95 | char ArgMnemonic[64]; 96 | Int32 ArgType; 97 | Int32 ArgSize; 98 | Int32 ArgPosition; 99 | UInt32 AccessMode; 100 | MEMORYTYPE Memory; 101 | UInt32 SegmentReg; 102 | } ARGTYPE; 103 | #pragma pack() 104 | 105 | 106 | 107 | #pragma pack(1) 108 | typedef struct _Disasm { 109 | UIntPtr EIP; 110 | UInt64 VirtualAddr; 111 | UInt32 SecurityBlock; 112 | char CompleteInstr[INSTRUCT_LENGTH]; 113 | UInt32 Archi; 114 | UInt64 Options; 115 | INSTRTYPE Instruction; 116 | ARGTYPE Argument1; 117 | ARGTYPE Argument2; 118 | ARGTYPE Argument3; 119 | PREFIXINFO Prefix; 120 | UInt32 Reserved_[40]; 121 | } DISASM, *PDISASM, *LPDISASM; 122 | #pragma pack() 123 | 124 | #define ESReg 1 125 | #define DSReg 2 126 | #define FSReg 3 127 | #define GSReg 4 128 | #define CSReg 5 129 | #define SSReg 6 130 | 131 | #define InvalidPrefix 4 132 | #define SuperfluousPrefix 2 133 | #define NotUsedPrefix 0 134 | #define MandatoryPrefix 8 135 | #define InUsePrefix 1 136 | 137 | #define LowPosition 0 138 | #define HighPosition 1 139 | 140 | enum INSTRUCTION_TYPE 141 | { 142 | GENERAL_PURPOSE_INSTRUCTION = 0x10000, 143 | FPU_INSTRUCTION = 0x20000, 144 | MMX_INSTRUCTION = 0x40000, 145 | SSE_INSTRUCTION = 0x80000, 146 | SSE2_INSTRUCTION = 0x100000, 147 | SSE3_INSTRUCTION = 0x200000, 148 | SSSE3_INSTRUCTION = 0x400000, 149 | SSE41_INSTRUCTION = 0x800000, 150 | SSE42_INSTRUCTION = 0x1000000, 151 | SYSTEM_INSTRUCTION = 0x2000000, 152 | VM_INSTRUCTION = 0x4000000, 153 | UNDOCUMENTED_INSTRUCTION = 0x8000000, 154 | AMD_INSTRUCTION = 0x10000000, 155 | ILLEGAL_INSTRUCTION = 0x20000000, 156 | AES_INSTRUCTION = 0x40000000, 157 | CLMUL_INSTRUCTION = (int)0x80000000, 158 | 159 | 160 | DATA_TRANSFER = 0x1, 161 | ARITHMETIC_INSTRUCTION, 162 | LOGICAL_INSTRUCTION, 163 | SHIFT_ROTATE, 164 | BIT_UInt8, 165 | CONTROL_TRANSFER, 166 | STRING_INSTRUCTION, 167 | InOutINSTRUCTION, 168 | ENTER_LEAVE_INSTRUCTION, 169 | FLAG_CONTROL_INSTRUCTION, 170 | SEGMENT_REGISTER, 171 | MISCELLANEOUS_INSTRUCTION, 172 | COMPARISON_INSTRUCTION, 173 | LOGARITHMIC_INSTRUCTION, 174 | TRIGONOMETRIC_INSTRUCTION, 175 | UNSUPPORTED_INSTRUCTION, 176 | LOAD_CONSTANTS, 177 | FPUCONTROL, 178 | STATE_MANAGEMENT, 179 | CONVERSION_INSTRUCTION, 180 | SHUFFLE_UNPACK, 181 | PACKED_SINGLE_PRECISION, 182 | SIMD128bits, 183 | SIMD64bits, 184 | CACHEABILITY_CONTROL, 185 | FP_INTEGER_CONVERSION, 186 | SPECIALIZED_128bits, 187 | SIMD_FP_PACKED, 188 | SIMD_FP_HORIZONTAL , 189 | AGENT_SYNCHRONISATION, 190 | PACKED_ALIGN_RIGHT , 191 | PACKED_SIGN, 192 | PACKED_BLENDING_INSTRUCTION, 193 | PACKED_TEST, 194 | PACKED_MINMAX, 195 | HORIZONTAL_SEARCH, 196 | PACKED_EQUALITY, 197 | STREAMING_LOAD, 198 | INSERTION_EXTRACTION, 199 | DOT_PRODUCT, 200 | SAD_INSTRUCTION, 201 | ACCELERATOR_INSTRUCTION, /* crc32, popcnt (sse4.2) */ 202 | ROUND_INSTRUCTION 203 | 204 | }; 205 | 206 | enum EFLAGS_STATES 207 | { 208 | TE_ = 1, 209 | MO_ = 2, 210 | RE_ = 4, 211 | SE_ = 8, 212 | UN_ = 0x10, 213 | PR_ = 0x20 214 | }; 215 | 216 | enum BRANCH_TYPE 217 | { 218 | JO = 1, 219 | JC = 2, 220 | JE = 3, 221 | JA = 4, 222 | JS = 5, 223 | JP = 6, 224 | JL = 7, 225 | JG = 8, 226 | JB = 2, /* JC == JB */ 227 | JECXZ = 10, 228 | JmpType = 11, 229 | CallType = 12, 230 | RetType = 13, 231 | JNO = -1, 232 | JNC = -2, 233 | JNE = -3, 234 | JNA = -4, 235 | JNS = -5, 236 | JNP = -6, 237 | JNL = -7, 238 | JNG = -8, 239 | JNB = -2 /* JNC == JNB */ 240 | }; 241 | 242 | enum ARGUMENTS_TYPE 243 | { 244 | NO_ARGUMENT = 0x10000000, 245 | REGISTER_TYPE = 0x20000000, 246 | MEMORY_TYPE = 0x40000000, 247 | CONSTANT_TYPE = (int)0x80000000, 248 | 249 | MMX_REG = 0x10000, 250 | GENERAL_REG = 0x20000, 251 | FPU_REG = 0x40000, 252 | SSE_REG = 0x80000, 253 | CR_REG = 0x100000, 254 | DR_REG = 0x200000, 255 | SPECIAL_REG = 0x400000, 256 | MEMORY_MANAGEMENT_REG = 0x800000, 257 | SEGMENT_REG = 0x1000000, 258 | 259 | RELATIVE_ = 0x4000000, 260 | ABSOLUTE_ = 0x8000000, 261 | 262 | READ = 0x1, 263 | WRITE = 0x2, 264 | 265 | REG0 = 0x1, 266 | REG1 = 0x2, 267 | REG2 = 0x4, 268 | REG3 = 0x8, 269 | REG4 = 0x10, 270 | REG5 = 0x20, 271 | REG6 = 0x40, 272 | REG7 = 0x80, 273 | REG8 = 0x100, 274 | REG9 = 0x200, 275 | REG10 = 0x400, 276 | REG11 = 0x800, 277 | REG12 = 0x1000, 278 | REG13 = 0x2000, 279 | REG14 = 0x4000, 280 | REG15 = 0x8000 281 | }; 282 | 283 | enum SPECIAL_INFO 284 | { 285 | UNKNOWN_OPCODE = -1, 286 | OUT_OF_BLOCK = 0, 287 | 288 | /* === mask = 0xff */ 289 | NoTabulation = 0x00000000, 290 | Tabulation = 0x00000001, 291 | 292 | /* === mask = 0xff00 */ 293 | MasmSyntax = 0x00000000, 294 | GoAsmSyntax = 0x00000100, 295 | NasmSyntax = 0x00000200, 296 | ATSyntax = 0x00000400, 297 | 298 | /* === mask = 0xff0000 */ 299 | PrefixedNumeral = 0x00010000, 300 | SuffixedNumeral = 0x00000000, 301 | 302 | /* === mask = 0xff000000 */ 303 | ShowSegmentRegs = 0x01000000 304 | }; 305 | 306 | 307 | #ifdef __cplusplus 308 | extern "C" 309 | #endif 310 | 311 | BEA_API int __bea_callspec__ Disasm (LPDISASM pDisAsm); 312 | BEA_API const__ char* __bea_callspec__ BeaEngineVersion (void); 313 | BEA_API const__ char* __bea_callspec__ BeaEngineRevision (void); 314 | #endif 315 | -------------------------------------------------------------------------------- /SampleDebuggerPart3/SampleDebuggerPart3/DebugExceptionHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugExceptionHandler.h" 2 | 3 | #include "Debugger.h" 4 | 5 | namespace CodeReversing 6 | { 7 | 8 | DebugExceptionHandler::DebugExceptionHandler(Debugger *pDebugger) : m_pDebugger{ pDebugger } 9 | { 10 | Initialize(); 11 | } 12 | 13 | void DebugExceptionHandler::Initialize() 14 | { 15 | Register(DebugExceptions::eAccessViolation, [&](const DEBUG_EVENT &dbgEvent) 16 | { 17 | fprintf(stderr, "Received access violation\n"); 18 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 19 | }); 20 | 21 | Register(DebugExceptions::eDataTypeMisalignment, [&](const DEBUG_EVENT &dbgEvent) 22 | { 23 | fprintf(stderr, "Received datatype misalignment\n"); 24 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 25 | }); 26 | 27 | Register(DebugExceptions::eBreakpoint, [&](const DEBUG_EVENT &dbgEvent) 28 | { 29 | auto &exceptionRecord = dbgEvent.u.Exception.ExceptionRecord; 30 | const DWORD_PTR dwExceptionAddress = (DWORD_PTR)exceptionRecord.ExceptionAddress; 31 | fprintf(stderr, "Received breakpoint at address %p.\n", dwExceptionAddress); 32 | 33 | Breakpoint *pBreakpoint = m_pDebugger->FindBreakpoint(dwExceptionAddress); 34 | if (pBreakpoint != nullptr) 35 | { 36 | if (pBreakpoint->Disable()) 37 | { 38 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 39 | CONTEXT ctx = m_pDebugger->GetExecutingContext(); 40 | #ifdef _M_IX86 41 | ctx.Eip = (DWORD_PTR)dwExceptionAddress; 42 | #elif defined _M_AMD64 43 | ctx.Rip = (DWORD_PTR)dwExceptionAddress; 44 | #else 45 | #error "Unsupported architecture" 46 | #endif 47 | ctx.EFlags |= 0x100; 48 | m_pDebugger->m_pLastBreakpoint = pBreakpoint; 49 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 50 | if (m_pDebugger->SetExecutingContext(ctx)) 51 | { 52 | fprintf(stderr, "Press c to continue or s to begin stepping.\n"); 53 | (void)m_pDebugger->WaitForContinue(); 54 | } 55 | } 56 | else 57 | { 58 | fprintf(stderr, "Could not remove breakpoint at address %p.", dwExceptionAddress); 59 | } 60 | } 61 | SetContinueStatus(DBG_CONTINUE); 62 | }); 63 | 64 | Register(DebugExceptions::eSingleStep, [&](const DEBUG_EVENT &dbgEvent) 65 | { 66 | auto &exceptionRecord = dbgEvent.u.Exception.ExceptionRecord; 67 | const DWORD_PTR dwExceptionAddress = (DWORD_PTR)exceptionRecord.ExceptionAddress; 68 | fprintf(stderr, "Received single step at address %p\n", dwExceptionAddress); 69 | if (m_pDebugger->m_bIsStepping) 70 | { 71 | fprintf(stderr, "Press s to continue stepping.\n"); 72 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 73 | CONTEXT ctx = m_pDebugger->GetExecutingContext(); 74 | if (m_pDebugger->SetExecutingContext(ctx)) 75 | { 76 | (void)m_pDebugger->WaitForContinue(); 77 | } 78 | } 79 | if (!m_pDebugger->m_pLastBreakpoint->IsEnabled()) 80 | { 81 | (void)m_pDebugger->m_pLastBreakpoint->Enable(); 82 | } 83 | 84 | SetContinueStatus(DBG_CONTINUE); 85 | }); 86 | 87 | Register(DebugExceptions::eArrayBoundsExceeded, [&](const DEBUG_EVENT &dbgEvent) 88 | { 89 | fprintf(stderr, "Received array bounds exceeded\n"); 90 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 91 | }); 92 | 93 | Register(DebugExceptions::eFltDenormal, [&](const DEBUG_EVENT &dbgEvent) 94 | { 95 | fprintf(stderr, "Received floating point denormal\n"); 96 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 97 | }); 98 | 99 | Register(DebugExceptions::eFltDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 100 | { 101 | fprintf(stderr, "Received floating point divide by zero\n"); 102 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 103 | }); 104 | 105 | Register(DebugExceptions::eFltInexactResult, [&](const DEBUG_EVENT &dbgEvent) 106 | { 107 | fprintf(stderr, "Received floating point inexact result\n"); 108 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 109 | }); 110 | 111 | Register(DebugExceptions::eFltInvalidOperation, [&](const DEBUG_EVENT &dbgEvent) 112 | { 113 | fprintf(stderr, "Received floating point invalid operation\n"); 114 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 115 | }); 116 | 117 | Register(DebugExceptions::eFltOverflow, [&](const DEBUG_EVENT &dbgEvent) 118 | { 119 | fprintf(stderr, "Received floating point overflow\n"); 120 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 121 | }); 122 | 123 | Register(DebugExceptions::eFltStackCheck, [&](const DEBUG_EVENT &dbgEvent) 124 | { 125 | fprintf(stderr, "Received floating point stack check\n"); 126 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 127 | }); 128 | 129 | Register(DebugExceptions::eFltUnderflow, [&](const DEBUG_EVENT &dbgEvent) 130 | { 131 | fprintf(stderr, "Received floating point underflow\n"); 132 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 133 | }); 134 | 135 | Register(DebugExceptions::eIntDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 136 | { 137 | fprintf(stderr, "Received integer divide by zero\n"); 138 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 139 | }); 140 | 141 | Register(DebugExceptions::eIntOverflow, [&](const DEBUG_EVENT &dbgEvent) 142 | { 143 | fprintf(stderr, "Received integer overflow\n"); 144 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 145 | }); 146 | 147 | Register(DebugExceptions::ePrivilegedInstruction, [&](const DEBUG_EVENT &dbgEvent) 148 | { 149 | fprintf(stderr, "Received privileged instruction\n"); 150 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 151 | }); 152 | 153 | Register(DebugExceptions::ePageError, [&](const DEBUG_EVENT &dbgEvent) 154 | { 155 | fprintf(stderr, "Received page error\n"); 156 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 157 | }); 158 | 159 | Register(DebugExceptions::eIllegalInstruction, [&](const DEBUG_EVENT &dbgEvent) 160 | { 161 | fprintf(stderr, "Received illegal instruction\n"); 162 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 163 | }); 164 | 165 | Register(DebugExceptions::eNoncontinuableException, [&](const DEBUG_EVENT &dbgEvent) 166 | { 167 | fprintf(stderr, "Received non-continuable exception\n"); 168 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 169 | }); 170 | 171 | Register(DebugExceptions::eStackOverflow, [&](const DEBUG_EVENT &dbgEvent) 172 | { 173 | fprintf(stderr, "Received stack overflow\n"); 174 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 175 | }); 176 | 177 | Register(DebugExceptions::eInvalidDisposition, [&](const DEBUG_EVENT &dbgEvent) 178 | { 179 | fprintf(stderr, "Received invalid disposition\n"); 180 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 181 | }); 182 | 183 | Register(DebugExceptions::eGuardPage, [&](const DEBUG_EVENT &dbgEvent) 184 | { 185 | fprintf(stderr, "Received guard page\n"); 186 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 187 | }); 188 | 189 | Register(DebugExceptions::eInvalidHandle, [&](const DEBUG_EVENT &dbgEvent) 190 | { 191 | fprintf(stderr, "Received invalid handle\n"); 192 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 193 | }); 194 | } 195 | 196 | const DWORD DebugExceptionHandler::ContinueStatus() const 197 | { 198 | return m_dwContinueStatus; 199 | } 200 | 201 | void DebugExceptionHandler::SetContinueStatus(const DWORD dwContinueStatus) 202 | { 203 | m_dwContinueStatus = dwContinueStatus; 204 | } 205 | 206 | } -------------------------------------------------------------------------------- /SampleDebuggerPart4/SampleDebuggerPart4/DebugExceptionHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugExceptionHandler.h" 2 | 3 | #include "Debugger.h" 4 | 5 | namespace CodeReversing 6 | { 7 | 8 | DebugExceptionHandler::DebugExceptionHandler(Debugger *pDebugger) : m_pDebugger{ pDebugger } 9 | { 10 | Initialize(); 11 | } 12 | 13 | void DebugExceptionHandler::Initialize() 14 | { 15 | Register(DebugExceptions::eAccessViolation, [&](const DEBUG_EVENT &dbgEvent) 16 | { 17 | fprintf(stderr, "Received access violation\n"); 18 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 19 | }); 20 | 21 | Register(DebugExceptions::eDataTypeMisalignment, [&](const DEBUG_EVENT &dbgEvent) 22 | { 23 | fprintf(stderr, "Received datatype misalignment\n"); 24 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 25 | }); 26 | 27 | Register(DebugExceptions::eBreakpoint, [&](const DEBUG_EVENT &dbgEvent) 28 | { 29 | auto &exceptionRecord = dbgEvent.u.Exception.ExceptionRecord; 30 | const DWORD_PTR dwExceptionAddress = (DWORD_PTR)exceptionRecord.ExceptionAddress; 31 | fprintf(stderr, "Received breakpoint at address %p.\n", dwExceptionAddress); 32 | 33 | Breakpoint *pBreakpoint = m_pDebugger->FindBreakpoint(dwExceptionAddress); 34 | if (pBreakpoint != nullptr) 35 | { 36 | if (pBreakpoint->Disable()) 37 | { 38 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 39 | CONTEXT ctx = m_pDebugger->GetExecutingContext(); 40 | #ifdef _M_IX86 41 | ctx.Eip = (DWORD_PTR)dwExceptionAddress; 42 | #elif defined _M_AMD64 43 | ctx.Rip = (DWORD_PTR)dwExceptionAddress; 44 | #else 45 | #error "Unsupported architecture" 46 | #endif 47 | ctx.EFlags |= 0x100; 48 | m_pDebugger->m_pLastBreakpoint = pBreakpoint; 49 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 50 | if (m_pDebugger->SetExecutingContext(ctx)) 51 | { 52 | fprintf(stderr, "Press c to continue or s to begin stepping.\n"); 53 | (void)m_pDebugger->WaitForContinue(); 54 | } 55 | } 56 | else 57 | { 58 | fprintf(stderr, "Could not remove breakpoint at address %p.", dwExceptionAddress); 59 | } 60 | } 61 | SetContinueStatus(DBG_CONTINUE); 62 | }); 63 | 64 | Register(DebugExceptions::eSingleStep, [&](const DEBUG_EVENT &dbgEvent) 65 | { 66 | auto &exceptionRecord = dbgEvent.u.Exception.ExceptionRecord; 67 | const DWORD_PTR dwExceptionAddress = (DWORD_PTR)exceptionRecord.ExceptionAddress; 68 | fprintf(stderr, "Received single step at address %p\n", dwExceptionAddress); 69 | if (m_pDebugger->m_bIsStepping) 70 | { 71 | fprintf(stderr, "Press s to continue stepping.\n"); 72 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 73 | CONTEXT ctx = m_pDebugger->GetExecutingContext(); 74 | if (m_pDebugger->SetExecutingContext(ctx)) 75 | { 76 | (void)m_pDebugger->WaitForContinue(); 77 | } 78 | } 79 | if (!m_pDebugger->m_pLastBreakpoint->IsEnabled()) 80 | { 81 | (void)m_pDebugger->m_pLastBreakpoint->Enable(); 82 | } 83 | 84 | SetContinueStatus(DBG_CONTINUE); 85 | }); 86 | 87 | Register(DebugExceptions::eArrayBoundsExceeded, [&](const DEBUG_EVENT &dbgEvent) 88 | { 89 | fprintf(stderr, "Received array bounds exceeded\n"); 90 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 91 | }); 92 | 93 | Register(DebugExceptions::eFltDenormal, [&](const DEBUG_EVENT &dbgEvent) 94 | { 95 | fprintf(stderr, "Received floating point denormal\n"); 96 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 97 | }); 98 | 99 | Register(DebugExceptions::eFltDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 100 | { 101 | fprintf(stderr, "Received floating point divide by zero\n"); 102 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 103 | }); 104 | 105 | Register(DebugExceptions::eFltInexactResult, [&](const DEBUG_EVENT &dbgEvent) 106 | { 107 | fprintf(stderr, "Received floating point inexact result\n"); 108 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 109 | }); 110 | 111 | Register(DebugExceptions::eFltInvalidOperation, [&](const DEBUG_EVENT &dbgEvent) 112 | { 113 | fprintf(stderr, "Received floating point invalid operation\n"); 114 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 115 | }); 116 | 117 | Register(DebugExceptions::eFltOverflow, [&](const DEBUG_EVENT &dbgEvent) 118 | { 119 | fprintf(stderr, "Received floating point overflow\n"); 120 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 121 | }); 122 | 123 | Register(DebugExceptions::eFltStackCheck, [&](const DEBUG_EVENT &dbgEvent) 124 | { 125 | fprintf(stderr, "Received floating point stack check\n"); 126 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 127 | }); 128 | 129 | Register(DebugExceptions::eFltUnderflow, [&](const DEBUG_EVENT &dbgEvent) 130 | { 131 | fprintf(stderr, "Received floating point underflow\n"); 132 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 133 | }); 134 | 135 | Register(DebugExceptions::eIntDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 136 | { 137 | fprintf(stderr, "Received integer divide by zero\n"); 138 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 139 | }); 140 | 141 | Register(DebugExceptions::eIntOverflow, [&](const DEBUG_EVENT &dbgEvent) 142 | { 143 | fprintf(stderr, "Received integer overflow\n"); 144 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 145 | }); 146 | 147 | Register(DebugExceptions::ePrivilegedInstruction, [&](const DEBUG_EVENT &dbgEvent) 148 | { 149 | fprintf(stderr, "Received privileged instruction\n"); 150 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 151 | }); 152 | 153 | Register(DebugExceptions::ePageError, [&](const DEBUG_EVENT &dbgEvent) 154 | { 155 | fprintf(stderr, "Received page error\n"); 156 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 157 | }); 158 | 159 | Register(DebugExceptions::eIllegalInstruction, [&](const DEBUG_EVENT &dbgEvent) 160 | { 161 | fprintf(stderr, "Received illegal instruction\n"); 162 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 163 | }); 164 | 165 | Register(DebugExceptions::eNoncontinuableException, [&](const DEBUG_EVENT &dbgEvent) 166 | { 167 | fprintf(stderr, "Received non-continuable exception\n"); 168 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 169 | }); 170 | 171 | Register(DebugExceptions::eStackOverflow, [&](const DEBUG_EVENT &dbgEvent) 172 | { 173 | fprintf(stderr, "Received stack overflow\n"); 174 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 175 | }); 176 | 177 | Register(DebugExceptions::eInvalidDisposition, [&](const DEBUG_EVENT &dbgEvent) 178 | { 179 | fprintf(stderr, "Received invalid disposition\n"); 180 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 181 | }); 182 | 183 | Register(DebugExceptions::eGuardPage, [&](const DEBUG_EVENT &dbgEvent) 184 | { 185 | fprintf(stderr, "Received guard page\n"); 186 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 187 | }); 188 | 189 | Register(DebugExceptions::eInvalidHandle, [&](const DEBUG_EVENT &dbgEvent) 190 | { 191 | fprintf(stderr, "Received invalid handle\n"); 192 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 193 | }); 194 | } 195 | 196 | const DWORD DebugExceptionHandler::ContinueStatus() const 197 | { 198 | return m_dwContinueStatus; 199 | } 200 | 201 | void DebugExceptionHandler::SetContinueStatus(const DWORD dwContinueStatus) 202 | { 203 | m_dwContinueStatus = dwContinueStatus; 204 | } 205 | 206 | } -------------------------------------------------------------------------------- /SampleDebuggerPart5/SampleDebuggerPart5/DebugExceptionHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "DebugExceptionHandler.h" 2 | 3 | #include "Debugger.h" 4 | 5 | namespace CodeReversing 6 | { 7 | 8 | DebugExceptionHandler::DebugExceptionHandler(Debugger *pDebugger) : m_pDebugger{ pDebugger } 9 | { 10 | Initialize(); 11 | } 12 | 13 | void DebugExceptionHandler::Initialize() 14 | { 15 | Register(DebugExceptions::eAccessViolation, [&](const DEBUG_EVENT &dbgEvent) 16 | { 17 | fprintf(stderr, "Received access violation\n"); 18 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 19 | }); 20 | 21 | Register(DebugExceptions::eDataTypeMisalignment, [&](const DEBUG_EVENT &dbgEvent) 22 | { 23 | fprintf(stderr, "Received datatype misalignment\n"); 24 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 25 | }); 26 | 27 | Register(DebugExceptions::eBreakpoint, [&](const DEBUG_EVENT &dbgEvent) 28 | { 29 | auto &exceptionRecord = dbgEvent.u.Exception.ExceptionRecord; 30 | const DWORD_PTR dwExceptionAddress = (DWORD_PTR)exceptionRecord.ExceptionAddress; 31 | fprintf(stderr, "Received breakpoint at address %p.\n", dwExceptionAddress); 32 | 33 | Breakpoint *pBreakpoint = m_pDebugger->FindBreakpoint(dwExceptionAddress); 34 | if (pBreakpoint != nullptr) 35 | { 36 | if (pBreakpoint->Disable()) 37 | { 38 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 39 | CONTEXT ctx = m_pDebugger->GetExecutingContext(); 40 | #ifdef _M_IX86 41 | ctx.Eip = (DWORD_PTR)dwExceptionAddress; 42 | #elif defined _M_AMD64 43 | ctx.Rip = (DWORD_PTR)dwExceptionAddress; 44 | #else 45 | #error "Unsupported architecture" 46 | #endif 47 | ctx.EFlags |= 0x100; 48 | m_pDebugger->m_pLastBreakpoint = pBreakpoint; 49 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 50 | if (m_pDebugger->SetExecutingContext(ctx)) 51 | { 52 | fprintf(stderr, "Press c to continue, s to step into, o to step over.\n"); 53 | (void)m_pDebugger->WaitForContinue(); 54 | } 55 | } 56 | else 57 | { 58 | fprintf(stderr, "Could not remove breakpoint at address %p.", dwExceptionAddress); 59 | } 60 | } 61 | 62 | SetContinueStatus(DBG_CONTINUE); 63 | }); 64 | 65 | Register(DebugExceptions::eSingleStep, [&](const DEBUG_EVENT &dbgEvent) 66 | { 67 | auto &exceptionRecord = dbgEvent.u.Exception.ExceptionRecord; 68 | const DWORD_PTR dwExceptionAddress = (DWORD_PTR)exceptionRecord.ExceptionAddress; 69 | fprintf(stderr, "Received step at address %p\n", dwExceptionAddress); 70 | if (m_pDebugger->m_bIsStepping) 71 | { 72 | fprintf(stderr, "Press c to continue, s to step into, o to step over.\n"); 73 | m_pDebugger->m_dwExecutingThreadId = dbgEvent.dwThreadId; 74 | CONTEXT ctx = m_pDebugger->GetExecutingContext(); 75 | if (m_pDebugger->SetExecutingContext(ctx)) 76 | { 77 | (void)m_pDebugger->WaitForContinue(); 78 | } 79 | } 80 | if (m_pDebugger->m_pLastBreakpoint != m_pDebugger->m_pStepPoint.get() && !m_pDebugger->m_pLastBreakpoint->IsEnabled()) 81 | { 82 | (void)m_pDebugger->m_pLastBreakpoint->Enable(); 83 | } 84 | 85 | SetContinueStatus(DBG_CONTINUE); 86 | }); 87 | 88 | Register(DebugExceptions::eArrayBoundsExceeded, [&](const DEBUG_EVENT &dbgEvent) 89 | { 90 | fprintf(stderr, "Received array bounds exceeded\n"); 91 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 92 | }); 93 | 94 | Register(DebugExceptions::eFltDenormal, [&](const DEBUG_EVENT &dbgEvent) 95 | { 96 | fprintf(stderr, "Received floating point denormal\n"); 97 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 98 | }); 99 | 100 | Register(DebugExceptions::eFltDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 101 | { 102 | fprintf(stderr, "Received floating point divide by zero\n"); 103 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 104 | }); 105 | 106 | Register(DebugExceptions::eFltInexactResult, [&](const DEBUG_EVENT &dbgEvent) 107 | { 108 | fprintf(stderr, "Received floating point inexact result\n"); 109 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 110 | }); 111 | 112 | Register(DebugExceptions::eFltInvalidOperation, [&](const DEBUG_EVENT &dbgEvent) 113 | { 114 | fprintf(stderr, "Received floating point invalid operation\n"); 115 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 116 | }); 117 | 118 | Register(DebugExceptions::eFltOverflow, [&](const DEBUG_EVENT &dbgEvent) 119 | { 120 | fprintf(stderr, "Received floating point overflow\n"); 121 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 122 | }); 123 | 124 | Register(DebugExceptions::eFltStackCheck, [&](const DEBUG_EVENT &dbgEvent) 125 | { 126 | fprintf(stderr, "Received floating point stack check\n"); 127 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 128 | }); 129 | 130 | Register(DebugExceptions::eFltUnderflow, [&](const DEBUG_EVENT &dbgEvent) 131 | { 132 | fprintf(stderr, "Received floating point underflow\n"); 133 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 134 | }); 135 | 136 | Register(DebugExceptions::eIntDivideByZero, [&](const DEBUG_EVENT &dbgEvent) 137 | { 138 | fprintf(stderr, "Received integer divide by zero\n"); 139 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 140 | }); 141 | 142 | Register(DebugExceptions::eIntOverflow, [&](const DEBUG_EVENT &dbgEvent) 143 | { 144 | fprintf(stderr, "Received integer overflow\n"); 145 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 146 | }); 147 | 148 | Register(DebugExceptions::ePrivilegedInstruction, [&](const DEBUG_EVENT &dbgEvent) 149 | { 150 | fprintf(stderr, "Received privileged instruction\n"); 151 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 152 | }); 153 | 154 | Register(DebugExceptions::ePageError, [&](const DEBUG_EVENT &dbgEvent) 155 | { 156 | fprintf(stderr, "Received page error\n"); 157 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 158 | }); 159 | 160 | Register(DebugExceptions::eIllegalInstruction, [&](const DEBUG_EVENT &dbgEvent) 161 | { 162 | fprintf(stderr, "Received illegal instruction\n"); 163 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 164 | }); 165 | 166 | Register(DebugExceptions::eNoncontinuableException, [&](const DEBUG_EVENT &dbgEvent) 167 | { 168 | fprintf(stderr, "Received non-continuable exception\n"); 169 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 170 | }); 171 | 172 | Register(DebugExceptions::eStackOverflow, [&](const DEBUG_EVENT &dbgEvent) 173 | { 174 | fprintf(stderr, "Received stack overflow\n"); 175 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 176 | }); 177 | 178 | Register(DebugExceptions::eInvalidDisposition, [&](const DEBUG_EVENT &dbgEvent) 179 | { 180 | fprintf(stderr, "Received invalid disposition\n"); 181 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 182 | }); 183 | 184 | Register(DebugExceptions::eGuardPage, [&](const DEBUG_EVENT &dbgEvent) 185 | { 186 | fprintf(stderr, "Received guard page\n"); 187 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 188 | }); 189 | 190 | Register(DebugExceptions::eInvalidHandle, [&](const DEBUG_EVENT &dbgEvent) 191 | { 192 | fprintf(stderr, "Received invalid handle\n"); 193 | SetContinueStatus(DBG_EXCEPTION_NOT_HANDLED); 194 | }); 195 | } 196 | 197 | const DWORD DebugExceptionHandler::ContinueStatus() const 198 | { 199 | return m_dwContinueStatus; 200 | } 201 | 202 | void DebugExceptionHandler::SetContinueStatus(const DWORD dwContinueStatus) 203 | { 204 | m_dwContinueStatus = dwContinueStatus; 205 | } 206 | 207 | } --------------------------------------------------------------------------------