├── README.md ├── ddr_client ├── Debug │ ├── ddr_stable.dll │ ├── ddr_stable.exp │ ├── ddr_stable.ilk │ ├── ddr_stable.lib │ └── ddr_stable.pdb ├── Release │ ├── ddr_stable.dll │ ├── ddr_stable.exp │ ├── ddr_stable.iobj │ ├── ddr_stable.ipdb │ ├── ddr_stable.lib │ └── ddr_stable.pdb ├── ddr_stable.sln ├── ddr_stable │ ├── Debug │ │ ├── ddr_helper_functions.obj │ │ ├── ddr_stable.Build.CppClean.log │ │ ├── ddr_stable.dll.recipe │ │ ├── ddr_stable.log │ │ ├── ddr_stable.tlog │ │ │ ├── CL.command.1.tlog │ │ │ ├── CL.read.1.tlog │ │ │ ├── CL.write.1.tlog │ │ │ ├── ddr_stable.lastbuildstate │ │ │ ├── ddr_stable.write.1u.tlog │ │ │ ├── link.command.1.tlog │ │ │ ├── link.read.1.tlog │ │ │ └── link.write.1.tlog │ │ ├── ddr_stable.vcxproj.FileListAbsolute.txt │ │ ├── dump_buffer1.obj │ │ ├── main.obj │ │ ├── patch_exe.obj │ │ ├── trace_instr.obj │ │ ├── vc142.idb │ │ └── vc142.pdb │ ├── DynRio_debug_x32_PropertySheet.props │ ├── DynRio_debug_x64_PropertySheet.props │ ├── DynRio_release_x64_PropertySheet.props │ ├── DynRio_release_x86_PropertySheet.props │ ├── Release │ │ ├── ddr_helper_functions.obj │ │ ├── ddr_stable.Build.CppClean.log │ │ ├── ddr_stable.dll.recipe │ │ ├── ddr_stable.log │ │ ├── ddr_stable.tlog │ │ │ ├── CL.command.1.tlog │ │ │ ├── CL.read.1.tlog │ │ │ ├── CL.write.1.tlog │ │ │ ├── ddr_stable.lastbuildstate │ │ │ ├── ddr_stable.write.1u.tlog │ │ │ ├── link.command.1.tlog │ │ │ ├── link.read.1.tlog │ │ │ └── link.write.1.tlog │ │ ├── ddr_stable.vcxproj.FileListAbsolute.txt │ │ ├── dump_buffer1.obj │ │ ├── main.obj │ │ ├── patch_exe.obj │ │ ├── trace_instr.obj │ │ └── vc142.pdb │ ├── ddr.h │ ├── ddr_config.txt │ ├── ddr_config64.txt │ ├── ddr_helper_functions.c │ ├── ddr_stable.vcxproj │ ├── ddr_stable.vcxproj.filters │ ├── ddr_stable.vcxproj.user │ ├── dump_buffer1.c │ ├── globals.h │ ├── main.c │ ├── patch_exe.c │ ├── trace_instr.c │ └── x64 │ │ ├── Debug │ │ ├── ddr_helper_functions.obj │ │ ├── ddr_stable.Build.CppClean.log │ │ ├── ddr_stable.dll.recipe │ │ ├── ddr_stable.log │ │ ├── ddr_stable.tlog │ │ │ ├── CL.command.1.tlog │ │ │ ├── CL.read.1.tlog │ │ │ ├── CL.write.1.tlog │ │ │ ├── ddr_stable.lastbuildstate │ │ │ ├── ddr_stable.write.1u.tlog │ │ │ ├── link.command.1.tlog │ │ │ ├── link.read.1.tlog │ │ │ └── link.write.1.tlog │ │ ├── ddr_stable.vcxproj.FileListAbsolute.txt │ │ ├── dump_buffer1.obj │ │ ├── main.obj │ │ ├── patch_exe.obj │ │ ├── trace_instr.obj │ │ ├── vc142.idb │ │ └── vc142.pdb │ │ └── Release │ │ ├── ddr_helper_functions.obj │ │ ├── ddr_stable.Build.CppClean.log │ │ ├── ddr_stable.dll.recipe │ │ ├── ddr_stable.log │ │ ├── ddr_stable.tlog │ │ ├── CL.command.1.tlog │ │ ├── CL.read.1.tlog │ │ ├── CL.write.1.tlog │ │ ├── ddr_stable.lastbuildstate │ │ ├── ddr_stable.write.1u.tlog │ │ ├── link.command.1.tlog │ │ ├── link.read.1.tlog │ │ └── link.write.1.tlog │ │ ├── ddr_stable.vcxproj.FileListAbsolute.txt │ │ ├── dump_buffer1.obj │ │ ├── main.obj │ │ ├── patch_exe.obj │ │ ├── trace_instr.obj │ │ └── vc142.pdb └── x64 │ ├── Debug │ ├── ddr_stable.dll │ ├── ddr_stable.exp │ ├── ddr_stable.ilk │ ├── ddr_stable.lib │ └── ddr_stable.pdb │ └── Release │ ├── ddr_stable.dll │ ├── ddr_stable.exp │ ├── ddr_stable.iobj │ ├── ddr_stable.ipdb │ ├── ddr_stable.lib │ └── ddr_stable.pdb ├── ddr_installer.zip └── ddr_installer ├── DDR_INSTALLER.py ├── README.txt ├── ddr_test_samples ├── testsample0_32_dyn.cfg ├── testsample0_32_dyn.exe ├── testsample0_64_dyn.cfg ├── testsample0_64_dyn.exe ├── testsample1_32.cfg ├── testsample1_32.exe ├── testsample1_64.cfg ├── testsample1_64.exe ├── testsample_with_args_x32.exe ├── testsample_with_args_x64.exe └── testsamples_README.txt ├── docs ├── ddr_client_dll_sample_config32.txt └── ddr_client_dll_sample_config64.txt ├── install_data ├── ddr32.dll ├── ddr32dbg.dll ├── ddr64.dll ├── ddr64dbg.dll ├── ddr_plugin.py ├── ddr_server.py └── installer_web_server.py ├── known_bugs.txt ├── release_notes.txt ├── requirements.in ├── requirements.txt ├── roadmap.txt └── templates ├── ddr_config_template.json ├── ddr_server_template.json └── ida_plugin_installer_template.py /README.md: -------------------------------------------------------------------------------- 1 | # Dynamic Data Resolver (DDR) 2 | 3 | --- 4 | 5 | Release date Version 1.0.2 beta: 17th of December 2020 15:00 CET 6 | 7 | New features: 8 | 9 | Start address - The instrumentation/analysis starts at this address 10 | 11 | Break address - The instrumentation and execution of the sample process stops here 12 | 13 | You can find a detailed description of the 1.0.2 features here at release time 14 | https://blog.talosintelligence.com/2020/12/talos-tools-of-trade.html 15 | 16 | --- 17 | 18 | Release date Version 1.0.1 beta: 20th of October 2020 17:00 CET 19 | 20 | You can find an overview of the 1.0.1 features here 21 | https://blog.talosintelligence.com/2020/10/ddr101beta.html 22 | 23 | --- 24 | 25 | Version 1.0 26 | 27 | Copyright (C) 2020 Cisco Talos 28 | Author: Holger Unterbrink (hunterbr@cisco.com) 29 | 30 | This program is free software; you can redistribute it and/or modify 31 | it under the terms of the GNU General Public License as published by 32 | the Free Software Foundation; either version 2 of the License, or 33 | (at your option) any later version. 34 | 35 | This program is distributed in the hope that it will be useful, 36 | but WITHOUT ANY WARRANTY; without even the implied warranty of 37 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 | GNU General Public License for more details. 39 | 40 | You should have received a copy of the GNU General Public License along 41 | with this program; if not, write to the Free Software Foundation, Inc., 42 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 43 | 44 | **Blog** 45 | 46 | Release date Version 1.0: 28th of May 2020 17:00 CET 47 | 48 | The documentation and installation description of the project can be found here at release time: 49 | 50 | https://blog.talosintelligence.com/tbd 51 | 52 | A quick feature walkthrough video is here: 53 | 54 | https://youtu.be/miSFddzvzL8 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /ddr_client/Debug/ddr_stable.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Debug/ddr_stable.dll -------------------------------------------------------------------------------- /ddr_client/Debug/ddr_stable.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Debug/ddr_stable.exp -------------------------------------------------------------------------------- /ddr_client/Debug/ddr_stable.ilk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Debug/ddr_stable.ilk -------------------------------------------------------------------------------- /ddr_client/Debug/ddr_stable.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Debug/ddr_stable.lib -------------------------------------------------------------------------------- /ddr_client/Debug/ddr_stable.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Debug/ddr_stable.pdb -------------------------------------------------------------------------------- /ddr_client/Release/ddr_stable.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Release/ddr_stable.dll -------------------------------------------------------------------------------- /ddr_client/Release/ddr_stable.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Release/ddr_stable.exp -------------------------------------------------------------------------------- /ddr_client/Release/ddr_stable.iobj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Release/ddr_stable.iobj -------------------------------------------------------------------------------- /ddr_client/Release/ddr_stable.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Release/ddr_stable.ipdb -------------------------------------------------------------------------------- /ddr_client/Release/ddr_stable.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Release/ddr_stable.lib -------------------------------------------------------------------------------- /ddr_client/Release/ddr_stable.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/Release/ddr_stable.pdb -------------------------------------------------------------------------------- /ddr_client/ddr_stable.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30114.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ddr_stable", "ddr_stable\ddr_stable.vcxproj", "{6C96058E-3DA0-4451-816B-2A5E2E714911}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Debug|x64.ActiveCfg = Debug|x64 17 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Debug|x64.Build.0 = Debug|x64 18 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Debug|x86.ActiveCfg = Debug|Win32 19 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Debug|x86.Build.0 = Debug|Win32 20 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Release|x64.ActiveCfg = Release|x64 21 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Release|x64.Build.0 = Release|x64 22 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Release|x86.ActiveCfg = Release|Win32 23 | {6C96058E-3DA0-4451-816B-2A5E2E714911}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {BA49BEBA-3B25-4C4C-9E8D-C9D724CF926D} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_helper_functions.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_helper_functions.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.Build.CppClean.log: -------------------------------------------------------------------------------- 1 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\vc142.pdb 2 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\vc142.idb 3 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\trace_instr.obj 4 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\patch_exe.obj 5 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\main.obj 6 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\dump_buffer1.obj 7 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_helper_functions.obj 8 | c:\tools\dev\git\dyndataresolver\ddr_client\debug\ddr_stable.lib 9 | c:\tools\dev\git\dyndataresolver\ddr_client\debug\ddr_stable.exp 10 | c:\tools\dev\git\dyndataresolver\ddr_client\debug\ddr_stable.ilk 11 | c:\tools\dev\git\dyndataresolver\ddr_client\debug\ddr_stable.dll 12 | c:\tools\dev\git\dyndataresolver\ddr_client\debug\ddr_stable.pdb 13 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_stable.tlog\cl.command.1.tlog 14 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_stable.tlog\cl.read.1.tlog 15 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_stable.tlog\cl.write.1.tlog 16 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_stable.tlog\ddr_stable.write.1u.tlog 17 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_stable.tlog\link.command.1.tlog 18 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_stable.tlog\link.read.1.tlog 19 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\debug\ddr_stable.tlog\link.write.1.tlog 20 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.dll.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | C:\tools\dev\git\DynDataResolver\ddr_client\Debug\ddr_stable.dll 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.log: -------------------------------------------------------------------------------- 1 |  ddr_helper_functions.c 2 | dump_buffer1.c 3 | main.c 4 | patch_exe.c 5 | trace_instr.c 6 | Generating Code... 7 | ddr_stable.vcxproj -> C:\tools\dev\git\DynDataResolver\ddr_client\Debug\ddr_stable.dll 8 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/ddr_stable.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.18362.0: 2 | Debug|Win32|C:\tools\dev\git\DynDataResolver\ddr_client\| 3 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/ddr_stable.write.1u.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.tlog/ddr_stable.write.1u.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/link.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.tlog/link.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/link.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.tlog/link.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.tlog/link.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.tlog/link.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/ddr_stable.vcxproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/ddr_stable.vcxproj.FileListAbsolute.txt -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/dump_buffer1.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/dump_buffer1.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/main.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/main.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/patch_exe.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/patch_exe.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/trace_instr.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/trace_instr.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/vc142.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/vc142.idb -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Debug/vc142.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Debug/vc142.pdb -------------------------------------------------------------------------------- /ddr_client/ddr_stable/DynRio_debug_x32_PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | C:\tools\dev\git\dynamorioX32_dbg\build\ext\include;C:\tools\dev\git\dynamorioX32_dbg\build\include;%(AdditionalIncludeDirectories) 9 | true 10 | 11 | WINDOWS;X86_32;WIN32;_DEBUG;DDRSTABLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 12 | false 13 | Level3 14 | true 15 | true 16 | MultiThreadedDebug 17 | 18 | 19 | C:\tools\dev\git\dynamorioX32_dbg\build\lib32\debug;C:\tools\dev\git\dynamorioX32_dbg\build\lib32;C:\tools\dev\git\dynamorioX32_dbg\build\ext\lib32\debug;C:\tools\dev\git\dynamorioX32_dbg\build\lib32\debug;%(AdditionalLibraryDirectories) 20 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dynamorio.lib;drmgr.lib;drreg.lib;drx.lib;drsyms.lib;drcontainers.lib;ntdll_imports.lib;drwrap.lib;%(AdditionalDependencies) 21 | DebugFull 22 | false 23 | false 24 | Windows 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/DynRio_debug_x64_PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | C:\tools\dev\git\dynamorioX64_dbg\build\ext\include;C:\tools\dev\git\dynamorioX64_dbg\build\include;%(AdditionalIncludeDirectories) 9 | 10 | 11 | 12 | 13 | true 14 | 15 | 16 | 17 | 18 | WINDOWS;X86_64;_WINDLL;X86_64;_DEBUG;DDRSTABLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 19 | 20 | 21 | 22 | 23 | false 24 | 25 | 26 | 27 | 28 | true 29 | 30 | 31 | 32 | 33 | true 34 | Level3 35 | 36 | MultiThreadedDebug 37 | 38 | 39 | C:\tools\dev\git\dynamorioX64_dbg\build\lib64\debug;C:\tools\dev\git\dynamorioX64_dbg\build\lib64;C:\tools\dev\git\dynamorioX64_dbg\build\ext\lib64\debug;C:\tools\dev\git\dynamorioX64_dbg\build\lib64\debug;%(AdditionalLibraryDirectories) 40 | 41 | 42 | dynamorio.lib;drmgr.lib;drreg.lib;drx.lib;drsyms.lib;drcontainers.lib;ntdll_imports.lib;drwrap.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 43 | 44 | 45 | false 46 | 47 | 48 | DebugFull 49 | 50 | 51 | Windows 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/DynRio_release_x64_PropertySheet.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | C:\tools\dev\git\dynamorioX64\build\ext\include;C:\tools\dev\git\dynamorioX64\build\include;%(AdditionalIncludeDirectories) 9 | Level3 10 | true 11 | WINDOWS;X86_64;%(PreprocessorDefinitions) 12 | MultiThreaded 13 | false 14 | true 15 | 16 | 17 | C:\tools\dev\git\dynamorioX64\build\lib64;C:\tools\dev\git\dynamorioX64\build\ext\lib64\release;C:\tools\dev\git\dynamorioX64\build\lib64\release;%(AdditionalLibraryDirectories) 18 | 19 | 20 | dynamorio.lib;drmgr.lib;drreg.lib;drx.lib;drsyms.lib;drcontainers.lib;ntdll_imports.lib;drwrap.lib;%(AdditionalDependencies) 21 | 22 | 23 | true 24 | 25 | 26 | true 27 | 28 | 29 | /FORCE:MULTIPLE %(AdditionalOptions) 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/DynRio_release_x86_PropertySheet.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | C:\tools\dev\git\dynamorioX32\build\lib32;C:\tools\dev\git\dynamorioX32\build\ext\lib32\release;C:\tools\dev\git\dynamorioX32\build\lib32\release;%(AdditionalLibraryDirectories) 9 | dynamorio.lib;drmgr.lib;drreg.lib;drx.lib;drsyms.lib;drcontainers.lib;ntdll_imports.lib;drwrap.lib; 10 | true 11 | true 12 | 13 | 14 | C:\tools\dev\git\dynamorioX32\build\ext\include;C:\tools\dev\git\dynamorioX32\build\include;%(AdditionalIncludeDirectories) 15 | 16 | 17 | Level3 18 | 19 | 20 | true 21 | 22 | 23 | WINDOWS;X86_32;%(PreprocessorDefinitions) 24 | 25 | 26 | MultiThreaded 27 | 28 | 29 | false 30 | 31 | 32 | true 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_helper_functions.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_helper_functions.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.Build.CppClean.log: -------------------------------------------------------------------------------- 1 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\vc142.pdb 2 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\trace_instr.obj 3 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\patch_exe.obj 4 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\main.obj 5 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\dump_buffer1.obj 6 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_helper_functions.obj 7 | c:\tools\dev\git\dyndataresolver\ddr_client\release\ddr_stable.lib 8 | c:\tools\dev\git\dyndataresolver\ddr_client\release\ddr_stable.exp 9 | c:\tools\dev\git\dyndataresolver\ddr_client\release\ddr_stable.ipdb 10 | c:\tools\dev\git\dyndataresolver\ddr_client\release\ddr_stable.iobj 11 | c:\tools\dev\git\dyndataresolver\ddr_client\release\ddr_stable.dll 12 | c:\tools\dev\git\dyndataresolver\ddr_client\release\ddr_stable.pdb 13 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_stable.tlog\cl.command.1.tlog 14 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_stable.tlog\cl.read.1.tlog 15 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_stable.tlog\cl.write.1.tlog 16 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_stable.tlog\ddr_stable.write.1u.tlog 17 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_stable.tlog\link.command.1.tlog 18 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_stable.tlog\link.read.1.tlog 19 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\release\ddr_stable.tlog\link.write.1.tlog 20 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.dll.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | C:\tools\dev\git\DynDataResolver\ddr_client\Release\ddr_stable.dll 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.log: -------------------------------------------------------------------------------- 1 |  ddr_helper_functions.c 2 | dump_buffer1.c 3 | main.c 4 | patch_exe.c 5 | trace_instr.c 6 | Creating library C:\tools\dev\git\DynDataResolver\ddr_client\Release\ddr_stable.lib and object C:\tools\dev\git\DynDataResolver\ddr_client\Release\ddr_stable.exp 7 | Generating code 8 | 11 of 56 functions (19.6%) were compiled, the rest were copied from previous compilation. 9 | 3 functions were new in current compilation 10 | 2 functions had inline decision re-evaluated but remain unchanged 11 | Finished generating code 12 | ddr_stable.vcxproj -> C:\tools\dev\git\DynDataResolver\ddr_client\Release\ddr_stable.dll 13 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/ddr_stable.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.18362.0: 2 | Release|Win32|C:\tools\dev\git\DynDataResolver\ddr_client\| 3 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/ddr_stable.write.1u.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.tlog/ddr_stable.write.1u.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/link.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.tlog/link.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/link.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.tlog/link.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.tlog/link.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.tlog/link.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/ddr_stable.vcxproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/ddr_stable.vcxproj.FileListAbsolute.txt -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/dump_buffer1.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/dump_buffer1.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/main.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/main.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/patch_exe.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/patch_exe.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/trace_instr.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/trace_instr.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/Release/vc142.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/Release/vc142.pdb -------------------------------------------------------------------------------- /ddr_client/ddr_stable/ddr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "dr_api.h" 3 | #include "drmgr.h" 4 | //#include "utils.h" 5 | #include "drreg.h" 6 | #include "drx.h" 7 | #include "drwrap.h" 8 | #include "dr_tools.h" 9 | #include "dr_ir_opnd.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // --- Defines --- 21 | #define DDR_VERSION "1.02 beta" 22 | 23 | #define CmdOpt_NormalTrace 1 24 | #define CmdOpt_DumpBuffer 2 25 | #define CmdOpt_Patch_EFLAG 4 26 | #define CmdOpt_Patch_NOP 8 27 | #define CmdOpt_Patch_CALL 16 28 | #define CmdOpt_Patch_Loop 32 29 | 30 | #ifdef X86_64 31 | #define PATCH_ADDR_SIZE 16 32 | #else 33 | #define PATCH_ADDR_SIZE 8 34 | #endif 35 | 36 | #define MAX_DUMP_FILENAME 256 37 | #define MAX_TRACE_FILENAME 256 38 | #define MAX_OP_PARA_LEN 3 39 | #define MAX_FILE_LINE_LEN 356 40 | #define MAX_CFG_LINE 350 41 | #define MAX_PROCESSES 255 42 | #define MAX_PROCESSNAME 255 43 | #define MAX_SEC_TO_WAIT_FOR_PROCS 20 44 | 45 | #define CF 5862190 46 | #define PF 5862619 47 | #define AF 5862124 48 | #define ZF 5862949 49 | #define SF 5862718 50 | #define DF 5862223 51 | #define OF 5862586 52 | #define FILENAME_OPT 2089071269 53 | 54 | #define MAX_INSTR_COUNT 100000 // max. number of instructions to trace 55 | #define MAX_NUM_DSTS_OP 9 // BUG workaround - TBD Fixed, will remove this after some final checks (popa = 8 DST_OP) 56 | #define MAX_NUM_SRCS_OP 9 // BUG workaround - TBD Fixed, will remove this after some final checks (pusha = 8 DST_OP) 57 | 58 | #ifdef _DEBUG 59 | #define debug_print(fmt, ...) \ 60 | do { dr_printf("[DDR] [DEBUG] %s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0) 61 | #else 62 | #define debug_print(...) 63 | #endif 64 | 65 | 66 | // --- Typedefs --- 67 | typedef struct p_eflag_para { 68 | unsigned char* patch_eflag_flag_str; 69 | reg_t patch_eflag_flag; 70 | size_t patch_eflag_PC; 71 | struct p_eflag_para* nextpe; 72 | } P_EFLAG_PARA; 73 | 74 | typedef struct p_nop_para { 75 | size_t patch_nop_start_PC; 76 | size_t patch_nop_end_PC; 77 | struct p_nop_para* nextpa; 78 | } P_NOP_PARA; 79 | 80 | typedef struct p_call_para { 81 | size_t patch_call_func_PC; 82 | size_t patch_call_ret; 83 | struct p_call_para* nextcp; 84 | } P_CALL_PARA; 85 | 86 | typedef struct s_dump_para { 87 | size_t bufferPC; 88 | char* bufferOp; 89 | int bufferOpnum; 90 | char bufferOptype; 91 | char bufferOptypePtrType; 92 | 93 | size_t sizePC; 94 | char* sizeOp; 95 | int sizeOpnum; 96 | char sizeOptype; 97 | char sizeOptypePtrType; 98 | 99 | size_t dumpPC; 100 | char* filename; 101 | struct s_dump_para* nextdp; 102 | } S_DUMP_PARA; 103 | 104 | typedef struct s_trace_para { 105 | size_t start; 106 | size_t end; 107 | size_t max_instr; 108 | bool light_trace_only; 109 | char* filename; 110 | file_t fpTracefile; 111 | struct s_trace_para* nexttr; 112 | } S_TRACE_PARA; 113 | 114 | typedef struct s_pListThreads { 115 | struct s_pListThreads* prevproc; 116 | process_id_t start_process_id; 117 | process_id_t process_id; 118 | thread_id_t threat_id; 119 | struct s_pListThreads* nextproc; 120 | } S_PROCS; 121 | 122 | 123 | // --- Functions prototypes --- 124 | 125 | // main 126 | DR_EXPORT void dr_client_main(client_id_t id, int argc, const char* argv[]); 127 | int parse_cmd_opt(); 128 | void event_exit(void); 129 | bool parse_loop_line(char* line, unsigned int linenr); 130 | bool parse_startaddr_line(char* line, unsigned int linenr); 131 | bool parse_breakaddr_line(char* line, unsigned int linenr); 132 | bool parse_cfgfile(char* filename); 133 | bool parse_patch_flag_line(char* line); 134 | bool parse_patch_nop_line(char* line); 135 | bool parse_patch_call_line(char* line); 136 | bool parse_dump_buffer_line(char* line, unsigned int linenr); 137 | bool parse_trace_line(char* line, unsigned int linenr); 138 | 139 | // ddr_helper_functions 140 | void usage(); 141 | bool CheckFileExists(const CHAR* fileName); 142 | char* getSubstr(char* str, char* p1, char* p2); 143 | char* escape_filename(char* filename); 144 | int escape_dir_str(char* dirStr); 145 | bool getOEPfromPEfile(char* pefile, app_pc* oep); 146 | void __cdecl print_disasm(void* drcontext, app_pc instr_addr, size_t instr_addr_fixed); 147 | unsigned long djb2_hash(unsigned char* str); 148 | unsigned char* strtoupper(unsigned char* t); 149 | void check_strlen(char* str, size_t maxlen, char* failmsg, unsigned int linenr); 150 | bool fix_comma_in_jsonfile(char* fname); 151 | app_pc my_opnd_compute_address(opnd_t opnd, dr_mcontext_t* mc); 152 | bool my_opnd_is_reg(opnd_t opnd); 153 | int IncProcCounter(); 154 | int DecProcCounter(); 155 | int GetProcCounter(); 156 | process_id_t* getSharedProcessIDs(process_id_t* pProcessids); 157 | char* getSharedProcessNames(char* pProcessnames); 158 | char* getLogFilePath(char* fullpath, char* dir); 159 | char* getSharedLogpath(char* pLogpath); 160 | 161 | // trace_instr 162 | void event_module_load_trace_instr(void* drcontext, const module_data_t* info, bool loaded); 163 | void event_thread_init_trace_instr(void* drcontext); 164 | void event_thread_exit_trace_instr(void* drcontext); 165 | //void __cdecl process_instr_trace_instr(app_pc instr_addr); 166 | void __cdecl process_instr_trace_instr_new(app_pc instr_addr, S_TRACE_PARA* tr); 167 | static void iterate_exports_trace_instr(const module_data_t* info); 168 | static bool lib_is_not_blacklisted_trace_instr(const module_data_t* info); 169 | static unsigned char* get_byte_string_trace_instr(unsigned char* bytesbuf, size_t bytesread, size_t* resultstr_size); 170 | static void log_bytestream_trace_instr(file_t f, unsigned char* bytesbuf, size_t bytesread, app_pc memaddr, uint instr_mem_size); 171 | static bool write_mem_data_trace_instr(file_t f, size_t numbytes, app_pc memaddr, char* json_field_str); 172 | static bool write_mem_to_file_trace_instr(file_t f, ssize_t numbytes, app_pc memaddr); 173 | static void write_src_op_to_logfile_trace_instr(file_t f, instr_t* instr, app_pc memaddr_src0, size_t bytesread, size_t numbytes); 174 | static void log_instr_opnds_trace_instr(file_t f, instr_t* instr, dr_mcontext_t* mc, void* drcontext, size_t numbytes); 175 | static void log_mem_at_reg_trace_instr(app_pc memaddr, char* regstr, file_t f); 176 | static void handler_instr_is_return(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes); 177 | static void handler_instr_is_call(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes); 178 | static void handler_instr_is_pop(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes); 179 | static void handler_instr_interesting_instr(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes); 180 | static void handler_all_other_mem_instr(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes); 181 | 182 | // dump_buffer 183 | void my_call_pre_wrapper(void* wrapcxt, OUT void** user_data); 184 | void event_thread_init_global(void* drcontext); 185 | int __cdecl get_mem_addr_dump_buffer(void* drcontext, reg_t* memaddr, char Optype, char OptypePtrType, int Opnum, app_pc instr_addr, dr_mcontext_t mc); 186 | int __cdecl get_op_size_dump_buffer(void* drcontext, reg_t* memaddr, char Optype, char OptypePtrType, int Opnum, app_pc instr_addr, dr_mcontext_t mc); 187 | dr_emit_flags_t event_bb_instr_global(void* drcontext, void* tag, instrlist_t* bb, instr_t* instr, bool for_trace, bool translating, void* user_data); 188 | void __cdecl process_instr_size_dump_buffer(app_pc instr_addr, S_DUMP_PARA* dp); 189 | void __cdecl process_instr_addr_dump_buffer(app_pc instr_addr, S_DUMP_PARA* dp); 190 | void __cdecl process_instr_dump_buffer(app_pc instr_addr, S_DUMP_PARA* dp); 191 | 192 | // patch_exe 193 | void __cdecl patch_eflag(app_pc instr_addr, P_EFLAG_PARA* pp); 194 | void __cdecl patch_sleep(app_pc instr_addr); 195 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/ddr_config.txt: -------------------------------------------------------------------------------- 1 | # --- DDR sample config file --- 2 | # 3 | # Lines should not be more than 80 characters long 4 | # 3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 5 | # 6 | # Comments must be written with a leading '#' 7 | # No extra spaces are allowed in config lines 8 | # Different fields are separated by exactly one blank 9 | # 10 | # All number/address values are expected to be hexadecimal values without any 11 | # leading character. 12 | # ----------------------------------------------------------------------------- 13 | 14 | # -- NOP out instructions -- 15 | # N 16 | # = Start program counter address for NOP'ing instructions (hex) 17 | # = End program counter address for NOP'ing instructions (hex) 18 | # and can be the same for NOP'ing one instr. 19 | # e.g. N 004012EE 004012F6 20 | #N 0040115A 0040115A 21 | #N 00401337 0040133A 22 | 23 | # -- Patch EFLAG -- 24 | # T 25 | # = [CF, PF, AF, ZF, SF, DF, OF] 26 | # = program counter address (hex) where to toggle the EFLAG before 27 | # instruction gets executed e.g. jle 28 | # e.g. T SF 004012C4 #example comment 29 | #T SF 004012BB 30 | #T SF 004012FB #example comment 31 | 32 | # -- Always skip function at when called -- 33 | # = Functions address which gets wrapped, call to func is skipped 34 | # = set return value of wrapped function (NEED TO BE UNSINGED INT) 35 | # C 36 | # e.g. C 00401100 00000001 37 | C 00401120 FFFFFFFF # = -1 38 | C 00401150 FF 39 | 40 | # -- Dump buffer to file --: 41 | # D 42 | # = program counter address where to get the size of the buffer 43 | # = operant at to get the buffer size from 44 | # e.g. SP0 = (S)ource operant 0. Value is a (P)ointer. 45 | # DV1 = (D)estination operant 1. Absolut (V)alue. 46 | # = program counter address where to get the buffer address 47 | # = operant at PC to get the buffer size from 48 | # = program counter address where to finally dump the buffer 49 | # = dump filename 50 | # 51 | # All numbers/addresses are hexdecimal values without any leading character 52 | # 53 | # e.g. D 0040117E SP0 0040118B SP0 004011F9 dump1.bin 54 | #D 004011B5 SP0 004011C2 SP0 00401230 dump1.bin 55 | #D 004013A2 SP0 004013AF SP0 0040141D dump2.bin 56 | # 57 | # -- Run Trace --: 58 | # start end max.instr breakaddr lighttrace filename (the last in the list will be used) 59 | L 4012BE 40130F 20000 na TRUE "C:\Users\Dex Dexter\Documents\test\test\buffertest_trace.json" 60 | L 401335 4013CA 20000 na TRUE "C:\Users\Dex Dexter\Documents\test\test\buffertest_trace.json" 61 | L 401411 40146E 20000 na TRUE "C:\Users\Dex Dexter\Documents\test\test\buffertest_trace.json" 62 | 63 | # -- Patch binary with endless Loop at address --: 64 | # loop-addr 65 | B 40170C 66 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/ddr_config64.txt: -------------------------------------------------------------------------------- 1 | # --- DDR sample config file --- 2 | # 3 | # Lines should not be more than 80 characters long 4 | # 3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 5 | # 6 | # Comments must be written with a leading '#' 7 | # No extra spaces are allowed in config lines 8 | # Different fields are separated by exactly one blank 9 | 10 | All number/address values are expected to be hexadecimal values without any 11 | leading character. 12 | # ----------------------------------------------------------------------------- 13 | 14 | # -- NOP out instructions -- 15 | # N 16 | # = Start program counter address for NOP'ing instructions (hex) 17 | # = End program counter address for NOP'ing instructions (hex) 18 | # and can be the same for NOP'ing one instr. 19 | # e.g. N 004012EE 004012F6 20 | N 000000014000121C 000000014000121C 21 | N 000000014000145A 000000014000145A 22 | 23 | # -- Patch EFLAG -- 24 | # T 25 | # = [CF, PF, AF, ZF, SF, DF, OF] 26 | # = program counter address where to toggle the EFLAG before 27 | # instruction gets executed e.g. jle (hex) 28 | # e.g. T SF 004012C4 #example comment 29 | T SF 00000001400013A7 30 | T SF 00000001400013E5 #example comment 31 | 32 | # -- Always skip function at when called -- 33 | # = Functions address which gets wrapped, call to func is skipped 34 | # = set return value of wrapped function (NEED TO BE UNSINGED INT) 35 | # C 36 | # e.g. C 00401100 00000001 37 | C 00000001400011E0 0 38 | C 0000000140001210 FFFFFFFFFFFFFFFF # -1 39 | 40 | # -- Dump buffer to file --: 41 | # D 42 | # = program counter address where to get the size of the buffer 43 | # = operant at to get the buffer size from 44 | # e.g. SP0 = (S)ource operant 0. Value is a (P)ointer. 45 | # DV1 = (D)estination operant 1. Absolut (V)alue. 46 | # = program counter address where to get the buffer address 47 | # = operant at PC to get the buffer size from 48 | # = program counter address where to finally dump the buffer 49 | # = dump filename 50 | # e.g. D 0040117E SP0 0040118B SP0 004011F9 dump1.bin 51 | D 0000000140001280 SP0 000000014000128D SP0 000000014000132B dump_x64_1.bin 52 | D 0000000140001494 SP0 00000001400014A1 SP0 000000014000153F dump_x64_2.bin 53 | # 54 | # -- Run Trace --: 55 | # start end max.instr breakaddr lighttrace filename (the last in the list will be used) 56 | L 140001000 140003000 20000 na FALSE trace_tmp_CBEFF9E003C9FA8D8C568CFB85A885AF.json 57 | # 58 | # -- Patch binary with endless Loop at address --: 59 | # loop-addr 60 | B 0000000140001280 -------------------------------------------------------------------------------- /ddr_client/ddr_stable/ddr_helper_functions.c: -------------------------------------------------------------------------------- 1 | #include "ddr.h" 2 | #include "globals.h" 3 | 4 | void usage() 5 | { 6 | // -no_follow_children drrun does not follow into any child processes 7 | dr_printf("\n"); 8 | dr_printf("Usage:\n"); 9 | dr_printf("drrun.exe -c -c -- \n"); 10 | #ifdef _DEBUG 11 | dr_printf("-d Set verbose level for debugging. (0-5)\n"); 12 | #endif 13 | dr_printf("-c Set Dump and patching configuration in \n"); 14 | dr_printf(" See sample \"ddr_config.cfg\" for details\n"); 15 | dr_printf(" Sample PE file to analyse\n\n"); 16 | dr_printf("Examples:\n"); 17 | dr_printf("C:\\DYNRIO_DIR\\bin64\\drrun.exe -c \"C:\\ddr\\ddr64.dll\" -c my_x32_config.cfg -- \"C:\\tools\\ddr\\samples\\buffertest.exe\"\n"); 18 | dr_printf("C:\\DYNRIO_DIR\\bin32\\drrun.exe -c \"C:\\ddr\\ddr32.dll\" -c my_x64_config.cfg -- \"C:\\tools\\ddr\\samples\\buffertest.exe\"\n\n"); 19 | } 20 | 21 | bool CheckFileExists(const CHAR* fileName) 22 | { 23 | DWORD fileAttr; 24 | 25 | fileAttr = GetFileAttributesA(fileName); 26 | if (0xFFFFFFFF == fileAttr) 27 | return false; 28 | return true; 29 | } 30 | 31 | // Get string between substring p1 and p2 32 | char* getSubstr(char* str, char* p1, char* p2) 33 | { 34 | char* ret; 35 | char* stmp1 = strstr(str, p1); 36 | char* stmp2; 37 | 38 | if (stmp1 != NULL) 39 | { 40 | size_t slen = strlen(p1); 41 | stmp2 = strstr(stmp1 + slen, p2); 42 | if (p2 != NULL) 43 | { 44 | size_t mlen = stmp2 - stmp1; 45 | if (mlen > 1) { 46 | ret = dr_global_alloc(mlen); 47 | if (ret != NULL) 48 | { 49 | memcpy(ret, stmp1 + 1, mlen - 1); 50 | ret[mlen - 1] = '\0'; 51 | return ret; 52 | } 53 | } 54 | } 55 | } 56 | return NULL; 57 | } 58 | 59 | char* escape_filename(char* filename) { 60 | // --- TBD --- 61 | return filename; 62 | } 63 | 64 | int escape_dir_str(char* dirStr) 65 | { 66 | int count; 67 | size_t SearchStrLen; 68 | size_t ReplaceStrLen; 69 | char* sp; 70 | const char* search = "\\"; 71 | const char* replace = "\\\\"; 72 | 73 | if ((sp = strstr(dirStr, search)) == NULL) { 74 | return(0); 75 | } 76 | count = 1; 77 | SearchStrLen = strlen(search); 78 | ReplaceStrLen = strlen(replace); 79 | if (SearchStrLen > ReplaceStrLen) { 80 | char* src = sp + SearchStrLen; 81 | char* dst = sp + ReplaceStrLen; 82 | while ((*dst = *src) != '\0') { dst++; src++; } 83 | } 84 | else if (SearchStrLen < ReplaceStrLen) { 85 | size_t tmpLen = strlen(sp) - SearchStrLen; 86 | char* stop = sp + ReplaceStrLen; 87 | char* src = sp + SearchStrLen + tmpLen; 88 | char* dst = sp + ReplaceStrLen + tmpLen; 89 | while (dst >= stop) { *dst = *src; dst--; src--; } 90 | } 91 | memcpy(sp, replace, ReplaceStrLen); 92 | 93 | //interate through string 94 | count += escape_dir_str(sp + ReplaceStrLen); 95 | 96 | return(count); 97 | } 98 | 99 | bool getOEPfromPEfile(char* pefile, app_pc* oep) { 100 | 101 | FILE* fp; 102 | errno_t err; 103 | err = fopen_s(&fp, pefile, "rb"); 104 | if (err != 0) { 105 | dr_printf("[DDR] [ERROR] Failed opening PE file\n", pefile); 106 | return FALSE; 107 | } 108 | if (fp != NULL) { 109 | fseek(fp, 0, SEEK_SET); 110 | } 111 | else { 112 | dr_printf("[DDR] [ERROR] Failed opening PE file. File pointer invalid.\n", pefile); 113 | return FALSE; 114 | } 115 | 116 | IMAGE_DOS_HEADER imgDosHdr; 117 | fread(&imgDosHdr, sizeof(IMAGE_DOS_HEADER), 1, fp); 118 | 119 | fseek(fp, imgDosHdr.e_lfanew, SEEK_SET); 120 | IMAGE_NT_HEADERS imgNtHdr; 121 | fread(&imgNtHdr, sizeof(IMAGE_NT_HEADERS), 1, fp); 122 | 123 | *oep = (app_pc)(imgNtHdr.OptionalHeader.ImageBase + imgNtHdr.OptionalHeader.AddressOfEntryPoint); 124 | 125 | fclose(fp); 126 | return TRUE; 127 | } 128 | 129 | void __cdecl print_disasm(void* drcontext, app_pc instr_addr, size_t instr_addr_fixed) { 130 | byte* pc; 131 | instr_t instr; 132 | instr_init(drcontext, &instr); 133 | instr_reset(drcontext, &instr); 134 | pc = decode(drcontext, instr_addr, &instr); // fill in instr 135 | 136 | size_t disasm_buf_size = 254; 137 | unsigned char* disasm_buf = (unsigned char*)dr_global_alloc(sizeof(unsigned char) * disasm_buf_size); 138 | instr_disassemble_to_buffer(dr_get_current_drcontext(), &instr, disasm_buf, disasm_buf_size); 139 | dr_printf("[DDR] [INFO] Disasm(PC 0x%x): %s\n", instr_addr_fixed, disasm_buf); 140 | dr_global_free(disasm_buf, sizeof(unsigned char) * disasm_buf_size); 141 | instr_free(drcontext, &instr); 142 | } 143 | 144 | unsigned long djb2_hash(unsigned char* str) { 145 | unsigned long hash = 5381; 146 | int c; 147 | 148 | while (c = *str++) 149 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 150 | 151 | return hash; 152 | } 153 | 154 | unsigned char* strtoupper(unsigned char* s) { 155 | char* t = s; 156 | while (*s) { 157 | *s = toupper(*s); 158 | s++; 159 | } 160 | return t; 161 | } 162 | 163 | void check_strlen(char* str, size_t maxlen, char* failmsg, unsigned int linenr) { 164 | if (strlen(str) > maxlen) { 165 | dr_printf("[DDR] [ERROR] %s. Max. length is %d for this field in Line %d.\n", failmsg, maxlen, linenr); 166 | usage(); 167 | dr_exit_process(1); 168 | } 169 | } 170 | 171 | bool fix_comma_in_jsonfile(char *fname) { 172 | // Checking for a wrong set comma at the end of the last block in the JSON file 173 | file_t f; 174 | bool ret = false; 175 | uint64 fsize = 0; 176 | char* buf; 177 | size_t buf_len; 178 | ssize_t i; 179 | bool c_bracket = false; 180 | bool s_bracket = false; 181 | bool next_c_bracket = false; 182 | 183 | dr_printf("[DDR] [INFO] Fixing file: %s\n", fname); 184 | 185 | f = dr_open_file(fname, DR_FILE_READ); 186 | if (f == INVALID_FILE) { 187 | dr_printf("[DDR] [ERROR] Can't open instruction log file for reading.\n"); 188 | dr_printf("[DDR] [ERROR] Filename: '%s'\n", fname); 189 | dr_exit_process(1); 190 | } 191 | 192 | dr_file_size(f, &fsize); 193 | if (fsize > UINT_MAX) { 194 | dr_printf("[DDR] [WARNING] Can't cleanup JSON file. File is too big. Filesize is %.0lf\n", fsize); 195 | } 196 | else { 197 | buf_len = (size_t)fsize; 198 | buf = dr_global_alloc(sizeof(char) * buf_len); 199 | ssize_t n = dr_read_file(f, buf, buf_len); 200 | dr_close_file(f); 201 | 202 | for (i = n; i > n - 12; i--) { 203 | if (buf[i] == '}') { 204 | c_bracket = true; 205 | } 206 | if (buf[i] == ']' && c_bracket) { 207 | s_bracket = true; 208 | } 209 | if (buf[i] == ',' && s_bracket) { 210 | buf[i] = ' '; 211 | dr_printf("[DDR] [INFO] Fixed comma at the end of JSON file.\n"); 212 | break; 213 | } 214 | if (buf[i] == '}' && s_bracket) { 215 | dr_printf("[DDR] [INFO] JSON file is ok, no comma at the end found.\n"); 216 | break; 217 | } 218 | } 219 | dr_printf("[DDR] [INFO] Opening file: %s for writing\n", fname); 220 | f = dr_open_file(fname, DR_FILE_WRITE_OVERWRITE); 221 | if (f == INVALID_FILE) { 222 | dr_printf("[DDR] [ERROR] Can't open file for writing.\n"); 223 | dr_printf("[DDR] [ERROR] Filename: '%s'\n", fname); 224 | dr_exit_process(1); 225 | } 226 | dr_printf("[DDR] [INFO] Writing fixed buffer to file: %s\n", fname); 227 | n = dr_write_file(f, buf, buf_len); 228 | if (buf_len != n) { 229 | dr_printf("[DDR] [WARNING] Org. JSON file (%d) and fixed JSON file (%d) have a different length. \n", buf_len, n); 230 | } 231 | else { 232 | ret = true; 233 | } 234 | 235 | dr_close_file(f); 236 | dr_printf("[DDR] [INFO] Done. Final logfile %s written. Length: %d bytes.\n", fname, n); 237 | 238 | dr_global_free(buf, sizeof(char) * buf_len); 239 | } 240 | 241 | return ret; 242 | } 243 | 244 | app_pc my_opnd_compute_address(opnd_t opnd, dr_mcontext_t* mc) { 245 | // Wrapper to opnd_compute_address that verifies that opnd is a memory reference 246 | app_pc pc; 247 | 248 | if (opnd_is_memory_reference(opnd)) { 249 | pc = opnd_compute_address(opnd, mc); 250 | } 251 | else { 252 | pc = 0; 253 | } 254 | 255 | return pc; 256 | } 257 | 258 | bool my_opnd_is_reg(opnd_t opnd) { 259 | // Wrapper to opnd_is_reg that verifies the operant is a register 260 | 261 | reg_id_t reg = 0; 262 | void* drcontext; 263 | 264 | if (opnd_is_reg(opnd)) { 265 | if (reg = opnd_get_reg(opnd)) { 266 | drcontext = dr_get_current_drcontext(); 267 | dr_mcontext_t mc = { sizeof(mc),DR_MC_ALL }; 268 | dr_get_mcontext(drcontext, &mc); 269 | if (reg_is_xmm(reg)) { 270 | #ifdef _DEBUG 271 | dr_printf("[DDR] [DEBUG] Operant is XMM Register this is not supported in the moment\n"); 272 | #endif 273 | return FALSE; 274 | } 275 | } 276 | return TRUE; 277 | } 278 | return FALSE; 279 | } 280 | 281 | int IncProcCounter() { 282 | // Initalize or increase process counter and return number of running processes launched by the sample 283 | 284 | HANDLE hMapFile; 285 | int Counter; 286 | int* pCounter = &Counter; 287 | 288 | hMapFile = OpenFileMapping( 289 | FILE_MAP_ALL_ACCESS, // read/write access 290 | FALSE, // do not inherit the name 291 | szName); // name of mapping object 292 | 293 | if (hMapFile == NULL) { 294 | debug_print("First instance.\n"); 295 | 296 | Counter = 1; 297 | 298 | hMapFile = CreateFileMapping( 299 | INVALID_HANDLE_VALUE, // use paging file 300 | NULL, // default security 301 | PAGE_READWRITE, // read/write access 302 | 0, // maximum object size (high-order DWORD) 303 | sizeof(unsigned int), // maximum object size (low-order DWORD) 304 | szName); // name of mapping object 305 | 306 | if (hMapFile == NULL) { 307 | dr_printf("[DDR] [ERROR] [%s:%d] Could not create file mapping object (%d).\n", GetLastError(), __FILE__, __LINE__); 308 | return -1; 309 | } 310 | pCounter = (unsigned int*)MapViewOfFile(hMapFile, // handle to map object 311 | FILE_MAP_ALL_ACCESS, // read/write permission 312 | 0, 313 | 0, 314 | sizeof(unsigned int)); 315 | 316 | if (pCounter == NULL) { 317 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 318 | CloseHandle(hMapFile); 319 | return -1; 320 | } 321 | 322 | CopyMemory((PVOID)pCounter, &Counter, sizeof(unsigned int)); 323 | 324 | debug_print("process counter = %u.\n", Counter); 325 | 326 | //UnmapViewOfFile(pBuf); TBD: unmap file after last process. 327 | //CloseHandle(hMapFile); 328 | 329 | return Counter; 330 | } 331 | else { 332 | debug_print("Not the first process.\n"); 333 | 334 | pCounter = (unsigned int*)MapViewOfFile(hMapFile, 335 | FILE_MAP_ALL_ACCESS, 336 | 0, 337 | 0, 338 | sizeof(unsigned int)); 339 | 340 | if (pCounter == NULL) { 341 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n",GetLastError(), __FILE__, __LINE__); 342 | CloseHandle(hMapFile); 343 | return -1; 344 | } 345 | 346 | Counter = ++(*pCounter); 347 | debug_print("Increased process counter = %u.\n", Counter); 348 | 349 | return Counter; 350 | } 351 | } 352 | 353 | int DecProcCounter() { 354 | // Decrease process counter and return number of running processes launched by the sample 355 | 356 | HANDLE hMapFile; 357 | int Counter; 358 | int* pCounter = &Counter; 359 | 360 | hMapFile = OpenFileMapping( 361 | FILE_MAP_ALL_ACCESS, 362 | FALSE, 363 | szName); 364 | 365 | if (hMapFile == NULL) { 366 | dr_printf("[DDR] [ERROR] [%s:%d] Failed to open shared object.\n", __FILE__, __LINE__); 367 | return -1; 368 | } 369 | 370 | pCounter = (int*)MapViewOfFile(hMapFile, 371 | FILE_MAP_ALL_ACCESS, 372 | 0, 373 | 0, 374 | sizeof(unsigned int)); 375 | 376 | if (pCounter == NULL) { 377 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 378 | CloseHandle(hMapFile); 379 | return -1; 380 | } 381 | 382 | Counter = --(*pCounter); 383 | debug_print("Decreased process counter = %u.\n", Counter); 384 | 385 | return Counter; 386 | } 387 | 388 | int GetProcCounter() { 389 | // Return number of launched processes by the sample 390 | 391 | HANDLE hMapFile; 392 | int Counter; 393 | int* pCounter = &Counter; 394 | 395 | hMapFile = OpenFileMapping( 396 | FILE_MAP_ALL_ACCESS, 397 | FALSE, 398 | szName); 399 | 400 | if (hMapFile == NULL) { 401 | dr_printf("[DDR] [ERROR] [%s:%d] Failed to open shared object.\n", __FILE__, __LINE__); 402 | return -1; 403 | } 404 | 405 | pCounter = (int*)MapViewOfFile(hMapFile, 406 | FILE_MAP_ALL_ACCESS, 407 | 0, 408 | 0, 409 | sizeof(unsigned int)); 410 | 411 | if (pCounter == NULL) { 412 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 413 | CloseHandle(hMapFile); 414 | return -1; 415 | } 416 | 417 | Counter = *pCounter; 418 | debug_print("process counter = %u.\n", Counter); 419 | 420 | return Counter; 421 | } 422 | 423 | process_id_t* getSharedProcessIDs(process_id_t* pProcessids) { 424 | // Return shared object pointing to Process IDs (pProcessids) 425 | 426 | HANDLE hMapFile; 427 | 428 | hMapFile = OpenFileMapping( 429 | FILE_MAP_ALL_ACCESS, 430 | FALSE, 431 | szProcIDs); 432 | 433 | if (hMapFile == NULL) { 434 | debug_print("Creating ProcessIDs shared memory.\n"); 435 | 436 | hMapFile = CreateFileMapping( 437 | INVALID_HANDLE_VALUE, 438 | NULL, 439 | PAGE_READWRITE, 440 | 0, 441 | MAX_PROCESSES * sizeof(process_id_t), 442 | szProcIDs); 443 | 444 | if (hMapFile == NULL) { 445 | dr_printf("[DDR] [ERROR] [%s:%d] Could not create file mapping object (%d).\n", GetLastError(), __FILE__, __LINE__); 446 | return NULL; 447 | } 448 | pProcessids = (process_id_t*)MapViewOfFile(hMapFile, 449 | FILE_MAP_ALL_ACCESS, 450 | 0, 451 | 0, 452 | MAX_PROCESSES * sizeof(process_id_t)); 453 | 454 | if (pProcessids == NULL) { 455 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 456 | CloseHandle(hMapFile); 457 | return NULL; 458 | } 459 | return pProcessids; 460 | } 461 | else { 462 | debug_print("Not the first process.\n"); 463 | 464 | pProcessids = (process_id_t*)MapViewOfFile(hMapFile, 465 | FILE_MAP_ALL_ACCESS, 466 | 0, 467 | 0, 468 | MAX_PROCESSES * sizeof(process_id_t)); 469 | 470 | if (pProcessids == NULL) { 471 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 472 | CloseHandle(hMapFile); 473 | return NULL; 474 | } 475 | return pProcessids; 476 | } 477 | } 478 | 479 | char* getSharedProcessNames(char* pProcessnames) { 480 | // Return shared object pointing to process names (pProcessnames) 481 | 482 | HANDLE hMapFile; 483 | 484 | hMapFile = OpenFileMapping( 485 | FILE_MAP_ALL_ACCESS, 486 | FALSE, 487 | szProcNames); 488 | 489 | if (hMapFile == NULL) { 490 | debug_print("Creating ProcessNames shared memory.\n"); 491 | 492 | hMapFile = CreateFileMapping( 493 | INVALID_HANDLE_VALUE, 494 | NULL, 495 | PAGE_READWRITE, 496 | 0, 497 | MAX_PROCESSES * MAX_PROCESSNAME * sizeof(char), 498 | szProcNames); 499 | 500 | if (hMapFile == NULL) { 501 | dr_printf("[DDR] [ERROR] [%s:%d] Could not create file mapping object (%d).\n", GetLastError(), __FILE__, __LINE__); 502 | return NULL; 503 | } 504 | pProcessnames = (char*)MapViewOfFile(hMapFile, 505 | FILE_MAP_ALL_ACCESS, 506 | 0, 507 | 0, 508 | MAX_PROCESSES * MAX_PROCESSNAME * sizeof(char)); 509 | 510 | if (pProcessnames == NULL) { 511 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 512 | CloseHandle(hMapFile); 513 | return NULL; 514 | } 515 | return pProcessnames; 516 | } 517 | else { 518 | debug_print("Not the first process.\n"); 519 | 520 | pProcessnames = (char*)MapViewOfFile(hMapFile, 521 | FILE_MAP_ALL_ACCESS, 522 | 0, 523 | 0, 524 | MAX_PROCESSES * MAX_PROCESSNAME * sizeof(char)); 525 | 526 | if (pProcessnames == NULL) { 527 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 528 | CloseHandle(hMapFile); 529 | return NULL; 530 | } 531 | return pProcessnames; 532 | } 533 | } 534 | 535 | char* getSharedLogpath(char* pLogpath) { 536 | // Return shared object pointing to plogpath 537 | // pLogpath will be the path from the sample file 538 | // pLogpath needs to be allocated by caller with min. MAX_PATH 539 | 540 | HANDLE hMapFile; 541 | 542 | hMapFile = OpenFileMapping( 543 | FILE_MAP_ALL_ACCESS, 544 | FALSE, 545 | szLogPath); 546 | 547 | if (hMapFile == NULL) { 548 | debug_print("Creating Logpath shared memory object.\n"); 549 | 550 | hMapFile = CreateFileMapping( 551 | INVALID_HANDLE_VALUE, 552 | NULL, 553 | PAGE_READWRITE, 554 | 0, 555 | MAX_PATH, 556 | szLogPath); 557 | 558 | if (hMapFile == NULL) { 559 | dr_printf("[DDR] [ERROR] [%s:%d] Could not create file mapping object (%d).\n", GetLastError(), __FILE__, __LINE__); 560 | return NULL; 561 | } 562 | pLogpath = (char*)MapViewOfFile(hMapFile, 563 | FILE_MAP_ALL_ACCESS, 564 | 0, 565 | 0, 566 | MAX_PATH); 567 | 568 | if (pLogpath == NULL) { 569 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 570 | CloseHandle(hMapFile); 571 | return NULL; 572 | } 573 | 574 | module_data_t *app = dr_get_main_module(); 575 | if (getLogFilePath(app->full_path, pLogpath) == NULL) { 576 | dr_printf("[DDR] [ERROR] [%s:%d] Failed to extract global logpath from log filename\n.", __FILE__, __LINE__); 577 | dr_exit_process(1); 578 | } 579 | dr_free_module_data(app); 580 | debug_print("[FIRST PROC FIRST THREAD] Using log path %s\n", pLogpath); 581 | 582 | return pLogpath; 583 | } 584 | else { 585 | debug_print("Not the first process.\n"); 586 | 587 | pLogpath = (char*)MapViewOfFile(hMapFile, 588 | FILE_MAP_ALL_ACCESS, 589 | 0, 590 | 0, 591 | MAX_PATH); 592 | 593 | if (pLogpath == NULL) { 594 | dr_printf("[DDR] [ERROR] [%s:%d] Could not map view of file (%d).\n", GetLastError(), __FILE__, __LINE__); 595 | 596 | CloseHandle(hMapFile); 597 | 598 | return NULL; 599 | } 600 | debug_print("[SUB THREAD] Using log path %s\n", pLogpath); 601 | return pLogpath; 602 | } 603 | } 604 | 605 | char* getLogFilePath(char* fullpath, char *dir) { 606 | // return path from fullpath e.g. "C:\\abc\\test.txt" -> "C:\\abc\\" 607 | // char *dir needs to allocated by caller with min. MAX_PATH 608 | 609 | errno_t e; 610 | char driveletter[3]; 611 | char dirpart[MAX_PATH]; 612 | 613 | e = _splitpath_s(fullpath, driveletter, 3, dirpart, MAX_PATH, NULL, 0, NULL, 0); 614 | 615 | if (e == 0) { 616 | CopyMemory((PVOID)dir, driveletter, sizeof(driveletter)); 617 | CopyMemory((PVOID)(dir+2), dirpart, MAX_PATH-2); 618 | return dir; 619 | } 620 | else { 621 | return NULL; 622 | } 623 | } 624 | 625 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/ddr_stable.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 16.0 34 | Win32Proj 35 | {6c96058e-3da0-4451-816b-2a5e2e714911} 36 | ddrstable 37 | 10.0 38 | 39 | 40 | 41 | DynamicLibrary 42 | true 43 | v142 44 | Unicode 45 | 46 | 47 | DynamicLibrary 48 | false 49 | v142 50 | true 51 | Unicode 52 | 53 | 54 | DynamicLibrary 55 | true 56 | v142 57 | Unicode 58 | 59 | 60 | DynamicLibrary 61 | false 62 | v142 63 | true 64 | Unicode 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | %(AdditionalLibraryDirectories) 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | %(AdditionalLibraryDirectories) 110 | 111 | 112 | 113 | 114 | 115 | 116 | %(AdditionalLibraryDirectories) 117 | 118 | 119 | 120 | 121 | 122 | 123 | %(AdditionalLibraryDirectories) 124 | 125 | 126 | 127 | 128 | %(AdditionalDependencies) 129 | 130 | 131 | 132 | 133 | %(AdditionalDependencies) 134 | 135 | 136 | 137 | 138 | %(AdditionalDependencies) 139 | 140 | 141 | 142 | 143 | %(AdditionalDependencies) 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/ddr_stable.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Resource Files 20 | 21 | 22 | Resource Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/ddr_stable.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/dump_buffer1.c: -------------------------------------------------------------------------------- 1 | #include "ddr.h" 2 | #include "globals.h" 3 | 4 | reg_t dumpbuf_size = 0; 5 | reg_t dumpbuf_addr = 0; 6 | 7 | void my_call_pre_wrapper(void* wrapcxt, OUT void** user_data) { 8 | 9 | size_t func_addr_fixed; 10 | size_t retval = 0x666; 11 | dr_mcontext_t* mc = drwrap_get_mcontext(wrapcxt); 12 | app_pc wrapped_func = drwrap_get_func(wrapcxt); 13 | 14 | pa_call_para = pa_call_para_start; 15 | while (pa_call_para) { 16 | 17 | if (!OEP_moved_plus) 18 | func_addr_fixed = pa_call_para->patch_call_func_PC - oep_diff; 19 | else 20 | func_addr_fixed = pa_call_para->patch_call_func_PC + oep_diff; 21 | 22 | if (func_addr_fixed == (size_t) wrapped_func) { 23 | retval = pa_call_para->patch_call_ret; 24 | } 25 | pa_call_para = pa_call_para->nextcp; 26 | } 27 | pa_call_para = pa_call_para_start; 28 | 29 | drwrap_skip_call(wrapcxt, (void*)retval, 0); 30 | 31 | dr_printf("[DDR] [INFO] Wrapped function "PFX" called from "PFX".\n", wrapped_func, mc->pc); 32 | dr_printf("[DDR] [INFO] Return value set to "PFX"(signed decimal:%d)(unsigned decimal:%u)\n", retval, retval, retval); 33 | } 34 | 35 | int __cdecl get_mem_addr_dump_buffer(void* drcontext, reg_t* memaddr, char Optype, char OptypePtrType, int Opnum, app_pc instr_addr, dr_mcontext_t mc) { 36 | byte* pc; 37 | opnd_t opnd; 38 | reg_id_t reg; 39 | instr_t instr; 40 | instr_init(drcontext, &instr); 41 | instr_reset(drcontext, &instr); 42 | pc = decode(drcontext, instr_addr, &instr); // fill in instr 43 | opnd = instr_get_src(&instr, Opnum); 44 | *memaddr = 0; 45 | 46 | // Source operant 47 | if (tolower(Optype) == 's') { 48 | dr_printf("[DDR] [INFO] Getting buffer address from source operant %d.\n", Opnum); 49 | // op is register 50 | if (my_opnd_is_reg(opnd)) { 51 | reg = opnd_get_reg(opnd); 52 | *memaddr = reg_get_value(reg, &mc); 53 | //dr_printf("[DDR] [DEBUG] inst_mem_addr_reg: "PFX"\n", *memaddr); 54 | } 55 | else if (opnd_is_immed(opnd)) { 56 | *memaddr = opnd_get_immed_int(opnd); 57 | //dr_printf("[DDR] [DEBUG] inst_mem_addr_immed: "PFX"\n", *memaddr); 58 | } 59 | // op is not a register 60 | else { 61 | *memaddr = (reg_t)my_opnd_compute_address(opnd, &mc); 62 | //dr_printf("[DDR] [DEBUG] inst_mem_addr_noreg: "PFX"\n", *memaddr); 63 | } 64 | } 65 | // Destination operant 66 | else if (tolower(Optype) == 'd') { 67 | dr_printf("[DDR] [INFO] Getting buffer address from destination operant %d.\n", Opnum); 68 | 69 | opnd = instr_get_dst(&instr, Opnum); 70 | 71 | // op is register 72 | if (my_opnd_is_reg(opnd)) { 73 | reg = opnd_get_reg(opnd); 74 | *memaddr = reg_get_value(reg, &mc); 75 | //dr_printf("[DDR] [INFO] inst_mem_addr_reg: "PFX"\n", *memaddr); 76 | } 77 | else if (opnd_is_immed(opnd)) { 78 | *memaddr = opnd_get_immed_int(opnd); 79 | //dr_printf("[DDR] [INFO] inst_mem_addr_immed: "PFX"\n", *memaddr); 80 | } 81 | // op is not a register 82 | else { 83 | *memaddr = (reg_t)my_opnd_compute_address(opnd, &mc); 84 | //dr_printf("[DDR] [INFO] inst_mem_addr_noreg: "PFX"\n", *memaddr); 85 | } 86 | } 87 | instr_free(drcontext, &instr); 88 | 89 | return (memaddr != 0) ? TRUE : FALSE; 90 | } 91 | 92 | int __cdecl get_op_size_dump_buffer(void* drcontext, reg_t* memaddr, char Optype, char OptypePtrType, int Opnum, app_pc instr_addr, dr_mcontext_t mc) { 93 | byte* pc; 94 | opnd_t opnd; 95 | reg_id_t reg; 96 | instr_t instr; 97 | instr_init(drcontext, &instr); 98 | instr_reset(drcontext, &instr); 99 | pc = decode(drcontext, instr_addr, &instr); // fill in instr 100 | opnd = instr_get_src(&instr, Opnum); 101 | *memaddr = 0; 102 | 103 | // Source operant 104 | if (tolower(Optype) == 's') { 105 | dr_printf("[DDR] [INFO] Getting buffer size from source operant %d.\n", Opnum); 106 | // op is register 107 | if (my_opnd_is_reg(opnd)) { 108 | reg = opnd_get_reg(opnd); 109 | *memaddr = (reg_t)reg_get_value(reg, &mc); 110 | //dr_printf("[DDR] [INFO] inst_mem_addr_reg: "PFX"\n", *memaddr); 111 | } 112 | // op is an immediate value 113 | else if (opnd_is_immed(opnd)) { 114 | *memaddr = (reg_t)opnd_get_immed_int(opnd); 115 | //dr_printf("[DDR] [INFO] inst_mem_addr_immed: "PFX"\n", *memaddr); 116 | } 117 | // op is not a register 118 | else { 119 | *memaddr = (reg_t)my_opnd_compute_address(opnd, &mc); 120 | //dr_printf("[DDR] [INFO] inst_mem_addr_noreg: "PFX"\n", *memaddr); 121 | } 122 | } 123 | // Destination operant 124 | else if (tolower(Optype) == 'd') { 125 | dr_printf("[DDR] [INFO] Getting buffer size from destination operant %d.\n", Opnum); 126 | 127 | opnd = instr_get_dst(&instr, Opnum); 128 | 129 | // op is register 130 | if (my_opnd_is_reg(opnd)) { 131 | reg = opnd_get_reg(opnd); 132 | *memaddr = reg_get_value(reg, &mc); 133 | //dr_printf("[DDR] [INFO] inst_mem_addr_reg: "PFX"\n", *memaddr); 134 | } 135 | // op is an immediate value 136 | else if (opnd_is_immed(opnd)) { 137 | *memaddr = opnd_get_immed_int(opnd); 138 | //dr_printf("[DDR] [INFO] inst_mem_addr_immed: "PFX"\n", *memaddr); 139 | } 140 | else { 141 | *memaddr = (reg_t)my_opnd_compute_address(opnd, &mc); 142 | //dr_printf("[DDR] [INFO] inst_mem_addr_noreg: "PFX"\n", *memaddr); 143 | } 144 | } 145 | instr_free(drcontext, &instr); 146 | 147 | return (memaddr != 0) ? TRUE : FALSE; 148 | } 149 | 150 | void event_thread_init_global(void* drcontext) 151 | { 152 | app_pc FileEntryPoint, PEEntryPoint, PEImagebase; 153 | module_data_t* app; 154 | 155 | char* samplename; 156 | char samplename_cleaned[MAX_PATH * 2]; 157 | byte* peb; 158 | 159 | size_t func_addr_fixed; 160 | static thread_id_t last_threat_id; 161 | 162 | thread_id = dr_get_thread_id(drcontext); 163 | process_id = dr_get_process_id(); 164 | dr_printf("[DDR] [INFO] New Threat initalization started. Process ID = %u Threat ID = %u\n", process_id, thread_id); 165 | 166 | if (last_threat_id != 0) { 167 | dr_printf("[DDR] [WARNING] This is not the first thread. Multithreaded is not supported, but works in many cases.\n"); 168 | 169 | if (patch_call_set) { 170 | 171 | pa_call_para = pa_call_para_start; 172 | 173 | while (pa_call_para) { 174 | 175 | if (!OEP_moved_plus) 176 | func_addr_fixed = pa_call_para->patch_call_func_PC - oep_diff; 177 | else 178 | func_addr_fixed = pa_call_para->patch_call_func_PC + oep_diff; 179 | 180 | drwrap_wrap((app_pc)func_addr_fixed, my_call_pre_wrapper, NULL); 181 | dr_printf("[DDR] [INFO] Function at "PFX" wrapped and return value set to "PFX"\n", func_addr_fixed, pa_call_para->patch_call_ret); 182 | pa_call_para = pa_call_para->nextcp; 183 | } 184 | 185 | pa_call_para = pa_call_para_start; 186 | } 187 | return; 188 | } 189 | else { 190 | first_thread_id = thread_id; 191 | dr_printf("[DDR] [INFO] First thread. Setting main thread id to %d\n", first_thread_id); 192 | } 193 | 194 | // Get sample filename 195 | app = dr_get_main_module(); 196 | samplename = app->full_path; 197 | if (strlen(samplename) > MAX_PATH) { 198 | dr_printf("[DDR] [ERROR] Filename path too long\n"); 199 | dr_exit_process(1); 200 | } 201 | else { 202 | memcpy(samplename_cleaned, samplename, strlen(samplename)); 203 | samplename_cleaned[strlen(samplename)] = '\0'; 204 | } 205 | dr_printf("[DDR] [INFO] Samplename: %s.\n", samplename_cleaned); 206 | 207 | // Get PEB 208 | peb = dr_get_app_PEB(); 209 | 210 | // Get Imagebase and EP from PE in memory 211 | PEEntryPoint = app->entry_point; 212 | PEImagebase = app->start; 213 | 214 | // Get EP from orginal file on disk like IDA sees it 215 | if (!getOEPfromPEfile(samplename, &FileEntryPoint)) { 216 | dr_printf("[DDR] [WARNING] OEP not found in file.\n"); 217 | FileEntryPoint = PEEntryPoint; 218 | } 219 | 220 | // Calculate the offset if the loader moved it 221 | if (FileEntryPoint >= PEEntryPoint) { 222 | oep_diff = FileEntryPoint - PEEntryPoint; 223 | } 224 | else { 225 | oep_diff = PEEntryPoint - FileEntryPoint; 226 | OEP_moved_plus = TRUE; 227 | } 228 | 229 | dr_printf("[DDR] [INFO] PEB : "PFX"\n", peb); 230 | dr_printf("[DDR] [INFO] PE Imagebase : "PFX"\n", PEImagebase); 231 | dr_printf("[DDR] [INFO] PE EP : "PFX"\n", PEEntryPoint); 232 | dr_printf("[DDR] [INFO] File EP : "PFX"\n", FileEntryPoint); 233 | dr_printf("[DDR] [INFO] EP diff : "PFX"\n", oep_diff); 234 | 235 | dr_free_module_data(app); 236 | 237 | if (patch_call_set) { 238 | 239 | pa_call_para = pa_call_para_start; 240 | 241 | while (pa_call_para) { 242 | 243 | if (!OEP_moved_plus) 244 | func_addr_fixed = pa_call_para->patch_call_func_PC - oep_diff; 245 | else 246 | func_addr_fixed = pa_call_para->patch_call_func_PC + oep_diff; 247 | 248 | drwrap_wrap((app_pc) func_addr_fixed, my_call_pre_wrapper, NULL); 249 | dr_printf("[DDR] [INFO] Function at "PFX" wrapped and return value set to "PFX"\n", func_addr_fixed, pa_call_para->patch_call_ret); 250 | pa_call_para = pa_call_para->nextcp; 251 | } 252 | 253 | pa_call_para = pa_call_para_start; 254 | } 255 | 256 | last_threat_id = thread_id; 257 | } 258 | 259 | void __cdecl process_instr_size_dump_buffer(app_pc instr_addr, S_DUMP_PARA* dp) { 260 | 261 | size_t instr_addr_fixed; 262 | void* drcontext; 263 | int ret; 264 | 265 | drcontext = dr_get_current_drcontext(); 266 | dr_mcontext_t mc = { sizeof(mc),DR_MC_ALL }; 267 | dr_get_mcontext(drcontext, &mc); 268 | 269 | // Calculate the instr addr in file/IDA 270 | if (!OEP_moved_plus) 271 | instr_addr_fixed = (size_t)instr_addr + oep_diff; 272 | else 273 | instr_addr_fixed = (size_t)instr_addr - oep_diff; 274 | 275 | // Disasm instruction at PC 276 | print_disasm(drcontext, instr_addr, instr_addr_fixed); 277 | 278 | // Get size of buffer in operator 279 | ret = get_op_size_dump_buffer(drcontext, &dumpbuf_size, dp->sizeOptype, dp->sizeOptypePtrType, dp->sizeOpnum, instr_addr, mc); 280 | 281 | if (ret) { 282 | dr_printf("[DDR] [INFO] buffer size = "PFX" (%d)\n", dumpbuf_size, dumpbuf_size); 283 | dumbuf_SizeFound = TRUE; 284 | } 285 | else { 286 | dr_printf("[DDR] [ERROR] Getting buffer size failed\n", dumpbuf_size); 287 | dr_exit_process(1); 288 | } 289 | } 290 | 291 | void __cdecl process_instr_addr_dump_buffer(app_pc instr_addr, S_DUMP_PARA* dp) { 292 | 293 | size_t instr_addr_fixed; 294 | void* drcontext; 295 | int ret; 296 | 297 | drcontext = dr_get_current_drcontext(); 298 | dr_mcontext_t mc = { sizeof(mc),DR_MC_ALL }; 299 | dr_get_mcontext(drcontext, &mc); 300 | 301 | // Calculate the instr addr in file/IDA 302 | if (!OEP_moved_plus) 303 | instr_addr_fixed = (size_t)instr_addr + oep_diff; 304 | else 305 | instr_addr_fixed = (size_t)instr_addr - oep_diff; 306 | 307 | // Disasm instruction at PC 308 | print_disasm(drcontext, instr_addr, instr_addr_fixed); 309 | 310 | // Get memory address of buffer in operator 311 | ret = get_mem_addr_dump_buffer(drcontext, &dumpbuf_addr, dp->bufferOptype, dp->bufferOptypePtrType, dp->bufferOpnum, instr_addr, mc); 312 | 313 | if (ret) { 314 | dr_printf("[DDR] [INFO] buffer address = "PFX"\n", dumpbuf_addr); 315 | dumpbuf_AddrFound = TRUE; 316 | } 317 | else { 318 | dr_printf("[DDR] [ERROR] Getting buffer address failed\n"); 319 | dr_exit_process(1); 320 | } 321 | } 322 | 323 | void __cdecl process_instr_dump_buffer(app_pc instr_addr, S_DUMP_PARA* dp) { 324 | 325 | size_t bytesread; 326 | char* bytesbuf; 327 | void* drcontext; 328 | size_t instr_addr_fixed; 329 | 330 | file_t dump_fp = dr_open_file(dp->filename, DR_FILE_WRITE_OVERWRITE); 331 | if (dump_fp == INVALID_FILE) { 332 | dr_printf("[DDR] [ERROR] Can't create dump file. Does the directory you specified exist?\n"); 333 | dr_exit_process(1); 334 | } 335 | 336 | drcontext = dr_get_current_drcontext(); 337 | 338 | // Calculate the instr addr in file/IDA 339 | if (!OEP_moved_plus) 340 | instr_addr_fixed = (size_t)instr_addr + oep_diff; 341 | else 342 | instr_addr_fixed = (size_t)instr_addr - oep_diff; 343 | 344 | // Print disasm at instr_addr 345 | print_disasm(drcontext, instr_addr, instr_addr_fixed); 346 | 347 | bytesbuf = (char*) dr_global_alloc(sizeof(char) * dumpbuf_size); 348 | 349 | // Safe memory buffer to file 350 | if (dr_safe_read((app_pc)dumpbuf_addr, (size_t) dumpbuf_size, bytesbuf, &bytesread)) { 351 | 352 | if (bytesread == dumpbuf_size) { 353 | dr_write_file(dump_fp, bytesbuf, dumpbuf_size); 354 | dr_close_file(dump_fp); 355 | dr_printf("[DDR] [INFO] [FINAL] Done. Written %d bytes from address "PFX" to file: %s.\n", dumpbuf_size, dumpbuf_addr, dp->filename); 356 | } 357 | else { 358 | dr_printf("[DDR] [ERROR] [FINAL] Data not written to file. Bytes read: %d.\n", bytesread); 359 | } 360 | } 361 | dr_global_free(bytesbuf, sizeof(char) * dumpbuf_size); 362 | } 363 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/globals.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern int cmd_opts; 4 | extern unsigned int dbgLevel; 5 | extern int tls_idx; 6 | extern int tls_idx2; 7 | extern int tls_idx3; 8 | extern client_id_t my_id; 9 | extern size_t oep_diff; 10 | extern size_t ref_flags; 11 | extern size_t from_addr; 12 | extern size_t to_addr; 13 | extern size_t inst_count; 14 | extern size_t inst_num; 15 | extern bool light_trace_only; 16 | extern bool trace_set; 17 | extern bool first_instr_set; 18 | extern bool OEP_moved_plus; 19 | 20 | extern bool patch_eflag_set; 21 | extern P_EFLAG_PARA* pa_flag_para; 22 | extern P_EFLAG_PARA* pa_flag_para_start; 23 | 24 | extern bool patch_nop_set; 25 | extern P_NOP_PARA* pa_nop_para; 26 | extern P_NOP_PARA* pa_nop_para_start; 27 | 28 | extern bool patch_call_set; 29 | extern P_CALL_PARA* pa_call_para; 30 | extern P_CALL_PARA* pa_call_para_start; 31 | 32 | extern bool dump_buffer_set; 33 | extern S_DUMP_PARA* dump_para; 34 | extern S_DUMP_PARA* dump_para_start; 35 | 36 | extern bool trace_para_set; 37 | extern S_TRACE_PARA* trace_para; 38 | extern S_TRACE_PARA* trace_para_start; 39 | 40 | extern S_PROCS* pListThreads; 41 | extern S_PROCS* pListThreads_start; 42 | extern unsigned int thread_counter; 43 | 44 | extern file_t global_fPidThreads; 45 | extern char* global_pidThreadsFilename; 46 | extern char* global_pidThreadsFullFilename; 47 | extern char* global_logpath; 48 | 49 | extern bool dumpbuf_AddrFound; 50 | extern bool dumbuf_SizeFound; 51 | 52 | extern char *global_trace_LogFilename; 53 | extern char *global_trace_ApiLogfilename; 54 | extern char* global_client_path; 55 | extern file_t global_trace_fp; 56 | extern file_t global_trace_api_fp; 57 | extern file_t global_exec_counter_fp; 58 | extern uint thread_couter; 59 | extern thread_id_t thread_id; 60 | extern process_id_t process_id; 61 | extern thread_id_t first_thread_id; 62 | extern unsigned int dr_exec_ctr; 63 | 64 | extern bool loop_set; 65 | extern size_t loop_addr; 66 | extern bool startaddr_set; 67 | extern size_t startaddr; 68 | extern bool breakaddr_set; 69 | extern size_t breakaddr; 70 | 71 | extern TCHAR szName[]; 72 | extern TCHAR szProcIDs[]; 73 | extern TCHAR szProcNames[]; 74 | extern TCHAR szLogPath[]; 75 | extern process_id_t *processids; 76 | 77 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/patch_exe.c: -------------------------------------------------------------------------------- 1 | #include "ddr.h" 2 | #include "globals.h" 3 | 4 | void __cdecl patch_eflag(app_pc instr_addr, P_EFLAG_PARA* pp) { 5 | void* drcontext; 6 | size_t instr_addr_fixed; 7 | byte* pc; 8 | 9 | drcontext = dr_get_current_drcontext(); 10 | dr_mcontext_t mc = { sizeof(mc),DR_MC_ALL }; 11 | dr_get_mcontext(drcontext, &mc); 12 | 13 | // Calculate the instr addr in file/IDA 14 | if (!OEP_moved_plus) 15 | instr_addr_fixed = (size_t)instr_addr + oep_diff; 16 | else 17 | instr_addr_fixed = (size_t)instr_addr - oep_diff; 18 | 19 | dr_printf("[DDR] [INFO] Toggling %s EFLAG at "PFX"\n", pp->patch_eflag_flag_str, instr_addr_fixed); 20 | print_disasm(drcontext, instr_addr, instr_addr_fixed); 21 | 22 | instr_t instr; 23 | instr_init(drcontext, &instr); 24 | instr_reset(drcontext, &instr); 25 | 26 | pc = decode(drcontext, instr_addr, &instr); 27 | if (pc == NULL) { 28 | dr_printf("[DDR] [ERROR] Invalid Instruction found! DynamoRIO can't decode instruction\n"); 29 | dr_exit_process(1); 30 | } 31 | 32 | dr_printf("[DDR] [INFO] EFLAGS register before toggling: 0x%x\n", mc.xflags); 33 | if (mc.xflags & pp->patch_eflag_flag) 34 | dr_printf("[DDR] [INFO] %s EFLAG = 1\n", pp->patch_eflag_flag_str); 35 | else 36 | dr_printf("[DDR] [INFO] %s EFLAG = 0\n", pp->patch_eflag_flag_str); 37 | 38 | mc.xflags ^= pp->patch_eflag_flag; // toggle eflag bit 39 | dr_set_mcontext(drcontext, &mc); 40 | 41 | dr_printf("[DDR] [INFO] EFLAGS register after toggling: 0x%x\n", mc.xflags); 42 | if (mc.xflags & pp->patch_eflag_flag) 43 | dr_printf("[DDR] [INFO] %s EFLAG set to 1\n", pp->patch_eflag_flag_str); 44 | else 45 | dr_printf("[DDR] [INFO] %s EFLAG set to 0\n", pp->patch_eflag_flag_str); 46 | 47 | instr_free(drcontext, &instr); 48 | } 49 | 50 | void __cdecl patch_sleep(app_pc instr_addr) { 51 | dr_messagebox("Execution stopped. Please click ok to proceed."); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/trace_instr.c: -------------------------------------------------------------------------------- 1 | /* This file handles the CmdOpt_NormalTrace */ 2 | 3 | #include "ddr.h" 4 | #include "globals.h" 5 | 6 | void event_module_load_trace_instr(void* drcontext, const module_data_t* info, bool loaded) 7 | { 8 | #ifdef _DEBUG 9 | dr_printf("[DDR] [DEBUG] event_module_load_trace_instr module loaded: %s:\n", dr_module_preferred_name(info)); 10 | #endif 11 | if (lib_is_not_blacklisted_trace_instr(info)) 12 | iterate_exports_trace_instr(info); 13 | } 14 | 15 | process_id_t getFirstPIDfromFile(char* pidsfilename) { 16 | 17 | file_t fPidsfile; 18 | uint max_retries; 19 | process_id_t pid = 0; 20 | size_t bytes_read; 21 | char data[MAX_PATH + 20]; 22 | char* sPid; 23 | size_t sPidLen=0; 24 | 25 | for (max_retries = 0; max_retries < 3; max_retries++) { 26 | dr_printf("[DDR] [INFO] Trying to open PID file: %s\n", pidsfilename); 27 | fPidsfile = dr_open_file(pidsfilename, DR_FILE_READ); // write PID to PIDs file 28 | if (fPidsfile == INVALID_FILE) { 29 | dr_printf("[DDR] [ERROR] Failed to open initial process log file: %s. Attempt number: %u\n", pidsfilename, max_retries); 30 | Sleep(300); 31 | continue; 32 | } 33 | break; 34 | } 35 | 36 | bytes_read = dr_read_file(fPidsfile, data, MAX_PATH + 10); 37 | data[bytes_read] = '\0'; 38 | sPid = getSubstr(data, "[", "]"); 39 | sPidLen = strlen(sPid); 40 | pid = (process_id_t) strtoull(sPid, NULL, 10); 41 | 42 | dr_close_file(fPidsfile); 43 | 44 | dr_global_free(sPid, strlen(sPid)+1); 45 | return pid; 46 | 47 | } 48 | 49 | void event_thread_init_trace_instr(void* drcontext) 50 | { 51 | #ifdef _DEBUG 52 | dr_printf("\n[DDR] [DEBUG] event_thread_init_trace_instr start.\n"); 53 | #endif 54 | 55 | app_pc FileEntryPoint, PEEntryPoint, PEImagebase; 56 | module_data_t* app; 57 | 58 | char* samplename; 59 | char samplename_cleaned[MAX_PATH * 2]; 60 | const char *app_name; 61 | byte* peb; 62 | static thread_id_t last_threat_id; 63 | size_t func_addr_fixed; 64 | 65 | thread_counter = thread_counter + 1; 66 | thread_id = dr_get_thread_id(drcontext); 67 | process_id = dr_get_process_id(); 68 | app_name = dr_get_application_name(); 69 | dr_printf("[DDR] [INFO] New thread initialization started. Appname = %s Process ID = %u Threat ID = %u Thread counter = %u\n", 70 | app_name, process_id, thread_id, thread_counter); 71 | 72 | // is this first thread of the process ? 73 | if (pListThreads == NULL) { 74 | // ---- New process, first threat. ---- 75 | dr_printf("[DDR] [INFO] New process, first thread started.\n"); 76 | 77 | // allocate memory for threads linked list (pListThreads) 78 | pListThreads = (S_PROCS*)dr_global_alloc(sizeof(S_PROCS)); 79 | pListThreads_start = pListThreads; 80 | 81 | #ifdef _DEBUG 82 | dr_printf("[DDR] [DEBUG] [MEMOP] allocated memory for main thread. Memaddr: "PFX" thread_id=%d process_id=%u\n", 83 | pListThreads, thread_id, process_id); 84 | #endif 85 | // create process-thread log file 86 | if (global_pidThreadsFullFilename == NULL) { 87 | global_pidThreadsFullFilename = (char*)dr_global_alloc(MAX_PATH); 88 | } 89 | 90 | dr_snprintf(global_pidThreadsFullFilename, MAX_PATH, "%s\\%s_%s_%u.txt", global_logpath, global_pidThreadsFilename, app_name, dr_get_process_id()); 91 | dr_printf("[DDR] [INFO] writing thread info to: %s\n", global_pidThreadsFullFilename); 92 | 93 | global_fPidThreads = dr_open_file(global_pidThreadsFullFilename, DR_FILE_WRITE_OVERWRITE); // write PID to PIDs file 94 | if (global_fPidThreads == INVALID_FILE) { 95 | dr_printf("[DDR] [ERROR] Failed to open individual threads log file: %s\n", global_pidThreadsFullFilename); 96 | } 97 | dr_global_free(global_pidThreadsFullFilename, MAX_PATH); 98 | 99 | dr_fprintf(global_fPidThreads, "%s [%u] [%u]\r\n", app_name, process_id, thread_id); 100 | 101 | // fill process structure 102 | // is this the first process ? 103 | if (*processids == process_id) { 104 | pListThreads->start_process_id = process_id; 105 | } 106 | else { 107 | pListThreads->start_process_id = *processids; 108 | } 109 | pListThreads->prevproc = NULL; 110 | pListThreads->process_id = process_id; 111 | pListThreads->threat_id = thread_id; 112 | pListThreads->nextproc = NULL; 113 | } 114 | else { 115 | // ---- Existing process 2nd to n thread ---- 116 | dr_printf("[DDR] [INFO] Existing process. New thread started.\n"); 117 | 118 | if (global_logpath) { 119 | debug_print("Using log path %s\n", global_logpath); 120 | } 121 | else { 122 | dr_printf("[DDR] [ERROR] [%s:%d] global logpath file not found\n", __FILE__, __LINE__); 123 | } 124 | 125 | // log process/thread info to process-thread file 126 | dr_fprintf(global_fPidThreads, "%s [%u] [%u]\r\n", app_name, process_id, thread_id); 127 | 128 | pListThreads->nextproc = (S_PROCS*)dr_global_alloc(sizeof(S_PROCS)); 129 | #ifdef _DEBUG 130 | dr_printf("[DDR] [DEBUG] [MEMOP] allocated memory for sub thread. Memaddr: "PFX" thread_id=%d process_id=%u\n", 131 | pListThreads->nextproc, thread_id, process_id); 132 | #endif 133 | pListThreads->nextproc->prevproc = pListThreads; 134 | pListThreads = pListThreads->nextproc; 135 | 136 | // is this the first process ? 137 | if (*processids == process_id) { 138 | pListThreads->start_process_id = process_id; 139 | } 140 | else { 141 | pListThreads->start_process_id = *processids; 142 | } 143 | pListThreads->process_id = process_id; 144 | pListThreads->threat_id = thread_id; 145 | pListThreads->nextproc = NULL; 146 | } 147 | 148 | if (last_threat_id != 0) { 149 | dr_printf("[DDR] [WARNING] This is not the first thread. Multithreaded is not supported, but works in many cases.\n"); 150 | 151 | if (patch_call_set) { 152 | 153 | pa_call_para = pa_call_para_start; 154 | 155 | while (pa_call_para) { 156 | 157 | if (!OEP_moved_plus) 158 | func_addr_fixed = pa_call_para->patch_call_func_PC - oep_diff; 159 | else 160 | func_addr_fixed = pa_call_para->patch_call_func_PC + oep_diff; 161 | 162 | drwrap_wrap((app_pc)func_addr_fixed, my_call_pre_wrapper, NULL); 163 | dr_printf("[DDR] [INFO] Function at "PFX" wrapped and return value set to "PFX"\n", func_addr_fixed, pa_call_para->patch_call_ret); 164 | pa_call_para = pa_call_para->nextcp; 165 | } 166 | 167 | pa_call_para = pa_call_para_start; 168 | } 169 | return; 170 | } 171 | else { 172 | first_thread_id = thread_id; 173 | dr_printf("[DDR] [INFO] First thread. Setting main thread id to %d\n", first_thread_id); 174 | } 175 | 176 | // Get sample Filename 177 | app = dr_get_main_module(); 178 | samplename = app->full_path; 179 | if (strlen(samplename) > MAX_PATH) { 180 | dr_printf("[DDR] [ERROR] Filename path too long\n"); 181 | dr_exit_process(1); 182 | } 183 | else { 184 | memcpy(samplename_cleaned, samplename, strlen(samplename)); 185 | samplename_cleaned[strlen(samplename)] = '\0'; 186 | } 187 | dr_printf("[DDR] [INFO] Samplename: %s.\n", samplename_cleaned); 188 | 189 | // Escape filename string for JSON file 190 | if (!escape_dir_str(samplename_cleaned)) { 191 | dr_printf("[DDR] [ERROR] Failed to escape file path\n"); 192 | dr_exit_process(1); 193 | } 194 | 195 | // Write meta data about the sample into the logfile 196 | // TBD: use a proper JSON lib instead 197 | dr_fprintf(global_trace_fp, "{\n\"samplename\" : \"%s\",\n", samplename_cleaned ? samplename_cleaned : "FILENAME_PARSING_ERROR"); 198 | 199 | #ifdef X86_64 200 | dr_fprintf(global_trace_fp, "\"architecture\" : \"x64\",\n"); 201 | #else 202 | dr_fprintf(global_trace_fp, "\"architecture\" : \"x32\",\n"); 203 | #endif 204 | 205 | dr_fprintf(global_trace_fp, "\"trace_start\" : \""PFX"\",\n", from_addr); 206 | dr_fprintf(global_trace_fp, "\"trace_end\" : \""PFX"\",\n", to_addr); 207 | dr_fprintf(global_trace_fp, "\"num_instr_to_trace\" : \"%d\",\n", inst_count); 208 | 209 | // Get PEB 210 | peb = dr_get_app_PEB(); 211 | 212 | PEEntryPoint = app->entry_point; 213 | PEImagebase = app->start; 214 | 215 | // get OEP from orginal file on disk 216 | if (!getOEPfromPEfile(samplename, &FileEntryPoint)) { 217 | dr_printf("[DDR] [WARNING] OEP not found in file.\n"); 218 | FileEntryPoint = PEEntryPoint; 219 | } 220 | 221 | // Calculate the offset if the loader moved it 222 | if (FileEntryPoint >= PEEntryPoint) { 223 | oep_diff = FileEntryPoint - PEEntryPoint; 224 | } 225 | else { 226 | oep_diff = PEEntryPoint - FileEntryPoint; 227 | OEP_moved_plus = TRUE; 228 | } 229 | 230 | dr_printf("[DDR] [INFO] PEB : "PFX"\n", peb); 231 | dr_printf("[DDR] [INFO] PE Imagebase : "PFX"\n", PEImagebase); 232 | dr_printf("[DDR] [INFO] PE EP : "PFX"\n", PEEntryPoint); 233 | dr_printf("[DDR] [INFO] File EP : "PFX"\n", FileEntryPoint); 234 | dr_printf("[DDR] [INFO] EP diff : "PFX"\n", oep_diff); 235 | 236 | dr_fprintf(global_trace_fp, "\"peb\" : \""PFX"\",\n", peb); 237 | dr_fprintf(global_trace_fp, "\"imagebase\" : \""PFX"\",\n", PEImagebase); 238 | dr_fprintf(global_trace_fp, "\"entrypoint\" : \""PFX"\",\n", PEEntryPoint); 239 | dr_fprintf(global_trace_fp, "\"oep\" : \""PFX"\",\n", FileEntryPoint); 240 | dr_fprintf(global_trace_fp, "\"oep_diff\" : \""PFX"\",\n", oep_diff); 241 | dr_fprintf(global_trace_fp, "\"instruction\" : \n[\n"); 242 | 243 | if (patch_call_set) { 244 | 245 | pa_call_para = pa_call_para_start; 246 | 247 | while (pa_call_para) { 248 | 249 | if (!OEP_moved_plus) 250 | func_addr_fixed = pa_call_para->patch_call_func_PC - oep_diff; 251 | else 252 | func_addr_fixed = pa_call_para->patch_call_func_PC + oep_diff; 253 | 254 | drwrap_wrap((app_pc)func_addr_fixed, my_call_pre_wrapper, NULL); 255 | dr_printf("[DDR] [INFO] Function at "PFX" wrapped and return value set to "PFX"\n", func_addr_fixed, pa_call_para->patch_call_ret); 256 | pa_call_para = pa_call_para->nextcp; 257 | } 258 | 259 | pa_call_para = pa_call_para_start; 260 | } 261 | 262 | //last_threat_id = thread_id; 263 | last_threat_id = dr_get_thread_id(drcontext); 264 | 265 | dr_free_module_data(app); 266 | 267 | #ifdef _DEBUG 268 | dr_printf("\n[DDR] [DEBUG] event_thread_init_trace_instr end.\n"); 269 | #endif 270 | } 271 | 272 | void event_thread_exit_trace_instr(void* drcontext) 273 | { 274 | //S_TRACE_PARA* trace_para_prev; 275 | S_PROCS* pListThreads_tmp; 276 | 277 | #ifdef _DEBUG 278 | dr_printf("\n[DDR] [DEBUG] event_thread_exit_trace_instr start.\n"); 279 | dr_printf("[DDR] [DEBUG] Thread counter: %u\n", thread_counter); 280 | #endif 281 | 282 | if (first_thread_id == dr_get_thread_id(drcontext)) { 283 | 284 | dr_printf("[DDR] [INFO] Main thread (id = %d) was terminated.\n", first_thread_id); 285 | dr_close_file(global_fPidThreads); 286 | 287 | // Fix trace file 288 | dr_fprintf(global_trace_fp, " ]\n}\n"); 289 | dr_close_file(global_trace_fp); 290 | 291 | dr_printf("[DDR] [INFO] Fixing trace file: %s\n", global_trace_LogFilename); 292 | fix_comma_in_jsonfile(global_trace_LogFilename); 293 | dr_printf("[DDR] [INFO] Trace file fixed.\n"); 294 | 295 | // Fix API trace file 296 | dr_file_seek(global_trace_api_fp, -2, DR_SEEK_CUR); 297 | dr_fprintf(global_trace_api_fp, "\n ]\n}\n"); 298 | dr_close_file(global_trace_api_fp); 299 | 300 | dr_printf("[DDR] [INFO] Fixing API trace file: %s\n", global_trace_ApiLogfilename); 301 | fix_comma_in_jsonfile(global_trace_ApiLogfilename); 302 | dr_printf("[DDR] [INFO] API trace file fixed.\n"); 303 | 304 | dr_global_free(global_trace_LogFilename, MAX_PATH); 305 | dr_global_free(global_trace_ApiLogfilename, MAX_PATH); 306 | 307 | /*if (trace_para_set) { 308 | trace_para = trace_para_start; 309 | while (trace_para) { 310 | dr_global_free(trace_para->filename, MAX_FILE_LINE_LEN); 311 | trace_para_prev = trace_para; 312 | trace_para = trace_para->nexttr; 313 | dr_global_free(trace_para_prev, sizeof(S_TRACE_PARA)); 314 | } 315 | }*/ 316 | 317 | SYSTEMTIME lt; 318 | GetLocalTime(<); 319 | dr_printf("[DDR] [INFO] Time : %02d:%02d:%02d:%d\n", lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds); 320 | } 321 | else { 322 | dr_printf("[DDR] [INFO] Thread with id %d was terminated\n", dr_get_thread_id(drcontext)); 323 | } 324 | 325 | // Is this the last living thread ? Free the linked list 326 | if (thread_counter == 1) { 327 | #ifdef _DEBUG 328 | dr_printf("[DDR] [DEBUG] [MEMOP] Last living thread (thread_id = %d proccess = %u) reached. Free'ing memory.\n", 329 | dr_get_thread_id(drcontext), dr_get_process_id()); 330 | #endif 331 | pListThreads = pListThreads_start; 332 | while (pListThreads) { 333 | pListThreads_tmp = pListThreads->nextproc; 334 | #ifdef _DEBUG 335 | dr_printf("[DDR] [DEBUG] [MEMOP] free'ing memory: "PFX" thread_id = %d\n", pListThreads, pListThreads->threat_id); 336 | #endif 337 | dr_global_free(pListThreads, sizeof(S_PROCS)); 338 | pListThreads = pListThreads_tmp; 339 | } 340 | #ifdef _DEBUG 341 | dr_printf("[DDR] [DEBUG] [MEMOP] process memory free'ed.\n"); 342 | #endif 343 | } 344 | thread_counter = thread_counter - 1; 345 | 346 | 347 | #ifdef _DEBUG 348 | dr_printf("\n[DDR] [DEBUG] event_thread_exit_trace_instr end.\n"); 349 | #endif 350 | } 351 | 352 | 353 | void __cdecl process_instr_trace_instr_new(app_pc instr_addr, S_TRACE_PARA* tr) 354 | { 355 | char* cf_bit = "cf=0"; 356 | char* pf_bit = "pf=0"; 357 | char* af_bit = "af=0"; 358 | char* zf_bit = "zf=0"; 359 | char* sf_bit = "sf=0"; 360 | char* df_bit = "df=0"; 361 | char* of_bit = "of=0"; 362 | 363 | size_t instr_addr_fixed; 364 | 365 | void* drcontext; 366 | byte* pc; 367 | 368 | drcontext = dr_get_current_drcontext(); 369 | dr_mcontext_t mc = { sizeof(mc),DR_MC_ALL }; 370 | dr_get_mcontext(drcontext, &mc); 371 | 372 | if (!OEP_moved_plus) 373 | instr_addr_fixed = (size_t)instr_addr + oep_diff; 374 | else 375 | instr_addr_fixed = (size_t)instr_addr - oep_diff; 376 | 377 | if (tr->max_instr <= 0) { 378 | dr_printf("[DDR] [WARNING] Max. number of instructions reached. Logging stopped at 0x%x.\n", instr_addr); 379 | dr_exit_process(0); // calls exit routines 380 | } 381 | 382 | #ifdef _DEBUG 383 | if (dbgLevel >= 5) { 384 | dr_printf("[DDR] [DEBUG] i:0x%x\n", instr_addr_fixed); 385 | } 386 | /* 387 | // Testing a crash.... 388 | // 389 | if (instr_addr_fixed == 0x401924) { 390 | dr_printf("[DDR] [DEBUG] -------- Create access violation when process instruction 0x401924. -----------\n"); 391 | memcpy(NULL, 0xffffffff, 50); // create access violation 392 | } 393 | */ 394 | #endif 395 | 396 | if ((instr_addr_fixed >= tr->start) && (instr_addr_fixed <= tr->end)) { 397 | 398 | instr_t instr; 399 | 400 | if (first_thread_id == dr_get_thread_id(drcontext)) { 401 | // light trace 402 | if (tr->light_trace_only) { 403 | dr_fprintf(global_trace_fp, " {\n \"instr_num\" : \"%d\",\n", inst_num++); 404 | // medium trace preparation: TBD add a medium trace option to config 405 | if (true) { 406 | instr_init(drcontext, &instr); 407 | instr_reset(drcontext, &instr); 408 | dr_fprintf(global_trace_fp, " \"address\" : \""PFX"\",\n", instr_addr_fixed); 409 | pc = decode(drcontext, instr_addr, &instr); 410 | 411 | size_t disasm_buf_size = 254; 412 | unsigned char* disasm_buf = (unsigned char*)dr_global_alloc(sizeof(unsigned char) * disasm_buf_size); 413 | instr_disassemble_to_buffer(dr_get_current_drcontext(), &instr, disasm_buf, disasm_buf_size); 414 | dr_fprintf(global_trace_fp, " \"disasm\" : \"%s\",\n", disasm_buf); 415 | dr_global_free(disasm_buf, sizeof(unsigned char) * disasm_buf_size); 416 | 417 | log_instr_opnds_trace_instr(global_trace_fp, &instr, &mc, drcontext, 16); 418 | instr_free(drcontext, &instr); 419 | } 420 | else { 421 | dr_fprintf(global_trace_fp, " \"address\" : \""PFX"\"\n", instr_addr_fixed); 422 | } 423 | dr_fprintf(global_trace_fp, " },\n"); 424 | tr->max_instr--; 425 | } 426 | // full trace 427 | else { 428 | instr_init(drcontext, &instr); 429 | instr_reset(drcontext, &instr); 430 | 431 | tr->max_instr--; 432 | 433 | pc = decode(drcontext, instr_addr, &instr); 434 | if (pc == NULL) { 435 | dr_fprintf(global_trace_fp, "ERROR: Invalid Instruction found! DynamoRIO can't decode instruction\n"); 436 | return; 437 | } 438 | 439 | // get flags and registers 440 | ref_flags = mc.xflags; 441 | 442 | if (EFLAGS_CF & ref_flags) cf_bit = "cf=1"; 443 | if (EFLAGS_PF & ref_flags) pf_bit = "pf=1"; 444 | if (EFLAGS_AF & ref_flags) af_bit = "af=1"; 445 | if (EFLAGS_ZF & ref_flags) zf_bit = "zf=1"; 446 | if (EFLAGS_SF & ref_flags) sf_bit = "sf=1"; 447 | if (EFLAGS_DF & ref_flags) df_bit = "df=1"; 448 | if (EFLAGS_OF & ref_flags) of_bit = "of=1"; 449 | 450 | if (first_instr_set) 451 | first_instr_set = FALSE; 452 | else 453 | dr_fprintf(global_trace_fp, ",\n"); 454 | 455 | dr_fprintf(global_trace_fp, " {\n"); 456 | dr_fprintf(global_trace_fp, " \"instr_num\" : \"%d\",\n", inst_num++); 457 | dr_fprintf(global_trace_fp, " \"address\" : \""PFX"\",\n", instr_addr_fixed); 458 | dr_fprintf(global_trace_fp, " \"xax\" : \""PFX"\",\n", mc.xax); 459 | log_mem_at_reg_trace_instr((app_pc)mc.xax, "xax", global_trace_fp); 460 | dr_fprintf(global_trace_fp, " \"xbx\" : \""PFX"\",\n", mc.xbx); 461 | log_mem_at_reg_trace_instr((app_pc)mc.xbx, "xbx", global_trace_fp); 462 | dr_fprintf(global_trace_fp, " \"xcx\" : \""PFX"\",\n", mc.xcx); 463 | log_mem_at_reg_trace_instr((app_pc)mc.xcx, "xcx", global_trace_fp); 464 | dr_fprintf(global_trace_fp, " \"xdx\" : \""PFX"\",\n", mc.xdx); 465 | log_mem_at_reg_trace_instr((app_pc)mc.xdx, "xdx", global_trace_fp); 466 | dr_fprintf(global_trace_fp, " \"xsp\" : \""PFX"\",\n", mc.xsp); 467 | log_mem_at_reg_trace_instr((app_pc)mc.xsp, "xsp", global_trace_fp); 468 | dr_fprintf(global_trace_fp, " \"xbp\" : \""PFX"\",\n", mc.xbp); 469 | log_mem_at_reg_trace_instr((app_pc)mc.xbp, "xbp", global_trace_fp); 470 | dr_fprintf(global_trace_fp, " \"xsi\" : \""PFX"\",\n", mc.xsi); 471 | log_mem_at_reg_trace_instr((app_pc)mc.xsi, "xsi", global_trace_fp); 472 | dr_fprintf(global_trace_fp, " \"xdi\" : \""PFX"\",\n", mc.xdi); 473 | log_mem_at_reg_trace_instr((app_pc)mc.xdi, "xdi", global_trace_fp); 474 | 475 | #ifdef X86_64 476 | dr_fprintf(global_trace_fp, " \"r8\" : \""PFX"\",\n", mc.r8); 477 | log_mem_at_reg_trace_instr((app_pc)mc.r8, "r8", global_trace_fp); 478 | dr_fprintf(global_trace_fp, " \"r9\" : \""PFX"\",\n", mc.r9); 479 | log_mem_at_reg_trace_instr((app_pc)mc.r9, "r9", global_trace_fp); 480 | dr_fprintf(global_trace_fp, " \"r10\" : \""PFX"\",\n", mc.r10); 481 | log_mem_at_reg_trace_instr((app_pc)mc.r10, "r10", global_trace_fp); 482 | dr_fprintf(global_trace_fp, " \"r11\" : \""PFX"\",\n", mc.r11); 483 | log_mem_at_reg_trace_instr((app_pc)mc.r11, "r11", global_trace_fp); 484 | dr_fprintf(global_trace_fp, " \"r12\" : \""PFX"\",\n", mc.r12); 485 | log_mem_at_reg_trace_instr((app_pc)mc.r12, "r12", global_trace_fp); 486 | dr_fprintf(global_trace_fp, " \"r13\" : \""PFX"\",\n", mc.r13); 487 | log_mem_at_reg_trace_instr((app_pc)mc.r13, "r13", global_trace_fp); 488 | dr_fprintf(global_trace_fp, " \"r14\" : \""PFX"\",\n", mc.r14); 489 | log_mem_at_reg_trace_instr((app_pc)mc.r14, "r14", global_trace_fp); 490 | dr_fprintf(global_trace_fp, " \"r15\" : \""PFX"\",\n", mc.r15); 491 | log_mem_at_reg_trace_instr((app_pc)mc.r15, "r15", global_trace_fp); 492 | #endif 493 | 494 | dr_fprintf(global_trace_fp, " \"eflags\" : \"0x%x\",\n", ref_flags); 495 | dr_fprintf(global_trace_fp, " \"cf_bit\" : \"%s\",\n", cf_bit); 496 | dr_fprintf(global_trace_fp, " \"pf_bit\" : \"%s\",\n", pf_bit); 497 | dr_fprintf(global_trace_fp, " \"af_bit\" : \"%s\",\n", af_bit); 498 | dr_fprintf(global_trace_fp, " \"zf_bit\" : \"%s\",\n", zf_bit); 499 | dr_fprintf(global_trace_fp, " \"sf_bit\" : \"%s\",\n", sf_bit); 500 | dr_fprintf(global_trace_fp, " \"df_bit\" : \"%s\",\n", df_bit); 501 | dr_fprintf(global_trace_fp, " \"of_bit\" : \"%s\",\n", of_bit); 502 | 503 | // Print DISASM of instruction to JSON file 504 | size_t disasm_buf_size = 254; 505 | unsigned char* disasm_buf = (unsigned char*)dr_global_alloc(sizeof(unsigned char) * disasm_buf_size); 506 | instr_disassemble_to_buffer(dr_get_current_drcontext(), &instr, disasm_buf, disasm_buf_size); 507 | dr_fprintf(global_trace_fp, " \"disasm\" : \"%s\",\n", disasm_buf); 508 | dr_global_free(disasm_buf, sizeof(unsigned char)* disasm_buf_size); 509 | 510 | log_instr_opnds_trace_instr(global_trace_fp, &instr, &mc, drcontext, 16); 511 | dr_fprintf(global_trace_fp, "\n"); 512 | dr_fprintf(global_trace_fp, " }"); 513 | 514 | instr_free(drcontext, &instr); 515 | } 516 | } 517 | } 518 | } 519 | 520 | static void iterate_exports_trace_instr(const module_data_t* info) 521 | { 522 | dr_symbol_export_iterator_t* exp_iter = 523 | dr_symbol_export_iterator_start(info->handle); 524 | while (dr_symbol_export_iterator_hasnext(exp_iter)) { 525 | dr_symbol_export_t* sym = dr_symbol_export_iterator_next(exp_iter); 526 | if ((sym->is_code) && (sym->addr != NULL)) { 527 | dr_fprintf(global_trace_api_fp, " {\"address\" : \""PFX"\",\n", sym->addr); 528 | dr_fprintf(global_trace_api_fp, " \"name\" : \"%s\",\n", sym->name); 529 | dr_fprintf(global_trace_api_fp, " \"module\" : \"%s\"},\n", dr_module_preferred_name(info)); 530 | } 531 | } 532 | dr_symbol_export_iterator_stop(exp_iter); 533 | } 534 | 535 | static bool lib_is_not_blacklisted_trace_instr(const module_data_t* info) { 536 | 537 | char* blacklist[] = { "dynamorio.dll", "drmgr.dll", "ddr.dll", NULL }; 538 | int i = 0; 539 | while (blacklist[i]) { 540 | if (strstr(dr_module_preferred_name(info), blacklist[i++]) != NULL) 541 | return FALSE; 542 | } 543 | return TRUE; 544 | } 545 | 546 | static unsigned char* get_byte_string_trace_instr(unsigned char* bytesbuf, size_t bytesread, size_t *resultstr_size) { 547 | 548 | if (bytesread < 1) return NULL; 549 | 550 | unsigned int i; 551 | unsigned char* bytestr = (unsigned char*)dr_global_alloc(sizeof(unsigned char) * (bytesread * 3 + 1)); 552 | unsigned char* bytestr_tmp = bytestr; 553 | unsigned char c; 554 | for (i = 0; i < bytesread; i++) { 555 | c = *(bytesbuf + i); 556 | dr_snprintf(bytestr_tmp, 4, "%02x ", c); 557 | bytestr_tmp += 3; 558 | } 559 | unsigned char* charstr = (unsigned char*)dr_global_alloc(sizeof(unsigned char) * (bytesread + 1)); 560 | unsigned char* charstr_tmp = charstr; 561 | for (i = 0; i < bytesread; i++) { 562 | c = *(bytesbuf + i); 563 | if ((c < 127) && (c > 31) && (c != 92) && (c != 34)) // exclude '\'=92 and "=34 for JSON comp. 564 | dr_snprintf(charstr_tmp++, 2, "%c", c); 565 | else 566 | dr_snprintf(charstr_tmp++, 2, "."); 567 | } 568 | 569 | *resultstr_size = strlen(bytestr) + strlen(charstr) + 3 + 1; //3 spaces in snprintf below 570 | unsigned char* resultstr = (unsigned char*)dr_global_alloc(sizeof(unsigned char) * (*resultstr_size)); 571 | if (resultstr) { 572 | dr_snprintf(resultstr, *resultstr_size, "%s %s", bytestr, charstr); 573 | 574 | dr_global_free(bytestr, sizeof(unsigned char) * (bytesread * 3 + 1)); 575 | dr_global_free(charstr, sizeof(unsigned char) * (bytesread + 1)); 576 | 577 | return resultstr; 578 | } 579 | else { 580 | dr_printf("[DDR] [ERROR] Failed to allocate memory in get_byte_string_trace_instr.\n"); 581 | dr_exit_process(1); 582 | } 583 | return NULL; 584 | } 585 | 586 | static void log_bytestream_trace_instr(file_t f, unsigned char* bytesbuf, size_t bytesread, app_pc memaddr, uint instr_mem_size) { 587 | 588 | size_t resultstr_size; 589 | 590 | char* bytesstr = get_byte_string_trace_instr(bytesbuf, bytesread, &resultstr_size); 591 | 592 | if (bytesstr) { 593 | dr_fprintf(f, " \"inst_mem_addr\" : \""PFX"\",\n", memaddr); 594 | dr_fprintf(f, " \"inst_mem_size\" : \""PFX"\",\n", instr_mem_size); 595 | dr_fprintf(f, " \"inst_mem_data\" : \"%s\",\n", bytesstr); 596 | dr_global_free(bytesstr, resultstr_size); 597 | } 598 | else { 599 | dr_fprintf(f, " \"inst_mem_addr\" : \""PFX"\",\n", memaddr); 600 | dr_fprintf(f, " \"inst_mem_size\" : \""PFX"\",\n", instr_mem_size); 601 | dr_fprintf(f, " \"inst_mem_data\" : \"NOT_DECODED\",\n"); 602 | } 603 | } 604 | 605 | static bool write_mem_data_trace_instr(file_t f, size_t numbytes, app_pc memaddr, char* json_field_str) { 606 | char* bytesbuf, * bytesstr; 607 | size_t bytesread; 608 | size_t resultstr_size; 609 | 610 | bytesbuf = (char*)dr_global_alloc(sizeof(char) * numbytes); 611 | if (bytesbuf) { 612 | dr_safe_read(memaddr, numbytes, bytesbuf, &bytesread); 613 | 614 | bytesstr = get_byte_string_trace_instr(bytesbuf, bytesread, &resultstr_size); 615 | if (bytesstr) { 616 | // only add to JSON file if not NULL 617 | dr_fprintf(f, ",\n"); 618 | dr_fprintf(f, " \"%s\" : \"%s\"", json_field_str, bytesstr); 619 | dr_global_free(bytesstr, resultstr_size); 620 | dr_global_free(bytesbuf, sizeof(char) * numbytes); 621 | return TRUE; 622 | } 623 | else { 624 | dr_global_free(bytesbuf, sizeof(char) * numbytes); 625 | return FALSE; 626 | } 627 | } 628 | else { 629 | dr_printf("[DDR] [ERROR] Failed to allocate memory in write_mem_data_trace_instr."); 630 | dr_exit_process(1); 631 | } 632 | return FALSE; 633 | } 634 | 635 | static bool write_mem_to_file_trace_instr(file_t f, ssize_t numbytes, app_pc memaddr) { 636 | char* bytesbuf; 637 | ssize_t bytesread; 638 | ssize_t byteswritten; 639 | 640 | bytesbuf = (char*)dr_global_alloc(sizeof(char) * numbytes); 641 | dr_safe_read(memaddr, numbytes, bytesbuf, &bytesread); 642 | dr_printf("[DDR] [INFO] Bytes read: %d\n", bytesread); 643 | 644 | byteswritten = dr_write_file(f, bytesbuf, numbytes); 645 | dr_printf("[DDR] [INFO] Bytes written: %d\n", byteswritten); 646 | 647 | if (bytesbuf) { 648 | dr_global_free(bytesbuf, sizeof(char) * numbytes); 649 | return FALSE; 650 | } 651 | } 652 | 653 | static void write_src_op_to_logfile_trace_instr(file_t f, instr_t* instr, app_pc memaddr_src0, size_t bytesread, size_t numbytes) { 654 | 655 | size_t memaddr_src0_ptr; 656 | 657 | dr_fprintf(f, " \"inst_mem_addr_src0\" : \""PFX"\"", memaddr_src0); 658 | write_mem_data_trace_instr(f, numbytes, memaddr_src0, "inst_mem_addr_src0_data"); 659 | dr_safe_read(memaddr_src0, sizeof(size_t), &memaddr_src0_ptr, &bytesread); 660 | dr_fprintf(f, ",\n \"inst_mem_addr_src0_data_ptr\" : \""PFX"\"", memaddr_src0_ptr); 661 | write_mem_data_trace_instr(f, numbytes, (app_pc)memaddr_src0_ptr, "inst_mem_addr_src0_data_ptr_data"); 662 | 663 | } 664 | 665 | static void log_instr_opnds_trace_instr(file_t f, instr_t* instr, dr_mcontext_t* mc, void* drcontext, size_t numbytes) { 666 | 667 | int num_dsts = 0, num_srcs = 0; 668 | opnd_t opnd_src0, opnd_dst0; 669 | app_pc memaddr_src0, memaddr_dst0; 670 | size_t memaddr_src0_ptr, memaddr_dst0_ptr; 671 | size_t bytesread = 0; 672 | reg_id_t reg; 673 | 674 | num_dsts = instr_num_dsts(instr); 675 | num_srcs = instr_num_srcs(instr); 676 | 677 | // --- handle memory access of special instructions --- : 678 | 679 | // direct call 680 | if (instr_is_call_direct(instr)) { 681 | 682 | opnd_src0 = instr_get_src(instr, 0); 683 | 684 | if (my_opnd_is_reg(opnd_src0)) { 685 | reg = opnd_get_reg(opnd_src0); 686 | memaddr_src0 = (app_pc)reg_get_value(reg, mc); 687 | } 688 | else { 689 | memaddr_src0 = opnd_get_pc(opnd_src0); 690 | } 691 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 692 | return; 693 | } 694 | // indirect call 695 | if (instr_is_call_indirect(instr)) { 696 | 697 | opnd_src0 = instr_get_src(instr, 0); 698 | if (my_opnd_is_reg(opnd_src0)) { 699 | reg = opnd_get_reg(opnd_src0); 700 | memaddr_src0 = (app_pc)reg_get_value(reg, mc); 701 | } 702 | else { 703 | memaddr_src0 = my_opnd_compute_address(opnd_src0, mc); 704 | } 705 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 706 | return; 707 | } 708 | 709 | // ret 710 | if (instr_is_return(instr)) { 711 | 712 | opnd_src0 = instr_get_src(instr, 0); 713 | if (my_opnd_is_reg(opnd_src0)) { 714 | reg = opnd_get_reg(opnd_src0); 715 | memaddr_src0 = (app_pc)reg_get_value(reg, mc); 716 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 717 | } 718 | 719 | if (opnd_is_immed(opnd_src0)) { 720 | memaddr_src0 = (app_pc) opnd_get_immed_int(opnd_src0); 721 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 722 | } 723 | 724 | return; 725 | } 726 | 727 | // unconditional direct branch (jmp, etc) 728 | if (instr_is_ubr(instr)) { 729 | 730 | opnd_src0 = instr_get_src(instr, 0); 731 | memaddr_src0 = opnd_get_pc(opnd_src0); 732 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 733 | return; 734 | } 735 | 736 | // conditional branch 737 | if (instr_is_cbr(instr)) { 738 | if (light_trace_only) { 739 | // skip if jump is not taken 740 | if (!instr_jcc_taken(instr, mc->xflags)) { 741 | dr_file_seek(f, -2, DR_SEEK_CUR); 742 | dr_fprintf(f, "\n"); 743 | return; 744 | } 745 | } 746 | opnd_src0 = instr_get_src(instr, 0); 747 | memaddr_src0 = opnd_get_pc(opnd_src0); 748 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 749 | return; 750 | } 751 | 752 | // Don't log anything further if light_trace_only is set 753 | if (light_trace_only) { 754 | // Delete last comma 755 | dr_file_seek(f, -2, DR_SEEK_CUR); 756 | dr_fprintf(f, "\n"); 757 | return; 758 | } 759 | 760 | // push 761 | if (instr_get_opcode(instr) == OP_push || instr_get_opcode(instr) == OP_push_imm) { 762 | opnd_src0 = instr_get_src(instr, 0); 763 | 764 | // operant is register 765 | if (my_opnd_is_reg(opnd_src0)) { 766 | reg = opnd_get_reg(opnd_src0); 767 | memaddr_src0 = (app_pc)reg_get_value(reg, mc); //TBD check typecast 768 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 769 | return; 770 | } 771 | // anyhing else 772 | else { 773 | memaddr_src0 = my_opnd_compute_address(opnd_src0, mc); 774 | write_src_op_to_logfile_trace_instr(f, instr, memaddr_src0, bytesread, numbytes); 775 | return; 776 | } 777 | } 778 | 779 | // CMP 780 | if (instr_get_opcode(instr) == OP_cmp) { 781 | dr_fprintf(f, " \"inst_mem_instr_opname_cmp\" : \"%s\",\n", decode_opcode_name(instr_get_opcode(instr))); 782 | 783 | opnd_src0 = instr_get_src(instr, 0); 784 | opnd_dst0 = instr_get_src(instr, 1); 785 | 786 | // src operant is register 787 | if (my_opnd_is_reg(opnd_src0)) { 788 | reg = opnd_get_reg(opnd_src0); 789 | memaddr_src0 = (app_pc)reg_get_value(reg, mc); //TBD check typecast 790 | dr_fprintf(f, " \"inst_mem_addr_src0\" : \""PFX"\"", memaddr_src0); 791 | write_mem_data_trace_instr(f, numbytes, memaddr_src0, "inst_mem_addr_src0_data"); 792 | dr_fprintf(f, ",\n"); 793 | } 794 | // src operant is anyhing else 795 | else { 796 | memaddr_src0 = my_opnd_compute_address(opnd_src0, mc); 797 | dr_fprintf(f, " \"inst_mem_addr_src0\" : \""PFX"\"", memaddr_src0); 798 | write_mem_data_trace_instr(f, numbytes, memaddr_src0, "inst_mem_addr_src0_data"); 799 | dr_fprintf(f, ",\n"); 800 | } 801 | 802 | // dst operant is register 803 | if (my_opnd_is_reg(opnd_dst0)) { 804 | reg = opnd_get_reg(opnd_dst0); 805 | memaddr_dst0 = (app_pc)reg_get_value(reg, mc); //TBD check typecast 806 | dr_fprintf(f, " \"inst_mem_addr_dst0\" : \""PFX"\"", memaddr_dst0); 807 | write_mem_data_trace_instr(f, numbytes, memaddr_dst0, "inst_mem_addr_dst0_data"); 808 | return; 809 | } 810 | // dst operant is anyhing else 811 | else { 812 | memaddr_dst0 = my_opnd_compute_address(opnd_dst0, mc); 813 | dr_fprintf(f, " \"inst_mem_addr_dst0\" : \""PFX"\"", memaddr_dst0); 814 | write_mem_data_trace_instr(f, numbytes, memaddr_dst0, "inst_mem_addr_dst0_data"); 815 | return; 816 | } 817 | } 818 | 819 | // --- handle all other instructions --- : 820 | if (((num_dsts > 0) && (num_dsts < MAX_NUM_DSTS_OP)) || (num_srcs > 0) && (num_dsts < MAX_NUM_SRCS_OP)) 821 | dr_fprintf(f, " \"inst_mem_instr_opname\" : \"%s\",\n", decode_opcode_name(instr_get_opcode(instr))); 822 | else 823 | dr_fprintf(f, " \"inst_mem_instr_opname\" : \"%s\"", decode_opcode_name(instr_get_opcode(instr))); 824 | 825 | // destination operant 826 | if ((num_dsts > 0) && (num_dsts < MAX_NUM_DSTS_OP)) { // '&& num_dsts < 3' covers dynamoRio bug 827 | 828 | opnd_dst0 = instr_get_dst(instr, 0); 829 | 830 | // op is register 831 | if (my_opnd_is_reg(opnd_dst0)) { 832 | reg = opnd_get_reg(opnd_dst0); 833 | memaddr_dst0 = (app_pc)reg_get_value(reg, mc); 834 | dr_fprintf(f, " \"inst_mem_addr_dst0\" : \""PFX"\"", memaddr_dst0); 835 | write_mem_data_trace_instr(f, numbytes, memaddr_dst0, "inst_mem_addr_dst0_data"); 836 | } 837 | // op is not a register 838 | else { 839 | memaddr_dst0 = my_opnd_compute_address(opnd_dst0, mc); 840 | dr_fprintf(f, " \"inst_mem_addr_dst0\" : \""PFX"\"", memaddr_dst0); 841 | write_mem_data_trace_instr(f, numbytes, memaddr_dst0, "inst_mem_addr_dst0_data"); 842 | } 843 | 844 | // the op is a memory reference 845 | if (opnd_is_memory_reference(opnd_dst0)) { 846 | dr_fprintf(f, ",\n"); 847 | dr_safe_read(memaddr_dst0, sizeof(size_t), &memaddr_dst0_ptr, &bytesread); 848 | dr_fprintf(f, " \"inst_mem_addr_dst0_data_ptr\" : \""PFX"\"", memaddr_dst0_ptr); 849 | write_mem_data_trace_instr(f, numbytes, (app_pc)memaddr_dst0_ptr, "inst_mem_addr_dst0_data_ptr_data"); 850 | } 851 | 852 | } 853 | // source operant 854 | if ((num_srcs > 0) && (num_dsts < MAX_NUM_SRCS_OP)) { // '&& num_dsts < 3' covers dynamoRio bug 855 | if ((num_dsts > 0) && (num_dsts < MAX_NUM_DSTS_OP)) 856 | dr_fprintf(f, ",\n"); 857 | 858 | opnd_src0 = instr_get_src(instr, 0); 859 | 860 | // op is register 861 | if (my_opnd_is_reg(opnd_src0)) { 862 | reg = opnd_get_reg(opnd_src0); 863 | memaddr_src0 = (app_pc)reg_get_value(reg, mc); 864 | dr_fprintf(f, " \"inst_mem_addr_src0\" : \""PFX"\"", memaddr_src0); 865 | write_mem_data_trace_instr(f, numbytes, memaddr_src0, "inst_mem_addr_src0_data"); 866 | } 867 | // op is not a register 868 | else { 869 | memaddr_src0 = my_opnd_compute_address(opnd_src0, mc); 870 | dr_fprintf(f, " \"inst_mem_addr_src0\" : \""PFX"\"", memaddr_src0); 871 | write_mem_data_trace_instr(f, numbytes, memaddr_src0, "inst_mem_addr_src0_data"); 872 | } 873 | 874 | // the op is a memory reference 875 | if (opnd_is_memory_reference(opnd_src0)) { 876 | dr_fprintf(f, ",\n"); 877 | dr_safe_read(memaddr_src0, sizeof(size_t), &memaddr_src0_ptr, &bytesread); 878 | dr_fprintf(f, " \"inst_mem_addr_src0_data_ptr\" : \""PFX"\"", memaddr_src0_ptr); 879 | write_mem_data_trace_instr(f, numbytes, (app_pc)memaddr_src0_ptr, "inst_mem_addr_src0_data_ptr_data"); 880 | } 881 | 882 | // --- Code for detecting an DynamoRIO bug with instr_t init --- 883 | if (num_dsts > MAX_NUM_DSTS_OP - 1) { 884 | dr_fprintf(f, "!! -- fail -- !!"); // break JSON format to generate error in IDA plugin, remove if you don't want this 885 | dr_fprintf(f, ",\n"); 886 | dr_fprintf(f, " \"inst_mem_addr_dst0_fail\" : \"DR_BUG_DETECTED\",\n"); 887 | dr_fprintf(f, " \"inst_mem_addr_dst0_num_dsts\" : \"%d\"", num_dsts); 888 | num_dsts = 0; 889 | } 890 | if (num_srcs > MAX_NUM_SRCS_OP - 1) { 891 | dr_fprintf(f, "!! -- fail -- !!"); // break JSON format to generate error in IDA plugin, remove if you don't want this 892 | dr_fprintf(f, ",\n"); 893 | dr_fprintf(f, ",\n"); 894 | dr_fprintf(f, " \"inst_mem_addr_src0_fail\" : \"DR_BUG_DETECTED\",\n"); 895 | dr_fprintf(f, " \"inst_mem_addr_src0_num_srcs\" : \"%d\"", num_srcs); 896 | num_srcs = 0; 897 | } 898 | // --- End --- 899 | 900 | // --- Maybe used in a future feature --- 901 | /* 902 | if (opnd_is_abs_addr(opnd_src0)) 903 | dr_fprintf(f, " \"opnd_is_abs_addr\" : \"true\"\n"); 904 | if (opnd_is_immed(opnd_src0)) 905 | dr_fprintf(f, " \"opnd_is_immed\" : \"true\"\n"); 906 | if (opnd_is_memory_reference(opnd_src0)) 907 | dr_fprintf(f, " \"opnd_is_memory_reference\" : \"true\"\n"); 908 | if (opnd_is_rel_addr(opnd_src0)) 909 | dr_fprintf(f, " \"opnd_is_rel_addr\" : \"true\"\n"); 910 | if (opnd_is_pc(opnd_src0)) 911 | dr_fprintf(f, " \"opnd_is_pc\" : \"true\"\n"); 912 | */ 913 | // --- End of maybe used in a future feature --- 914 | } 915 | } 916 | 917 | static void log_mem_at_reg_trace_instr(app_pc memaddr, char* regstr, file_t f) { 918 | 919 | size_t bytesread; 920 | size_t bytesbuf_len = 16; 921 | size_t resultstr_size; 922 | char* bytesstr; 923 | char* bytesbuf = (char*)dr_global_alloc(sizeof(char) * bytesbuf_len); 924 | 925 | if (dr_safe_read(memaddr, 16, bytesbuf, &bytesread)) { 926 | 927 | bytesstr = get_byte_string_trace_instr(bytesbuf, bytesread, &resultstr_size); 928 | if (bytesstr) { 929 | dr_fprintf(f, " \"%s_ptr_data\" : \"%s\",\n", regstr, bytesstr); 930 | dr_global_free(bytesstr, strlen(bytesstr) + 1); 931 | dr_global_free(bytesbuf, sizeof(char) * bytesbuf_len); 932 | return; 933 | } 934 | else { 935 | dr_global_free(bytesbuf, sizeof(char) * bytesbuf_len); 936 | } 937 | } 938 | dr_fprintf(f, " \"%s_ptr_data\" : \"NO_DATA\",\n", regstr); 939 | } 940 | 941 | static void handler_instr_is_return(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes) { 942 | return; 943 | } 944 | 945 | static void handler_instr_is_call(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes) { 946 | return; 947 | } 948 | 949 | static void handler_instr_is_pop(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes) { 950 | return; 951 | } 952 | 953 | static void handler_instr_interesting_instr(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes) { 954 | opnd_t op = instr_get_src(instr, 0); 955 | app_pc memaddr = my_opnd_compute_address(op, mc); 956 | size_t bytesread; 957 | 958 | uint instr_mem_size = instr_memory_reference_size(instr); 959 | 960 | char* bytesbuf = (char*)dr_global_alloc(sizeof(char) * numbytes); 961 | dr_safe_read(memaddr, numbytes, bytesbuf, &bytesread); 962 | 963 | log_bytestream_trace_instr(f, bytesbuf, bytesread, memaddr, instr_mem_size); 964 | 965 | dr_global_free(bytesbuf, sizeof(char) * numbytes); 966 | return; 967 | } 968 | 969 | static void handler_all_other_mem_instr(file_t f, instr_t* instr, dr_mcontext_t* mc, size_t numbytes) { 970 | 971 | opnd_t op = instr_get_src(instr, 0); 972 | app_pc memaddr = my_opnd_compute_address(op, mc); 973 | size_t bytesread; 974 | 975 | uint instr_mem_size = instr_memory_reference_size(instr); 976 | 977 | char* bytesbuf = (char*)dr_global_alloc(sizeof(char) * numbytes); 978 | dr_safe_read(memaddr, numbytes, bytesbuf, &bytesread); 979 | 980 | log_bytestream_trace_instr(f, bytesbuf, bytesread, memaddr, instr_mem_size); 981 | 982 | dr_global_free(bytesbuf, sizeof(char) * numbytes); 983 | 984 | return; 985 | } 986 | 987 | 988 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_helper_functions.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_helper_functions.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.Build.CppClean.log: -------------------------------------------------------------------------------- 1 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\vc142.pdb 2 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\vc142.idb 3 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\trace_instr.obj 4 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\patch_exe.obj 5 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\main.obj 6 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\dump_buffer1.obj 7 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_helper_functions.obj 8 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\debug\ddr_stable.lib 9 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\debug\ddr_stable.exp 10 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\debug\ddr_stable.pdb 11 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\cl.command.1.tlog 12 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\cl.read.1.tlog 13 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\cl.write.1.tlog 14 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\ddr_stable.write.1u.tlog 15 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.10364-cvtres.read.1.tlog 16 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.10364-cvtres.write.1.tlog 17 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.10364-rc.read.1.tlog 18 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.10364-rc.write.1.tlog 19 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.10364.read.1.tlog 20 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.10364.write.1.tlog 21 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.command.1.tlog 22 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.read.1.tlog 23 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\debug\ddr_stable.tlog\link.write.1.tlog 24 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.dll.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | C:\tools\dev\git\DynDataResolver\ddr_client\x64\Debug\ddr_stable.dll 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.log: -------------------------------------------------------------------------------- 1 |  ddr_helper_functions.c 2 | dump_buffer1.c 3 | main.c 4 | patch_exe.c 5 | trace_instr.c 6 | Generating Code... 7 | ddr_stable.vcxproj -> C:\tools\dev\git\DynDataResolver\ddr_client\x64\Debug\ddr_stable.dll 8 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/ddr_stable.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.18362.0: 2 | Debug|x64|C:\tools\dev\git\DynDataResolver\ddr_client\| 3 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/ddr_stable.write.1u.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/ddr_stable.write.1u.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/link.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/link.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/link.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/link.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/link.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.tlog/link.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/ddr_stable.vcxproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/ddr_stable.vcxproj.FileListAbsolute.txt -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/dump_buffer1.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/dump_buffer1.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/main.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/main.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/patch_exe.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/patch_exe.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/trace_instr.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/trace_instr.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/vc142.idb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/vc142.idb -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Debug/vc142.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Debug/vc142.pdb -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_helper_functions.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_helper_functions.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.Build.CppClean.log: -------------------------------------------------------------------------------- 1 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\vc142.pdb 2 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\trace_instr.obj 3 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\patch_exe.obj 4 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\main.obj 5 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\dump_buffer1.obj 6 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_helper_functions.obj 7 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\release\ddr_stable.lib 8 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\release\ddr_stable.exp 9 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\release\ddr_stable.ipdb 10 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\release\ddr_stable.iobj 11 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\release\ddr_stable.dll 12 | c:\tools\dev\git\dyndataresolver\ddr_client\x64\release\ddr_stable.pdb 13 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_stable.tlog\cl.command.1.tlog 14 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_stable.tlog\cl.read.1.tlog 15 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_stable.tlog\cl.write.1.tlog 16 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_stable.tlog\ddr_stable.write.1u.tlog 17 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_stable.tlog\link.command.1.tlog 18 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_stable.tlog\link.read.1.tlog 19 | c:\tools\dev\git\dyndataresolver\ddr_client\ddr_stable\x64\release\ddr_stable.tlog\link.write.1.tlog 20 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.dll.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | C:\tools\dev\git\DynDataResolver\ddr_client\x64\Release\ddr_stable.dll 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.log: -------------------------------------------------------------------------------- 1 |  ddr_helper_functions.c 2 | dump_buffer1.c 3 | main.c 4 | patch_exe.c 5 | trace_instr.c 6 | Creating library C:\tools\dev\git\DynDataResolver\ddr_client\x64\Release\ddr_stable.lib and object C:\tools\dev\git\DynDataResolver\ddr_client\x64\Release\ddr_stable.exp 7 | Generating code 8 | 11 of 56 functions (19.6%) were compiled, the rest were copied from previous compilation. 9 | 3 functions were new in current compilation 10 | 2 functions had inline decision re-evaluated but remain unchanged 11 | Finished generating code 12 | ddr_stable.vcxproj -> C:\tools\dev\git\DynDataResolver\ddr_client\x64\Release\ddr_stable.dll 13 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/ddr_stable.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.18362.0: 2 | Release|x64|C:\tools\dev\git\DynDataResolver\ddr_client\| 3 | -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/ddr_stable.write.1u.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/ddr_stable.write.1u.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/link.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/link.command.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/link.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/link.read.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/link.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.tlog/link.write.1.tlog -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/ddr_stable.vcxproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/ddr_stable.vcxproj.FileListAbsolute.txt -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/dump_buffer1.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/dump_buffer1.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/main.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/main.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/patch_exe.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/patch_exe.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/trace_instr.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/trace_instr.obj -------------------------------------------------------------------------------- /ddr_client/ddr_stable/x64/Release/vc142.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/ddr_stable/x64/Release/vc142.pdb -------------------------------------------------------------------------------- /ddr_client/x64/Debug/ddr_stable.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Debug/ddr_stable.dll -------------------------------------------------------------------------------- /ddr_client/x64/Debug/ddr_stable.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Debug/ddr_stable.exp -------------------------------------------------------------------------------- /ddr_client/x64/Debug/ddr_stable.ilk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Debug/ddr_stable.ilk -------------------------------------------------------------------------------- /ddr_client/x64/Debug/ddr_stable.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Debug/ddr_stable.lib -------------------------------------------------------------------------------- /ddr_client/x64/Debug/ddr_stable.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Debug/ddr_stable.pdb -------------------------------------------------------------------------------- /ddr_client/x64/Release/ddr_stable.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Release/ddr_stable.dll -------------------------------------------------------------------------------- /ddr_client/x64/Release/ddr_stable.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Release/ddr_stable.exp -------------------------------------------------------------------------------- /ddr_client/x64/Release/ddr_stable.iobj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Release/ddr_stable.iobj -------------------------------------------------------------------------------- /ddr_client/x64/Release/ddr_stable.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Release/ddr_stable.ipdb -------------------------------------------------------------------------------- /ddr_client/x64/Release/ddr_stable.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Release/ddr_stable.lib -------------------------------------------------------------------------------- /ddr_client/x64/Release/ddr_stable.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_client/x64/Release/ddr_stable.pdb -------------------------------------------------------------------------------- /ddr_installer.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer.zip -------------------------------------------------------------------------------- /ddr_installer/DDR_INSTALLER.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # 3 | # IDA Pro Plug-in: Dynamic Data Resolver (DDR) Server Installer script 4 | # 5 | # Version 1.0 6 | # 7 | # Copyright (C) 2020 Cisco Talos 8 | # Author: Holger Unterbrink (hunterbr@cisco.com) 9 | # 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License along 21 | # with this program; if not, write to the Free Software Foundation, Inc., 22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | # 24 | # ------------------------------------------------------------------------------ 25 | # 26 | # Hint: This script does not have any dependencies. All non default dependencies 27 | # will be installed into a virtual envirmoent at run time. 28 | # 29 | # ------------------------------------------------------------------------------ 30 | 31 | import venv 32 | import os 33 | import sys 34 | import subprocess 35 | import pathlib 36 | import time 37 | import os 38 | import sys 39 | import subprocess 40 | import importlib 41 | import tempfile 42 | import zipfile 43 | import glob 44 | import shutil 45 | import string 46 | import random 47 | import re 48 | import platform 49 | from distutils.dir_util import copy_tree 50 | 51 | # IDA DDR plugin globals 52 | IDA_PLUGIN_ZIP = "ddr_plugin.zip" 53 | DDR_PLUGIN_SRCPATH = "ddr_plugin" 54 | IDA_DEFAULT_INSTALL_DIR = os.getenv('ProgramW6432') + "\\IDA Pro 7.5" 55 | IDA_DEFAULT_PLUGIN_DIR = os.getenv('APPDATA') + "\\Hex-Rays\\IDA Pro\\plugins" 56 | IDA_DEFAULT_PYTHON_PATH = os.getenv('ProgramW6432') + "\\Python38" 57 | 58 | # DDR Server 59 | DYNRIO_DOWNLOAD_URL = r"https://github.com/DynamoRIO/dynamorio/releases/download/release_8.0.0-1/DynamoRIO-Windows-8.0.0-1.zip" 60 | #DYNRIO_DOWNLOAD_URL_LATEST = r"https://github.com/DynamoRIO/dynamorio/releases/download/cronbuild-8.0.18547/DynamoRIO-Windows-8.0.18547.zip" 61 | DYNRIO_DOWNLOAD_URL_LATEST = r"https://github.com/DynamoRIO/dynamorio/releases/download/cronbuild-8.0.18585/DynamoRIO-Windows-8.0.18585.zip" 62 | DDRSERVER_CONFIG_FILE_TEMPLATE = "templates\\ddr_server_template.json" 63 | DDRSERVER_CONFIG_FILE = "ddr_server.cfg" 64 | DDRSERVER_VERSION = "1.02 beta" 65 | APILOGGING = "DEBUG" 66 | DEBUG_API_JSON = "false" 67 | MY_FQDN = "malwarehost.local" # only used as name in the certificate, no DNS required. 68 | MAX_CFG_LINE_LENGTH = 356 69 | DDR_DLL32 = "ddr32.dll" 70 | DDR_DLL64 = "ddr64.dll" 71 | DDR_CERT_FILENAME = "ddr_server.crt" 72 | DDR_CERT_KEY_FILENAME = "ddr_server.key" 73 | DDR_APIKEY_FILE = "ddr_apikey.txt" 74 | DDR_APIKEY = "not set" 75 | DDR_VIRTENV_NAME = "ddr_venv" 76 | MAX_INSTALL_DIR = 160 77 | DDR_SERVER_IP = "0.0.0.0" 78 | DDR_SERVER_PORT = "5000" 79 | 80 | def proceed(question): 81 | """ 82 | Do you want to proceed [Y/n]. Returns True if 'yes' and False if 'no' 83 | """ 84 | valid = ["y"] 85 | 86 | while True: 87 | sys.stdout.write(question) 88 | choice = input().lower() 89 | if choice == '': 90 | return True 91 | elif choice == 'y': 92 | return True 93 | else: 94 | return False 95 | 96 | def is_venv(): 97 | """ 98 | Do we run in a virtual enviroment 99 | """ 100 | return (hasattr(sys, 'real_prefix') or 101 | (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)) 102 | 103 | def get_ida_dir(): 104 | print("[DDR_PLUGIN_INSTALLER][INFO] Please enter the IDA installation directory.") 105 | print("[DDR_PLUGIN_INSTALLER][INFO] Default is {}".format(IDA_DEFAULT_INSTALL_DIR)) 106 | ida_dir = input("[DDR_PLUGIN_INSTALLER][INFO] IDA installation directory: ") or IDA_DEFAULT_INSTALL_DIR 107 | print() 108 | return ida_dir 109 | 110 | def get_ida_plugin_dir(): 111 | print("[DDR_PLUGIN_INSTALLER][INFO] Please go to IDA and find out where the user plugin directory is.") 112 | print("[DDR_PLUGIN_INSTALLER][INFO] You can do that by entering the follwing into the Python command prompt of IDA:") 113 | print("[DDR_PLUGIN_INSTALLER][INFO] print(os.path.join(idaapi.get_user_idadir(), \"plugins\"))") 114 | print("[DDR_PLUGIN_INSTALLER][INFO] Default plugin directory is {}".format(IDA_DEFAULT_PLUGIN_DIR)) 115 | ida_plugin_dir = input("[DDR_PLUGIN_INSTALLER][INFO] IDA plugin directory: ") or IDA_DEFAULT_PLUGIN_DIR 116 | print() 117 | return ida_plugin_dir 118 | 119 | def get_ida_python_version(): 120 | print("[DDR_PLUGIN_INSTALLER][INFO] Please go to IDA and find out which Python version IDA is using.") 121 | print("[DDR_PLUGIN_INSTALLER][INFO] You can do that by entering the follwing into the Python command prompt of IDA:") 122 | print("[DDR_PLUGIN_INSTALLER][INFO] print(sys.exec_prefix)") 123 | print("[DDR_PLUGIN_INSTALLER][INFO] Default plugin directory is {}".format(IDA_DEFAULT_PYTHON_PATH)) 124 | ida_python_path = input("[DDR_PLUGIN_INSTALLER][INFO] Please enter the IDA Python directory path: ") or IDA_DEFAULT_PYTHON_PATH 125 | print() 126 | return ida_python_path 127 | 128 | def create_apikey(apikey_file): 129 | """ 130 | Generate API key 131 | """ 132 | global DDR_APIKEY 133 | 134 | try: 135 | DDR_APIKEY = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(24)) 136 | with open(apikey_file, "w") as text_file: 137 | text_file.write("{}".format(DDR_APIKEY)) 138 | print("[DDR_INSTALLER][INFO] --------------------------------------------------------------------------------") 139 | print("[DDR_INSTALLER][INFO] Generated new API Key and wrote it to {}".format(apikey_file)) 140 | print("[DDR_INSTALLER][INFO] --------------------------------------------------------------------------------\n") 141 | return True 142 | except: 143 | print("[DDR_INSTALLER][ERROR] Genrating API Key file {} failed.".format(apikey_file)) 144 | raise 145 | return False 146 | 147 | def create_self_signed_cert(my_ipaddr, cert_file, key_file): 148 | """ 149 | Create self signed certificate and key 150 | """ 151 | 152 | print("We need a serial number for the certificate.") 153 | print("If this is the first time you are generating and using the certificate,") 154 | print("you can use the default number (1001). If this is not the first time, ") 155 | print("you should pick a higher number than you used the last time. Otherwise,") 156 | print("you might run into serial number re-use issues with some browsers.") 157 | cert_serial = input("Please enter the serial number for the certificate (Default: 1001) :") or "1001" 158 | cert_serial = int(cert_serial) 159 | 160 | # create a key pair 161 | k = OpenSSL.crypto.PKey() 162 | k.generate_key(OpenSSL.crypto.TYPE_RSA, 1024) 163 | 164 | # create a self-signed cert 165 | cert = OpenSSL.crypto.X509() 166 | cert.get_subject().C = "DE" # country of residence 167 | cert.get_subject().ST = "Berlin" # state of residence 168 | cert.get_subject().L = "SomeLocality" # locality 169 | cert.get_subject().O = "Talos" # organization 170 | cert.get_subject().OU = "Security" # organizational unit 171 | cert.get_subject().CN = my_ipaddr # common name IP or FQDN 172 | san_list = ["IP:" + my_ipaddr, "DNS:" + my_ipaddr] # subjectAltName list 173 | cert.add_extensions([ OpenSSL.crypto.X509Extension(b'subjectAltName', False, bytes(', '.join(san_list), 'utf-8'))]) 174 | cert.set_serial_number(1001) 175 | cert.gmtime_adj_notBefore(0) 176 | cert.gmtime_adj_notAfter(10*365*24*60*60) 177 | cert.set_issuer(cert.get_subject()) 178 | cert.set_pubkey(k) 179 | cert.sign(k, 'sha1') 180 | open(cert_file, "wt").write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert).decode()) 181 | open(key_file, "wt").write(OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, k).decode()) 182 | 183 | print("") 184 | print("[DDR_INSTALLER][INFO] -------------------------------------------------------------") 185 | print("[DDR_INSTALLER][INFO] Individual self signed certificate and secret key generated. ") 186 | print("[DDR_INSTALLER][INFO] DDR will use these credentials to encrypt the HTTPS traffic ") 187 | print("[DDR_INSTALLER][INFO] between the DDR IDA plugin and the DDR server. ") 188 | print("[DDR_INSTALLER][INFO] -------------------------------------------------------------") 189 | 190 | 191 | def load_mod(mod_name): 192 | """ 193 | Load modules at runtime by name stored in variable 194 | """ 195 | globals()[mod_name] = importlib.import_module(mod_name) 196 | 197 | def runcmd(my_cmd): 198 | """ 199 | Execute shell command 200 | """ 201 | 202 | print("[DDR_INSTALLER][INFO] Executing cmd: \n{}\n".format(my_cmd)) 203 | 204 | stdout = False 205 | stderr = False 206 | 207 | try: 208 | #process = subprocess.Popen(my_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 209 | #stdout, stderr = process.communicate() 210 | process = subprocess.run(my_cmd) 211 | 212 | if process.returncode != 0: 213 | print("\n[DDR_INSTALLER][WARNING] Command execution failed. Error code: {:d}".format(process.returncode)) 214 | ret = False 215 | else: 216 | ret = True 217 | 218 | # if stderr: 219 | # print("[DDR_INSTALLER][WARNING] Command execution failed. Stderr:") 220 | # print("{}".format(stderr.decode("utf-8"))) 221 | 222 | # ret['stderr'] = stderr 223 | # ret['status'] = False 224 | 225 | # if stdout: 226 | # print("[DDR_INSTALLER][INFO] Command execution stdout:") 227 | # print("{}".format(stdout.decode("utf-8"))) 228 | 229 | # ret['stdout'] = stdout 230 | # ret['status'] = True 231 | 232 | except : 233 | print("[DDR_INSTALLER][ERROR] Exception: Command execution failed with unknown error.") 234 | ret = False 235 | 236 | return ret 237 | 238 | def check_files_exist(files = [], dirs = []): 239 | """ 240 | Verify if the files and dirs configured exist 241 | """ 242 | ret = True 243 | 244 | for dir in dirs: 245 | if not os.path.isdir(dir): 246 | print("[DDR_INSTALLER][ERROR] Directory: {} not found.".format(dir)) 247 | ret = False 248 | 249 | for fname in files: 250 | if not os.path.isfile(fname): 251 | print("[DDR_INSTALLER][ERROR] File: {} not found.".format(fname)) 252 | ret = False 253 | 254 | return ret 255 | 256 | def zip_is_valid(zipfilename): 257 | """ 258 | Check if zipfilename is a valid zip file. Return True if valid. False if not valid. 259 | """ 260 | 261 | if not os.path.isfile(zipfilename): 262 | print("[DDR_INSTALLER][ERROR] Zip file not found.") 263 | return False 264 | 265 | try: 266 | zip_file = zipfile.ZipFile(zipfilename) 267 | res = zip_file.testzip() 268 | 269 | if res is not None: 270 | print("[DDR_INSTALLER][ERROR] Bad file in zip archive: {}".format(res)) 271 | return False 272 | else: 273 | return True 274 | except: 275 | print("[DDR_INSTALLER][ERROR] Zip file: {} is corrupt.".format(zipfilename)) 276 | os.remove(zipfilename) 277 | print("[DDR_INSTALLER][ERROR] Corrupt zip file: {} deleted.".format(zipfilename)) 278 | return False 279 | 280 | def download_zip_and_unpack(unpack_dir, url): 281 | """ 282 | Download zip file from url and unpack it to directory unpack_dir. Verify if zip file is valid. 283 | Return True if successfully downloaded file and deleted the temp. files. 284 | Return False if anything went wrong. 285 | """ 286 | print("Downloading from url: {}".format(url)) 287 | zipfilename = tempfile.gettempdir() + "\\tmp.zip" 288 | 289 | with requests.get(url, stream=True) as res: 290 | if res.status_code == 200: 291 | with open(zipfilename, 'wb') as f: 292 | total_length = int(res.headers.get('content-length')) 293 | for chunk in clint.textui.progress.bar(res.iter_content(chunk_size=1024), expected_size=(total_length/1024) + 1): 294 | if chunk: 295 | f.write(chunk) 296 | f.flush() 297 | print("\n[DDR_INSTALLER] [INFO] File downloaded.") 298 | else: 299 | print("[DDR_INSTALLER] [ERROR] Download failed.") 300 | 301 | # Verify zip file is valid 302 | if not zip_is_valid(zipfilename): 303 | print("[DDR_INSTALLER] [ERROR] Zip file verification failed.") 304 | return False 305 | 306 | # check if unpack_dir exists otherwise create it 307 | pathlib.Path(unpack_dir).mkdir(parents=True, exist_ok=True) 308 | 309 | # Extract files from zip archive 310 | with zipfile.ZipFile(zipfilename, "r") as ziparchive: 311 | print("[DDR_INSTALLER] [INFO] Extracting files to {}".format(unpack_dir)) 312 | ziparchive.extractall(unpack_dir) 313 | 314 | # Delete zip archive 315 | print("[DDR_INSTALLER] [INFO] Deleting downloaded archive: {}".format(zipfilename)) 316 | try: 317 | os.remove(zipfilename) 318 | except: 319 | print("[DDR_INSTALLER] [ERROR] Failed to delete zip file: {}".format(zipfilename)) 320 | pass 321 | 322 | return True 323 | 324 | def cpu_is_AMD(): 325 | """ 326 | Check if CPU is from AMD 327 | """ 328 | cpu = platform.processor() 329 | 330 | if "amd" in cpu.lower(): 331 | return True 332 | 333 | return False 334 | 335 | 336 | def install_deps(venv, ddr_default_dir): 337 | """ 338 | Main installer routine to install all neccessary 339 | dependencies for DDR 340 | """ 341 | 342 | global DDR_SERVER_IP 343 | global DDR_SERVER_PORT 344 | 345 | # update pip in virtual enviroment 346 | print("[DDR_INSTALLER][INFO] Updating pip in virtual enviroment.") 347 | my_cmd = venv + "\\Scripts\\activate.bat && " + "python -m pip install --upgrade pip" 348 | if runcmd(my_cmd): 349 | print("[DDR_INSTALLER][INFO] pip updated.") 350 | else: 351 | print("Failed to update pip.") 352 | return False 353 | 354 | # Install pip tools 355 | print("[DDR_INSTALLER][INFO] Installing pip-tools.") 356 | my_cmd = venv + "\\Scripts\\activate.bat && " + "pip install --upgrade pip-tools" 357 | if runcmd(my_cmd): 358 | print("[DDR_INSTALLER][INFO] pip tools installed.") 359 | else: 360 | print("Failed to install pip tools.") 361 | return False 362 | 363 | # Sync DDR Python dependencies 364 | # https://stackoverflow.com/questions/10333814/tell-pip-to-install-the-dependencies-of-packages-listed-in-a-requirement-file 365 | # 366 | print("[DDR_INSTALLER][INFO] Installing DDR Python dependencies.") 367 | my_cmd = venv + "\\Scripts\\activate.bat && " + "pip-sync" 368 | if runcmd(my_cmd): 369 | print("[DDR_INSTALLER][INFO] DDR Python dependencies installed and synchronized.") 370 | else: 371 | print("Failed to install DDR Python dependencies.") 372 | return False 373 | 374 | # Load non standard modules 375 | load_mod("requests") 376 | load_mod("clint") 377 | 378 | # Install DynamoRio 379 | if proceed("Should we proceed with downloading and installing DynamoRio to {} [Y/n] ?".format(ddr_default_dir)): 380 | if cpu_is_AMD(): 381 | print("[DDR_INSTALLER][WARNING] It seems to be you have an AMD CPU. There is a AMD CPU which makes DynamoRio fail in WOW64 operations.") 382 | print("[DDR_INSTALLER][WARNING] Details can be found here: https://github.com/DynamoRIO/dynamorio/issues/4091#") 383 | print("[DDR_INSTALLER][WARNING] with an AMD processor it is highly recommend to use the latest DynamoRio GIT version.") 384 | 385 | if proceed("Should we install the weekly package (recommended - includes AMD CPU bug fix) or the latest stable release. [W/S] ? ".format(ddr_default_dir)): 386 | print("[DDR_INSTALLER][WARNING] Installing weekly DynamoRio package:\n{}".format(DYNRIO_DOWNLOAD_URL_LATEST)) 387 | download_zip_and_unpack(ddr_default_dir, DYNRIO_DOWNLOAD_URL_LATEST) 388 | else: 389 | print("[DDR_INSTALLER][WARNING] Installing latest stable DynamoRio package:\n{}".format(DYNRIO_DOWNLOAD_URL_LATEST)) 390 | download_zip_and_unpack(ddr_default_dir, DYNRIO_DOWNLOAD_URL) 391 | 392 | try: 393 | dynrio_path = glob.glob(ddr_default_dir + '\\DynamoRIO-Windows*')[0] 394 | dynrio_run32 = dynrio_path + "\\bin32\\drrun.exe" 395 | dynrio_run64 = dynrio_path + "\\bin64\\drrun.exe" 396 | except: 397 | print("[DDR_INSTALLER][ERROR] DynamoRio installation not found.") 398 | return False 399 | 400 | if not check_files_exist(dirs = [dynrio_path]): 401 | print("[DDR_INSTALLER][ERROR] DynamoRio directory does not exist. Installation failed.") 402 | return False 403 | else: 404 | print("[DDR_INSTALLER][INFO] DynamoRio directory found.") 405 | 406 | if not check_files_exist(files = [dynrio_run32, dynrio_run64]): 407 | print("[DDR_INSTALLER][ERROR] DynamoRio drrun file(s) do not exist. Installation failed.") 408 | return False 409 | else: 410 | print("[DDR_INSTALLER][INFO] DynamoRio run binaries found.\n") 411 | 412 | # Network setup 413 | print("[DDR_INSTALLER][INFO] Network setup:") 414 | 415 | DDR_SERVER_PORT = input("[DDR_INSTALLER][INFO] Please enter server PORT to listen on (Default is 5000) :") or "5000" 416 | 417 | process = subprocess.run("ipconfig",stdout=subprocess.PIPE, stderr=subprocess.PIPE) 418 | data = process.stdout.decode() 419 | ip_list = re.findall(r'IPv4 Address.*: (\d+\.\d+\.\d+\.\d+)',data) 420 | ip_list = [(ip) for ip in ip_list if not ip.startswith("255")] 421 | 422 | if not ip_list: 423 | print("[DDR_INSTALLER][WARNING] Didn't find any local IP addresses on this machine.") 424 | print("[DDR_INSTALLER][WARNING] Keep in mind this address needs to be reachable from the DDR IDA plugin.") 425 | DDR_SERVER_IP = input("[DDR_INSTALLER][INFO] Pls enter the server IP address manually: ") 426 | 427 | else: 428 | print("[DDR_INSTALLER][INFO] Found the following IP addresses:") 429 | for num, ip in enumerate(ip_list): 430 | print("[{:d}] {}".format(num,ip)) 431 | 432 | DDR_SERVER_IP = input("[DDR_INSTALLER][INFO] Please choose server IP address (Default is 0) :") or "0" 433 | DDR_SERVER_IP = ip_list[int(DDR_SERVER_IP)] 434 | 435 | if DDR_SERVER_IP == "": 436 | print("[DDR_INSTALLER][ERROR] No server IP address found.") 437 | exit(1) 438 | 439 | print("[DDR_INSTALLER][INFO] server will listen on {}:{}".format(DDR_SERVER_IP, DDR_SERVER_PORT)) 440 | 441 | # Create Certificates and copy them to server directory 442 | ddr_escaped_default_dir = ddr_default_dir.replace("\\","\\\\") 443 | ddr_cert_file = ddr_escaped_default_dir + "\\\\" + DDR_CERT_FILENAME 444 | ddr_key_file = ddr_escaped_default_dir + "\\\\" + DDR_CERT_KEY_FILENAME 445 | load_mod("OpenSSL") 446 | create_self_signed_cert(DDR_SERVER_IP, ddr_cert_file, ddr_key_file) 447 | 448 | # Create DDR server API key file 449 | apikey_file = ddr_default_dir + "\\" + DDR_APIKEY_FILE 450 | escapced_apikey_file = apikey_file.replace("\\","\\\\") 451 | if not create_apikey(apikey_file): 452 | return False 453 | 454 | # Create DDR server config file 455 | with open(DDRSERVER_CONFIG_FILE_TEMPLATE, 'r') as f: 456 | ddrserver_cfg_file = f.read() 457 | 458 | escaped_dynrio_run32 = dynrio_run32.replace("\\","\\\\") 459 | escaped_dynrio_run64 = dynrio_run64.replace("\\","\\\\") 460 | escaped_venv = venv.replace("\\","\\\\") 461 | 462 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , DDRSERVER_VERSION) 463 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , APILOGGING) 464 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , DEBUG_API_JSON) 465 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , DDR_CERT_FILENAME) 466 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , DDR_CERT_KEY_FILENAME) 467 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , DDR_APIKEY_FILE) 468 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , DDR_SERVER_IP) 469 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , DDR_SERVER_PORT) 470 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , MY_FQDN) 471 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , ddr_escaped_default_dir) 472 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , escaped_venv) 473 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , str(MAX_CFG_LINE_LENGTH)) 474 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , escaped_dynrio_run32) 475 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , ddr_escaped_default_dir + "\\\\" + DDR_DLL32) 476 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , escaped_dynrio_run64) 477 | ddrserver_cfg_file = ddrserver_cfg_file.replace("" , ddr_escaped_default_dir + "\\\\" + DDR_DLL64) 478 | 479 | # save individualized config file 480 | ddrserver_cfg_filename = ddr_default_dir + "\\" + DDRSERVER_CONFIG_FILE 481 | with open(ddrserver_cfg_filename, 'w') as f: 482 | f.write(ddrserver_cfg_file) 483 | print("[DDR_INSTALLER][INFO] Wrote DDR server configuration to {}".format(ddrserver_cfg_filename)) 484 | 485 | # copy DDR files to installation directory 486 | filename_list = [ "ddr_server.py", DDR_DLL32, DDR_DLL64] 487 | for fn in filename_list: 488 | shutil.copyfile( "install_data\\" + fn, ddr_default_dir + "\\" + fn) 489 | print("[DDR_INSTALLER][INFO] Copied file: {}".format(fn)) 490 | 491 | return True 492 | 493 | def built_plugin_zip(ddr_default_dir): 494 | 495 | ida_plugin_tmp = "install_data\\ddr_plugin" 496 | ida_plugin_cfg_template = "templates\\ddr_config_template.json" 497 | ida_plugin_install_template = "templates\\ida_plugin_installer_template.py" 498 | ida_install_dir = get_ida_dir() 499 | ida_plugin_dir = get_ida_plugin_dir() 500 | ida_python_path = get_ida_python_version() 501 | 502 | print("[DDR_INSTALLER][INFO] Using the following directories:") 503 | print("[DDR_INSTALLER][INFO] IDA install dir: {}".format(ida_install_dir)) 504 | print("[DDR_INSTALLER][INFO] IDA plugin dir : {}".format(ida_plugin_dir)) 505 | print("[DDR_INSTALLER][INFO] IDA Python dir : {}\n".format(ida_python_path)) 506 | 507 | if not proceed("[DDR_INSTALLER][INFO] Is this correct ? [Y/n]"): 508 | exit(1) 509 | 510 | # copy plugin, plugin config file and cert file 511 | filename_list = [ "ddr_server.crt" ] 512 | os.makedirs(ida_plugin_tmp + "\\ddr", exist_ok=True) 513 | for fn in filename_list: 514 | cf = shutil.copyfile(ddr_default_dir + "\\" + fn, ida_plugin_tmp + "\\ddr\\" + fn) 515 | print("[DDR_INSTALLER][INFO] Copied file: {}".format(cf)) 516 | 517 | cf = shutil.copyfile("install_data\\ddr_plugin.py", ida_plugin_tmp + "\\ddr_plugin.py") 518 | print("[DDR_INSTALLER][INFO] Copied file: {}".format(cf)) 519 | 520 | # Create DDR plugin config file 521 | with open(ida_plugin_cfg_template, 'r') as f: 522 | ddrplugin_cfg_file = f.read() 523 | 524 | ida_plugin_dir_escaped = ida_plugin_dir.replace("\\", "\\\\") 525 | 526 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , DDR_SERVER_IP) 527 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , DDR_SERVER_PORT) 528 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , DDR_APIKEY) 529 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , ida_plugin_dir_escaped + "\\\\ddr\\\\" + DDR_CERT_FILENAME) 530 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "true") 531 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "tmp_dump.cfg") 532 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "30.0") 533 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "2") 534 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("", "20000") 535 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "5") 536 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "3") 537 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "50") 538 | ddrplugin_cfg_file = ddrplugin_cfg_file.replace("" , "3") 539 | 540 | ddrplugin_cfg_filename = ida_plugin_tmp + "\\ddr\\ddr_config.json" 541 | 542 | with open(ddrplugin_cfg_filename, 'w') as f: 543 | f.write(ddrplugin_cfg_file) 544 | 545 | print("[DDR_INSTALLER][INFO] Created IDA DDR plugin config file: {}".format(ddrplugin_cfg_filename)) 546 | 547 | # Create plugin installer python script 548 | with open(ida_plugin_install_template, 'r') as f: 549 | ddrplugin_install_script = f.read() 550 | 551 | ddrplugin_install_script = ddrplugin_install_script.replace("" , ida_install_dir) 552 | ddrplugin_install_script = ddrplugin_install_script.replace("" , ida_plugin_dir) 553 | ddrplugin_install_script = ddrplugin_install_script.replace("" , ida_python_path) 554 | 555 | ddrplugin_install_script_filename = ida_plugin_tmp + "\\ida_plugin_installer.py" 556 | 557 | with open(ddrplugin_install_script_filename, 'w') as f: 558 | f.write(ddrplugin_install_script) 559 | print("[DDR_INSTALLER][INFO] Created IDA DDR plugin installer script: {}".format(ddrplugin_install_script_filename)) 560 | 561 | #Copy test files 562 | test_samples_dir = ida_plugin_tmp + "\\ddr\\ddr_test_samples" 563 | os.makedirs(test_samples_dir, exist_ok=True) 564 | cf = copy_tree("ddr_test_samples", test_samples_dir) 565 | 566 | print("Copied test samples to:") 567 | for copied_file in cf: 568 | print(copied_file) 569 | 570 | # Create ZIP archive 571 | res = shutil.make_archive(ida_plugin_tmp, 'zip', ida_plugin_tmp) 572 | 573 | print("\n[DDR_INSTALLER][INFO] Created IDA DDR plugin zip archive: {}\n".format(ddrplugin_cfg_filename)) 574 | 575 | def installer_done(): 576 | """ 577 | Finalize installation and start DDR server in virtual environment. 578 | """ 579 | print("\n") 580 | print("[DDR_INSTALLER][INFO] ------------------- Installer is done ------------------------") 581 | print("[DDR_INSTALLER][INFO] You can now go to '{}' and run 'python ddr_server.py'".format(ddr_default_dir)) 582 | print("[DDR_INSTALLER][INFO] This will start the DDR server.\n") 583 | print("[DDR_INSTALLER][INFO] Make sure to allow the Windows Firewall rule") 584 | print("[DDR_INSTALLER][INFO] the first time you start the DDR server\n") 585 | print("[DDR_INSTALLER][INFO] You can test connectifity by going to the") 586 | print("[DDR_INSTALLER][INFO] following test website:\n") 587 | print("[DDR_INSTALLER][INFO] https://{}:{} \n".format(DDR_SERVER_IP, DDR_SERVER_PORT)) 588 | print("[DDR_INSTALLER][INFO] with your prefered browser.") 589 | print("[DDR_INSTALLER][INFO] Once the server is running, you can start using the") 590 | print("[DDR_INSTALLER][INFO] IDA DDR plugin.") 591 | print("[DDR_INSTALLER][INFO] --------------------------------------------------------------\n") 592 | 593 | if not proceed("[DDR_INSTALLER][INFO] Should we proceed with starting the DDR server (ddr_server.py) for you ? [Y/n]"): 594 | print("[DDR_INSTALLER][INFO] Good bye !") 595 | exit(0) 596 | 597 | print("") 598 | my_cmd = 'python "' + ddr_default_dir + '"\\ddr_server.py "' + ddr_default_dir + '"\\ddr_server.cfg' 599 | try: 600 | print("[DDR_INSTALLER][INFO] Starting DDR server:") 601 | print("[DDR_INSTALLER][INFO] {}".format(my_cmd)) 602 | subprocess.run(my_cmd) 603 | except KeyboardInterrupt: 604 | pass 605 | exit(0) 606 | 607 | # --- Main --- 608 | if __name__ == "__main__": 609 | 610 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 611 | mydir = os.path.realpath(__file__) 612 | print("\n[DDR_INSTALLER][INFO] Running from directory {}\n".format(mydir)) 613 | 614 | TMP_FILE1 = "ddr_install_dir.tmp" 615 | 616 | if not sys.version_info >= (3, 0): 617 | print("[DDR_INSTALLER][ERROR] This script only runs in Python 3. Please install Python 3 first") 618 | print("[DDR_INSTALLER][ERROR] Reminder: The same applies to the IDA server and plugin.") 619 | print("[DDR_INSTALLER][INFO] Due to an IDA bug it is recommended to use Python 3.7 in the moment") 620 | print("[DDR_INSTALLER][INFO] on the machine where IDA is running on. You should still use Python 3.8") 621 | print("[DDR_INSTALLER][INFO] for the DDR server machine (this one). If it is the same machine, go for 3.7") 622 | print("[DDR_INSTALLER][INFO] Again, the latter is NOT recommended, better use two separate machines !") 623 | exit(1) 624 | 625 | if not os.path.isfile(TMP_FILE1): 626 | print("\n[DDR_INSTALLER][INFO] --- Welcome to the DDR Server installer script ---") 627 | print("[DDR_INSTALLER][INFO] This script installs the DDR server and all its dependencies. It will create a virtual environment") 628 | print("[DDR_INSTALLER][INFO] for all Python dependencies to make sure that it will not interfere with your existing Python setup.") 629 | print("[DDR_INSTALLER][INFO] Both DDR server and the DDR plugin only support Python version 3 and higher.") 630 | print("[DDR_INSTALLER][INFO] ------------------------------------- READ THIS ----------------------------------------------------") 631 | print("[DDR_INSTALLER][INFO] If you are using IDA < 7.5 you should use Python 3.7 on the IDA machine. This is due to a") 632 | print("[DDR_INSTALLER][INFO] bug in IDA 7.4 which is fixed in 7.5. If you are using 7.5 we recommend to use Python 3.8.") 633 | print("[DDR_INSTALLER][INFO] In any case it is recommended to use Python 3.8 for the DDR server machine. If it is the") 634 | print("[DDR_INSTALLER][INFO] same machine, go for 3.7. Again, the latter setup is NOT recommended, better use two separate") 635 | print("[DDR_INSTALLER][INFO] machines !") 636 | print("[DDR_INSTALLER][INFO] ----------------------------------------------------------------------------------------------------") 637 | if not proceed("[DDR_INSTALLER][INFO] Do you want to proceed ? [Y/n] ? "): 638 | print("[DDR_INSTALLER][INFO] Good bye!") 639 | exit(0) 640 | 641 | print("[DDR_INSTALLER][INFO] Please enter installation directory for DDR server or hit enter for default directory.") 642 | ddr_default_dir = input("[DDR_INSTALLER][INFO] Default is C:\\tools\\DDR : ") or "C:\\tools\\DDR" 643 | if ddr_default_dir[-1:] == "\\": 644 | ddr_default_dir = ddr_default_dir[:-1] 645 | 646 | if len(ddr_default_dir) > MAX_INSTALL_DIR: 647 | print("[DDR_INSTALLER][ERROR] Max. install directory length is {:d}. Please use a shorter path.".format(MAX_INSTALL_DIR)) 648 | print("[DDR_INSTALLER][ERROR] Your DDR installation path is {:d} characters long.".format(len(ddr_default_dir))) 649 | exit(1) 650 | 651 | if os.path.exists(ddr_default_dir): 652 | print("[DDR_INSTALLER][INFO] Directory '{}' exists.".format(ddr_default_dir)) 653 | print("[DDR_INSTALLER][INFO] If this is an update it is recommended to delete the old installation first.") 654 | if proceed("[DDR_INSTALLER][INFO] Should we delete the Directory '{}' [Y/n] ?"): 655 | shutil.rmtree(ddr_default_dir) 656 | 657 | print("[DDR_INSTALLER][INFO] Installing DDR server to directory: {}".format(ddr_default_dir)) 658 | 659 | try: 660 | pathlib.Path(ddr_default_dir).mkdir(parents=True, exist_ok=True) 661 | except PermissionError: 662 | print("[DDR_INSTALLER][ERROR] You do not have the access rights to create this directory.") 663 | exit(1) 664 | 665 | with open(TMP_FILE1, 'w') as f: 666 | f.write(ddr_default_dir) 667 | else: 668 | with open(TMP_FILE1, 'r') as f: 669 | ddr_default_dir = f.read() 670 | print("[DDR_INSTALLER][INFO] Found DDR directory: {} for phase 2.".format(ddr_default_dir)) 671 | 672 | venv=ddr_default_dir + "\\" + DDR_VIRTENV_NAME 673 | 674 | if not os.path.isdir(venv): 675 | # Phase 1: Create virtual enviroment 676 | if proceed("[DDR_INSTALLER][INFO] Installing virtual enviroment to '{}' Proceed [Y/n] ? ".format(venv) ): 677 | print("[DDR_INSTALLER][INFO] Phase 1: Create virtual enviroment.") 678 | runcmd("python -m venv \"" + venv + "\"") 679 | else: 680 | print("[DDR_INSTALLER][ERROR] Installation aborted.") 681 | exit(1) 682 | 683 | if not is_venv(): 684 | # Phase 2: Activate virtual enviroment and restart this script in it 685 | print("[DDR_INSTALLER][INFO] Phase 2: Activating virtual enviroment.") 686 | python_bin = venv + "\\Scripts\\python.exe" 687 | script_file = os.path.realpath(__file__) 688 | try: 689 | subprocess.run([python_bin, script_file]) 690 | except KeyboardInterrupt: 691 | pass 692 | exit(0) 693 | else: 694 | if sys.prefix == venv: 695 | print("[DDR_INSTALLER][INFO] We are running in the right virtual enviroment : {}".format(sys.prefix)) 696 | os.remove(TMP_FILE1) 697 | print("[DDR_INSTALLER][INFO] Temp. file: {} deleted. Starting main installation routine.".format(TMP_FILE1)) 698 | 699 | # Main installation routine 700 | # Install virtual enviroment and dependancies 701 | if install_deps(venv, ddr_default_dir): 702 | print("[DDR_INSTALLER][INFO] Successfully installed DDR server to {}".format(ddr_default_dir)) 703 | 704 | if not proceed("[DDR_INSTALLER][INFO] Should we proceed with the installation of the plugin ? [Y/n]"): 705 | print("[DDR_INSTALLER][INFO] IDA Plugin installation skipped.") 706 | installer_done() 707 | exit(0) 708 | 709 | #Prepare IDA plugin files and config and built zip file 710 | built_plugin_zip(ddr_default_dir) 711 | 712 | # start web server 713 | python_bin = venv + "\\Scripts\\python.exe" 714 | script_file = "install_data\\installer_web_server.py" 715 | args = "{}".format(DDR_SERVER_IP) 716 | try: 717 | subprocess.run([python_bin, script_file, args]) 718 | except KeyboardInterrupt: 719 | pass 720 | 721 | installer_done() 722 | else: 723 | print("[DDR_INSTALLER][ERROR] Failed installing dependencies.") 724 | exit(1) 725 | else: 726 | print("[DDR_INSTALLER][ERROR] We are in a different virtual enviroment : {}".format(sys.prefix)) 727 | exit(1) 728 | 729 | exit(0) 730 | 731 | 732 | 733 | 734 | 735 | 736 | -------------------------------------------------------------------------------- /ddr_installer/README.txt: -------------------------------------------------------------------------------- 1 | 2 | Usual setup: 3 | ------------ 4 | 5 | Analyst PC (IDA, ddr_plugin.py) 6 | | 7 | | IP network (Allow port DDR_CONFIG_SETTINGS.WEBSERVER_PORT (Default: 5000) 8 | | in your firewall. There should be a pop when you run ddr_server.py) 9 | | the first time during installation. 10 | V 11 | Malware PC (DynamoRio, ddr32.dll, ddr64.dll, ddr_server.py) 12 | 13 | Notes: 14 | ------ 15 | Installing both the server and the plugin on the same PC, should work to, but is not 16 | recommended. Keep in mind that the malware sample is executed by the DynamoRio framework. 17 | 18 | 19 | Installation: 20 | ------------- 21 | Copy this directory to the Malware PC (ddr_server PC) and run DDR_INSTALLER.py. 22 | The script will download all dependencies and create all necessary configuration files 23 | for your environment. It will guide you through the whole installation process of the 24 | DDR server and IDA plugin. 25 | It will not touch your local python environment, instead it creates a dedicated virtual 26 | Python environment for all dependencies. It will also create individual cryptographic 27 | material for the SSL encrypted traffic between the DDR server and IDA plugin. 28 | 29 | Pls report bugs and issues to hunterbr@cisco.com 30 | 31 | =========================================================================================== 32 | You can find more infos at https://blog.talosintelligence.com/ search for DDR or Dynamic 33 | Data Resolver to find the latest blog about DDR. It is highly recommended to read this blog 34 | as far as DDR is a complex tool and without knowing some basics, it might be difficult to 35 | use the tool in a proper way. 36 | ============================================================================================ 37 | 38 | Dependencies: 39 | ============= 40 | 41 | Python 3.7 or 3.8 42 | ------------------ 43 | If you are using IDA < 7.5 you should use Python 3.7 on the IDA machine. This is due to a 44 | bug in IDA 7.4 which is fixed in 7.5. If you are using 7.5 we recommend to use Python 3.8. 45 | In any case it is recommended to use Python 3.8 for the DDR server machine. If it is the 46 | same machine, go for 3.7. Again, the latter setup is NOT recommended, better use two separate 47 | machines ! 48 | 49 | Latest versions of IDA are supporting Python 3.8, if your IDA setup is up to date, you can run 50 | Python 3.8 on the DDR server and plugin side. 51 | 52 | See https://blog.talosintelligence.com/ for details. 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample0_32_dyn.cfg: -------------------------------------------------------------------------------- 1 | S 40119F 2 | A 4011FD 3 | L 401000 403000 20000 TRUE "C:\tools\DDR\samples\trace_tmp_A1FB519FD6C00B8116BCB1D78567BAE0.json" 4 | -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample0_32_dyn.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/ddr_test_samples/testsample0_32_dyn.exe -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample0_64_dyn.cfg: -------------------------------------------------------------------------------- 1 | T SF 14000124C 2 | S 140001241 3 | A 140001275 4 | L 140001000 140003000 20000 FALSE "C:\tools\DDR\samples\trace_tmp_CBEFF9E003C9FA8D8C568CFB85A885AF.json" 5 | -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample0_64_dyn.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/ddr_test_samples/testsample0_64_dyn.exe -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample1_32.cfg: -------------------------------------------------------------------------------- 1 | T ZF 4016D8 2 | S 4016D3 3 | A 401813 4 | L 401000 403000 20000 TRUE "C:\tools\DDR\samples\trace_tmp_A1FB519FD6C00B8116BCB1D78567BAE0.json" 5 | -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample1_32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/ddr_test_samples/testsample1_32.exe -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample1_64.cfg: -------------------------------------------------------------------------------- 1 | S 14000178B 2 | L 140001000 140003000 20000 TRUE "C:\tools\DDR\samples\trace_tmp_B4AB561A5A8A53E262C3D09738FFBFA3.json" 3 | -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample1_64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/ddr_test_samples/testsample1_64.exe -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample_with_args_x32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/ddr_test_samples/testsample_with_args_x32.exe -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsample_with_args_x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/ddr_test_samples/testsample_with_args_x64.exe -------------------------------------------------------------------------------- /ddr_installer/ddr_test_samples/testsamples_README.txt: -------------------------------------------------------------------------------- 1 | These are test sample to test DDR with if you don't want to use real malware. 2 | 3 | NN = 32 bit or 64 bit 4 | 5 | testsample0_NN_dyn.exe - simple program doing a couple of calculations, memory allocs and function calls 6 | 7 | testsample1_NN.exe - Simulates real malware, but doesn't do anything malicious. It copies itself to the 8 | %TEMP% folder and launces a 2nd instance of itself as EvIlMaLwArE.exe 9 | Also launches write.exe/wordpad.exe in the beginning and a notepad.exe at the end 10 | 11 | testsample_with_args_xNN.exe - test sample which prints out its command line arguments, allocates a buffer and uses a function. 12 | 13 | 14 | HINT: 15 | ----- 16 | MS Defender detects some of the samples as malicious. This is nonsense and a FP. You might need to disable Defender 17 | or make an exception for them. 18 | 19 | It is a good idea to analyse the samples in IDA first anyway, so you have a good understanding about what they do and what/when/where it makes sense to 20 | use certain DDR features. 21 | 22 | 23 | Caveats: 24 | -------- 25 | 26 | 0) Some test samples need the MS Visual C++ 2015-2019 Redistributables. Sorry, I was too lazy to compile them statically. Run the samples stand alone first 27 | to make sure that they are executing on your machine. 28 | 29 | --- 30 | 31 | 1) There is an issue with DynamoRIO in the moment. It doesn't support injection for 32bit processes which are launching 32 | 64bit child processes. A Scenario which some of the test samples above are doing e.g. testsample2_32.exe launches notepad.exe 33 | which could be 64bit process depending on the OS you are running it on. 34 | You can still analyse those processes with DDR, the only caveat is that DDR (or better the underlying DynmaoRIO) is not recognizing 35 | the 64bit processes in this scenario and thou will not trace any data for it. The initial 32bit process is still analysed. 36 | 37 | If you run in such a scenario and want to verify it, you could run DynamoRio in debug mode e.g. : 38 | 39 | C:\tools\DDR\DynamoRIO-Windows-8.0.0-1\bin32\drrun.exe -debug -checklevel 0 -loglevel 2 -- testsample32.exe 40 | 41 | this will write a detailed logging file to C:\tools\DDR\DynamoRIO-Windows-8.0.0-1\logs\\log..html 42 | 43 | You can find an entry like this one in it: 44 | 45 | --- snip --- 46 | syscall: NtCreateUserProcess presys \??\C:\windows\write.exe 47 | Exit from system call 48 | post syscall: sysnum=0x000000aa, params @0x0016f22c, result=0x00000000 49 | syscall: NtCreateUserProcess => 0x0 50 | syscall: NtCreateUserProcess created process 0x848 with main thread 0xd28 51 | WARNING: make_writable 0x73dc6000: param size 0x3f000 vs. mbi size 0x2c000 base 0x73dc6000 52 | WARNING: make_writable 0x73df2000: param size 0x13000 vs. mbi size 0x7000 base 0x73df2000 53 | WARNING: make_unwritable 0x73dc6000: param size 0x3f000 vs. mbi size 0x2c000 base 0x73dc6000 54 | WARNING: make_unwritable 0x73df2000: param size 0x13000 vs. mbi size 0x7000 base 0x73df2000 55 | SYSLOG_WARNING: Injecting from 32-bit into 64-bit process is not yet supported. 56 | syscall: NtCreateUserProcess: WARNING: failed to get cxt of thread (0xc000000d) so can't follow children on WOW64. 57 | --- snip --- 58 | 59 | Luckily for malware analysis, this scenario is not happening very often. 60 | 61 | You can find more infos at https://blog.talosintelligence.com/ search for DDR or Dynamic 62 | Data Resolver to find the latest blog about DDR. 63 | 64 | --- 65 | 66 | 2) Under certain rare contitions the client DLL is crashing if you have NOP'ed out instructions. This bug is under investigation. A 67 | dirty workaround is to clear the configuration in IDA (DDR/Config/Clear configured DDR request) and re-run the sample again. 68 | 69 | 70 | -------------------------------------------------------------------------------- /ddr_installer/docs/ddr_client_dll_sample_config32.txt: -------------------------------------------------------------------------------- 1 | # --- DDR sample config file --- 2 | # 3 | # Lines should not be more than 350 characters long, file names not more than 256 4 | # characters. 5 | # 6 | # Comments must be written with a leading '#' 7 | # No extra spaces are allowed in config lines 8 | # Different fields are separated by exactly one blank 9 | # 10 | # All number/address values are expected to be hexadecimal values without any 11 | # leading character. 12 | # ----------------------------------------------------------------------------- 13 | 14 | # -- NOP out instructions -- 15 | # N 16 | # = Start program counter address for NOP'ing instructions (hex) 17 | # = End program counter address for NOP'ing instructions (hex) 18 | # and can be the same for NOP'ing one instr. 19 | # e.g. N 004012EE 004012F6 20 | #N 0040115A 0040115A 21 | #N 00401337 0040133A 22 | 23 | # -- Patch EFLAG -- 24 | # T 25 | # = [CF, PF, AF, ZF, SF, DF, OF] 26 | # = program counter address (hex) where to toggle the EFLAG before 27 | # instruction gets executed e.g. jle 28 | # e.g. T SF 004012C4 #example comment 29 | #T SF 004012BB 30 | #T SF 004012FB #example comment 31 | 32 | # -- Always skip function at when called -- 33 | # = Functions address which gets wrapped, call to func is skipped 34 | # = set return value of wrapped function (NEED TO BE UNSINGED INT) 35 | # C 36 | # e.g. C 00401100 00000001 37 | C 00401120 FFFFFFFF # = -1 38 | C 00401150 FF 39 | 40 | # -- Dump buffer to file --: 41 | # D 42 | # = program counter address where to get the size of the buffer 43 | # = operant at to get the buffer size from 44 | # e.g. SP0 = (S)ource operant 0. Value is a (P)ointer. 45 | # DV1 = (D)estination operant 1. Absolut (V)alue. 46 | # = program counter address where to get the buffer address 47 | # = operant at PC to get the buffer size from 48 | # = program counter address where to finally dump the buffer 49 | # = dump filename 50 | # 51 | # All numbers/addresses are hexdecimal values without any leading character 52 | # 53 | # e.g. D 0040117E SP0 0040118B SP0 004011F9 dump1.bin 54 | #D 004011B5 SP0 004011C2 SP0 00401230 dump1.bin 55 | #D 004013A2 SP0 004013AF SP0 0040141D dump2.bin 56 | # 57 | # -- Run Trace --: 58 | # start end max.instr lighttrace filename (the last filename in the list will be used) 59 | # 401335 4013CA 20000 TRUE "C:\Users\Dex Dexter\Documents\test\test\buffertest_trace.json" 60 | # e.g. 61 | L 4012BE 40130F 20000 TRUE "C:\Users\Dex Dexter\Documents\test\test\buffertest_trace.json" 62 | L 401335 4013CA 20000 TRUE "C:\Users\Dex Dexter\Documents\test\test\buffertest_trace.json" 63 | L 401411 40146E 20000 FALSE "C:\Users\Dex Dexter\Documents\test\test\buffertest_trace.json" 64 | 65 | # -- Patch binary with endless Loop at address --: 66 | # loop-addr 67 | B 40170C 68 | 69 | # --- use a start address --- 70 | # DDR will start the instrumentation/analysis at this address 71 | # it is useful to use this if the start/end alone doesn't do the trick 72 | # e.g. the sample later jump to an address wich is smaller than the start address 73 | # you handed over in the trace(L) line for example 74 | S 40119F 75 | 76 | # --- use a break address --- 77 | # DDR stops instrumentation and execution of the process at this address 78 | A 4011FD -------------------------------------------------------------------------------- /ddr_installer/docs/ddr_client_dll_sample_config64.txt: -------------------------------------------------------------------------------- 1 | # --- DDR sample config file --- 2 | # 3 | # Lines should not be more than 350 characters long, file names not more than 256 4 | # characters. 5 | # 6 | # Comments must be written with a leading '#' 7 | # No extra spaces are allowed in config lines 8 | # Different fields are separated by exactly one blank 9 | 10 | All number/address values are expected to be hexadecimal values without any 11 | leading character. 12 | # ----------------------------------------------------------------------------- 13 | 14 | # -- NOP out instructions -- 15 | # N 16 | # = Start program counter address for NOP'ing instructions (hex) 17 | # = End program counter address for NOP'ing instructions (hex) 18 | # and can be the same for NOP'ing one instr. 19 | # e.g. N 004012EE 004012F6 20 | N 000000014000121C 000000014000121C 21 | N 000000014000145A 000000014000145A 22 | 23 | # -- Patch EFLAG -- 24 | # T 25 | # = [CF, PF, AF, ZF, SF, DF, OF] 26 | # = program counter address where to toggle the EFLAG before 27 | # instruction gets executed e.g. jle (hex) 28 | # e.g. T SF 004012C4 #example comment 29 | T SF 00000001400013A7 30 | T SF 00000001400013E5 #example comment 31 | 32 | # -- Always skip function at when called -- 33 | # = Functions address which gets wrapped, call to func is skipped 34 | # = set return value of wrapped function (NEED TO BE UNSINGED INT) 35 | # C 36 | # e.g. C 00401100 00000001 37 | C 00000001400011E0 0 38 | C 0000000140001210 FFFFFFFFFFFFFFFF # -1 39 | 40 | # -- Dump buffer to file --: 41 | # D 42 | # = program counter address where to get the size of the buffer 43 | # = operant at to get the buffer size from 44 | # e.g. SP0 = (S)ource operant 0. Value is a (P)ointer. 45 | # DV1 = (D)estination operant 1. Absolut (V)alue. 46 | # = program counter address where to get the buffer address 47 | # = operant at PC to get the buffer size from 48 | # = program counter address where to finally dump the buffer 49 | # = dump filename 50 | # e.g. D 0040117E SP0 0040118B SP0 004011F9 dump1.bin 51 | D 0000000140001280 SP0 000000014000128D SP0 000000014000132B dump_x64_1.bin 52 | D 0000000140001494 SP0 00000001400014A1 SP0 000000014000153F dump_x64_2.bin 53 | # 54 | # -- Run Trace --: 55 | # start end max.instr lighttrace filename (the last filename in the 56 | # list will be used) 57 | L 140001000 140003000 20000 FALSE trace_tmp_CBEFF9E003C9FA8D8C568CFB85A885AF.json 58 | # 59 | # -- Patch binary with endless Loop at address --: 60 | # loop-addr 61 | B 0000000140001280 62 | 63 | # --- use a start address --- 64 | # DDR will start the instrumentation/analysis at this address 65 | # it is useful to use this if the start/end alone doesn't do the trick 66 | # e.g. the sample later jump to an address wich is smaller than the start address 67 | # you handed over in the trace(L) line for example 68 | S 140001241 69 | 70 | # --- use a break address --- 71 | # DDR stops instrumentation and execution of the process at this address 72 | A 140001275 -------------------------------------------------------------------------------- /ddr_installer/install_data/ddr32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/install_data/ddr32.dll -------------------------------------------------------------------------------- /ddr_installer/install_data/ddr32dbg.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/install_data/ddr32dbg.dll -------------------------------------------------------------------------------- /ddr_installer/install_data/ddr64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/install_data/ddr64.dll -------------------------------------------------------------------------------- /ddr_installer/install_data/ddr64dbg.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cisco-Talos/DynDataResolver/e630bd3d81062f790d932bbe7c594fde93da5f5f/ddr_installer/install_data/ddr64dbg.dll -------------------------------------------------------------------------------- /ddr_installer/install_data/installer_web_server.py: -------------------------------------------------------------------------------- 1 | import flask 2 | import json 3 | import sys 4 | import os 5 | import shutil 6 | import zipfile 7 | import ctypes 8 | from cheroot.wsgi import Server as WSGIServer 9 | 10 | IDA_PLUGIN_ZIP = "ddr_plugin.zip" 11 | MY_IP = sys.argv[1] 12 | MY_PORT = "80" 13 | 14 | app = flask.Flask(__name__) 15 | app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 16 | 17 | # prevent cached responses. Sets no-cache parameters header for every flask response. 18 | @app.after_request 19 | def add_header(r): 20 | """ 21 | Add headers to both force latest IE rendering engine or Chrome Frame, 22 | and also to cache the rendered page for 10 minutes. 23 | """ 24 | r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" 25 | r.headers["Pragma"] = "no-cache" 26 | r.headers["Expires"] = "0" 27 | r.headers['Cache-Control'] = 'public, max-age=0' 28 | return r 29 | 30 | @app.route('/', methods=['GET']) 31 | def ddr_plugin_installation(): 32 | 33 | webcontent = ''' 34 | 35 |
DDR IDA Plugin Installer Website
36 | 37 |
38 | Hello DDR User,
39 |
40 | Just download ,
41 | unzip it and execute the ida_plugin_installer.py script.
42 |
43 | 44 | 45 | ''' 46 | webcontent = webcontent.replace('', IDA_PLUGIN_ZIP) 47 | webcontent = webcontent.replace('' , MY_IP) 48 | webcontent = webcontent.replace('' , MY_PORT) 49 | 50 | return webcontent 51 | 52 | @app.route('/get_plugin', methods=['GET']) 53 | def ddr_plugin_download(): 54 | return flask.send_file(IDA_PLUGIN_ZIP, as_attachment=True) 55 | 56 | def run_webserver(): 57 | 58 | server = WSGIServer(bind_addr=(MY_IP, int(MY_PORT)), wsgi_app=app, numthreads=100) 59 | 60 | print("[DDR_INSTALLER][INFO] ------------------------------------------------------------------------") 61 | print("[DDR_INSTALLER][INFO] Starting IDA plugin installation.") 62 | print("[DDR_INSTALLER][INFO] Please go to your IDA machine and point your browser to:\n") 63 | print("[DDR_INSTALLER][INFO] http://{}:{}\n".format(MY_IP,MY_PORT)) 64 | print("[DDR_INSTALLER][INFO] Once you are done installing the IDA plugin, hit Ctrl-C here to stop the") 65 | print("[DDR_INSTALLER][INFO] webserver and proceed with the installation.") 66 | print("[DDR_INSTALLER][INFO] ------------------------------------------------------------------------") 67 | 68 | try: 69 | server.start() 70 | except KeyboardInterrupt: 71 | server.stop() 72 | except: 73 | print("[DDR_INSTALLER][ERROR] Failed to start installation server. Please check if you") 74 | print("[DDR_INSTALLER][ERROR] have configured a valid NGINX IP address above.\n") 75 | raise 76 | 77 | if __name__ == "__main__": 78 | 79 | run_webserver() 80 | -------------------------------------------------------------------------------- /ddr_installer/known_bugs.txt: -------------------------------------------------------------------------------- 1 | 1) Injection for 32bit processes which are launching 64bit child processes 2 | 3 | There is an issue with DynamoRIO in the moment. It doesn't support injection for 32bit processes which are launching 4 | 64bit child processes. A Scenario which some of the test samples above are doing e.g. testsample2_32.exe launches notepad.exe 5 | which could be 64bit process depending on the OS you are running it on. 6 | You can still analyse those processes with DDR, the only caveat is that DDR (or better the underlying DynmaoRIO) is not recognizing 7 | the 64bit processes in this scenario and thou will not trace any data for it. The initial 32bit process is still analysed. 8 | 9 | If you run in such a scenario and want to verify it, you could run DynamoRio in debug mode e.g. : 10 | 11 | C:\tools\DDR\DynamoRIO-Windows-8.0.0-1\bin32\drrun.exe -debug -checklevel 0 -loglevel 2 -- testsample32.exe 12 | 13 | this will write a detailed logging file to C:\tools\DDR\DynamoRIO-Windows-8.0.0-1\logs\\log..html 14 | 15 | You can find an entry like this one in it: 16 | 17 | --- snip --- 18 | syscall: NtCreateUserProcess presys \??\C:\windows\write.exe 19 | Exit from system call 20 | post syscall: sysnum=0x000000aa, params @0x0016f22c, result=0x00000000 21 | syscall: NtCreateUserProcess => 0x0 22 | syscall: NtCreateUserProcess created process 0x848 with main thread 0xd28 23 | WARNING: make_writable 0x73dc6000: param size 0x3f000 vs. mbi size 0x2c000 base 0x73dc6000 24 | WARNING: make_writable 0x73df2000: param size 0x13000 vs. mbi size 0x7000 base 0x73df2000 25 | WARNING: make_unwritable 0x73dc6000: param size 0x3f000 vs. mbi size 0x2c000 base 0x73dc6000 26 | WARNING: make_unwritable 0x73df2000: param size 0x13000 vs. mbi size 0x7000 base 0x73df2000 27 | SYSLOG_WARNING: Injecting from 32-bit into 64-bit process is not yet supported. 28 | syscall: NtCreateUserProcess: WARNING: failed to get cxt of thread (0xc000000d) so can't follow children on WOW64. 29 | --- snip --- 30 | 31 | Luckily for malware analysis, this scenario is not happening very often. 32 | 33 | You can find more infos at https://blog.talosintelligence.com/ search for DDR or Dynamic 34 | Data Resolver to find the latest blog about DDR. 35 | 36 | =========================================================================================================================================================== 37 | 38 | 2) Under certain rare contitions the client DLL is crashing if you have NOP'ed out instructions. This bug is under investigation. A 39 | dirty workaround is to clear the configuration in IDA (DDR/Config/Clear configured DDR request) and re-run the sample again. 40 | 41 | =========================================================================================================================================================== 42 | 43 | 3) AMD CPU bug 44 | There is a DDR independent AMD CPU bug which crashes the DynamoRio framework if a 32bit sample is executed on a 64bit machine and the WoW64 architecture is switching between the 32 and 64 bit world. The issue is identified and the root cause found. The DynamoRio team has released a special build here which fixes the issue. You can download it and replace the original DynamoRio directory with this one. Unzip DynamoRIO-Windows-8.0.18547.zip and rename or backup the old directory (C:\tools\DDR\DynamoRIO-Windows-8.0.0-1), give the downloaded one the same name like the old one and move it to the same place. 45 | 46 | You can read more details here . The bug is confirmed on Ryzen CPUs, but may also occur on other AMD CPUs. We haven’t seen any issues on Intel CPUs. 47 | 48 | In some cases, a possible workaround, until we have an updated version of DynamoRio, is to set MaxLoaderThreads to 1 in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ 49 | 50 | =========================================================================================================================================================== 51 | 52 | 4) Access violations from 'dynamorio!safe_read_asm_xxx' functions are expected and can be ignored in WinDbg.They are caused by the way DynamoRio has implemented these functions (Try-Except).They are handled by DynamoRio internally if you haven’t attached a debugger. In In WinDbg, just proceed (F5) if something like below happens: 53 | 54 | WinDbg Console: 55 | (1df0.1a28) : Access violation - code c0000005(first chance) 56 | First chance exceptions are reported before any exception handling. 57 | This exception may be expected and handled. 58 | dynamorio!safe_read_asm_pre 59 | 60 | The functions are heavily used in DDR, so you might see a lot of these exceptions. You can filter them by disable Access Violations in WInDbg. Most serious exceptions will still break into the debugger. 61 | 62 | =========================================================================================================================================================== 63 | 64 | 5) IDA Debugger and image relocation in IDA is not supported in DDR in the moment. 65 | 66 | If you use the IDA debugger for a sample which is using reloacation, IDA is rebasing the segments (or you rebase the segments manually), than DDR will use the 67 | rebased EA address, which will not work as far as DDR server/ DDR client need the org. PE RVA. 68 | 69 | 70 | Missing features: 71 | ================= 72 | 73 | - autom. add break address to full trace basic block (last address in basic block) 74 | - add break and start address feature to dump buffer and other features (works only for trace feature itm) -------------------------------------------------------------------------------- /ddr_installer/release_notes.txt: -------------------------------------------------------------------------------- 1 | #### Release Notes #### 2 | 3 | Version 1.02 4 | - Added 'start offset' feature. You can now set a start offset for traces. DDR starts the analysis at that address. 5 | - Added 'break address' feature. You can now add an address where DDR should break/stop the anaylsis. 6 | - Added an option to pass command line parameters to the sample 7 | - Added a check to pop up a warning if the sample was relocated in IDA 8 | - updated DynamoRio version 9 | - updated uvicorn library to 0.12.3 10 | - updated cryptography to 3.2.1 11 | - updated some test samples 12 | - fixed a few minor bugs 13 | 14 | -------------------------------------------------------------------------------- /ddr_installer/requirements.in: -------------------------------------------------------------------------------- 1 | fastapi 2 | uvicorn 3 | requests 4 | clint 5 | Flask 6 | pyOpenSSL 7 | cheroot 8 | werkzeug 9 | python-multipart 10 | aiofiles 11 | psutil -------------------------------------------------------------------------------- /ddr_installer/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile 3 | # To update, run: 4 | # 5 | # pip-compile requirements.in 6 | # 7 | aiofiles==0.5.0 # via -r requirements.in 8 | args==0.1.0 # via clint 9 | certifi==2020.4.5.1 # via requests 10 | cffi==1.14.0 # via cryptography 11 | chardet==3.0.4 # via requests 12 | cheroot==8.3.0 # via -r requirements.in 13 | click==7.1.2 # via flask, uvicorn 14 | clint==0.5.1 # via -r requirements.in 15 | cryptography==3.2.1 # via pyopenssl 16 | fastapi==0.54.2 # via -r requirements.in 17 | flask==1.1.2 # via -r requirements.in 18 | h11==0.9.0 # via uvicorn 19 | idna==2.9 # via requests 20 | itsdangerous==1.1.0 # via flask 21 | jaraco.functools==3.0.1 # via cheroot 22 | jinja2==2.11.2 # via flask 23 | markupsafe==1.1.1 # via jinja2 24 | more-itertools==8.3.0 # via cheroot, jaraco.functools 25 | psutil==5.7.0 # via -r requirements.in 26 | pycparser==2.20 # via cffi 27 | pydantic==1.5.1 # via fastapi 28 | pyopenssl==19.1.0 # via -r requirements.in 29 | python-multipart==0.0.5 # via -r requirements.in 30 | requests==2.23.0 # via -r requirements.in 31 | six==1.14.0 # via cheroot, cryptography, pyopenssl, python-multipart 32 | starlette==0.13.2 # via fastapi 33 | urllib3==1.25.9 # via requests 34 | uvicorn==0.12.3 # via -r requirements.in 35 | websockets==8.1 # via uvicorn 36 | werkzeug==1.0.1 # via -r requirements.in, flask 37 | -------------------------------------------------------------------------------- /ddr_installer/roadmap.txt: -------------------------------------------------------------------------------- 1 | Feature requests and roadmap: 2 | (no special order, not committed, just brainstorming) 3 | 4 | - Snapshots for loaded trace files (pull-down menu to quickly jump between different scans) 5 | - highlighting of executed instructions in IDAs decompiler view 6 | - patch register at PC n 7 | - exec shellcode at PC n 8 | - pause and exec custom app/tool at PC n 9 | - dump custom memory range at PC n 10 | -------------------------------------------------------------------------------- /ddr_installer/templates/ddr_config_template.json: -------------------------------------------------------------------------------- 1 | { "WEBSERVER" : "", 2 | "WEBSERVER_PORT" : "", 3 | "DDR_WEBAPI_KEY" : "", 4 | "CA_CERT" : "", 5 | "VERIFY_CERT" : , 6 | "DUMP_CFG_FILE" : "", 7 | "MAX_API_TIMEOUT" : , 8 | "DBG_LEVEL" : , 9 | "MAX_INSTR_TO_EXECUTE" : , 10 | "MAX_LOG_ROUNDS" : , 11 | "MAX_CMT_ROUNDS" : , 12 | "MAX_INSTR_COUNT" : , 13 | "MAX_UPLOAD_ATTEMPTS" : 14 | } -------------------------------------------------------------------------------- /ddr_installer/templates/ddr_server_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "DDR_SERVER_VERSION" : "", 3 | "APILOGGING" : "", 4 | "DEBUG_API_JSON" : , 5 | "CERT_FILE" : "", 6 | "KEY_FILE" : "", 7 | "APIKEY_FILE" : "", 8 | "SERVER_IP" : "", 9 | "SERVER_PORT" : "", 10 | "MY_FQDN" : "", 11 | "CONFDIR" : "", 12 | "DDR_VIRTENV" : "", 13 | "MAX_CFG_LINE_LENGTH" : , 14 | "CFG_DYNRIO_DRRUN_X32" : "", 15 | "CFG_DYNRIO_CLIENTDLL_X32" : "", 16 | "CFG_DYNRIO_DRRUN_X64" : "", 17 | "CFG_DYNRIO_CLIENTDLL_X64" : "" 18 | } 19 | -------------------------------------------------------------------------------- /ddr_installer/templates/ida_plugin_installer_template.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import subprocess 4 | import shutil 5 | from distutils import dir_util, file_util 6 | 7 | # List of Python module dependencies 8 | DEPS = ["requests", "pefile"] 9 | 10 | def proceed(question): 11 | """ 12 | Do you want to proceed [Y/n]. Returns True if 'yes' and False if 'no' 13 | """ 14 | valid = ["y"] 15 | 16 | while True: 17 | sys.stdout.write(question) 18 | choice = input().lower() 19 | if choice == '': 20 | return True 21 | elif choice == 'y': 22 | return True 23 | else: 24 | return False 25 | 26 | 27 | def runcmd(my_cmd): 28 | """ 29 | Execute shell command 30 | """ 31 | 32 | print("[DDR_INSTALLER][INFO] Executing cmd: \n{}\n".format(my_cmd)) 33 | 34 | stdout = False 35 | stderr = False 36 | 37 | try: 38 | process = subprocess.run(my_cmd) 39 | 40 | if process.returncode != 0: 41 | print("\n[DDR_INSTALLER][WARNING] Command execution failed. Error code: {:d}".format(process.returncode)) 42 | ret = False 43 | else: 44 | ret = True 45 | 46 | except : 47 | print("[DDR_INSTALLER][ERROR] Exception: Command execution failed with unknown error.") 48 | ret = False 49 | 50 | return ret 51 | 52 | def install_deps(ida_python_path): 53 | """ 54 | Main installer routine to install all neccessary 55 | dependencies for DDR IDA plugin 56 | """ 57 | 58 | ida_python_interpreter = ida_python_path + "\\python.exe" 59 | ida_python_pip = ida_python_path + "\\Scripts\\pip.exe" 60 | 61 | # update pip in virtual enviroment 62 | pip_latest_version = False 63 | while pip_latest_version == False: 64 | print("[DDR_INSTALLER][INFO] Checking for pip in virtual enviroment...") 65 | my_cmd = ida_python_interpreter + " -m pip install --no-warn-script-location --upgrade pip" 66 | if runcmd(my_cmd): 67 | print("[DDR_INSTALLER][INFO] pip tools upgraded/installed.\n") 68 | pip_latest_version=True 69 | else: 70 | print("\n[DDR_INSTALLER][ERROR] pip is not the latest version.") 71 | print("[DDR_INSTALLER][ERROR] Please update your pip tools manually first") 72 | print("[DDR_INSTALLER][ERROR] Installing/Updating the pip tools likely needs admin rights in your setup.") 73 | print("[DDR_INSTALLER][ERROR] Run a command prompt (cmd.exe) as administrator and enter:") 74 | print("[DDR_INSTALLER][ERROR] \"{}\\python.exe\" -m pip install --upgrade pip\n".format(ida_python_path)) 75 | proceed("[DDR_INSTALLER][ERROR] Hit any key once you have updated pip.") 76 | 77 | # Install pip tools 78 | print("[DDR_INSTALLER][INFO] Installing pip-tools.") 79 | my_cmd = ida_python_pip + " install --no-warn-script-location --upgrade pip-tools" 80 | if runcmd(my_cmd): 81 | print("[DDR_INSTALLER][INFO] pip-tools upgraded/installed.\n") 82 | else: 83 | print("\n[DDR_INSTALLER][ERROR] Failed to upgrad/install pip-tools.") 84 | return False 85 | 86 | # Install dependencies 87 | for m in DEPS: 88 | print("[DDR_INSTALLER][INFO] --- Installing {} ---".format(m)) 89 | my_cmd = ida_python_pip + " install --no-warn-script-location --upgrade " + m 90 | if runcmd(my_cmd): 91 | print("[DDR_INSTALLER][INFO] --- {} installed. ---\n".format(m)) 92 | else: 93 | print("[DDR_INSTALLER][ERROR] Failed to install {}.\n".format(m)) 94 | return False 95 | 96 | # --- Main --- 97 | if __name__ == "__main__": 98 | 99 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 100 | mydir = os.path.realpath(__file__) 101 | print("\n[DDR_INSTALLER][INFO] Running from directory {}\n".format(mydir)) 102 | 103 | ida_install_dir = r"" 104 | ida_plugin_dir = r"" 105 | ida_python_path = r"" 106 | 107 | print("[DDR_INSTALLER][INFO] Using the following directories:") 108 | print("[DDR_INSTALLER][INFO] IDA install dir: {}".format(ida_install_dir)) 109 | print("[DDR_INSTALLER][INFO] IDA plugin dir : {}".format(ida_plugin_dir)) 110 | print("[DDR_INSTALLER][INFO] IDA Python dir : {}\n".format(ida_python_path)) 111 | 112 | if os.path.isdir(ida_install_dir) == False: 113 | print("[DDR_INSTALLER][ERROR] {} is not a directory.".format(ida_install_dir)) 114 | exit(1) 115 | 116 | if os.path.isdir(ida_plugin_dir) == False: 117 | # Doesn't exist or is no directory 118 | if os.path.exists(ida_plugin_dir): 119 | print("[DDR_INSTALLER][ERROR] {} is not a directory.".format(ida_plugin_dir)) 120 | exit(1) 121 | else: 122 | if proceed("[DDR_INSTALLER][WARNING] {} does not exist. Should I create it [Y/n] ?".format(ida_plugin_dir)): 123 | try: 124 | os.makedirs(ida_plugin_dir) 125 | print("Directory {} successfully created.".format(ida_plugin_dir)) 126 | except: 127 | print("[DDR_INSTALLER][ERROR] Failed to create directory; {}" , ida_plugin_dir) 128 | exit(1) 129 | 130 | if os.path.isdir(ida_python_path) == False: 131 | print("[DDR_INSTALLER][ERROR] {} is not a directory.".format(ida_python_path)) 132 | exit(1) 133 | 134 | if os.path.isfile(ida_plugin_dir + "\\ddr_plugin.py"): 135 | print("[DDR_INSTALLER][INFO] IDA plugin exists at {}".format(ida_plugin_dir + "\\ddr_plugin.py")) 136 | if os.path.exists(ida_plugin_dir + "\\ddr"): 137 | print("[DDR_INSTALLER][INFO] IDA plugin directory exists at {}".format(ida_plugin_dir + "\\ddr")) 138 | print("[DDR_INSTALLER][INFO] If this is an update it is recommended to delete the old installation first.") 139 | if proceed("[DDR_INSTALLER][INFO] Should we delete it [Y/n] ?"): 140 | os.remove(ida_plugin_dir + "\\ddr_plugin.py") 141 | shutil.rmtree(ida_plugin_dir + "\\ddr") 142 | print("[DDR_INSTALLER][INFO] Old installation removed") 143 | 144 | # Install dependencies 145 | if proceed("[DDR_INSTALLER][INFO] Should we proceed with installing the Python module dependencies ? [Y/n]"): 146 | install_deps(ida_python_path) 147 | 148 | # Copy DDR files to plugin directory 149 | if proceed("[DDR_INSTALLER][INFO] Should we proceed with copying the DDR plugin files to the IDA plugin directory? [Y/n]"): 150 | print("[DDR_INSTALLER][INFO] Copying plugin files to {}...".format(ida_plugin_dir)) 151 | flist = dir_util.copy_tree("ddr", ida_plugin_dir + "\\ddr") 152 | for f in flist: 153 | print("[DDR_INSTALLER][INFO] File: {} copied.".format(f)) 154 | 155 | f = file_util.copy_file("ddr_plugin.py", ida_plugin_dir + "\\ddr_plugin.py") 156 | print("[DDR_INSTALLER][INFO] File: {} copied.".format(f[0])) 157 | 158 | print("\nDone. Go back to the malware machine side and start the DDR server. By default: C:\\tools\\DDR\\ddr_server.py") 159 | print("(If you still have the DDR server installer open, it will do that for you if you hit Ctrl-C.)\n") 160 | print("Then start IDA and ... Happy reversing !\n") 161 | 162 | proceed("[DDR_INSTALLER][INFO] Hit any key to end installer.\n") 163 | 164 | 165 | --------------------------------------------------------------------------------