首页
社区
课程
招聘
[原创]使用IDAPython开发复制RVA的插件
2022-12-28 22:28 13922

[原创]使用IDAPython开发复制RVA的插件

2022-12-28 22:28
13922

在逆向的过程中经常遇到一个问题,由于ASLR的原因,IDA中代码的基地址跟x64dbg等调试器中的对应不起来。一般情况下大家都会选择禁用掉ASLR或者修改IDA中的镜像基地址,但是这两种方式都缺点,禁用ASLR可能对dll没有用,改IDA中的基地址的话需要每次调试都要重新改一下。我一直比较纳闷IDA为什么没有直接加一个复制RVA和跳转到RVA的功能(但是却有个跳转到文件偏移的功能),网上找了一下也没有发现有啥插件能实现这个功能,没办法只能自己动手丰衣足食了,同时简单记录一下开发过程。
搭建开发环境比较简单,IDE选择的是VSCode+Python插件,想要VSC能识别到IDAPython的接口,需要在启动前先设置PYTHONPATH环境变量指向IDA目录下的“python\3”这个目录,然后就可以正常的开发IDAPython代码了,对IDAPython的模块也可以有代码提示。
然后是找IDAPython的API,这个官网上的文档非常粗糙,基本上就是把注释弄出来搞成了个文档,还不如直接看API的注释。后来发现了这个repo:idapython-cheatsheet,有一定的帮助,但是没有找到获取光标所在位置的地址的方法。后来想到keypatch中有用到这个功能,于是去翻了一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# handler for Patcher menu
def patcher(self):
    # be sure that this arch is supported by Keystone
    if self.kp_asm.arch is None:
        warning("ERROR: Keypatch cannot handle this architecture (unsupported by Keystone), quit!")
        return
 
    selection, addr_begin, addr_end = read_range_selection()
    if selection:
        # call Fill Range function on this selected code
        return self.fill_range()
 
    address = get_screen_ea()
 
    if self.opts is None:
        self.load_configuration()
 
    init_assembly = None
    while True:
        f = Keypatch_Patcher(self.kp_asm, address, assembly=init_assembly, opts=self.opts)
        ok = f.Execute()

这个get_screen_ea()就是获取光标位置地址的方法。除此之外怎样在右键菜单中添加菜单项的代码也有了,基本上照着写就行。
完成后的基本功能有三个,可以在反汇编界面和F5界面直接右键复制当前位置的VA、RVA、x64dbg格式的RVA,也就是RVA开头加了个“:$”。

完整代码地址:https://github.com/junjiexing/XCopy,直接下载zip然后把XCopy.py放到IDA的plugins目录即可。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞11
打赏
分享
最新回复 (7)
雪    币: 2370
活跃值: (9190)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
TkBinary 5 2022-12-29 10:10
2
0

谢谢分享优质插件,还有论坛有人发过类似插件. 我根据它的代码改了一下. 输出更贴合自己使用. 跟你的类似. 你的可以在右键菜单提供菜单项,另一个哥们开发的直接使用快捷键即可. (我只是把输出改成更贴合自己使用的) 原始文件好像叫做 PatternGen  论坛链接:PatternGen 这个快捷键是ALT+Z 原本是一个输出特征码的插件.提取特征码. 我依据它的代码做了少许修改,可以直接获取 VA RVA X64Dbg跳转.(不输出特征码) 插件快捷键 ALT+/.

下面是我魔改过的输出, X64DBG CTRL+G 支持 模块名.0 + 偏移 方式,跟你写的XCOPY 一样, 也支持  $ 当做前缀符号跳转. 更多X64dbg小技巧可以看下我博客. X64dbg使用小技巧 希望能帮到大家. 下列是我魔改过的输出.

下列代码直接复制下来,改为`.py`后缀. 然后放到`plugin`里面即可. 快捷键 `alt+z` 兼容性 支持最新`IDA8.2`

# -*- coding: utf-8 -*-
import math

import idaapi
import idc
#import clipboard

try:
    class Kp_Menu_Context(idaapi.action_handler_t):
        def __init__(self):
            idaapi.action_handler_t.__init__(self)

        @classmethod
        def get_name(self):
            return self.__name__

        @classmethod
        def get_label(self):
            return self.label

        @classmethod
        def register(self, plugin, label):
            self.plugin = plugin
            self.label = label
            instance = self()
            return idaapi.register_action(idaapi.action_desc_t(
                self.get_name(),  # Name. Acts as an ID. Must be unique.
                instance.get_label(),  # Label. That's what users see.
                instance  # Handler. Called when activated, and for updating
            ))

        @classmethod
        def unregister(self):
            """Unregister the action.
            After unregistering the class cannot be used.
            """
            idaapi.unregister_action(self.get_name())

        @classmethod
        def activate(self, ctx):
            # dummy method
            return 1

        @classmethod
        def update(self, ctx):
            if ctx.form_type == idaapi.BWN_DISASM:
                return idaapi.AST_ENABLE_FOR_FORM
            return idaapi.AST_DISABLE_FOR_FORM


    class Searcher(Kp_Menu_Context):
        def activate(self, ctx):
            self.plugin.search()
            return 1
except:
    pass

class GetOffsetInfo_Plugin_t(idaapi.plugin_t):
    comment = "GetOffset By IBinary"
    help = "todo"
    wanted_name = "GetOffset"
    wanted_hotkey = "ALT+/"
    flags = idaapi.PLUGIN_KEEP

    def init(self):
        try:
            print ("GetOffset By IBinary")
            Searcher.register(self, "GetOffset")
        except:
            pass
        return idaapi.PLUGIN_KEEP

    def term(self):
        pass

    def printAvd(slef):
        print (100* "-")

    def formatByte(self,ea):
        return " "+"{:02X}".format(idc.get_wide_byte(ea))

    def calcStr(self,ea, endcount):
        hstr = ""
        firstByte = self.formatByte(ea)
        hstr += self.formatByte(ea)
        hstr = hstr + self.formatByte(ea + 1) if (firstByte == "FF" or firstByte == "66" or firstByte == "67") else hstr
        #print(math.ceil(endcount - len(hstr) / 2))
        hstr = hstr + math.ceil(endcount - len(hstr) / 2) * " ??" if endcount >= 2 else hstr
        return hstr

    def extractCode(self):
        self.printAvd()
        result = ""
        szIdbName = idc.get_idb_path();
        szIdbName = szIdbName[szIdbName.rfind("\\")+1:-4];
        base = idaapi.get_imagebase();
        here = idc.here();
        offset = here - base;
        functionName = idc.get_func_name(here);
        print ("functionName %s  Address:0x%x Offset:0x%x ImageBase:0x%x             " % (functionName,here, offset,base))
        print ("Rva = %s+0x%x    x64dbgCtrl+G = %s.0+0x%x                              " % (szIdbName,offset,szIdbName,offset))
        self.printAvd()
        # print result
        return result

    def run(self, arg):
        if (idc.BADADDR != idc.here()):
            copyContent = self.extractCode();
            print(copyContent)
            # clipboard.copy(copyContent)


# register IDA plugin
def PLUGIN_ENTRY():
    return GetOffsetInfo_Plugin_t();


最后于 2022-12-29 10:21 被TkBinary编辑 ,原因: 增加X64dbg小技巧
雪    币: 12040
活跃值: (15364)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
pureGavin 2 2022-12-29 10:28
3
0
感谢分享
IDA8.2…… 我酸了
雪    币: 211
活跃值: (511)
能力值: ( LV9,RANK:172 )
在线值:
发帖
回帖
粉丝
vmtest 2022-12-29 14:44
4
0
x64dbg 还有一个  :#文件偏移   可以支持一下
雪    币: 6517
活跃值: (8410)
能力值: ( LV17,RANK:787 )
在线值:
发帖
回帖
粉丝
无名侠 12 2022-12-29 18:01
5
0
https://github.com/P4nda0s/LazyIDA
这个可以复制RVA
雪    币: 1257
活跃值: (1424)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yllen 2022-12-30 11:09
6
0
缺8.2
雪    币: 204
活跃值: (714)
能力值: ( LV9,RANK:195 )
在线值:
发帖
回帖
粉丝
palkiver 2023-3-1 17:35
7
0
缺8.2
雪    币: 1187
活跃值: (395)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
YZJClear 2023-9-7 13:23
8
0
GetOffset By IBinary
.text:0000000182D4FE4C: Too many lines

这什么意思
游客
登录 | 注册 方可回帖
返回