其他
简易的IDAPython脚本
本文为看雪论坛优秀文章
看雪论坛作者ID:GitRoy
0x0 写在前面
0x1 简述流程
1、首先创建代理脚本.py文件,我这边是roy_hook_proxy.py文件,内容如下:
# encoding: utf-8
import sys
sys.path.append('/Users/roy/Documents/PycharmProjects/roytool')
from royhook import RoyHook
def PLUGIN_ENTRY():
return RoyHook()
2、然后将roy_hook_proxy.py文件拷贝到ida插件目录
3、编写插件主入口
import sys
# 引入ida提供给我们的api
import idaapi
# 引入pyqt,编写交互界面
from PyQt5 import QtWidgets
# 这里一定要继承ida提供的插件的base类
class RoyHook(idaapi.plugin_t):
flags = idaapi.PLUGIN_KEEP
comment = "royhook a ida pro plugin"
help = ""
# ida插件的名字
wanted_name = "royhook"
# ida插件的快捷键
wanted_hotkey = "Alt+F6"
windows = None
def __init__(self):
super(RoyHook, self).__init__()
flags = idaapi.PLUGIN_KEEP
pass
# 脚本初始化的时候调用
def init(self):
return idaapi.PLUGIN_OK
# 初始化后开始运行的时候调用
def run(self, arg):
idaapi.require('view')
idaapi.require('view.main_view')
main_window = view.main_view.MainView()
if self.windows is None or not self.windows.isVisible():
self.windows = QtWidgets.QMainWindow()
main_window.setupUi(self.windows)
self.windows.showNormal()
pass
# 脚本结束的时候调用
def term(self):
return idaapi.PLUGIN_OK
4、实时更新插件代码
idaapi.require('view')
idaapi.require('view.logsaver_view')
0x2 提高效率
1、快速定位某个函数
def goInitarray(self):
# _get_modules是idc提供的接口,如其名
for module in idc._get_modules():
# 遍历所有module,找到linker
module_name = module.name
if 'linker' in module_name:
print 'linker address is ' + str(hex(module.base + 0x2464))
# 0x2464是Android某个版本的init_array的偏移地址,
# jumpto可以直接跳转到目标地址
idc.jumpto(module.base + 0x2464)
# 在init_array上下个断点
idc.add_bpt(module.base + 0x2464, 1)
# makecode更不用说了,相当于C
idaapi.auto_make_code(module.base + 0x2464)
2、保存日志、函数名字
# 通过起始地址,终止地址,以及偏移地址去保存日志
def saveDebugMessage(self):
# create file first
# 用个轻量级的存储shelve
f = shelve.open(self.id)
# 保存日志的起始地址
addr_start = int(self.address_start, 16)
# 保存日志的终止地址
addr_end = int(self.address_end, 16)
log_dict = {}
log_dict_list = []
for num in range(addr_start, addr_end):
# 获取我们当前地址的日志
com = idc.GetCommentEx(num, True)
if com != None:
#获取函数名
fun_name = idc.GetFunctionName(num)
print fun_name
if fun_name != None and not 'sub' in fun_name:
log_dict = {'offset': str(num - addr_start), 'msg': str(com), 'funtion_name': str(fun_name)}
else:
log_dict = {'offset': str(num - addr_start), 'msg': str(com)}
log_dict_list.append(log_dict)
pass
print(log_dict_list)
# 保存日志
f['info'] = log_dict_list
f.close()
# 通过起始地址即可,会自动判断长度,并且获取偏移地址去设置日志
def loadDebugMessage(self):
f = shelve.open(self.id)
data = f['info']
addr_start = int(self.address_start, 16)
for num in range(0, len(data)):
offset = data[num]['offset']
msg = data[num]['msg']
fun_name = data[num]['funtion_name']
idc.MakeRptCmt(addr_start + int(offset), msg)
if fun_name is not None and fun_name != '':
idc.SetFunctionCmt(addr_start + int(offset), fun_name, False)
3、过一些简单的花指令
0x3 使用pyqt交互界面,让脚本更人性化
1、推荐工具Qt Designer工具进行画界面
2、demo
class LogSaver_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(476, 410)
self.windows = QtWidgets.QMainWindow()
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(110, 100, 91, 16))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(110, 170, 91, 16))
self.label_2.setObjectName("label_2")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(210, 100, 131, 21))
self.textEdit.setObjectName("textEdit")
self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_2.setGeometry(QtCore.QRect(210, 170, 131, 21))
self.textEdit_2.setObjectName("textEdit_2")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(100, 240, 113, 51))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(260, 240, 113, 51))
self.pushButton_2.setObjectName("pushButton_2")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(110, 50, 60, 16))
self.label_3.setObjectName("label_3")
self.textEdit_3 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_3.setGeometry(QtCore.QRect(210, 50, 131, 21))
self.textEdit_3.setObjectName("textEdit_3")
self.checkBox = QtWidgets.QCheckBox(MainWindow)
self.checkBox.setGeometry(QtCore.QRect(90, 360, 141, 20))
self.checkBox.setObjectName("checkBox")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
print('create windows')
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "日志工具"))
self.label.setText(_translate("MainWindow", "开始地址:"))
self.label_2.setText(_translate("MainWindow", "结束地址:"))
self.pushButton.setText(_translate("MainWindow", "存储"))
self.pushButton_2.setText(_translate("MainWindow", "加载"))
self.label_3.setText(_translate("MainWindow", "唯一id:"))
self.checkBox.setText(_translate("Dialog", "是否自动保存函数名"))
self.pushButton.clicked.connect(self.showDialog)
self.pushButton_2.clicked.connect(self.showDialogLoad)
看雪ID:GitRoy
https://bbs.pediy.com/user-762912.htm
*本文由看雪论坛 GitRoy 原创,转载请注明来自看雪社区。
推荐文章++++
好书推荐