[原创] VS2017 修改移植 "IDA IPyhon QTconsole" 到 IDA 7.0
发表于:
2018-10-15 12:21
3081
[原创] VS2017 修改移植 "IDA IPyhon QTconsole" 到 IDA 7.0
由于IDA 7.0的SDK许多关键结构和函数已经改动,以前的插件项目都需要代码重构才能用。
参考github项目
github 上 ida_ipython 项目代码更新最新已经是三年前,其中的 ReadMe 倒是去年六月有更新
ida_ipython github 参考链接:
#-------
import base64
base64.b64decode('aHR0cHM6Ly9naXRodWIuY29tL2phbWVzOTFiL2lkYV9pcHl0aG9u')
#-------
由于使用VS2017,ida_ipython项目的代码自带的MinHook目录没有对应的分发版本,只能自行编译VS2017版MinHook
MiHook github 参考链接
#-------
import base64
base64.b64decode('aHR0cHM6Ly9naXRodWIuY29tL1RzdWRhS2FnZXl1L21pbmhvb2s=')
#------- MinHook项目
VS2017 直接使用 minhook-master\build\VC15\MinHookVC15.sln 解决方案编译分发
设置不同选项,主要是/MD与/MT和x64与win32,可得到不同发行版
以下是 MinHook_lib_2017_x64_x86_mt_md.zip 附件中编译发VS2017分发版文件
libMinHook.x64.vs2017.md.lib
libMinHook.x64.vs2017.mt.lib
libMinHook.x86.vs2017.md.lib
libMinHook.x86.vs2017.mt.lib
MinHook.h
MinHook.x64.vs2017.md.dll
MinHook.x64.vs2017.mt.dll
MinHook.x86.vs2017.md.dll
MinHook.x86.vs2017.mt.dll
由于我的IDA 7.0版本是x64的,且ida_ipython默认了静态链接,
这里我们只使用 MinHook.h和libMinHook.x64.vs2017.md.lib ida_python项目
解决方案中我们只需针对x64的IDA7.0 的32与64位分析对象编译ida64_ipython插件。
直接编译毫无疑问会有编译错误。这是由于IDA 7.0的SDK许多关键结构和函数已经改动,
以前的插件项目都需要代码重构才能用。
我们做以下修改 (1)在IDA 7.0的SDK下述文件的头文件引入之后添加__X64__定义
#define __X64__
强制选用64位指针成员结构,完成编译发行后,为保证源码一致性,记得撤销修改。
文件idasdk70\include\loader.hpp
#include <ida.hpp>
#define __X64__
#ifdef __X64__
CASSERT(sizeof(plugin_t) == 64);
#else
CASSERT(sizeof(plugin_t) == 36);
#endif
文件idasdk70\include\idp.hpp
#include <config.hpp>
#define __X64__
#ifdef __X64__
CASSERT(sizeof(processor_t) == 144);
#else
CASSERT(sizeof(processor_t) == 104);
#endif
(2)ida_ipython-master\src\ida_ipython.cpp
//原 parse_command_line(carg, &out_args);
parse_command_line(&out_args, NULL, carg, 0); //修改 by tritium 2018/10/14
原因是parse_command_line在IDA 7.0 SDK的 原型为
/// Parse a space separated string (escaping with backslash is supported).
/// \param[out] args a string vector to hold the results
/// \param[out] redirs map of channel redirections found in cmdline
/// - if NULL, redirections won't be parsed
/// - if there are syntax errors in redirections, consider them as arguments
/// \param cmdline the string to be parsed
/// \param flags #LP_PATH_WITH_ARGS or 0
/// \return the number of parsed arguments
idaman THREAD_SAFE size_t ida_export parse_command_line(
qstrvec_t *args,
channel_redirs_t *redirs,
const char *cmdline,
int flags); (3)ida_ipython-master\src\ida_ipython.cpp
//原 void idaapi run(int options)
bool idaapi run(size_t options) //修改 by tritium
{
//原 ipython_start_qtconsole();
return ipython_start_qtconsole(); //修改 by tritium
}
这是由于IDA 7.0 SDK的响应执行函数原型已经发生变更,不改动会出现以下错误
错误(活动) E0144
"void (__stdcall *)(int options)" 类型的值不能用于初始化
"bool (__stdcall *)(size_t arg)" 类型的实体 ida32_ipython ida_ipython-master\src\ida_ipython.cpp 101 Intellisense
(4)ida_ipython-master\src\ipythonEmbed.cpp
修改函数原型,并添加返回状态,与上面的执行函数调用保持一致。
//void ipython_start_qtconsole()
bool ipython_start_qtconsole() //by tritium
{
bool ret = true; //添加 by tritium
PyGILState_STATE state = PyGILState_Ensure();
PyObject *ipython_embed_module = NULL,
*ipython_qtconsole_func = NULL;
ipython_embed_module = PyImport_ImportModule(IPYTHON_EMBED_MODULE);
if (ipython_embed_module == NULL) {
warning("could not import ipythonEmbed module");
ret = false;//添加
goto cleanup;
}
ipython_qtconsole_func = PyObject_GetAttrString(ipython_embed_module, IPYTHON_EMBED_START_QTCONSOLE_METHOD_NAME);
if (ipython_qtconsole_func == NULL) {
warning("could not find start_qtconsole function");
ret = false;//添加
goto cleanup;
}
if (!PyCallable_Check(ipython_qtconsole_func)) {
warning("ipython start_qtconsole function is not callable");
ret = false;//添加
goto cleanup;
}
PyObject_CallObject(ipython_qtconsole_func, NULL);
cleanup:
Py_XDECREF(ipython_embed_module);
Py_XDECREF(ipython_qtconsole_func);
PyGILState_Release(state);
return ret;//添加
} (5)ida_ipython-master\src\ipythonEmbed.cpp
//原 static const char EVENT_LOOP_FUNC_NAME[] = "?processEvents@QEventDispatcherWin32@QT@@UAE_NV?$QFlags@W4ProcessEventsFlag@QEventLoop@QT@@@2@@Z";
//修改为,这个是针对IDA 7.0 Qt5Core.dll的导出函数符号已经作为微小改动, by tritium
static const char EVENT_LOOP_FUNC_NAME[] = "?processEvents@QEventDispatcherWin32@QT@@UEAA_NV?$QFlags@W4ProcessEventsFlag@QEventLoop@QT@@@2@@Z";
//原 nArgs = parse_command_line3(GetCommandLineA(), &out_args, NULL, 0);
//修改为
nArgs = parse_command_line(&out_args, NULL, GetCommandLineA(), 0); // by tritium
//eventloop_address函数直接修改为加载QT5,这个修改与否问题都不大
FARPROC eventloop_address()
{
HMODULE qtmodule = GetModuleHandleA(QT5_MODULE_NAME);
if (NULL == qtmodule) {
warning("Can not GetModuleHnadleA of %s\n", QT5_MODULE_NAME);
}
FARPROC src = GetProcAddress(qtmodule, EVENT_LOOP_FUNC_NAME);
return src;
} (6)从ida_ipython复制到IDA 7.0\python的ipythonEmbed.py
根据 base64.b64decode('aHR0cHM6Ly9naXRodWIuY29tL3RtcjIzMi9pZGFfaXB5dGhvbg==') 的ida_ipython 修改
qtconsole_processes = []
qtconsole_action = None #add
def remove_idaipython_menu():
idaapi.detach_action_from_menu('View/IDAIPython QtConsole', 'IDAIPython:QtConsole')
def remove_menus():
if qtconsole_action is not None:
remove_idaipython_menu()
idaapi.unregister_action(qtconsole_action.name)
#
for menu_item in menu_items:
idaapi.del_menu_item(menu_item)
def add_idaipython_menu_new(callback):
class MyHandler(idaapi.action_handler_t):
def __init__(self):
idaapi.action_handler_t.__init__(self)
def activate(self, ctx):
callback()
return 1
def update(self, ctx):
return idaapi.AST_ENABLE_ALWAYS
action_name = 'IDAIPython:QtConsole'
action_desc = idaapi.action_desc_t(
action_name,
'IDAIPython QtConsole',
MyHandler(),
'',
'Launch IDAIPython QtConsole',
-1)
idaapi.register_action(action_desc)
idaapi.attach_action_to_menu(
'View/',
action_name,
idaapi.SETMENU_INS)
return action_desc
def add_idaipython_menu():
try:
menu_item = idaapi.add_menu_item('View/', 'IDAIPython QtConsole', '', 0, start_qtconsole, tuple())
menu_items.append(menu_item)
except:
qtconsole_action = add_idaipython_menu_new(start_qtconsole) (7)属性配置中,链接器》输入》附加依赖项,编辑添加以下依赖项
..\lib\MinHook_13_lib\lib\libMinHook.x64.vs2017.md.lib 这指向我们自己发行的MinHooK.lib
为一致性,也用我们发行的MinHook.h覆盖 lib\MinHook_13_lib\include\MinHook.h
D:\Program Files\IDA 7.0\plugins\hexrays_sdk\idasdk70\lib\x64_win_vc_64\ida.lib
这个是针对x64位IDA分析64位程序(即ida64.exe)的插件lib。
在“配置属性》常规”中,”目标文件名“我们改为"ida_ipython64"(IDA 7.0的ida64.exe插件后缀一般为64.dll),目标文件扩展名改为普通的".dll".
因为“配置属性》C/C++》代码生成》运行库"里是/MD,所以我们上面的MinHook.lib选择MD版本。
针对x64位IDA分析32位程序(即ida.exe)的插件lib,选用
D:\Program Files\IDA 7.0\plugins\hexrays_sdk\idasdk70\lib\x64_win_vc_32\ida.lib
”目标文件名“我们改为"ida_ipython" (8)若安装执行出现 R6034错误(虽然不影响使用),可以考虑键python安装目录的msvcr90.dll屏蔽,若添加后缀.bak
比如我的Anaconda2版本以下目录的三个dll全部备份屏蔽未dll.bak
D:\ProgramData\Anaconda2\Library\bin
D:\ProgramData\Anaconda2
msvcr90.dll
msvcp90.dll
msvcm90.dll
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Runtime Error!
Program: D:\Program Files\IDA 7.0\ida.exe
R6034
An application has made an attempt to load the C runtime library incorrectly.
Please contact the application's support team for more information.
安装好插件后,打开IDA。Edit》Plugin》IDA IPython QTConsole 启动,在出现的console中若没出现输入提示,多按以下回车即可出现。
官方演示:
------- 声明:以下两图片引用自github上 ida_ipython 官方项目文件-------
附件为相应编译插件及关联文件
编辑补充:
写完才发现坛友评论的 base64.b64decode('aHR0cHM6Ly9naXRodWIuY29tL3RtcjIzMi9pZGFfaXB5dGhvbg==') github项目
在目标测试的Sark项目同一层,由文章所述的ida_python 直接fork出来的纯python版。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2018-10-15 14:21
被tritium编辑
,原因: 更新附件内容,编辑补充
上传的附件: