首页
社区
课程
招聘
[原创] VS2017 修改移植 "IDA IPyhon QTconsole" 到 IDA 7.0
发表于: 2018-10-15 12:21 3081

[原创] VS2017 修改移植 "IDA IPyhon QTconsole" 到 IDA 7.0

2018-10-15 12:21
3081
由于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编辑 ,原因: 更新附件内容,编辑补充
上传的附件:
收藏
免费 1
支持
分享
打赏 + 2.00雪花
打赏次数 1 雪花 + 2.00
 
赞赏  junkboy   +2.00 2018/10/15
最新回复 (3)
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持
2018-10-15 12:28
0
雪    币: 440
活跃值: (1163)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
佩服楼主的研究精神,我就直接用下面的方式安装的

ida_ipython
链接:https://github.com/tmr232/ida_ipython

安装方式
```
pip2 install ipykernel
pip2 install qtconsole
pip2 install PySide
Copy ida_ipython.py into IDA's plugins directory
2018-10-15 12:58
0
雪    币: 16416
活跃值: (1660)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不错,这个论坛待遇低下,不能给楼主加分。。。。
2018-10-15 13:37
0
游客
登录 | 注册 方可回帖
返回
//