├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── README.md
├── img
├── 1.jpg
├── 11.png
├── 12.png
├── 13.png
├── 14.PNG
├── 16.PNG
├── 2.png
├── 3.png
├── 4.png
├── 5.png
├── 6.png
├── 7.png
├── 8.png
├── ida7.0_mac_target.png
├── ida7.1_mac_target.png
├── ida7.2.png
└── m1.png
├── src
├── HexRaysCodeXplorer.sln
├── HexRaysCodeXplorer.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── HexRaysCodeXplorer
│ ├── CodeXplorer.cpp
│ ├── Common.h
│ ├── CtreeExtractor.cpp
│ ├── CtreeExtractor.h
│ ├── CtreeGraphBuilder.cpp
│ ├── CtreeGraphBuilder.h
│ ├── Debug.cpp
│ ├── Debug.h
│ ├── GCCObjectFormatParser.cpp
│ ├── GCCObjectFormatParser.h
│ ├── GCCTypeInfo.cpp
│ ├── GCCTypeInfo.h
│ ├── GCCVtableInfo.cpp
│ ├── GCCVtableInfo.h
│ ├── HexRaysCodeXplorer.vcxproj
│ ├── HexRaysCodeXplorer.vcxproj.user
│ ├── IObjectFormatParser.cpp
│ ├── IObjectFormatParser.h
│ ├── Linux.h
│ ├── MSVCObjectFormatParser.cpp
│ ├── MSVCObjectFormatParser.h
│ ├── Makefile.osx
│ ├── ObjectExplorer.cpp
│ ├── ObjectExplorer.h
│ ├── PropertySheet.props
│ ├── TypeExtractor.cpp
│ ├── TypeExtractor.h
│ ├── TypeReconstructor.cpp
│ ├── TypeReconstructor.h
│ ├── Utility.cpp
│ ├── Utility.h
│ ├── makefile.lnx
│ ├── makefile.mac
│ └── makefile7.mac
└── targets
├── IDA_v6.8
├── Linux
│ └── HexRaysCodeXplorer.plx
├── Mac
│ ├── HexRaysCodeXplorer.pmc
│ └── HexRaysCodeXplorer.pmc64
└── Win
│ ├── HexRaysCodeXplorer.p64
│ └── HexRaysCodeXplorer.plw
├── IDA_v6.9
└── Win
│ ├── HexRaysCodeXplorer.p64
│ └── HexRaysCodeXplorer.plw
├── IDA_v6.95
└── Win
│ ├── HexRaysCodeXplorer.p64
│ └── HexRaysCodeXplorer.plw
├── IDA_v7.0
├── HexRaysCodeXplorer.dylib
└── HexRaysCodeXplorer64.dylib
├── IDA_v7.1
├── HexRaysCodeXplorer.dylib
└── HexRaysCodeXplorer64.dylib
└── IDA_v7.2
├── HexRaysCodeXplorer.dylib
└── HexRaysCodeXplorer64.dylib
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | #*.so
8 | #*.dylib
9 |
10 | # Compiled Static libraries
11 | *.lai
12 | *.la
13 | *.a
14 | /src/HexRaysCodeXplorer/x64
15 | /src/.vs
16 | /src/*.db
17 | /src/*.opendb
18 | build-7.1-32/*
19 | build-7.1-64/*
20 | build
21 | build-7.2-32
22 | build-7.2-64
23 |
24 | src/HexRaysCodeXplorer.xcodeproj/project.xcworkspace/xcuserdata
25 | src/HexRaysCodeXplorer.xcodeproj/xcuserdata
26 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "ida-cmake"]
2 | path = ida-cmake
3 | url = https://github.com/fjh658/ida-cmake.git
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.1)
2 | project(HexRaysCodeXplorer)
3 |
4 | include("ida-cmake/cmake/IDA.cmake")
5 |
6 | set(CMAKE_CXX_STANDARD 11)
7 |
8 | set(sources "src/HexRaysCodeXplorer/Debug.cpp"
9 | "src/HexRaysCodeXplorer/CtreeExtractor.cpp"
10 | "src/HexRaysCodeXplorer/GCCObjectFormatParser.cpp"
11 | "src/HexRaysCodeXplorer/GCCTypeInfo.cpp"
12 | "src/HexRaysCodeXplorer/GCCVtableInfo.cpp"
13 | "src/HexRaysCodeXplorer/IObjectFormatParser.cpp"
14 | "src/HexRaysCodeXplorer/MSVCObjectFormatParser.cpp"
15 | "src/HexRaysCodeXplorer/ObjectExplorer.cpp"
16 | "src/HexRaysCodeXplorer/CodeXplorer.cpp"
17 | "src/HexRaysCodeXplorer/CtreeGraphBuilder.cpp"
18 | "src/HexRaysCodeXplorer/TypeReconstructor.cpp"
19 | "src/HexRaysCodeXplorer/TypeExtractor.cpp"
20 | "src/HexRaysCodeXplorer/Utility.cpp")
21 |
22 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
23 | # using AppleClang
24 | set(CMAKE_C_FLAGS "-DUSE_DANGEROUS_FUNCTIONS=1 -DUSE_STANDARD_FILE_FUNCTIONS=1")
25 | set(CMAKE_CXX_FLAGS "-DUSE_DANGEROUS_FUNCTIONS=1 -DUSE_STANDARD_FILE_FUNCTIONS=1")
26 |
27 | elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
28 | # using Clang
29 | # TODO
30 |
31 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
32 | # using GCC
33 | # TODO
34 |
35 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
36 | # using Intel C++
37 | # TODO
38 |
39 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
40 | # using Visual Studio C++
41 | # TODO
42 | endif()
43 |
44 | add_ida_plugin(${CMAKE_PROJECT_NAME} ${sources})
45 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | _ _ ______ _____ _ __ __ _
3 | | | | | | ___ \ / __ \ | | \ \ / / | |
4 | | |_| | _____ _| |_/ /__ _ _ _ ___| / \/ ___ __| | ___ \ V / _ __ | | ___ _ __ ___ _ __
5 | | _ |/ _ \ \/ / // _` | | | / __| | / _ \ / _` |/ _ \/ \| '_ \| |/ _ \| '__/ _ \ '__|
6 | | | | | __/> <| |\ \ (_| | |_| \__ \ \__/\ (_) | (_| | __/ /^\ \ |_) | | (_) | | | __/ |
7 | \_| |_/\___/_/\_\_| \_\__,_|\__, |___/\____/\___/ \__,_|\___\/ \/ .__/|_|\___/|_| \___|_|
8 | __/ | | |
9 | |___/ |_|
10 |
11 | ## changelist:
12 | 1. #### Add support ida7.0/ida7.1/ida7.2 for macOS
13 |
14 | 
15 |
16 | - build script
17 |
18 | ```shell
19 | ida-cmake/build.py -i /Users/shared/idasdk72 -t 7.2 --idaq-path "/Applications/IDA_Pro_7.2/ida.app/Contents/MacOS"
20 | ```
21 | - Generate Xcode
22 | - 64bit
23 | ```
24 | mkdir build-64 && cd build-64
25 | cmake -G Xcode -DIDA_SDK=/Users/shared/idasdk72 -DIDA_VERSION=720 -DIDA_BINARY_64=ON -DIDA_INSTALL_DIR=/Applications/IDA_Pro_7.2/ida.app/Contents/MacOS -DCMAKE_INSTALL_PREFIX=/Applications/IDA_Pro_7.2/ida.app/Contents/MacOS -DIDA_EA_64=TRUE ..
26 | ```
27 | `Note: -DIDA_EA_64=TRUE`
28 |
29 | - 32bit
30 | ```
31 | mkdir build-32 && cd build-32
32 | cmake -G Xcode -DIDA_SDK=/Users/shared/idasdk72 -DIDA_VERSION=720 -DIDA_BINARY_64=ON -DIDA_INSTALL_DIR=/Applications/IDA_Pro_7.2/ida.app/Contents/MacOS -DCMAKE_INSTALL_PREFIX=/Applications/IDA_Pro_7.2/ida.app/Contents/MacOS -DIDA_EA_64=FALSE ..
33 | ```
34 | `Note: -DIDA_EA_64=FALSE`
35 |
36 | - compile & install
37 | ```
38 | cmake --build . -j 4 --clean-first --target install -- VERBOSE=1
39 | ```
40 | - Debugging the plugin in Xcode
41 | - Attach to process
42 |
43 |
44 | [](http://www.gnu.org/licenses/gpl-3.0)
45 | [](https://codeclimate.com/github/REhints/HexRaysCodeXplorer)
46 | [](https://codeclimate.com/github/REhints/HexRaysCodeXplorer)
47 | [](https://gitter.im/REhints/HexRaysCodeXplorer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
48 | [](https://www.codewake.com/p/hexrayscodexplorer)
49 |
50 | The Hex-Rays Decompiler plugin for better code navigation in RE process. CodeXplorer automates code REconstruction of C++ applications or modern malware like Stuxnet, Flame, Equation, Animal Farm ... :octocat:
51 |
52 | The CodeXplorer plugin is one of the [first publicly available](https://www.hex-rays.com/products/decompiler/manual/third_party.shtml) Hex-Rays Decompiler plugins. We keep updated this project [since summer of 2013](https://www.hex-rays.com/contests/2013/) and continue contributing new features frequently. Also most interesting feutures of CodeXplorer have been presented on numerous security conferences like: REcon, ZeroNights, H2HC, NSEC and BHUS :space_invader:
53 |
54 | __Contributors__:
55 |
56 | Alex Matrosov ([@matrosov](https://github.com/matrosov))
57 |
58 | Eugene Rodionov ([@rodionov](https://github.com/rodionov))
59 |
60 | Rodrigo Branco ([@rrbranco](https://github.com/rrbranco))
61 |
62 | Gabriel Barbosa ([@gabrielnb](https://github.com/gabrielnb))
63 |
64 | __Supported versions of Hex-Rays products:__ everytime we focus on last versions of IDA and Decompiler because trying to use new interesting features in new SDK releases. It's also mean we tested just on last versions of Hex-Rays products and not guaranteed stable work on previous ones.
65 |
66 | __Why not IdaPython:__ all code developed on C/C++ because it's more stable way to support complex plugin for Hex-Rays Decompiler.
67 |
68 | __Supported Platforms:__ x86/x64 for Win, Linux and Mac.
69 |
70 | __HexRaysCodeXplorer__ - Hex-Rays Decompiler plugin for easier code navigation. Right-click context menu in the Pseudocode window shows CodeXplorer plugin commands:
71 |
72 | 
73 |
74 | :gem: __Here are the main features of the CodeXplorer plugin:__ :gem:
75 |
76 | * ***Automatic type REconstruction*** for C++ objects. To be able to reconstruct a type using HexRaysCodeXplorer one needs to select the variable holding pointer to the instance of position independed code or to an object and by right-button mouse click select from the context menu «REconstruct Type» option:
77 |
78 | 
79 |
80 | The reconstructed structure is displayed in “Output window”. Detailed information about type Reconstruction feature is provided in the blog post “[Type REconstruction in HexRaysCodeXplorer](http://rehints.com/2013-09-02-Type-REconstruction-in-HexRaysCodeXplorer.html)”.
81 |
82 | Also CodeXplorer plugin supports auto REconstruction type into IDA local types storage.
83 |
84 | 
85 |
86 | * ***Virtual function table identification*** - automatically identifies references to virtual function tables during type reconstruction. When a reference to a virtual function table is identified the plugin generates a corresponding C-structure. As shown below during reconstructing `struct_local_data_storage` two virtual function tables were identified and, as a result, two corresponding structures were generated: `struct_local_data_storage_VTABLE_0` and `struct_local_data_storage_VTABLE_4`.
87 |
88 | 
89 |
90 | * ***C-tree graph visualization*** – a special tree-like structure representing a decompiled routine in citem_t terms (hexrays.hpp). Useful feature for understanding how the decompiler works. The highlighted graph node corresponds to the current cursor position in the HexRays Pseudocode window:
91 |
92 | 
93 |
94 | * ***Ctree Item View*** – show ctree representation for highlighted element:
95 |
96 | 
97 |
98 | * ***Extract Ctrees to File*** – dump calculate SHA1 hash and dump all ctrees to file.
99 |
100 | 
101 |
102 | * ***Extract Types to File*** – dump all types information (include reconstructed types) into file.
103 |
104 | * ***Navigation through virtual function calls*** in HexRays Pseudocode window. After representing C++ objects by C-structures this feature make possible navigation by mouse clicking to the virtual function calls as structure fields:
105 |
106 | 
107 |
108 | * ***Jump to Disasm*** - small feature for navigate to assembly code into "IDA View window" from current Pseudocode line position. It is help to find a place in assembly code associated with decompiled line.
109 |
110 | 
111 |
112 | * ***Object Explorer*** – useful interface for navigation through virtual tables (VTBL) structures. Object Explorer outputs VTBL information into IDA custom view window. The output window is shown by choosing «Object Explorer» option in right-button mouse click context menu:
113 |
114 | 
115 |
116 | __Object Explorer supports following features:__
117 | * Auto structures generation for VTBL into IDA local types
118 |
119 | * Navigation in virtual table list and jump to VTBL address into "IDA View" window by click
120 |
121 | * Show hints for current position in virtual table list
122 |
123 | * Shows cross-references list by click into menu on "Show XREFS to VTBL"
124 |
125 | 
126 |
127 | * Support auto parsing RTTI objects:
128 |
129 | 
130 |
131 | __The Batch mode contains following features:__
132 |
133 | * Batch mode - useful feature to use CodeXplorer for processing multiple files without any interaction from user. We add this feature after Black Hat research in 2015 for processing 2 millions samples.
134 |
135 | ```
136 | Example (dump types and ctrees for functions with name prefix "crypto_"):
137 | idaq.exe -OHexRaysCodeXplorer:dump_types:dump_ctrees:CRYPTOcrypto_path_to_idb
138 | ```
139 |
140 | __Compiling__:
141 |
142 | ***Windows:***
143 | * Open the solution in Visual Studio
144 | * Open file `src/HexRaysCodeXplorer/PropertySheet.props` in notepad(++) and update values of `IDADIR` and `IDASDK` paths to point to IDA installation path and IDA7 SDK path accordingly. HexRays SDK should be in `$IDADIR\plugins\hexrays_sdk` (like by default)
145 | * Build `Release | x64` and `Release x64 | x64` configurations
146 |
147 | ***Linux***:
148 | * cd src/HexRaysCodeXplorer/
149 | * IDA_DIR= IDA_SDK= EA64=0 make -f makefile.lnx
150 | * IDA_DIR= IDA_SDK= EA64=0 make -f makefile.lnx
151 |
152 | ***Mac***:
153 | * cd src/HexRaysCodeXplorer/
154 | * IDA_DIR= IDA_SDK= make -f makefile.mac
155 | * The Mac makefile might need some hand editing, pull requests welcome!
156 | * IDA 7.0 `.pmc` file extension should be `.dylib`
157 | * bash$ `export IDA_DIR="/Applications/IDA\ Pro\ 7.0/ida.app/Contents/MacOS" && export IDA_SDK="/Applications/IDA\ Pro\ 7.0/ida.app/Contents/MacOS/idasdk" && make -f makefile7.mac`
158 | * Or open project in Xcode `HexRaysCodeXplorer.xcodeproj`
159 |
160 | ============================================================================
161 |
162 | __Conference talks about CodeXplorer plugin:__
163 | * **2015**
164 | * "Distributing the REconstruction of High-Level IR for Large Scale Malware Analysis", BHUS [[slides]](https://github.com/REhints/Publications/blob/master/Conferences/BH'2015/BH_2015.pdf)
165 | * "Object Oriented Code RE with HexraysCodeXplorer", NSEC [[slides]](https://github.com/REhints/Publications/raw/master/Conferences/Nsec'2015/nsec_2015.pdf)
166 | * **2014**
167 | * "HexRaysCodeXplorer: object oriented RE for fun and profit", H2HC [[slides]](https://github.com/REhints/Publications/blob/master/Conferences/ZeroNights'2013/ZN_2013_pdf.pdf)
168 | * **2013**
169 | * "HexRaysCodeXplorer: make object-oriented RE easier", ZeroNights [[slides]](https://github.com/REhints/Publications/blob/master/Conferences/ZeroNights'2013/ZN_2013_pdf.pdf)
170 | * "Reconstructing Gapz: Position-Independent Code Analysis Problem", REcon [[slides]](https://github.com/REhints/Publications/blob/master/Conferences/RECON'2013/RECON_2013.pdf)
171 |
--------------------------------------------------------------------------------
/img/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/1.jpg
--------------------------------------------------------------------------------
/img/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/11.png
--------------------------------------------------------------------------------
/img/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/12.png
--------------------------------------------------------------------------------
/img/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/13.png
--------------------------------------------------------------------------------
/img/14.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/14.PNG
--------------------------------------------------------------------------------
/img/16.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/16.PNG
--------------------------------------------------------------------------------
/img/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/2.png
--------------------------------------------------------------------------------
/img/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/3.png
--------------------------------------------------------------------------------
/img/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/4.png
--------------------------------------------------------------------------------
/img/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/5.png
--------------------------------------------------------------------------------
/img/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/6.png
--------------------------------------------------------------------------------
/img/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/7.png
--------------------------------------------------------------------------------
/img/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/8.png
--------------------------------------------------------------------------------
/img/ida7.0_mac_target.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/ida7.0_mac_target.png
--------------------------------------------------------------------------------
/img/ida7.1_mac_target.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/ida7.1_mac_target.png
--------------------------------------------------------------------------------
/img/ida7.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/ida7.2.png
--------------------------------------------------------------------------------
/img/m1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjh658/HexRaysCodeXplorer/7484b852f388b43f58c7c80a3aacce2c2030cb2f/img/m1.png
--------------------------------------------------------------------------------
/src/HexRaysCodeXplorer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HexRaysCodeXplorer", "HexRaysCodeXplorer\HexRaysCodeXplorer.vcxproj", "{F7E6B557-41F3-444A-BCA4-3527547DD665}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug x64|x64 = Debug x64|x64
11 | Debug|x64 = Debug|x64
12 | Release x64|x64 = Release x64|x64
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Debug x64|x64.ActiveCfg = Debug x64|x64
17 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Debug x64|x64.Build.0 = Debug x64|x64
18 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Debug|x64.ActiveCfg = Debug|x64
19 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Debug|x64.Build.0 = Debug|x64
20 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Release x64|x64.ActiveCfg = Release x64|x64
21 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Release x64|x64.Build.0 = Release x64|x64
22 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Release|x64.ActiveCfg = Release|x64
23 | {F7E6B557-41F3-444A-BCA4-3527547DD665}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | VisualSVNWorkingCopyRoot = .
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/src/HexRaysCodeXplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/HexRaysCodeXplorer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/HexRaysCodeXplorer/CodeXplorer.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2013-2016
2 | REhints
3 | All rights reserved.
4 |
5 | ==============================================================================
6 |
7 | This file is part of HexRaysCodeXplorer
8 |
9 | HexRaysCodeXplorer is free software: you can redistribute it and/or modify it
10 | under the terms of the GNU General Public License as published by
11 | the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | This program is distributed in the hope that it will be useful, but
15 | WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | General Public License for more details.
18 |
19 | You should have received a copy of the GNU General Public License
20 | along with this program. If not, see
21 | .
22 |
23 | ==============================================================================
24 | */
25 |
26 | #include "Common.h"
27 | #include "CtreeGraphBuilder.h"
28 | #include "ObjectExplorer.h"
29 | #include "TypeReconstructor.h"
30 | #include "TypeExtractor.h"
31 | #include "CtreeExtractor.h"
32 | #include "Utility.h"
33 |
34 | #include "Debug.h"
35 | #include "IObjectFormatParser.h"
36 | #include "MSVCObjectFormatParser.h"
37 | #include "GCCObjectFormatParser.h"
38 |
39 | #include
40 |
41 | extern plugin_t PLUGIN;
42 |
43 | IObjectFormatParser *objectFormatParser = 0;
44 | #if defined (__LINUX__) || defined (__MAC__)
45 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
46 | #endif
47 |
48 | // Hex-Rays API pointer
49 | hexdsp_t *hexdsp = NULL;
50 |
51 | namespace {
52 |
53 | static bool inited = false;
54 |
55 | // Hotkey for the new command
56 | static const char hotkey_dg[] = "T";
57 | static const char hotkey_ce[] = "O";
58 | static const char hotkey_rt[] = "R";
59 | static const char hotkey_gd[] = "J";
60 | static const char hotkey_et[] = "S";
61 | static const char hotkey_ec[] = "C";
62 | static const char hotkey_vc[] = "V";
63 | static const char hotkey_so[] = "Q"; // After positioning cursor at source code user can press Q to copy to clipboard string of form modulename + 0xoffset.
64 | // It can be useful while working with WinDbg.
65 |
66 | static const char hotkey_rv[] = "E"; // Automatic renaming of duplicating variables by pressing E.
67 | // All duplicating successors obtain _2, _3 ... postfixes.
68 |
69 | static const qstring kCryptoPrefixParam = "CRYPTO";
70 |
71 |
72 |
73 | //--------------------------------------------------------------------------
74 | // Helper class to build graph from ctree.
75 | struct graph_builder_t : public ctree_parentee_t
76 | {
77 | callgraph_t &cg;
78 | std::map reverse; // Reverse mapping for tests and adding edges
79 |
80 | graph_builder_t(callgraph_t &_cg) : cg(_cg) {}
81 |
82 | // overriding functions
83 | int add_node(citem_t *i);
84 | int process(citem_t *i);
85 |
86 | // We treat expressions and statements the same way: add them to the graph
87 | int idaapi visit_insn(cinsn_t *i) { return process(i); }
88 | int idaapi visit_expr(cexpr_t *e) { return process(e); }
89 | };
90 |
91 | // Add a new node to the graph
92 | int graph_builder_t::add_node(citem_t *i)
93 | {
94 | // Check if the item has already been encountered during the traversal
95 | if (reverse.find(i) != reverse.end())
96 | {
97 | warning("bad ctree - duplicate nodes!");
98 | logmsg(DEBUG, "bad ctree - duplicate nodes!");
99 | return -1;
100 | }
101 |
102 | // Add a node to the graph
103 | int n = cg.add(i);
104 |
105 | // Also remember the reverse mapping (citem_t* -> n)
106 | reverse[i] = n;
107 |
108 | return n;
109 | }
110 |
111 | // Process a ctree item
112 | int graph_builder_t::process(citem_t *item)
113 | {
114 | // Add a node for citem
115 | int n = add_node(item);
116 | if (n == -1)
117 | return -1; // error
118 |
119 | if (parents.size() > 1) // The current item has a parent?
120 | {
121 | int p = reverse[parents.back()]; // Parent node number
122 | // cg.add_edge(p, n); // Add edge from the parent to the current item
123 | cg.create_edge(p, n);
124 | }
125 |
126 | return 0;
127 | }
128 |
129 | typedef map to_raname_t;
130 |
131 | const qstring kRoot = "*&|";
132 |
133 | struct ida_local renamer_t : public ctree_visitor_t
134 | {
135 | to_raname_t& to_rename_;
136 | lvars_t& lvars_;
137 |
138 | renamer_t(to_raname_t& to_rename, lvars_t& lvars)
139 | : ctree_visitor_t(CV_FAST)
140 | , to_rename_(to_rename)
141 | , lvars_(lvars)
142 | {
143 | }
144 |
145 | map valid_rvars;
146 | map postfixes;
147 | map> roots;
148 |
149 | qstring rvar_depends_on(cexpr_t* e) {
150 | qstring rvar_name = lvars_[e->y->v.idx].name;
151 | map>::iterator it;
152 | for (it = roots.begin(); it != roots.end(); ++it)
153 | {
154 | if (it->first == rvar_name)
155 | return kRoot;
156 | vector::iterator yt;
157 | for (yt = it->second.begin(); yt != it->second.end(); ++yt)
158 | {
159 | if (*yt == rvar_name)
160 | return it->first;
161 | }
162 | }
163 | return kRoot;
164 | }
165 |
166 | int idaapi visit_expr(cexpr_t *e)
167 | {
168 | char pstx_buf[8];
169 | qstring new_name;
170 | qstring lvar_name, rvar_name, tvar_name;
171 | if (e->op == cot_asg && e->x->op == cot_var && e->y->op == cot_var)
172 | {
173 | lvar_name = lvars_[e->x->v.idx].name;
174 | rvar_name = lvars_[e->y->v.idx].name;
175 | tvar_name = rvar_depends_on(e);
176 | if (tvar_name == kRoot)
177 | {
178 | //rvar is root variable
179 | if (rvar_name != lvar_name)
180 | roots[rvar_name].push_back(lvar_name);
181 | }
182 | else
183 | {
184 | //rvar is dependant
185 | if (tvar_name != lvar_name)
186 | {
187 | rvar_name = tvar_name;
188 | roots[tvar_name].push_back(lvar_name);
189 | }
190 | }
191 |
192 | for (size_t i = 0; i < roots[lvar_name].size(); i++)
193 | {
194 | if (roots[lvar_name][i] == rvar_name)
195 | return 0;
196 | }
197 |
198 | postfixes.insert(pair(rvar_name, 2));
199 | sprintf(pstx_buf, "%d", postfixes[rvar_name]++);
200 | new_name = rvar_name + "_" + pstx_buf;
201 | to_rename_[&lvars_[e->x->v.idx]] = new_name;
202 | roots[rvar_name].push_back(new_name);
203 | }
204 | return 0;
205 | }
206 | };
207 |
208 | } // anonymous
209 |
210 | #define DECLARE_GI_VAR \
211 | graph_info_t *gi = (graph_info_t *) ud
212 |
213 | #define DECLARE_GI_VARS \
214 | DECLARE_GI_VAR; \
215 | callgraph_t *fg = &gi->fg
216 |
217 | //--------------------------------------------------------------------------
218 | static ssize_t idaapi gr_callback(void *ud, int code, va_list va)
219 | {
220 | bool result = false;
221 | switch (code)
222 | {
223 | // refresh user-defined graph nodes and edges
224 | case grcode_user_refresh:
225 | // in: mutable_graph_t *g
226 | // out: success
227 | {
228 | DECLARE_GI_VARS;
229 | func_t *f = get_func(gi->func_ea);
230 | if (f == NULL)
231 | break;
232 |
233 | graph_builder_t gb(*fg); // Graph builder helper class
234 | gb.apply_to(&gi->vu->cfunc->body, NULL);
235 |
236 | mutable_graph_t *mg = va_arg(va, mutable_graph_t *);
237 |
238 | // we have to resize
239 | mg->resize(fg->count());
240 |
241 | callgraph_t::edge_iterator end = fg->end_edges();
242 | for (callgraph_t::edge_iterator it = fg->begin_edges();
243 | it != end;
244 | ++it)
245 | {
246 | mg->add_edge(it->id1, it->id2, NULL);
247 | }
248 |
249 | fg->clear_edges();
250 | result = true;
251 | }
252 | break;
253 |
254 | // retrieve text for user-defined graph node
255 | case grcode_user_text:
256 | //mutable_graph_t *g
257 | // int node
258 | // const char **result
259 | // bgcolor_t *bg_color (maybe NULL)
260 | // out: must return 0, result must be filled
261 | // NB: do not use anything calling GDI!
262 | {
263 | DECLARE_GI_VARS;
264 | va_arg(va, mutable_graph_t *);
265 | int node = va_arg(va, int);
266 | const char **text = va_arg(va, const char **);
267 | bgcolor_t *bgcolor = va_arg(va, bgcolor_t *);
268 |
269 | callgraph_t::nodeinfo_t *ni = fg->get_info(node);
270 | result = ni != NULL;
271 | if (result)
272 | {
273 | *text = ni->name.c_str();
274 | if (bgcolor != NULL)
275 | *bgcolor = ni->color;
276 | }
277 | }
278 | break;
279 |
280 | case grcode_user_hint:
281 | {
282 | DECLARE_GI_VARS;
283 | va_arg(va, mutable_graph_t *);
284 | int mousenode = va_argi(va, int);
285 | int to = va_argi(va, int);
286 | int from = va_argi(va, int);
287 | char **hint = va_arg(va, char **);
288 |
289 | callgraph_t::nodeinfo_t *ni = fg->get_info(mousenode);
290 | result = ni != NULL;
291 | if (result && ni->ea != BADADDR)
292 | {
293 | qstring s;
294 | get_text_disasm(ni->ea, s);
295 | *hint = qstrdup(s.c_str());
296 | }
297 | }
298 | break;
299 |
300 | case grcode_dblclicked:
301 | {
302 | DECLARE_GI_VARS;
303 | graph_viewer_t *v = va_arg(va, graph_viewer_t *);
304 | selection_item_t *s = va_arg(va, selection_item_t *);
305 | if (s != NULL) {
306 | callgraph_t::nodeinfo_t *ni = fg->get_info(s->node);
307 | result = ni != NULL;
308 | if (result && s->is_node && ni->ea != BADADDR)
309 | jumpto(ni->ea);
310 | }
311 | }
312 | break;
313 |
314 | }
315 | return (int)result;
316 | }
317 |
318 |
319 | // Display ctree graph for current decompiled function
320 | static bool idaapi display_ctree_graph(void *ud)
321 | {
322 | vdui_t &vu = *(vdui_t *)ud;
323 |
324 | // Determine the ctree item to highlight
325 | vu.get_current_item(USE_KEYBOARD);
326 | citem_t *highlight = vu.item.is_citem() ? vu.item.e : NULL;
327 | graph_info_t *gi = graph_info_t::create(vu.cfunc->entry_ea, highlight);
328 |
329 | netnode id;
330 | id.create();
331 |
332 | qstring title = gi->title;
333 |
334 | TWidget *widget = find_widget(title.c_str());
335 | if (widget)
336 | {
337 | warning("Ctree Graph window already open. Switching to it.\n");
338 | logmsg(DEBUG, "Ctree Graph window already open. Switching to it.\n");
339 | activate_widget(widget, true);
340 | return true;
341 | }
342 | widget = create_empty_widget(title.c_str());
343 |
344 | gi->vu = (vdui_t *)ud;
345 | gi->widget = widget;
346 | gi->gv = create_graph_viewer("ctree", id, gr_callback, gi, 0, widget);
347 | activate_widget(widget, true);
348 | #if (defined(IDA_SDK_VERSION) && IDA_SDK_VERSION == 720)
349 | display_widget(widget, WOPN_TAB);
350 | #else
351 | display_widget(widget, WOPN_TAB | WOPN_MENU);
352 | #endif
353 | viewer_fit_window(gi->gv);
354 |
355 | return true;
356 | }
357 |
358 | // Get pointer to func_t by routine name
359 | func_t * get_func_by_name(const char *func_name)
360 | {
361 | #if 0
362 | func_t * result_func = NULL;
363 | size_t func_total = get_func_qty();
364 | if (func_total > 0)
365 | {
366 | char tmp[1024];
367 | for (unsigned int i = 0; i < func_total - 1; i++)
368 | {
369 | func_t * func = getn_func(i);
370 | if (func != NULL)
371 | {
372 | memset(tmp, 0x00, sizeof(tmp));
373 | qstring func_n;
374 | if (get_func_name(&func_n, func->start_ea) > 0)
375 | {
376 | if (!strcmp(func_name, func_n.c_str()))
377 | {
378 | result_func = func;
379 | break;
380 | }
381 | }
382 | }
383 | }
384 | }
385 | return result_func;
386 | #endif // 0
387 | return get_func(get_name_ea(BADADDR, func_name));
388 | }
389 |
390 |
391 | static bool get_expr_name(citem_t *citem, qstring& rv)
392 | {
393 | if (!citem->is_expr())
394 | return false;
395 |
396 | cexpr_t *e = (cexpr_t *)citem;
397 |
398 | // retrieve the name of the routine
399 | print1wrapper(e, &rv, NULL);
400 | tag_remove(&rv);
401 |
402 | return true;
403 | }
404 |
405 |
406 | static bool idaapi decompile_func(vdui_t &vu)
407 | {
408 | // Determine the ctree item to highlight
409 | vu.get_current_item(USE_KEYBOARD);
410 | citem_t* highlight = vu.item.is_citem() ? vu.item.e : NULL;
411 | if (!highlight)
412 | return false;
413 |
414 | // if it is an expression
415 | if (!highlight->is_expr())
416 | return false;
417 |
418 | cexpr_t *e = (cexpr_t *)highlight;
419 |
420 | qstring qcitem_name;
421 | if (!get_expr_name(highlight, qcitem_name))
422 | return false;
423 |
424 | const char* citem_name = qcitem_name.c_str();
425 | const char *proc_name = citem_name + strlen(citem_name);
426 |
427 | while ((proc_name > citem_name) && (*(proc_name - 1) != '>')) // WTF is going here?
428 | proc_name--;
429 |
430 | if (proc_name != citem_name)
431 | {
432 | if (func_t* func = get_func_by_name(proc_name))
433 | open_pseudocode(func->start_ea, -1);
434 | }
435 |
436 | return true;
437 | }
438 |
439 | /*
440 | * TODO: Make changes persistent
441 | */
442 |
443 | static bool idaapi rename_simple_expr(void *ud)
444 | {
445 | vdui_t &vu = *(vdui_t *)ud;
446 | cfuncptr_t pfunc = vu.cfunc;
447 |
448 | lvars_t& lvars = *pfunc->get_lvars();
449 |
450 | map to_rename;
451 | renamer_t zc{to_rename, lvars};
452 | zc.apply_to(&pfunc->body, NULL);
453 | for (map::iterator it = to_rename.begin(); it != to_rename.end(); ++it)
454 | vu.rename_lvar(it->first, it->second.c_str(), 0);
455 | vu.refresh_ctext();
456 | return true;
457 | }
458 |
459 | static bool idaapi show_offset_in_windbg_format(void *ud) {
460 | char _offset[32] = { 0 };
461 | char module_name[256] = { 0 };
462 | qstring result;
463 | adiff_t offset;
464 | vdui_t &vu = *(vdui_t *)ud;
465 | vu.get_current_item(USE_KEYBOARD);
466 | offset = vu.item.i->ea - get_imagebase();
467 |
468 | if (offset < 0)
469 | {
470 | info("Locate pointer after = sign or at operand of function\n");
471 | return false;
472 | }
473 |
474 | get_root_filename(module_name, 255);
475 | for (int i = 0; i < 255; i++)
476 | if (module_name[i] == '.') { module_name[i] = 0; break; }
477 | #ifdef __EA64__
478 | const char *fmt = "%llx";
479 | #else
480 | const char *fmt = "%x";
481 | #endif
482 | sprintf(_offset, fmt, offset);
483 | result.cat_sprnt("%s+0x%s", module_name, _offset);
484 |
485 | qstring title;
486 | title.cat_sprnt("0x%X", vu.item.i->ea);
487 | show_string_in_custom_view(&vu, title, result);
488 |
489 | #if defined (__LINUX__) || defined (__MAC__)
490 | msg("%s", result.c_str());
491 | #else
492 | OpenClipboard(0);
493 | EmptyClipboard();
494 | HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, result.size());
495 |
496 | if (!hg)
497 | {
498 | CloseClipboard();
499 | msg("Can't alloc\n");
500 | return false;
501 | }
502 |
503 | CopyMemory(GlobalLock(hg), result.c_str(), result.size());
504 | GlobalUnlock(hg);
505 | SetClipboardData(CF_TEXT, hg);
506 | CloseClipboard();
507 | GlobalFree(hg);
508 | #endif
509 | return true;
510 | }
511 |
512 | // show disassembly line for ctree->item
513 | bool idaapi decompiled_line_to_disasm_cb(void *ud)
514 | {
515 | vdui_t &vu = *(vdui_t *)ud;
516 | vu.ctree_to_disasm();
517 |
518 | vu.get_current_item(USE_KEYBOARD);
519 | citem_t *highlight = vu.item.is_citem() ? vu.item.e : NULL;
520 |
521 | return true;
522 | }
523 |
524 |
525 | // extract ctree to custom view
526 | static bool idaapi show_current_citem_in_custom_view(void *ud)
527 | {
528 | vdui_t &vu = *(vdui_t *)ud;
529 | vu.get_current_item(USE_KEYBOARD);
530 | citem_t *highlight_item = vu.item.is_citem() ? vu.item.e : NULL;
531 | if (!highlight_item)
532 | return false;
533 |
534 | ctree_dumper_t ctree_dump;
535 | qstring ctree_item;
536 | ctree_dump.parse_ctree_item(highlight_item, ctree_item);
537 |
538 | if (highlight_item->is_expr())
539 | {
540 | cexpr_t *e = (cexpr_t *)highlight_item;
541 | qstring item_name;
542 | get_expr_name(highlight_item, item_name);
543 | show_citem_custom_view(&vu, ctree_item, item_name);
544 | }
545 | return true;
546 | }
547 |
548 | bool initObjectFormatParser()
549 | {
550 | if (!objectFormatParser)
551 | {
552 | //if (isMSVC())
553 | if (compilerIs(MSVC_COMPILER_ABBR))
554 | objectFormatParser = new MSVCObjectFormatParser();
555 | if (compilerIs(GCC_COMPILER_ABBR))
556 | objectFormatParser = new GCCObjectFormatParser();
557 | if (!objectFormatParser)
558 | {
559 | info("CodeXplorer doesn't support parsing of not MSVC VTBL's");
560 | return false;
561 | }
562 | }
563 | return true;
564 | }
565 |
566 | // display Object Explorer
567 | static bool idaapi display_vtbl_objects(void *ud)
568 | {
569 | if (!initObjectFormatParser())
570 | return false;
571 |
572 | search_objects();
573 | object_explorer_form_init();
574 | return true;
575 | }
576 |
577 |
578 | //--------------------------------------------------------------------------
579 | // This callback handles various hexrays events.
580 | static ssize_t idaapi callback(void* ud, hexrays_event_t event, va_list va)
581 | {
582 | switch (event)
583 | {
584 | case hxe_populating_popup:
585 | {
586 | TWidget *widget = va_arg(va, TWidget *);
587 | TPopupMenu *popup = va_arg(va, TPopupMenu *);
588 | vdui_t &vu = *va_arg(va, vdui_t *);
589 |
590 | // add new command to the popup menu
591 | attach_action_to_popup(vu.ct, popup, "codexplorer::display_ctree_graph");
592 | attach_action_to_popup(vu.ct, popup, "codexplorer::object_explorer");
593 | attach_action_to_popup(vu.ct, popup, "codexplorer::reconstruct_type");
594 |
595 | attach_action_to_popup(vu.ct, popup, "codexplorer::extract_types_to_file");
596 | attach_action_to_popup(vu.ct, popup, "codexplorer::extract_ctrees_to_file");
597 | attach_action_to_popup(vu.ct, popup, "codexplorer::ctree_item_view");
598 | attach_action_to_popup(vu.ct, popup, "codexplorer::jump_to_disasm");
599 | attach_action_to_popup(vu.ct, popup, "codexplorer::show_copy_item_offset");
600 | attach_action_to_popup(vu.ct, popup, "codexplorer::rename_vars");
601 | }
602 | break;
603 |
604 | case hxe_double_click:
605 | {
606 | vdui_t &vu = *va_arg(va, vdui_t *);
607 | decompile_func(vu);
608 | }
609 | break;
610 | default:
611 | break;
612 | }
613 | return 0;
614 | }
615 |
616 | void parse_plugin_options(qstring &options, bool &dump_types, bool &dump_ctrees, qstring &crypto_prefix) {
617 | qvector params;
618 | qstring splitter = ":";
619 | split_qstring(options, splitter, params);
620 |
621 | dump_types = false;
622 | dump_ctrees = false;
623 | crypto_prefix = "";
624 |
625 | for (const qstring& param : params) {
626 | if (param == "dump_types") {
627 | dump_types = true;
628 | }
629 | else if (param == "dump_ctrees") {
630 | dump_ctrees = true;
631 | }
632 | else if (param.length() > kCryptoPrefixParam.length() && param.find(kCryptoPrefixParam) == 0) {
633 | crypto_prefix = param.substr(kCryptoPrefixParam.length());
634 | }
635 | else {
636 | qstring message = "Invalid argument: ";
637 | message += param + "\n";
638 | logmsg(INFO, message.c_str());
639 | }
640 | }
641 | }
642 |
643 | namespace {
644 |
645 | class MenuActionHandler : public action_handler_t
646 | {
647 | public:
648 | typedef std::function handler_t;
649 |
650 | MenuActionHandler(handler_t handler)
651 | : handler_(handler)
652 | {
653 | }
654 | virtual int idaapi activate(action_activation_ctx_t *ctx)
655 | {
656 | auto vdui = get_widget_vdui(ctx->widget);
657 | return handler_(vdui) ? TRUE : FALSE;
658 | }
659 |
660 | virtual action_state_t idaapi update(action_update_ctx_t *ctx)
661 | {
662 | return ctx->widget_type == BWN_PSEUDOCODE ? AST_ENABLE_FOR_WIDGET : AST_DISABLE_FOR_WIDGET;
663 | }
664 |
665 | private:
666 | handler_t handler_;
667 | };
668 |
669 | static MenuActionHandler kDisplayCtreeGraphHandler{ display_ctree_graph };
670 | static MenuActionHandler kObjectExplorerHandler{ display_vtbl_objects };
671 | static MenuActionHandler kReconstructTypeHandler{ reconstruct_type_cb };
672 | static MenuActionHandler kExtractAllTypesHandler{ extract_all_types };
673 | static MenuActionHandler kExtractAllCtreesHandler{ extract_all_ctrees };
674 | static MenuActionHandler kShowCurrentCItemInCustomView{ show_current_citem_in_custom_view };
675 | static MenuActionHandler kJumpToDisasmHandler{ decompiled_line_to_disasm_cb };
676 | static MenuActionHandler kShowOffsetInWindbgFormatHandler{ show_offset_in_windbg_format };
677 | static MenuActionHandler kRenameVarsHandler{ rename_simple_expr };
678 |
679 | static action_desc_t kActionDescs[] = {
680 | ACTION_DESC_LITERAL("codexplorer::display_ctree_graph", "Display Ctree Graph", &kDisplayCtreeGraphHandler, hotkey_dg, nullptr, -1),
681 | ACTION_DESC_LITERAL("codexplorer::object_explorer", "Object Explorer", &kObjectExplorerHandler, hotkey_ce, nullptr, -1),
682 | ACTION_DESC_LITERAL("codexplorer::reconstruct_type", "REconstruct Type", &kReconstructTypeHandler, hotkey_rt, nullptr, -1),
683 | ACTION_DESC_LITERAL("codexplorer::extract_types_to_file", "Extract Types to File", &kExtractAllTypesHandler, hotkey_et, nullptr, -1),
684 | ACTION_DESC_LITERAL("codexplorer::extract_ctrees_to_file", "Extract Ctrees to File", &kExtractAllCtreesHandler, hotkey_ec, nullptr, -1),
685 | ACTION_DESC_LITERAL("codexplorer::ctree_item_view", "Ctree Item View", &kShowCurrentCItemInCustomView, hotkey_vc, nullptr, -1),
686 | ACTION_DESC_LITERAL("codexplorer::jump_to_disasm", "Jump to Disasm", &kJumpToDisasmHandler, hotkey_gd, nullptr, -1),
687 | ACTION_DESC_LITERAL("codexplorer::show_copy_item_offset", "Show/Copy item offset", &kShowOffsetInWindbgFormatHandler, hotkey_so, nullptr, -1),
688 | ACTION_DESC_LITERAL("codexplorer::rename_vars", "Rename vars", &kRenameVarsHandler, hotkey_rv, nullptr, -1)
689 | };
690 |
691 | }
692 | //--------------------------------------------------------------------------
693 | // Initialize the plugin.
694 | int idaapi init(void)
695 | {
696 | logmsg(INFO, "\nHexRaysCodeXplorer plugin by @REhints loaded.\n\n\n");
697 |
698 | if (!init_hexrays_plugin())
699 | return PLUGIN_SKIP; // no decompiler
700 |
701 | bool dump_types = false;
702 | bool dump_ctrees = false;
703 | qstring crypto_prefix;
704 |
705 | qstring options = get_plugin_options(PLUGIN.wanted_name);
706 | parse_plugin_options(options, dump_types, dump_ctrees, crypto_prefix);
707 |
708 | for (unsigned i = 0; i < _countof(kActionDescs); ++i)
709 | register_action(kActionDescs[i]);
710 |
711 | install_hexrays_callback((hexrays_cb_t*)callback, nullptr);
712 | logmsg(INFO, "Hex-rays version %s has been detected\n", get_hexrays_version());
713 | inited = true;
714 |
715 | if (dump_ctrees || dump_types) {
716 | auto_wait();
717 |
718 | if (dump_types) {
719 | logmsg(DEBUG, "Dumping types\n");
720 | extract_all_types(NULL);
721 |
722 | int file_id = qcreate("codexplorer_types_done", 511);
723 | if (file_id != -1)
724 | qclose(file_id);
725 | }
726 |
727 | if (dump_ctrees) {
728 | logmsg(DEBUG, "Dumping ctrees\n");
729 | dump_funcs_ctree(NULL, crypto_prefix);
730 |
731 | int file_id = qcreate("codexplorer_ctrees_done", 511);
732 | if (file_id != -1)
733 | qclose(file_id);
734 | }
735 |
736 | logmsg(INFO, "\nHexRaysCodeXplorer plugin by @REhints exiting...\n\n\n");
737 | }
738 |
739 | return PLUGIN_KEEP;
740 | }
741 |
742 | //--------------------------------------------------------------------------
743 | void idaapi term(void)
744 | {
745 | if (inited)
746 | {
747 | logmsg(INFO, "\nHexRaysCodeXplorer plugin by @REhints terminated.\n\n\n");
748 | remove_hexrays_callback((hexrays_cb_t*)callback, NULL);
749 | term_hexrays_plugin();
750 | }
751 | }
752 |
753 | //--------------------------------------------------------------------------
754 | bool idaapi run(size_t)
755 | {
756 | // This function won't be called because our plugin is invisible (no menu
757 | // item in the Edit, Plugins menu) because of PLUGIN_HIDE
758 | return true;
759 | }
760 |
761 | //--------------------------------------------------------------------------
762 | static const char comment[] = "HexRaysCodeXplorer plugin by @REhints";
763 |
764 | //--------------------------------------------------------------------------
765 | //
766 | // PLUGIN DESCRIPTION BLOCK
767 | //
768 | //--------------------------------------------------------------------------
769 | plugin_t PLUGIN =
770 | {
771 | IDP_INTERFACE_VERSION,
772 | PLUGIN_HIDE, // plugin flags
773 | init, // initialize
774 | term, // terminate. this pointer may be NULL.
775 | run, // invoke plugin
776 | comment, // long comment about the plugin
777 | // it could appear in the status line or as a hint
778 | "", // multiline help about the plugin
779 | "HexRaysCodeXplorer by @REhints", // the preferred short name of the plugin (PLUGIN.wanted_name)
780 | "" // the preferred hotkey to run the plugin
781 | };
782 |
--------------------------------------------------------------------------------
/src/HexRaysCodeXplorer/Common.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2013-2015
2 | REhints
3 | All rights reserved.
4 |
5 | ==============================================================================
6 |
7 | This file is part of HexRaysCodeXplorer
8 |
9 | HexRaysCodeXplorer is free software: you can redistribute it and/or modify it
10 | under the terms of the GNU General Public License as published by
11 | the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | This program is distributed in the hope that it will be useful, but
15 | WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | General Public License for more details.
18 |
19 | You should have received a copy of the GNU General Public License
20 | along with this program. If not, see .
21 |
22 | ==============================================================================
23 | */
24 |
25 | #ifndef __H_COMMON__
26 | #define __H_COMMON__
27 |
28 | #pragma once
29 |
30 | #if !defined (__LINUX__) && !defined (__MAC__)
31 | #pragma warning (disable: 4996 4800 )
32 | #else
33 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
34 | #endif
35 |
36 | #if !defined (__LINUX__) && !defined (__MAC__)
37 | #include
38 | #include
39 | #else
40 | #include "Linux.h"
41 | #endif
42 |
43 | #ifdef __NT__
44 | #pragma warning(push)
45 | #pragma warning(disable:4309 4244 4267) // disable "truncation of constant value" warning from IDA SDK, conversion from 'ssize_t' to 'int', possible loss of data
46 | #endif // __NT__
47 | #ifndef USE_DANGEROUS_FUNCTIONS
48 | #define USE_DANGEROUS_FUNCTIONS
49 | #endif
50 | #ifdef __clang__
51 | #pragma clang diagnostic push
52 | #pragma clang diagnostic ignored "-Wsign-compare"
53 | #pragma clang diagnostic ignored "-Wvarargs"
54 | #pragma clang diagnostic ignored "-Wlogical-op-parentheses"
55 | #pragma clang diagnostic ignored "-Wunused-private-field"
56 | #endif
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include
62 | #include
63 | #include
64 | #include
65 | #include
66 | #include
67 | #include
68 | #include
69 | #include
70 | #include
71 | #include
72 | #include
73 | #include
74 | #include
75 | #ifdef __NT__
76 | #pragma warning(pop)
77 | #endif // __NT__
78 | #ifdef __clang__
79 | #pragma clang diagnostic pop
80 | #endif
81 |
82 | template
83 | struct print1_accepts_qstring
84 | {
85 | template struct yay_sfinae {};
86 | template static char test(yay_sfinae*);
87 | template static int test(...);
88 | static const bool value = sizeof(test(0)) == sizeof(char);
89 | };
90 |
91 | // For IDA7.1 and newer
92 | template
93 | void print1wrapper(std::true_type, const T *e, qstring *qbuf, const cfunc_t *func) {
94 | e->print1(qbuf, func);
95 | };
96 |
97 | // For older SDKs
98 | template
99 | void print1wrapper(std::false_type, const T *e, qstring *qbuf, const cfunc_t *func) {
100 | char lbuf[MAXSTR];
101 | const size_t len = e->print1(lbuf, sizeof(lbuf) - 1, func);
102 | qstring temp(lbuf, len);
103 | qbuf->swap(temp);
104 | };
105 |
106 | template
107 | void print1wrapper(const T *e, qstring *qbuf, const cfunc_t *func) {
108 | return print1wrapper(
109 | std::integral_constant::value>(),
110 | e, qbuf, func);
111 | }
112 |
113 |
114 |
115 | #include
116 | #include
117 | #include
118 |
119 | #include
120 | #include
121 | #include
122 | #include
123 | #include
124 | #include