FRIDA 实用手册

news/2024/7/3 5:46:54

FRIDA 实用手册
本文目的是作为工具类文章,收集整理了一些 FRIDA 的使用技巧和用例,方便同学们在开发使用过程中开袋即食。

frida 的基础教程可以直接参看官网说明。

Python 部分
JS 中文支持
使用 codecs.open(scriptpath, "r", "utf-8") 打开文件读取 js 即可。

获取指定 UID 设备
device = frida.get_device_manager().get_device("094fdb0a0b0df7f8")
获取远程设备
mgr = frida.get_device_manager()
device = mgr.add_remote_device("30.137.25.128:13355")
启动调试进程
pid = device.spawn([packename])
process = device.attach(pid)
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
device.resume(pid)
python 与 js 交互的官方示例
from future import print_function
import frida
import sys

session = frida.attach("hello")
script = session.create_script("""
Interceptor.attach(ptr("%s"), {

onEnter: function(args) {
    send(args[0].toString());
    var op = recv('input', function(value) {
        args[0] = ptr(value.payload);
    });
    op.wait();
}

});
""" % int(sys.argv[1], 16))
def on_message(message, data):

print(message)
val = int(message['payload'], 16)
script.post({'type': 'input', 'payload': str(val * 2)})

script.on('message', on_message)
script.load()
sys.stdin.read()
从 bytecode 加载脚本

-- coding: utf-8 --

from future import print_function

import frida

system_session = frida.attach(0)
bytecode = system_session.compile_script(name="bytecode-example", source="""\
'use strict';
rpc.exports = {
listThreads: function () {

return Process.enumerateThreadsSync();

}
};
""")

session = frida.attach("Twitter")
script = session.create_script_from_bytes(bytecode)
script.load()
api = script.exports

这里的 list_threads 是 listThreads 驼峰命名法自动转换后的结果,由 rpc exports 功能导出给 python 调用

print("api.list_threads() =>", api.list_threads())
JS 部分
hook Android 短信发送 SendDataMessage
function hook_sms() {

var SmsManager = Java.use('android.telephony.SmsManager');
SmsManager.sendDataMessage.implementation = function (
    destinationAddress, scAddress, destinationPort, data, sentIntent, deliveryIntent) {
    console.log("sendDataMessage destinationAddress: " + destinationAddress + " port: " + destinationPort);
    showStacks();
    this.sendDataMessage(destinationAddress, scAddress, destinationPort, data, sentIntent, deliveryIntent);
}

}
定时执行函数
setTimeout 延迟执行一次
setTimeout(funcA, 15000);
setInterval 间隔循环执行
var id_ = setInterval(funcB, 15000);
clearInterval(id_); // 终止
bin array 转字符串
function bin2String(array) {

if (null == array) {
    return "null";
}
var result = "";
try {
    var String_java = Java.use('java.lang.String');
    result = String_java.$new(array);
}
catch (e) {
    dmLogout("== use bin2String_2 ==");
    result = bin2String_2(array);
}

return result;

}

function bin2String_2(array) {

var result = "";
try {
    var tmp = 0;
    for (var i = 0; i < array.length; i++) {
        tmp = parseInt(array[i]);
        if ( tmp == 0xc0
            || (tmp < 32 && tmp != 10)
            || tmp > 126 )  {
            return result;
        }  // 不是可见字符就返回了, 换行符除外
        result += String.fromCharCode(parseInt(array[i].toString(2), 2));
    }
}
catch (e) {
    console.log(e);
}
return result;

}
自己封装输出函数加入线程ID 和时间

function getFormatDate() {

var date = new Date();
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
    month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
    strDate = "0" + strDate;
}
var currentDate = date.getFullYear() + "-" + month + "-" + strDate
        + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
return currentDate;

}

function dmLogout(str) {

var threadid = Process.getCurrentThreadId();
console.log("["+threadid+"][" + getFormatDate() + "]" + str);

}
打印 Android Java 层堆栈
var showStacks = function () {

Java.perform(function () {
    dmLogout(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));  // 打印堆栈
});

}
TracerPid fgets 反调试
var anti_fgets = function () {

dmLogout("anti_fgets");
var fgetsPtr = Module.findExportByName("libc.so", "fgets");
var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
    var retval = fgets(buffer, size, fp);
    var bufstr = Memory.readUtf8String(buffer);
    if (bufstr.indexOf("TracerPid:") > -1) {
        Memory.writeUtf8String(buffer, "TracerPid:\t0");
        // dmLogout("tracerpid replaced: " + Memory.readUtf8String(buffer));
    }
    return retval;
}, 'pointer', ['pointer', 'int', 'pointer']));

};
反调试时读取 LR 寄存器溯源
var anti_antiDebug = function() {

var funcPtr = null;

 funcPtr = Module.findExportByName("xxxx.so", "p57F7418DCD0C22CD8909F9B22F0991D3");

dmLogout("anti_antiDebug " + funcPtr);
Interceptor.replace(funcPtr, new NativeCallback(function (pathPtr, flags) {
    dmLogout("anti ddddddddddddddebug LR: " + this.context.lr);
    return 0;
}, 'int', ['int', 'int']));

};
hook JNI API NewStringUTF
function hook_native_newString() {

var env = Java.vm.getEnv();
var handlePointer = Memory.readPointer(env.handle);
dmLogout("env handle: " + handlePointer);
var NewStringUTFPtr = Memory.readPointer(handlePointer.add(0x29C));
dmLogout("NewStringUTFPtr addr: " + NewStringUTFPtr);
Interceptor.attach(NewStringUTFPtr, {
    onEnter: function (args) {
        ...
    }
});

}
hook JNI API GetStringUTFChars
function hook_native_GetStringUTFChars() {

var env = Java.vm.getEnv();
var handlePointer = Memory.readPointer(env.handle);
dmLogout("env handle: " + handlePointer);
var GetStringUTFCharsPtr = Memory.readPointer(handlePointer.add(0x2A4));
dmLogout("GetStringUTFCharsPtr addr: " + GetStringUTFCharsPtr);
Interceptor.attach(GetStringUTFCharsPtr, {
    onEnter: function (args) {
        var str = "";
        Java.perform(function () {
            str = Java.cast(args[1], Java.use('java.lang.String'));
        });
        dmLogout("GetStringUTFChars: " + str);
        if (str.indexOf("linkData:") > -1) {    // 设置过滤条件
            dmLogout("========== found linkData LR: " + this.context.lr + "  ==========");
        }
    }
});

};
循环输出参数的值
Interceptor.attach(Module.findExportByName("libc.so", "strcat"), {

onEnter: function (args) {
    for (var i = 0; i < args.length; i ++) {
        dmLogout("strcat args[" + i + "](" + ptr(args[i]) + "): " + Memory.readUtf8String(args[i]));
    }
}

});
hook Android URI 打印堆栈
var hook_uri = function() {

// coord: (7520,0,19) | addr: Ljava/net/URI;->parseURI(Ljava/lang/String;Z)V | loc: ?
var uri = Java.use('java.net.URI');
uri.parseURI.implementation = function (a1, a2) {
    a1 = a1.replace("xxxx.com", "yyyy.com");

    dmLogout("uri: " + a1);
    showStacks();
    return this.parseURI(a1, a2);
}

}
hook KXmlSerializer 拼装内容
function hook_xml() {

var xmlSerializer = Java.use('org.kxml2.io.KXmlSerializer');    // org.xmlpull.v1.XmlSerializer
xmlSerializer.text.overload('java.lang.String').implementation = function (text) {
    dmLogout("xtext: " + text);
    if ("GPRS" == text) {
        dmLogout("======>>> found GPRS");
        showStacks();
    }
    return this.text(text);
}

}
hook Android Log 输出
function hook_log() {

dmLogout(TAG, "do hook log");
var Log = Java.use('android.util.Log');
Log.v.overload('java.lang.String', 'java.lang.String').implementation = function (tag, content) {
    dmLogout(tag + " v", content);
};
Log.d.overload('java.lang.String', 'java.lang.String').implementation = function (tag, content) {
    dmLogout(tag + " d", content);
};
Log.w.overload('java.lang.String', 'java.lang.String').implementation = function (tag, content) {
    dmLogout(tag + " w", content);
};
Log.i.overload('java.lang.String', 'java.lang.String').implementation = function (tag, content) {
    dmLogout(tag + " i", content);
};
Log.e.overload('java.lang.String', 'java.lang.String').implementation = function (tag, content) {
    dmLogout(tag + " e", content);
};

}
native 主动调用
var friendlyFunctionName = new NativeFunction(friendlyFunctionPtr, 'void', ['pointer', 'pointer']);
var returnValue = Memory.alloc(sizeOfLargeObject);
friendlyFunctionName(returnValue, param1);
就先整理这么多,日后再追加。欢迎大佬们追加分享和指正错误。

本文作者:星均

阅读原文

本文为云栖社区原创内容,未经允许不得转载。


http://www.niftyadmin.cn/n/2606776.html

相关文章

hdu2199 二分搜索

这是很简单的二分搜索&#xff1b;需要注意的是精度。一开始我用的是right-left<1e-4,测试样例中100我输出的最后一位为1&#xff0c;不合要求。 后来自己写了个四舍五入的一段&#xff0c;但交上去WA&#xff0c;于是改成1e-6&#xff0c;AC了。 代码题目如下&#xff1a; …

实用的设计模式1——单例模式

在软件工程中&#xff0c;设计模式&#xff08; design pattern &#xff09;是对软件设计中普遍存在&#xff08;反复出现&#xff09;的各种问题&#xff0c;所提出的解决方案。 看维基上对设计模式的定义&#xff0c;你就知道设计模式的重要性&#xff0c;但是往往编程中设计…

一条502报警引发的胡思乱想

安心倒计时 忙完了今天的工作, 终于到了周五,可以好好休息下了。 睡梦惊醒 就在安心养神的时候, 同事转给了我一条nginx 502的报警, 赶紧去线上一顿排查。 首先得先找出哪台机器报出的(同时喊运维看下线上负载情况), 发现01机器的nginx日志在报警时间点的错误信息: *272881176 …

工作一年了的心得体会

工作至今有一年的时间了&#xff0c;这一年有过开心&#xff0c;也有失落。但是回首看看&#xff0c;似乎更多的是迷茫。 刚来公司的时候&#xff0c;打心底想好好学一学技术&#xff0c;学一点有用的东西。但是进公司之后发现很多和自己想的不太一样。来到了一个做监控平台的组…

Zookeeper学习(一) 概述

0. 前言 前段时间在工作中参与了一个分布式项目的开发&#xff0c;其中一个重要的模块就是Zookeeper。可以说这个项目及其之后的一段学习让我找到了自己的兴趣点&#xff0c;自己最近也学习了一些Zookeeper的知识&#xff0c;在这里也把自己学到的和一些思考写下来~ 1. 分布式协…

[转]React Native 语言基础之ES6

React Native 是基于 React 这个前端框架来构建native app的架构。React Native基于ES6&#xff08;即ECMAScript2015&#xff09;语言进行开发的。 JS的组成 1) 核心&#xff08;ECMAScript&#xff09;&#xff1a;描述了该语言的语法和基本对象。担当的是一个翻译的角色&am…

canvas 实现vue 手势解锁组件

1.手机锁屏九宫格解锁组件 2.代码如下 <template><canvas id"gesture" ref"canvas" :style"style" /></template><script>export default {name: GestureLock,props: {chooseType: {type: Number,default: 3 // 3: 3*3,…

Scala - 快速学习06 - 面向对象

1- 类 1.1- 简介&#xff1a;类、方法及对象 类是用来创建对象的蓝图。Scala文件中包含的多个类之间&#xff0c;都是彼此可见的&#xff0c;不需要声明为public。创建对象定义好类以后&#xff0c;就可以使用new关键字来创建对象。字段默认为public&#xff0c;在类外部和内部…