LazyIDA源码阅读

发布时间:2023年12月20日

LazyIDA是一款IDA插件,项目地址GitHub - L4ys/LazyIDA: Make your IDA Lazy!

外部引用

from __future__ import division
from __future__ import print_function
from struct import unpack
import idaapi
import idautils
import idc

from PyQt5.Qt import QApplication

from __future__ import division: 这行代码是用于确保Python 2和Python 3之间的兼容性。在Python 2中,除法运算默认是整数除法,而在Python 3中,除法运算默认是浮点数除法。通过这行代码,你可以确保在Python 2中使用浮点数除法。

from __future__ import print_function: 这行代码是为了确保在Python 2中使用print作为函数而不是语句。在Python 3中,print是一个函数,而在Python 2中,它是一个语句。这行代码是为了让Python 2的print行为更接近于Python 3

from struct import unpack:?struct模块用于在Python中处理C结构。unpack函数用于将打包的二进制数据解包为Python数据类型。

import idaapi: 这行代码导入了IDA Pro的API,允许你使用IDA Pro的功能和插件。

import idautils:?idautils模块包含了一些实用的工具函数,用于处理和操作IDA Pro中的数据。

import idc:?idc是IDA Pro的核心模块,提供了与IDA Pro数据库交互的功能

from PyQt5.Qt import QApplication:这行代码从PyQt5的Qt模块导入了QApplication类。PyQt5是一个用于创建图形用户界面(GUI)的Python库,而QApplication类是所有PyQt5 GUI应用程序的入口点。

全局变量和函数

这部分定义了一些元组和字符串,之后要说的重点是u16,u32和u64这三个函数

ACTION_CONVERT = ["lazyida:convert%d" % i for i in range(10)]
ACTION_SCANVUL = "lazyida:scanvul"
ACTION_COPYEA = "lazyida:copyea"
ACTION_GOTOCLIP = "lazyida:gotoclip"
ACTION_XORDATA = "lazyida:xordata"
ACTION_FILLNOP = "lazyida:fillnop"

ACTION_HX_REMOVERETTYPE = "lazyida:hx_removerettype"
ACTION_HX_COPYEA = "lazyida:hx_copyea"
ACTION_HX_COPYNAME = "lazyida:hx_copyname"
ACTION_HX_GOTOCLIP = "lazyida:hx_gotoclip"

u16 = lambda x: unpack("<H", x)[0]
u32 = lambda x: unpack("<I", x)[0]
u64 = lambda x: unpack("<Q", x)[0]

ARCH = 0
BITS = 0

u16,u32,u64函数

这三个函数涉及的库函数解读和lambda表达式在下文,还有一个demo,这里概述一下三个函数的作用

这三个函数都接受一个x作为参数

然后调用unpack函数将pack函数打包成的bytes对象解包

<表示的是小端序,H表示的是两个字节,16位

I表示的是四个字节,32位

Q表示的八个字节,64位

lambda表达式

例如u16

lambda表达式,定义了一个函数u16

lambda x:表示接受的变量是x

函数的操作是unpack("<H", x)[0]

unpack函数

在上文from struct import unpack中导入了unpack

官网解释

struct — Interpret bytes as packed binary data — Python 3.12.1 documentation

This module converts between Python values and C structs represented as Python?bytes?objects.?

这个库是用字节码实现在Python的值和C的结构体之间的转换

unpack

struct.unpack(format, buffer)

这个函数用于解包由?pack?函数打包过的 buffer。其中,format 是打包时使用的格式字符串(Format string),buffer 是打包后的字节串。

calcsize

struct.calcsize?返回与格式字符串?format?对应的结构体(以及由 pack(format,…)生成的 bytes 对象)的大小。

Format string

格式字符串描述了在打包和解包数据时的数据布局。它们由格式字符构建,这些格式字符指定了正在打包/解包的数据类型。此外,特殊字符还控制字节顺序、大小和对齐方式。每个格式字符串由一个可选的前缀字符组成,该字符描述数据的整体属性,以及一个或多个格式字符,这些字符描述实际的数据值和填充。

格式字符串的第一个字符可用于指示打包数据的字节顺序、大小和对齐方式

Native byte order取决于host system

标准大小仅取决于格式字符;请参阅“格式字符”部分中的表格

demo

from struct import *
print(pack("<i", 1))
print(pack(">i", 1))

'''
运行结果
b'\x01\x00\x00\x00'
b'\x00\x00\x00\x01'
'''

函数和类

copy_to_clip

def copy_to_clip(data):
    QApplication.clipboard().setText(data)

设置剪贴板内容

clip_text

def clip_text():
    return QApplication.clipboard().text()

返回剪贴板的内容

parse_location

def parse_location(loc):
    try:
        loc = int(loc, 16)
    except ValueError:
        try:
            loc = idc.get_name_ea_simple(loc.encode().strip())
        except:
            return idaapi.BADADDR
    return loc

try中将输入的数字转换成16进制

否则就用idc.get_name_ea_simple获取函数名对应的地址

如果都不是就返回BADADDR异常

hotkey_action_handler_t

这个类用于处理IDA pro中的动作

ida_kernwin API documentation

class hotkey_action_handler_t(idaapi.action_handler_t):
    """
    Action handler for hotkey actions
    """
    def __init__(self, action):
        idaapi.action_handler_t.__init__(self)
        self.action = action

    def activate(self, ctx):
        if self.action == ACTION_COPYEA:
            ea = idc.get_screen_ea()
            if ea != idaapi.BADADDR:
                copy_to_clip("0x%X" % ea)
                print("Address 0x%X has been copied to clipboard" % ea)
        elif self.action == ACTION_GOTOCLIP:
            loc = parse_location(clip_text())
            if loc != idaapi.BADADDR:
                print("Goto location 0x%x" % loc)
                idc.jumpto(loc)
        return 1

    def update(self, ctx):
        if idaapi.IDA_SDK_VERSION >= 770:
            target_attr = "widget_type"
        else:
            target_attr = "form_type"
        if ctx.__getattribute__(target_attr) in (idaapi.BWN_DISASM, idaapi.BWN_DUMP):
            return idaapi.AST_ENABLE_FOR_WIDGET
        else:
            return idaapi.AST_DISABLE_FOR_WIDGET

可以看到?hotkey_action_handler_t这个类继承了?action_handler_t类,并重写了activate这个函数

action_handler_t类

def?activate(self, ctx)

激活一个动作。这个函数实现了动作的内核行为。当动作被触发时,它会被调用,无论是从菜单、弹出菜单、工具栏还是通过程序。

返回:非零值:所有IDA窗口将刷新。

def?update(self, ctx)

这个函数是一个更新函数,通常在图形用户界面(GUI)编程中用于更新动作的状态。这个函数的名字是 "update",它接受一个名为 "ctx" 的参数,这个参数通常包含了与当前上下文相关的信息。

函数的目的是根据上下文的变化来更新动作的一些属性,例如标签、图标等。此外,这个函数还让 IDA(可能是一个软件的名字)知道该动作是否启用,以及何时再次查询动作的可用性。

需要注意的是,这个回调函数不用于改变应用程序的状态,除非通过调用这个动作上的 "update_action_*()" 函数来实现。这意味着该函数的主体只用于更新动作的属性,而不用于改变其他与应用程序状态相关的内容。

总的来说,这个 "update" 函数是一个用于更新动作状态和属性的回调函数,它在 UI 上下文变化时被调用。

重写的activite函数

ACTION_COPYEA = "lazyida:copyea"在前面已经定义了

get_screen_ea()是获取光标所在的位置的地址(address)

jumpto函数

将光标跳转到一个地址

重写的update函数

慢慢看,持续更新

文章来源:https://blog.csdn.net/m0_73644864/article/details/135087887
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。