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
这三个函数涉及的库函数解读和lambda表达式在下文,还有一个demo,这里概述一下三个函数的作用
这三个函数都接受一个x作为参数
然后调用unpack函数将pack函数打包成的bytes对象解包
<表示的是小端序,H表示的是两个字节,16位
I表示的是四个字节,32位
Q表示的八个字节,64位
例如u16
lambda表达式,定义了一个函数u16
lambda x:表示接受的变量是x
函数的操作是unpack("<H", x)[0]
在上文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的结构体之间的转换
struct.unpack(format, buffer)
这个函数用于解包由?pack
?函数打包过的 buffer。其中,format 是打包时使用的格式字符串(Format string),buffer 是打包后的字节串。
struct.calcsize
?返回与格式字符串?format
?对应的结构体(以及由 pack(format,…)生成的 bytes 对象)的大小。
格式字符串描述了在打包和解包数据时的数据布局。它们由格式字符构建,这些格式字符指定了正在打包/解包的数据类型。此外,特殊字符还控制字节顺序、大小和对齐方式。每个格式字符串由一个可选的前缀字符组成,该字符描述数据的整体属性,以及一个或多个格式字符,这些字符描述实际的数据值和填充。
格式字符串的第一个字符可用于指示打包数据的字节顺序、大小和对齐方式
Native byte order取决于host system
标准大小仅取决于格式字符;请参阅“格式字符”部分中的表格
from struct import *
print(pack("<i", 1))
print(pack(">i", 1))
'''
运行结果
b'\x01\x00\x00\x00'
b'\x00\x00\x00\x01'
'''
def copy_to_clip(data):
QApplication.clipboard().setText(data)
设置剪贴板内容
def clip_text():
return QApplication.clipboard().text()
返回剪贴板的内容
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异常
这个类用于处理IDA pro中的动作
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这个函数
def?activate(self, ctx)
激活一个动作。这个函数实现了动作的内核行为。当动作被触发时,它会被调用,无论是从菜单、弹出菜单、工具栏还是通过程序。
返回:非零值:所有IDA窗口将刷新。
def?update(self, ctx)
这个函数是一个更新函数,通常在图形用户界面(GUI)编程中用于更新动作的状态。这个函数的名字是 "update",它接受一个名为 "ctx" 的参数,这个参数通常包含了与当前上下文相关的信息。
函数的目的是根据上下文的变化来更新动作的一些属性,例如标签、图标等。此外,这个函数还让 IDA(可能是一个软件的名字)知道该动作是否启用,以及何时再次查询动作的可用性。
需要注意的是,这个回调函数不用于改变应用程序的状态,除非通过调用这个动作上的 "update_action_*()" 函数来实现。这意味着该函数的主体只用于更新动作的属性,而不用于改变其他与应用程序状态相关的内容。
总的来说,这个 "update" 函数是一个用于更新动作状态和属性的回调函数,它在 UI 上下文变化时被调用。
ACTION_COPYEA = "lazyida:copyea"在前面已经定义了
get_screen_ea()是获取光标所在的位置的地址(address)
jumpto函数
将光标跳转到一个地址
慢慢看,持续更新