MENU

Migrate IDA Free 8.1 Golang plugin to IDA Pro 7.7

October 10, 2022 • Read: 385 • Reverse

Migrate IDA Free 8.1 Golang plugin to IDA Pro 7.7

背景

总所周知,IDA 从 8.0 开始支持 golang 1.18 的符号解析,我一直很眼馋(笑

image-20221010173636574

但在一次比赛中,偶然的发现 IDA Freeware 8.0 (官网就能下)中是有该 Golang 处理器的 dll 文件的,而且该文件能够直接放到 IDA Pro 7.7 中使用,从而做到解析 golang 1.18,实现白嫖。

最近看查 IDA 文档的时候,顺便看到了 IDA 官网,发现 IDA 都更新到 8.1 版本了,又有一些新增的 golang 解析功能,于是又想着白嫖一下试试

image-20221010174032076

然后我像之前一样,把新版的 golang64.dll 放置到 IDA 目录下的 plugins 文件夹,结果这次 IDA 报错了

image-20221010174357225

本文就是对解决这个问题的过程,做一个记录

报错原因

该文件是我刚刚放进去的,所以文件一定是存在的,那么为什么会报错为找不到指定程序呢?

我这里最初的想法是,可能新版的 IDA 在加载过程中做了检测,如果 IDA 版本不符合则拒绝加载程序,所以导致了 dll 无法正常加载,所以应该找到 dll 中对应的检测代码,并且绕过检测即可,结果我尝试用 IDA 进行调试,发现根本没有走到 dll 的入口点,这说明肯定是加载过程中 dll 的某些数据不兼容旧版导致的,而不是内部检测,于是我着重在 LoadLibrary 的错误号 0xC0000139 进行搜索,通过搜索找到了一些信息 —— 如果加载的 DLL 的导出表信息无法找到(依赖 dll 缺少对应方法),也会导致产生 ”找不到指定的程序“ 这个错误。

所以应该转移注意到程序的导出表上,我这里用 IDA 分别打开新版和旧版的 golang64.dll 文件,Copy All 复制出对应的导出表数据,并且编写一个程序进行比对

new = '''000000018000D000        RtlCaptureContext    KERNEL32
000000018000D008        RtlLookupFunctionEntry    KERNEL32
000000018000D010        RtlVirtualUnwind    KERNEL32
000000018000D018        UnhandledExceptionFilter    KERNEL32
000000018000D020        SetUnhandledExceptionFilter    KERNEL32
000000018000D028        GetCurrentProcess    KERNEL32
000000018000D030        TerminateProcess    KERNEL32
000000018000D038        IsProcessorFeaturePresent    KERNEL32
000000018000D040        QueryPerformanceCounter    KERNEL32
000000018000D048        GetCurrentProcessId    KERNEL32
000000018000D050        GetCurrentThreadId    KERNEL32
000000018000D058        GetSystemTimeAsFileTime    KERNEL32
000000018000D060        DisableThreadLibraryCalls    KERNEL32
000000018000D068        InitializeSListHead    KERNEL32
000000018000D070        IsDebuggerPresent    KERNEL32
000000018000D080        std::_Xlength_error(char const *)    MSVCP140
000000018000D090        __std_type_info_destroy_list    VCRUNTIME140
000000018000D098        __C_specific_handler    VCRUNTIME140
000000018000D0A0        memset    VCRUNTIME140
000000018000D0A8        memmove    VCRUNTIME140
000000018000D0B0        memcpy    VCRUNTIME140
000000018000D0B8        _CxxThrowException    VCRUNTIME140
000000018000D0C0        strstr    VCRUNTIME140
000000018000D0C8        __std_exception_destroy    VCRUNTIME140
000000018000D0D0        __std_exception_copy    VCRUNTIME140
000000018000D0D8        __std_terminate    VCRUNTIME140
000000018000D0E0        _purecall    VCRUNTIME140
000000018000D0F0        __CxxFrameHandler4    VCRUNTIME140_1
000000018000D100        _callnewh    api-ms-win-crt-heap-l1-1-0
000000018000D108        malloc    api-ms-win-crt-heap-l1-1-0
000000018000D110        free    api-ms-win-crt-heap-l1-1-0
000000018000D120        _initterm_e    api-ms-win-crt-runtime-l1-1-0
000000018000D128        _initterm    api-ms-win-crt-runtime-l1-1-0
000000018000D130        _seh_filter_dll    api-ms-win-crt-runtime-l1-1-0
000000018000D138        _configure_narrow_argv    api-ms-win-crt-runtime-l1-1-0
000000018000D140        _initialize_onexit_table    api-ms-win-crt-runtime-l1-1-0
000000018000D148        _execute_onexit_table    api-ms-win-crt-runtime-l1-1-0
000000018000D150        _cexit    api-ms-win-crt-runtime-l1-1-0
000000018000D158        _initialize_narrow_environment    api-ms-win-crt-runtime-l1-1-0
000000018000D168        strcmp    api-ms-win-crt-string-l1-1-0
000000018000D170        strncmp    api-ms-win-crt-string-l1-1-0
000000018000D180        read_config2    ida64
000000018000D188        hook_event_listener    ida64
000000018000D190        remove_event_listener    ida64
000000018000D198        get_ph    ida64
000000018000D1A0        get_modctx    ida64
000000018000D1A8        set_module_data    ida64
000000018000D1B0        clr_module_data    ida64
000000018000D1B8        get_plugin_options    ida64
000000018000D1C0        set_name    ida64
000000018000D1C8        validate_name    ida64
000000018000D1D0        get_name_ea    ida64
000000018000D1D8        copy_argloc    ida64
000000018000D1E0        cleanup_argloc    ida64
000000018000D1E8        set_compiler    ida64
000000018000D1F0        h2ti    ida64
000000018000D1F8        alloc_type_ordinals    ida64
000000018000D200        build_anon_type_name    ida64
000000018000D208        import_type    ida64
000000018000D210        apply_tinfo    ida64
000000018000D218        get_idati    ida64
000000018000D220        copy_tinfo_t    ida64
000000018000D228        clear_tinfo_t    ida64
000000018000D230        create_tinfo    ida64
000000018000D238        get_tinfo_details    ida64
000000018000D240        get_tinfo_size    ida64
000000018000D248        get_tinfo_pdata    ida64
000000018000D250        get_tinfo_property    ida64
000000018000D258        get_idasgn_desc    ida64
000000018000D260        serialize_tinfo    ida64
000000018000D268        get_stock_tinfo    ida64
000000018000D270        save_tinfo    ida64
000000018000D278        begin_type_updating    ida64
000000018000D280        end_type_updating    ida64
000000018000D288        get_struc_qty    ida64
000000018000D290        get_struc_by_idx    ida64
000000018000D298        get_struc    ida64
000000018000D2A0        get_struc_id    ida64
000000018000D2A8        get_struc_name    ida64
000000018000D2B0        get_struc_size    ida64
000000018000D2B8        add_struc    ida64
000000018000D2C0        add_struc_member    ida64
000000018000D2C8        get_enum    ida64
000000018000D2D0        set_enum_width    ida64
000000018000D2D8        get_enum_member    ida64
000000018000D2E0        add_enum    ida64
000000018000D2E8        create_xrefs_from    ida64
000000018000D2F0        set_enum_cmt    ida64
000000018000D2F8        add_enum_member    ida64
000000018000D300        set_bmask_name    ida64
000000018000D308        op_offset_ex    ida64
000000018000D310        dirtree_mkdir    ida64
000000018000D318        dirtree_rename    ida64
000000018000D320        get_std_dirtree    ida64
000000018000D328        under_debugger    ida64
000000018000D330        callui    ida64
000000018000D338        create_insn    ida64
000000018000D340        get_idasgn_qty    ida64
000000018000D348        plan_to_apply_idasgn    ida64
000000018000D350        get_func_name    ida64
000000018000D358        set_func_end    ida64
000000018000D360        set_func_start    ida64
000000018000D368        add_func_ex    ida64
000000018000D370        set_func_cmt    ida64
000000018000D378        get_func    ida64
000000018000D380        bin_search2    ida64
000000018000D388        set_cmt    ida64
000000018000D390        create_strlit    ida64
000000018000D398        get_strlit_contents    ida64
000000018000D3A0        get_max_strlit_length    ida64
000000018000D3A8        create_align    ida64
000000018000D3B0        create_data    ida64
000000018000D3B8        get_flags_by_size    ida64
000000018000D3C0        del_items    ida64
000000018000D3C8        get_bytes    ida64
000000018000D3D0        get_data_value    ida64
000000018000D3D8        get_qword    ida64
000000018000D3E0        get_dword    ida64
000000018000D3E8        get_word    ida64
000000018000D3F0        get_byte    ida64
000000018000D3F8        is_loaded    ida64
000000018000D400        get_flags_ex    ida64
000000018000D408        get_item_end    ida64
000000018000D410        prev_not_tail    ida64
000000018000D418        next_head    ida64
000000018000D420        next_that    ida64
000000018000D428        add_sourcefile    ida64
000000018000D430        get_segm_name    ida64
000000018000D438        get_segm_by_name    ida64
000000018000D440        get_first_seg    ida64
000000018000D448        get_next_seg    ida64
000000018000D450        getseg    ida64
000000018000D458        unregister_custom_refinfo    ida64
000000018000D460        register_custom_refinfo    ida64
000000018000D468        set_enum_bf    ida64
000000018000D470        verror    ida64
000000018000D478        set_source_linnum    ida64
000000018000D480        get_aflags    ida64
000000018000D488        get_strid    ida64
000000018000D490        netnode_supset    ida64
000000018000D498        netnode_altval    ida64
000000018000D4A0        netnode_check    ida64
000000018000D4A8        setinf    ida64
000000018000D4B0        getinf_flag    ida64
000000018000D4B8        getinf_buf    ida64
000000018000D4C0        getinf    ida64
000000018000D4C8        qvector_reserve    ida64
000000018000D4D0        qalloc_or_throw    ida64
000000018000D4D8        qvsnprintf    ida64
000000018000D4E0        qsnprintf    ida64
000000018000D4E8        qfree    ida64
000000018000D4F0        set_tinfo_property    ida64
000000018000D4F8        interr    ida64
'''

old = '''000000018000D000        RtlCaptureContext    KERNEL32
000000018000D008        RtlLookupFunctionEntry    KERNEL32
000000018000D010        RtlVirtualUnwind    KERNEL32
000000018000D018        UnhandledExceptionFilter    KERNEL32
000000018000D020        SetUnhandledExceptionFilter    KERNEL32
000000018000D028        GetCurrentProcess    KERNEL32
000000018000D030        TerminateProcess    KERNEL32
000000018000D038        IsProcessorFeaturePresent    KERNEL32
000000018000D040        QueryPerformanceCounter    KERNEL32
000000018000D048        GetCurrentProcessId    KERNEL32
000000018000D050        GetCurrentThreadId    KERNEL32
000000018000D058        GetSystemTimeAsFileTime    KERNEL32
000000018000D060        DisableThreadLibraryCalls    KERNEL32
000000018000D068        InitializeSListHead    KERNEL32
000000018000D070        IsDebuggerPresent    KERNEL32
000000018000D080        std::_Xlength_error(char const *)    MSVCP140
000000018000D090        __std_type_info_destroy_list    VCRUNTIME140
000000018000D098        __C_specific_handler    VCRUNTIME140
000000018000D0A0        memset    VCRUNTIME140
000000018000D0A8        memmove    VCRUNTIME140
000000018000D0B0        memcpy    VCRUNTIME140
000000018000D0B8        _CxxThrowException    VCRUNTIME140
000000018000D0C0        strstr    VCRUNTIME140
000000018000D0C8        __std_exception_destroy    VCRUNTIME140
000000018000D0D0        __std_exception_copy    VCRUNTIME140
000000018000D0D8        __std_terminate    VCRUNTIME140
000000018000D0E0        _purecall    VCRUNTIME140
000000018000D0F0        __CxxFrameHandler4    VCRUNTIME140_1
000000018000D100        _callnewh    api-ms-win-crt-heap-l1-1-0
000000018000D108        malloc    api-ms-win-crt-heap-l1-1-0
000000018000D110        free    api-ms-win-crt-heap-l1-1-0
000000018000D120        _initterm_e    api-ms-win-crt-runtime-l1-1-0
000000018000D128        _initterm    api-ms-win-crt-runtime-l1-1-0
000000018000D130        _seh_filter_dll    api-ms-win-crt-runtime-l1-1-0
000000018000D138        _configure_narrow_argv    api-ms-win-crt-runtime-l1-1-0
000000018000D140        _initialize_onexit_table    api-ms-win-crt-runtime-l1-1-0
000000018000D148        _execute_onexit_table    api-ms-win-crt-runtime-l1-1-0
000000018000D150        _cexit    api-ms-win-crt-runtime-l1-1-0
000000018000D158        _initialize_narrow_environment    api-ms-win-crt-runtime-l1-1-0
000000018000D168        strncmp    api-ms-win-crt-string-l1-1-0
000000018000D178        read_config2    ida64
000000018000D180        hook_event_listener    ida64
000000018000D188        remove_event_listener    ida64
000000018000D190        get_ph    ida64
000000018000D198        set_module_data    ida64
000000018000D1A0        clr_module_data    ida64
000000018000D1A8        get_plugin_options    ida64
000000018000D1B0        set_name    ida64
000000018000D1B8        validate_name    ida64
000000018000D1C0        get_name_ea    ida64
000000018000D1C8        copy_argloc    ida64
000000018000D1D0        cleanup_argloc    ida64
000000018000D1D8        set_compiler    ida64
000000018000D1E0        h2ti    ida64
000000018000D1E8        alloc_type_ordinals    ida64
000000018000D1F0        build_anon_type_name    ida64
000000018000D1F8        import_type    ida64
000000018000D200        apply_tinfo    ida64
000000018000D208        get_idati    ida64
000000018000D210        copy_tinfo_t    ida64
000000018000D218        clear_tinfo_t    ida64
000000018000D220        create_tinfo    ida64
000000018000D228        get_tinfo_details    ida64
000000018000D230        get_tinfo_size    ida64
000000018000D238        get_tinfo_pdata    ida64
000000018000D240        get_tinfo_property    ida64
000000018000D248        create_insn    ida64
000000018000D250        serialize_tinfo    ida64
000000018000D258        get_stock_tinfo    ida64
000000018000D260        save_tinfo    ida64
000000018000D268        begin_type_updating    ida64
000000018000D270        end_type_updating    ida64
000000018000D278        get_struc_qty    ida64
000000018000D280        get_struc_by_idx    ida64
000000018000D288        get_struc    ida64
000000018000D290        get_struc_id    ida64
000000018000D298        get_struc_name    ida64
000000018000D2A0        get_struc_size    ida64
000000018000D2A8        add_struc    ida64
000000018000D2B0        add_struc_member    ida64
000000018000D2B8        get_enum    ida64
000000018000D2C0        set_enum_width    ida64
000000018000D2C8        get_enum_member    ida64
000000018000D2D0        add_enum    ida64
000000018000D2D8        set_enum_bf    ida64
000000018000D2E0        set_enum_cmt    ida64
000000018000D2E8        add_enum_member    ida64
000000018000D2F0        set_bmask_name    ida64
000000018000D2F8        op_offset_ex    ida64
000000018000D300        dirtree_mkdir    ida64
000000018000D308        dirtree_rename    ida64
000000018000D310        get_std_dirtree    ida64
000000018000D318        under_debugger    ida64
000000018000D320        callui    ida64
000000018000D328        get_idasgn_desc    ida64
000000018000D330        get_idasgn_qty    ida64
000000018000D338        plan_to_apply_idasgn    ida64
000000018000D340        get_func_name    ida64
000000018000D348        set_func_end    ida64
000000018000D350        set_func_start    ida64
000000018000D358        add_func_ex    ida64
000000018000D360        set_func_cmt    ida64
000000018000D368        get_func    ida64
000000018000D370        bin_search2    ida64
000000018000D378        set_cmt    ida64
000000018000D380        create_strlit    ida64
000000018000D388        get_strlit_contents    ida64
000000018000D390        get_max_strlit_length    ida64
000000018000D398        create_align    ida64
000000018000D3A0        create_data    ida64
000000018000D3A8        get_flags_by_size    ida64
000000018000D3B0        del_items    ida64
000000018000D3B8        get_bytes    ida64
000000018000D3C0        get_data_value    ida64
000000018000D3C8        get_qword    ida64
000000018000D3D0        get_dword    ida64
000000018000D3D8        get_word    ida64
000000018000D3E0        get_byte    ida64
000000018000D3E8        is_loaded    ida64
000000018000D3F0        get_flags_ex    ida64
000000018000D3F8        get_item_end    ida64
000000018000D400        prev_not_tail    ida64
000000018000D408        next_head    ida64
000000018000D410        next_that    ida64
000000018000D418        add_sourcefile    ida64
000000018000D420        get_segm_name    ida64
000000018000D428        get_segm_by_name    ida64
000000018000D430        get_first_seg    ida64
000000018000D438        get_next_seg    ida64
000000018000D440        getseg    ida64
000000018000D448        unregister_custom_refinfo    ida64
000000018000D450        register_custom_refinfo    ida64
000000018000D458        create_xrefs_from    ida64
000000018000D460        set_source_linnum    ida64
000000018000D468        get_aflags    ida64
000000018000D470        get_strid    ida64
000000018000D478        netnode_supset    ida64
000000018000D480        netnode_altval    ida64
000000018000D488        netnode_check    ida64
000000018000D490        setinf    ida64
000000018000D498        getinf_flag    ida64
000000018000D4A0        getinf_buf    ida64
000000018000D4A8        getinf    ida64
000000018000D4B0        qvector_reserve    ida64
000000018000D4B8        qalloc_or_throw    ida64
000000018000D4C0        qvsnprintf    ida64
000000018000D4C8        qsnprintf    ida64
000000018000D4D0        qfree    ida64
000000018000D4D8        set_tinfo_property    ida64
000000018000D4E0        interr    ida64'''


list = []
for i in old.splitlines():
    s = i.split("\t")
    list.append(s[3] + "_" + s[2])

for i in new.splitlines():
    s = i.split("\t")
    n = s[3] + "_" + s[2]
    if n not in list:
        print(n)

程序运行结果为

api-ms-win-crt-string-l1-1-0_strcmp
ida64_get_modctx
ida64_verror

其中,api-ms-win-crt-string-l1-1-0_strcmpida64_verror 通过搜索能够确定是存在的,那么不能运行的原因主要就在 ida64_get_modctx,在 ida64.dll 中,只有新版才存在这个函数,而旧版不存在。

解决思路

我想到的解决思路主要是以下两种

  1. 在旧版的 ida64.dll 文件中加入 get_modctx 函数
  2. 删除在新版的 golang64.dll 中该函数的导入表

经过简单的评估,前者需要在 dll 中插入一段代码,并且需要新增一个导出表项,但是好处在于之后如果又有版本更新,我可以直接使用新版的 dll 文件;后者则只需要删除 get_modctx 函数的相关引用,并且删除(修改)对应导入表内容为正确值。因为当天时间比较晚了,且第二天还要早 8,所以我考虑了用后者来解决这个问题

删除交叉引用

通过交叉引用搜索到新版在插件初始化中,对此处函数有如下引用

image-20221010175947094

而在旧版的同样位置,这里直接赋值为 0

image-20221010180023086

那思路很简单,只要 NOP CALL 并修改为 XOR RAX RAX 即可

image-20221010180618690

修改后的伪代码:

image-20221010180642319

修改导入表

我认为,删除一个导出表项那需要重组整个导入表,那肯定是非常麻烦的,所以我考虑修改这个导出表为其他一个已经存在的导出表函数名,因为这个函数不会被引用到,所以这样修改能保证程序正常执行。

用 DIE 可以查看对应的导入表

image-20221010180923886

这里可以看到与 get_modctx 相邻的有一个 get_ph 函数,我用 010 搜索一下,并且修改值为 get_ph 即可,多余的字符串用 \x00 填充

使用 010 进行修改

image-20221010181104013

修复成功

打开一个 golang 1.18 以上版本生产的程序,程序符号名称都可以正常解析了

image-20221010181415986

sig

新版本中新增了很多的 sig 文件(包括新版本的 golang,MSVC 等),如果要正常的解析新版的 golang,还需要替换一下新版的 sig 文件,这里无需进行任何的修复,直接替换即可。

其他

IDA Free 8.1 的目录下,除了我所说的 golang64.dll ,实际上还有很多其他 dll 有进行更新,理论上来说,都能够通过我本文中的方法进行更改适配,不过由于其他更改对笔者来说用处不大,其他的 dll 适配就交给各位读者自行解决了。

image-20221010181633056

Last Modified: October 21, 2022
Archives QR Code
QR Code for this page
Tipping QR Code
Leave a Comment

已有 1 条评论
  1. RivenDell RivenDell

    师傅,应该是导入表吧