首页 > 其他分享 >IDA插件

IDA插件

时间:2024-12-16 17:11:59浏览次数:9  
标签:addr 插件 name trace so func print IDA

IDA插件

trace_Native and stalker_trace_so

这俩插件都是对于Native层也就是对于so的trace,其中的源码的意思都差不多,这里是对应于俩插件在相同层次上不同的实现

stalker_trace_so:

trace中的function函数的地址获取:

通过UI界面,判断鼠标选择的区域来判定所需要进行的trace跟踪的范围值,并且取得函数指针的list表

        if ctx.widget_type == idaapi.BWN_FUNCS:  #这里说明是在函数窗口的位置
            selected = [idaapi.getn_func(idx).start_ea for idx in ctx.chooser_selection]
        else:
            selected = idautils.Functions() #这里没用选定函数窗口,那么就是整个so文件函数进行
        generate_js_script(selected) #selected这里得到的是函数指针的list表

trace中函数偏移地址的获取

def generate_js_script(func_list):
    func_addr = []
    func_name = []
    so_base = get_imagebase()
    for func_ea in func_list:
        # thumb mode
        if idc.get_sreg(func_ea, "T"):  #这里判定是不是Thumb模式  是的话 addr+1
            func_addr.append(hex(func_ea + 1 - so_base))  #这里就添加偏移地址了
        else:
            func_addr.append(hex(func_ea - so_base))
        func_name.append('"{}"'.format(idc.get_func_name(func_ea)))
    so_path, so_name = os.path.split(ida_nalt.get_input_file_path()) #ida_nalt.get_input_file_path()得到当前的路径,os.path.split将路径和文件名进行分割,得到so_path, so_name

利用python实现JS数据的替换

def generate_hook_code(template_js, func_addr, func_name, so_name):
    replacements = {
        "[func_addr]": ', '.join(func_addr),
        "[func_name]": ', '.join(func_name),
        "[so_name]": "%s" % so_name
    }
    return reduce(lambda acc, item: acc.replace(item[0], item[1]), replacements.items(), template_js)

这里普及一下reduce()这个工具函数reduce 函数的签名如下:

reduce(function, iterable, [initializer])
  • function:是一个函数(或者其他可调用对象),它接收两个参数,并返回一个结果。
  • iterable:是一个可迭代对象(如列表、元组等)。
  • [initializer](可选):是一个初始值,作为第一次迭代的“累积值”。
reduce(lambda acc, item: acc.replace(item[0], item[1]), replacements.items(), template_js)

function:lambda acc, item: acc.replace(item[0], item[1]) 这里的item就是字典里的键值对,item[0]键,item[1]值

iterable:replacements.items() 这个是传入的元组 只要这个元组里面还没遍历完,那么就继续遍历迭代

[initializer]:template_js这个值是(即模板字符串),也就是要去被替换的位置

var func_addr = [[func_addr]];
var func_name = [[func_name]];
var so_name = "[so_name]";
/*
    @param print_stack: Whether printing stack info, default is false.
*/4
var print_stack = false;
/*
    @param print_stack_mode
    - FUZZY: print as much stack info as possible
    - ACCURATE: print stack info as accurately as possible
    - MANUAL: if printing the stack info in an error and causes exit, use this option to manually print the address
*/
var print_stack_mode = "FUZZY";

function addr_in_so(addr){
    var process_Obj_Module_Arr = Process.enumerateModules();
    for(var i = 0; i < process_Obj_Module_Arr.length; i++) {
        if(addr>process_Obj_Module_Arr[i].base && addr<process_Obj_Module_Arr[i].base.add(process_Obj_Module_Arr[i].size)){
            console.log(addr.toString(16),"is in",process_Obj_Module_Arr[i].name,"offset: 0x"+(addr-process_Obj_Module_Arr[i].base).toString(16));
        }
    }
}
function hook_dlopen() {
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    //console.log(path);
                    if (path.indexOf(so_name) >= 0) {
                        this.is_can_hook = true;
                    }
                }
            },
            onLeave: function (retval) {
                if (this.is_can_hook) {
                    // note: you can do any thing before or after stalker trace so.

                    trace_so();
                }
            }
        }
    );
}

function trace_so(){
    var times = 1;
    var module = Process.getModuleByName(so_name);
    var pid = Process.getCurrentThreadId();
    console.log("start Stalker!");
    Stalker.exclude({
        "base": Process.getModuleByName("libc.so").base,
        "size": Process.getModuleByName("libc.so").size
    })
    Stalker.follow(pid,{
        events:{
            call:false,
            ret:false,
            exec:false,
            block:false,
            compile:false
        },
        onReceive:function(events){
        },
        transform: function (iterator) {
            var instruction = iterator.next();
            do{
                if (func_addr.indexOf(instruction.address - module.base) !== -1) {
                    console.log("call" + times + ":" + func_name[func_addr.indexOf(instruction.address - module.base)])
                    times = times + 1
                    if (print_stack) {
                        if (print_stack_mode === "FUZZY") {
                            iterator.putCallout((context) => {
                                console.log("backtrace:\\n"+Thread.backtrace(context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join('\\n'));
                                console.log('---------------------')
                            });
                        }
                        else if (print_stack_mode === "ACCURATE") {
                            iterator.putCallout((context) => {
                                console.log("backtrace:\\n"+Thread.backtrace(context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\\n'));
                                console.log('---------------------')
                            })
                        }

                        else if (print_stack_mode === "MANUAL") {
                            iterator.putCallout((context) => {
                                console.log("backtrace:")
                                Thread.backtrace(context, Backtracer.FUZZY).map(addr_in_so);
                                console.log('---------------------')
                            })
                        }
                    }
                }
                iterator.keep();
            } while ((instruction = iterator.next()) !== null);
        },
        onCallSummary:function(summary){
        }
    });
    console.log("Stalker end!");
}

setImmediate(hook_dlopen,0)

所以这个trace的是通过python去得到对应so文件函数的偏移地址和函数名,然后通过JS来实现生成的frida脚本来实现的

trace_Native

trace_Native 通过判断是否是存在于text段来查看是否记录地址,并且通过这个区间进行函数的获取

def getSegAddr():
    textStart = []
    textEnd = []

    for seg in idautils.Segments():
        if (idc.get_segm_name(seg)).lower() == '.text' or (
        idc.get_segm_name(seg)).lower() == 'text':
            tempStart = idc.get_segm_start(seg)  #获取text段的起始地址
            tempEnd = idc.get_segm_end(seg)  #结束地址
            textStart.append(tempStart)  
            textEnd.append(tempEnd)

    return min(textStart), max(textEnd)

在代码段中寻找函数,并且将函数的偏移地址记录下来

    def run(self, arg):
        # 查找需要的函数
        ea, ed = getSegAddr()
        search_result = []
        for func in idautils.Functions(ea, ed):
            try:
                functionName = str(idaapi.ida_funcs.get_func_name(func))
                if len(list(idautils.FuncItems(func))) > 10:
                    # 如果是thumb模式,地址+1
                    arm_or_thumb = idc.get_sreg(func, "T")
                    if arm_or_thumb:
                        func += 1
                    search_result.append(hex(func))
            except:
                pass

生成路径和写入文件

    so_path, so_name = getSoPathAndName()
    search_result = [f"'{offset}'" for offset in search_result]
    search_result = ",".join(search_result)
    search_result = '['+search_result+']'
    script_name = so_name.split(".")[0] + "_" + str(int(time.time())) +".txt" #so_name = "libnative.so",那么 so_name.split(".")[0] 将得到 "libnative",libnative_1684675100.txt
    save_path = os.path.join(so_path, script_name) #/path/to/so/libnative_1684675100.txt
    with open(save_path, "w", encoding="utf-8")as F:
        F.write(search_result)

    print("使用方法如下:")
    print(f"frida-trace -UF -O {save_path}")

相对于Stalker_trace_so来说这个只是对于函数的地址进行了偏移地址的记录,相对的Stalker_trace_so利用了frida的打印堆栈信息的打印,可以在源码中去设置选择mode,但是起始打印出来很乱而且作用不好

但是有些插件也可以连着用,结合findhash和traceNatives插件合成的升级自吐算法

通过获取函数偏移地址,直接进行函数的HOOK,也挺有用的,不过这里就可以把trace_Native的里面对应判断代码段的大小的位置设置大一点,这样HOOK的函数就可以少一点,实现一个小范围的细致HOOK

function hook_suspected_function(targetSo) {
    const funcs = ['0x152c','0x16c4','0x16fc','0x1734','0x177c','0x187c','0x18b4','0x18f4','0x193c','0x1974','0x19a8','0x1b60','0x1c5c','0x1e04','0x1ecc','0x1f14','0x1fb0','0x1ff0','0x21c4','0x2380','0x25ac','0x25ec','0x262c','0x2854','0x2a1c','0x2a8c','0x2d04','0x4264','0x4360','0x449c'];
    for (var i in funcs) {
        let relativePtr = funcs[i];
        let funcPtr = targetSo.add(relativePtr);
    hook_native_addr(funcPtr);
}
function hook_native_addr(funcPtr){
	var module = Process.findModuleByAddress(funcPtr);
	Interceptor.attach(funcPtr, {
		onEnter: function(args){
			this.args0 = args[0];
			this.args1 = args[1];
			this.args2 = args[2];
			this.args3 = args[3];
			this.logs = [];
			this.logs.push("call " + module.name + "!" + ptr(funcPtr).sub(module.base) + "\n");
			this.logs.push("this.args0 onEnter: " + print_arg(this.args0));
			this.logs.push("this.args1 onEnter: " + print_arg(this.args1));
			this.logs.push("this.args2 onEnter: " + print_arg(this.args2));
			this.logs.push("this.args3 onEnter: " + print_arg(this.args3));
			
		}, onLeave: function(retval){
			this.logs.push("this.args0 onLeave: " + print_arg(this.args0));
			this.logs.push("this.args1 onLeave: " + print_arg(this.args1));
			this.logs.push("this.args2 onLeave: " + print_arg(this.args2));
			this.logs.push("this.args3 onLeave: " + print_arg(this.args3));
			this.logs.push("retval onLeave: " + retval + "\n");
			console.log(this.logs);
		}
	});
}

标签:addr,插件,name,trace,so,func,print,IDA
From: https://www.cnblogs.com/ovo-fisherman/p/18610596

相关文章

  • 20种炫酷打开模态窗口动画特效插件xdialog
    xdialog是一款炫酷打开模态窗口动画特效插件。该插件提供20种打开模态窗口的动画特效,并提供丰富的配置参数和api来控制模态窗口,非常实用。 在线演示下载  使用方法在页面中引入xdialog.css和xdialog.js文件。<linkrel="stylesheet"href="xdialog/xdialog.css"......
  • bootstrap4标签输入框插件
    这是一款基于Bootstrap4的标签输入框插件。该插件使用Bootstrap4badge组件来制作标签输入和移除的效果。 在线演示 下载  使用方法在页面中引入下面的文件。<linkhref="bootstrap.min.css"rel="stylesheet"type="text/css"/><linkhref="jquery-tagsinp......
  • 响应式圆形js轮播图插件
    jcircle.js是一款响应式圆形js轮播图插件。该轮播图插件能够将图片或文字以圆形轮播图的方式进行展示。并且该轮播图以响应式设计,可以自动进行圆形轮播。 在线演示 下载  使用方法在页面中引入jCircle.css和jCircle.min.js文件<linkhref="jCircle.css"rel="s......
  • 你有写过Less的插件吗?
    很抱歉,我本身并没有直接写过Less的插件。但是我可以为你提供一些关于如何编写Less插件的信息。在前端开发中,Less是一种动态样式语言,它扩展了CSS语言,增加了变量、Mixin、函数等特性,使CSS更易维护和扩展。如果你想为Less编写插件,通常是为了扩展Less的功能,比如添加新的函数、Mixin等......
  • Visual Code 的 Vim 插件极简使用手册
    VisualCode的Vim插件极简使用手册文章目录VisualCode的Vim插件极简使用手册极简配置常用命令光标移动(普通模式)标记移动(普通模式)编辑选定文本可视模式下的操作寄存器折叠代码案例'.'命令极简配置文件->首选项->设置->搜索vim,向下找到在setting.......
  • 带搜索过滤功能的jQuery国家地区选择下拉框插件
    nicecountryinput.js是一款带搜索过滤功能的jQuery国家地区选择下拉框插件。该下拉框插件通过简单的代码就可以实现所有国家和地区的选择下拉框,并且可以通过搜索框对国家地区名称进行搜索。 在线预览下载  使用方法在页面中引入jquery.min.js和niceCountryInput.js文件......
  • 抖店工作台客服设置自动回复 - 浏览器插件 vx : llike620
    应用场景主流直播平台后台评论自动回复与循环发送话术某些客服平台网页端咨询消息自动回复功能介绍这是一个电脑端浏览器插件扩展,实现模拟人工收发消息,解放双手,摆脱重复工作利用浏览器多开,可以在一台电脑上运行多个浏览器,每个浏览器登录不同账号,同时运行插件。插件不限制直......
  • 抖店如何设置客服自动回复?- 浏览器插件详细步骤解析- vx : llike620
    应用场景主流直播平台后台评论自动回复与循环发送话术某些客服平台网页端咨询消息自动回复功能介绍这是一个电脑端浏览器插件扩展,实现模拟人工收发消息,解放双手,摆脱重复工作利用浏览器多开,可以在一台电脑上运行多个浏览器,每个浏览器登录不同账号,同时运行插件。插件不限制直......
  • vue3 - 解决NPM安装插件报错npm error code ERESOLVE | npm error ERESOLVE could not
    问题说明在vue3、nuxt3项目开发中,使用npm安装插件时出现报错:npmerrorcodeERESOLVE|npmerrorERESOLVEcouldnotresolve,后面一连串各种提示错误,导致项目安装第三方插件失败问题,另外也可能出现在项目安装依赖npminstall时发生,也可能在单独安装插件上,很奇怪的问题......
  • jQuery鼠标拖动旋转DOM元素插件
    Propeller.js是一款jQuery鼠标拖动旋转DOM元素插件。通过该插件,可以使用鼠标拖动旋转页面中的任意DOM元素。 使用方法通过npm安装插件。npminstallPropeller HTML结构例如要拖动旋转一张图片。<imgsrc="demo.jpg"id="img"> 初始化插件......