Skip to content

Commit

Permalink
v1.0 source code upload
Browse files Browse the repository at this point in the history
  • Loading branch information
matrosov committed Sep 21, 2013
1 parent 478d176 commit 433cf59
Show file tree
Hide file tree
Showing 22 changed files with 2,794 additions and 0 deletions.
Binary file removed beta-test/Beta1_21-07-2013/HexRaysCodeXplorer.plw
Binary file not shown.
Binary file removed beta-test/Beta2_02-09-2013/HexRaysCodeXplorer.plw
Binary file not shown.
23 changes: 23 additions & 0 deletions sources/HexRaysCodeXplorer.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HexRaysCodeXplorer", "HexRaysCodeXplorer\HexRaysCodeXplorer.vcxproj", "{F7E6B557-41F3-444A-BCA4-3527547DD665}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F7E6B557-41F3-444A-BCA4-3527547DD665}.Debug|Win32.ActiveCfg = Debug|Win32
{F7E6B557-41F3-444A-BCA4-3527547DD665}.Debug|Win32.Build.0 = Debug|Win32
{F7E6B557-41F3-444A-BCA4-3527547DD665}.Release|Win32.ActiveCfg = Release|Win32
{F7E6B557-41F3-444A-BCA4-3527547DD665}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
VisualSVNWorkingCopyRoot = .
EndGlobalSection
EndGlobal
Binary file added sources/HexRaysCodeXplorer.suo
Binary file not shown.
375 changes: 375 additions & 0 deletions sources/HexRaysCodeXplorer/CodeXplorer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,375 @@
/* Copyright (c) 2013
REhints <info@rehints.com>
All rights reserved.
============================================================================
This file is part of HexRaysCodeXplorer
HexRaysCodeXplorer is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
<http://www.gnu.org/licenses/>.
*/


#include "Common.h"
#include "GraphBuilder.h"
#include "ObjectExplorer.h"
#include "ObjectType.h"


// Hex-Rays API pointer
hexdsp_t *hexdsp = NULL;

static bool inited = false;

// Hotkey for the new command
static const char hotkey_dg[] = "G";
static ushort hotcode_dg;

static const char hotkey_ce[] = "E";
static ushort hotcode_ce;

static const char hotkey_rt[] = "R";
static ushort hotcode_rt;



//--------------------------------------------------------------------------
// Helper class to build graph from ctree.
struct graph_builder_t : public ctree_parentee_t
{
callgraph_t &cg;
std::map<citem_t *, int> reverse; // Reverse mapping for tests and adding edges

graph_builder_t(callgraph_t &_cg) : cg(_cg) {}

// overriding functions
int add_node(citem_t *i);
int process(citem_t *i);

// We treat expressions and statements the same way: add them to the graph
int idaapi visit_insn(cinsn_t *i) { return process(i); }
int idaapi visit_expr(cexpr_t *e) { return process(e); }
};

// Add a new node to the graph
int graph_builder_t::add_node(citem_t *i)
{
// Check if the item has already been encountered during the traversal
if ( reverse.find(i) != reverse.end() )
{
warning("bad ctree - duplicate nodes!");
return -1;
}

// Add a node to the graph
int n = cg.add(i);

// Also remember the reverse mapping (citem_t* -> n)
reverse[i] = n;

return n;
}

// Process a ctree item
int graph_builder_t::process(citem_t *item)
{
// Add a node for citem
int n = add_node(item);
if ( n == -1 )
return -1; // error

if ( parents.size() > 1 ) // The current item has a parent?
{
int p = reverse[parents.back()]; // Parent node number
// cg.add_edge(p, n); // Add edge from the parent to the current item
cg.create_edge(p, n);
}

return 0;
}

#define DECLARE_GI_VAR \
graph_info_t *gi = (graph_info_t *) ud

#define DECLARE_GI_VARS \
DECLARE_GI_VAR; \
callgraph_t *fg = &gi->fg

//--------------------------------------------------------------------------
static int idaapi gr_callback(void *ud, int code, va_list va)
{
bool result = false;
switch ( code )
{
// refresh user-defined graph nodes and edges
case grcode_user_refresh:
// in: mutable_graph_t *g
// out: success
{
DECLARE_GI_VARS;
func_t *f = get_func(gi->func_ea);
if (f == NULL)
break;

graph_builder_t gb(*fg); // Graph builder helper class
//fg->walk_func(f);
gb.apply_to(&gi->vu->cfunc->body, NULL);

mutable_graph_t *mg = va_arg(va, mutable_graph_t *);

// we have to resize
mg->resize(fg->count());

callgraph_t::edge_iterator end = fg->end_edges();
for ( callgraph_t::edge_iterator it=fg->begin_edges();
it != end;
++it )
{
mg->add_edge(it->id1, it->id2, NULL);
}

fg->clear_edges();
result = true;
}
break;

// retrieve text for user-defined graph node
case grcode_user_text:
//mutable_graph_t *g
// int node
// const char **result
// bgcolor_t *bg_color (maybe NULL)
// out: must return 0, result must be filled
// NB: do not use anything calling GDI!
{
DECLARE_GI_VARS;
va_arg(va, mutable_graph_t *);
int node = va_arg(va, int);
const char **text = va_arg(va, const char **);
bgcolor_t *bgcolor = va_arg(va, bgcolor_t *);

callgraph_t::nodeinfo_t *ni = fg->get_info(node);
result = ni != NULL;
if ( result )
{
*text = ni->name.c_str();
if ( bgcolor != NULL )
*bgcolor = ni->color;
}
}
break;
}
return (int)result;
}


static bool idaapi display_graph(void *ud)
{
vdui_t &vu = *(vdui_t *)ud;

// Determine the ctree item to highlight
vu.get_current_item(USE_KEYBOARD);
citem_t *highlight = vu.item.is_citem() ? vu.item.e : NULL;

graph_info_t *gi = graph_info_t::create(vu.cfunc->entry_ea, highlight);

netnode id;
id.create();

// get function name
qstring title = gi->title;//"Funcion ctree graph";

HWND hwnd = NULL;
TForm *form = create_tform(title.c_str(), &hwnd);

gi->vu = (vdui_t *)ud;
gi->form = form;
gi->gv = create_graph_viewer(form, id, gr_callback, gi, 0);
open_tform(form, FORM_TAB | FORM_MENU | FORM_QWIDGET);
viewer_fit_window(gi->gv);

return true;
}

// Get poinyter to func_t by routine name
func_t * get_func_by_name(const char *func_name)
{
func_t * result_func = NULL;
size_t func_total = get_func_qty();
if(func_total > 0)
{
char tmp[1024];
for (unsigned int i = 0 ; i < func_total - 1 ; i ++)
{
func_t * func = getn_func(i);
if(func != NULL)
{
memset(tmp, 0x00, sizeof(tmp));
char *func_n = get_func_name(func->startEA, tmp, sizeof(tmp));
if(func_n != NULL)
{
if(!strcmp(func_name, func_n))
{
result_func = func;
break;
}
}
}
}
}
return result_func;
}

static bool idaapi decompile_func(vdui_t &vu)
{
// Determine the ctree item to highlight
vu.get_current_item(USE_KEYBOARD);
citem_t *highlight = vu.item.is_citem() ? vu.item.e : NULL;

if(highlight != NULL)
{
// if it is an expression
if(highlight->is_expr())
{
cexpr_t *e = (cexpr_t *)highlight;

// retireve the name of the routine
char tmp[1024];
memset(tmp, 0x00, sizeof(tmp));
e->print1(tmp, sizeof(tmp), NULL);
tag_remove(tmp, tmp, sizeof(tmp));

char *proc_name = tmp + strlen(tmp);

while((proc_name > tmp) && (*(proc_name - 1) != '>'))
proc_name --;

func_t * func = get_func_by_name(proc_name);
if(func != NULL)
{
vdui_t * decompiled_window = open_pseudocode(func->startEA, -1);
}
}
}

return true;
}

//display Class Explorer
static bool idaapi display_objects(void *ud)
{
vdui_t &vu = *(vdui_t *)ud;
search_vtbl();
custom_form_init();

return true;
}

//--------------------------------------------------------------------------
// This callback handles various hexrays events.
static int idaapi callback(void *, hexrays_event_t event, va_list va)
{
switch ( event )
{
case hxe_right_click:
{
vdui_t &vu = *va_arg(va, vdui_t *);
// add new command to the popup menu
add_custom_viewer_popup_item(vu.ct, "Display Graph", hotkey_dg, display_graph, &vu);
add_custom_viewer_popup_item(vu.ct, "Object Explorer", hotkey_ce, display_objects, &vu);
add_custom_viewer_popup_item(vu.ct, "REconstruct Type", hotkey_rt, reconstruct_type, &vu);
}
break;

case hxe_keyboard:
{
vdui_t &vu = *va_arg(va, vdui_t *);
int keycode = va_arg(va, int);
int shift = va_arg(va, int);
// check for the hotkey
if ( lookup_key_code(keycode, shift, true) == hotcode_dg && shift == 0 )
return display_graph(&vu);
if ( lookup_key_code(keycode, shift, true) == hotcode_dg && shift == 0 )
return display_objects(&vu);
if ( lookup_key_code(keycode, shift, true) == hotcode_rt && shift == 0 )
return reconstruct_type(&vu);
}
break;
case hxe_double_click:
{
vdui_t &vu = *va_arg(va, vdui_t *);
decompile_func(vu);
}
break;
default:
break;
}
return 0;
}

//--------------------------------------------------------------------------
// Initialize the plugin.
int idaapi init(void)
{
if ( !init_hexrays_plugin() )
return PLUGIN_SKIP; // no decompiler
install_hexrays_callback(callback, NULL);
const char *hxver = get_hexrays_version();
msg("Hex-rays version %s has been detected, %s ready to use\n", hxver, PLUGIN.wanted_name);
inited = true;
hotcode_dg = get_key_code(hotkey_dg); // convert the hotkey to binary form
hotcode_rt = get_key_code(hotkey_rt); // convert the hotkey to binary form

return PLUGIN_KEEP;
}

//--------------------------------------------------------------------------
void idaapi term(void)
{
if ( inited )
{
remove_hexrays_callback(callback, NULL);
term_hexrays_plugin();
}
}

//--------------------------------------------------------------------------
void idaapi run(int)
{
// This function won't be called because our plugin is invisible (no menu
// item in the Edit, Plugins menu) because of PLUGIN_HIDE
}

//--------------------------------------------------------------------------
static char comment[] = "HexRaysCodeXplorer plugin";

//--------------------------------------------------------------------------
//
// PLUGIN DESCRIPTION BLOCK
//
//--------------------------------------------------------------------------
plugin_t PLUGIN =
{
IDP_INTERFACE_VERSION,
PLUGIN_HIDE, // plugin flags
init, // initialize
term, // terminate. this pointer may be NULL.
run, // invoke plugin
comment, // long comment about the plugin
// it could appear in the status line or as a hint
"", // multiline help about the plugin
"HexRaysCodeXplorer", // the preferred short name of the plugin
"" // the preferred hotkey to run the plugin
};
Loading

0 comments on commit 433cf59

Please sign in to comment.