Frida相关脚本代码样例(Windows下经过测试)

本文介绍了如何使用Frida在Windows环境中追踪malloc和free函数的调用,包括原始地址、完整调用栈以及生成火焰图的基本步骤。还提到在Windows下符号信息的获取需求和与Linux的不同点。
摘要由CSDN通过智能技术生成

一、追踪malloc以及free的调用地址(不含调用栈)

import sys
import frida

def on_message(message, data):
    if message['type'] == 'send':
        print(message['payload'])

pid = int(input("请输入目标进程的PID: "))

session = frida.attach(pid)

print("attach suscess")

script = session.create_script("""
Interceptor.attach(Module.findExportByName(null, "malloc"), {
  onEnter: function(args) {
    send("malloc called with: " + args[0]);
  }  
});

Interceptor.attach(Module.findExportByName(null, "free"), {
  onEnter: function(args) {
    send("free called with: " + args[0]); 
  }
});
""")

script.on('message', on_message)
script.load()
print("js load failed")

sys.stdin.read()
session.detach()

二、追踪malloc以及free的函数调用栈

import sys
import frida

def on_message(message, data):
    if message['type'] == 'send':
        print(message['payload'])

pid = int(input("请输入目标进程的PID: "))

session = frida.attach(pid)

print("attach success")

script = session.create_script("""
Interceptor.attach(Module.findExportByName(null, "malloc"), {
  onEnter: function(args) {
    send("malloc called with: " + args[0]);
    send("Call stack: " + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\\n"));
  }  
});

Interceptor.attach(Module.findExportByName(null, "free"), {
  onEnter: function(args) {
    send("free called with: " + args[0]);
    send("Call stack: " + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\\n"));
  }
});
""")

script.on('message', on_message)
script.load()
print("js load success")

sys.stdin.read()
session.detach()

三、追踪malloc以及free调用栈(输出到文件中)

import sys
import frida

pid = int(input("请输入目标进程的PID: "))
session = frida.attach(pid)

print("attach success")

# 打开文件并将标准输出重定向到该文件
f_output = open('output.txt', 'w')
f_stdout = sys.stdout
sys.stdout = f_output

script = session.create_script("""
Interceptor.attach(Module.findExportByName(null, "malloc"), {
  onEnter: function(args) {
    send("malloc called with: " + args[0]);
    send("Call stack: " + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\\n"));
  }  
});

Interceptor.attach(Module.findExportByName(null, "free"), {
  onEnter: function(args) {
    send("free called with: " + args[0]);
    send("Call stack: " + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\\n"));
  }
});
""")

def on_message(message, data):
    if message['type'] == 'send':
        print(message['payload'])

script.on('message', on_message)
script.load()

try:
	sys.stdin.read()
except KeyboardInterrupt:
	f_stdout.write(f" exit\n")
	f_output.flush()
	session.detach()


四、统计调用栈次数与详细信息并输出到文件中:

import sys
import frida

pid = int(input("请输入目标进程的PID: "))
session = frida.attach(pid)

print("attach success")

call_stacks = []

def on_message(message, data):
    if message['type'] == 'send':
        print(message['payload'])
        if "Call stack" in message['payload']:
            call_stacks.append(message['payload'])

script = session.create_script("""
Interceptor.attach(Module.findExportByName(null, "malloc"), {
  onEnter: function(args) {
    send("Call stack: \\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\\n"));
  }  
});

Interceptor.attach(Module.findExportByName(null, "free"), {
  onEnter: function(args) {
    send("Call stack: \\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\\n"));
  }
});
""")

script.on('message', on_message)
script.load()
print("js load success")

try:
    sys.stdin.read()
except KeyboardInterrupt:
    # 打开文件并将标准输出重定向到该文件
    f_output = open('output.txt', 'w')
    f_stdout = sys.stdout
    sys.stdout = f_output
    # 将调用栈信息整理成火焰图格式
    flamegraph_data = {}
    for stack in call_stacks:
        stack_lines = stack.split("\n")
        for line in stack_lines:
            if line.startswith("0x"):
                if line in flamegraph_data:
                    flamegraph_data[line] += 1
                else:
                    flamegraph_data[line] = 1
    # 输出火焰图格式数据
    for addr, count in flamegraph_data.items():
        print(f"次数:{count} 详细信息:{addr}")
    f_stdout.write(" exit\n")
    f_output.flush()
    session.detach()

关于Frida目前研究的总结:
1、在Windows下无论是Release还是Debug都可以分析malloc以及free的调用栈,只不过Debug信息更详细,如果将Release的优化关闭两者信息基本一致。
2、在Windows下符号信息仍需要pdb文件协助,这不同于Linux,好消息是只需要将pdb与测试的PE文件放在同一目录Frida可以自动搜寻到符号信息。

目前时间只够我研究到上面四个情况,第四种已经基本满足需求了,如果后续需要转换为火焰图的话还需要加以改进,但是整体脚本框架无需很大变动了,可以参考内存增长与火焰图这篇文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值