各种类型读取和转换
var String_java = Java.use('java.lang.String');
var args_4 = Java.cast(args[4], String_java);
send("get args[4] value: " + args_4);
一个封装过的:
function print_dump(addr,size){
var buf = Memory.readByteArray(addr,size)
console.log("[function] send[*] " + addr.toString() + " "+ "length: " + size.toString() + "\n[data]")
console.log(hexdump(buf, {
offset: 0,
length: size,
header: false,
ansi: false
}));
console.log("")
}
调用的时候类似print_dump(args[4], 100)
即可,size传大些也行。
转int32
args[2].toInt32()
读取string
Memory.readUtf8String(args[0],23)
读取指针对应的字符串值(可以给地址加偏移)
Memory.readUtf8String(Memory.readPointer(securityCheck.sub(0x11a8).add(0x628c)))
创建调试进程并附加
device = frida.get_usb_device()
pid = device.spawn(["com.android.browser"])
print("PID: " + str(pid))
session = device.attach(pid)
device.resume(pid)
将调试信息写入文件日志
def on_message(message ,data):
file_object=open("log.txt",'ab+')
file_object.write(message['payload'].encode())
file_object.write(data.split(b'\x00')[0])
file_object.write('\n'.encode())
file_object.close()
send函数的原型是send(message[, data])
,第二个参数为data
。
可见第二个参数是需要
ArrayBuffer
类型的,而Memory.readByteArray(args[0],256)
的返回值刚好是ArrayBuffer类型的,所以直接传值就可以。如果不是ArrayBuffer类型的怎么办,比如说文档中的hexdump(target[, options])函数,它的返回值不是ArrayBuffer类型的,那么我们就需要利用下面的函数来转换:
function str2ab(str) {
var buf = new ArrayBuffer(str.length); // 1 bytes for each char
var bufView = new Uint8Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
注入so层
#coding=utf-8
import frida
import sys
session = frida.get_remote_device().attach("com.example.hooktest")
#print session.enumerate_modules()
jscode = """
Java.perform(function(){
send("Running Script");
var getString = undefined;
var i = undefined;
var exports = Module.enumerateExportsSync("libtest.so");
for(i=0; i
或者,例如hook在libc
中的open
函数:
setImmediate(function() {
Interceptor.attach(Module.findExportByName("libc.so" , "open"), {
onEnter: function(args) {
log('open(pathname='+Memory.readUtf8String(args[0])+") flag: "+args[1]);
},
onLeave:function(retval){
}
});
});
在这里,读取内存还可以用Memory.readByteArray(args[0],256)
,例如send("open called! args[0]:",Memory.readByteArray(args[0],256));
获取(遍历)so层的导入导出函数地址
- 方法一:
var exports = Module.enumerateExportsSync("libnative-lib.so");
for (i = 0; i < exports.length; i++) {
if (exports[i].name == "Java_com_iscc_crackme_MainActivity_checkSecond") {
checkSecond = exports[i].address;
//console.log(checkSecond);
send("checkSecond is at " + checkSecond);
break;
}
}
- 方法二:
var chat = Module.findExportByName("libGameLogic.so", "_ZN6Player4ChatEPKc");
console.log("Player::Chat() at address: " + chat);
Interceptor.attach(chat, {
onEnter: function (args) { // 0 => this; 1 => cont char* (our text)
var chatMsg = Memory.readCString(args[1]);
console.log("[Chat]: " + chatMsg);
}
});
修改so中变量或内存
//Get base address of library
var libfoo = Module.findBaseAddress("libfoo.so");
//Calculate address of variable
var initialized = libfoo.add(ptr("0x400C"));
//Write 1 to the variable
Memory.writeInt(initialized,1);
反反调试
此处hook掉exit的调用
Java.perform(function() {
exitClass = Java.use("java.lang.System");
exitClass.exit.implementation = function() {
console.log("[*] System.exit called");
}
console.log("[*] Hooking calls to System.exit");
});
获取程序所有模块并打印
def on_message(message, data):
print("[on_message] message:", message, "data:", data)
# session = frida.attach("notepad.exe")
session = frida.get_remote_device().attach('com.iscc.crackme')
script = session.create_script("""'use strict';
rpc.exports.enumerateModules = function () {
return Process.enumerateModulesSync();
};
""")
script.on("message", on_message)
script.load()
print([m["name"] for m in script.exports.enumerate_modules()])
C++ demangle
# Extract exports & demangle it
import frida
import cxxfilt
session = frida.attach("PwnAdventure3-Linux-Shipping")
script = session.create_script("""
var exports = Module.enumerateExportsSync("libGameLogic.so");
for (i = 0; i < exports.length; i++) {
send(exports[i].name);
}
""");
def on_message(message, data):
print message["payload"] + " - " + cxxfilt.demangle(message["payload"])
script.on('message', on_message)
script.load()
Hook okhttp3.Interceptor
function hook_okhttp3() {
Java.perform(function () {
var ByteString = Java.use("com.android.okhttp.okio.ByteString");
var Buffer = Java.use("com.android.okhttp.okio.Buffer");
var Interceptor = Java.use("okhttp3.Interceptor");
var MyInterceptor = Java.registerClass({
name: "okhttp3.MyInterceptor",
implements: [Interceptor],
methods: {
intercept: function (chain) {
var request = chain.request();
try {
console.log("MyInterceptor.intercept onEnter:", request, "\nrequest headers:\n", request.headers());
var requestBody = request.body();
var contentLength = requestBody ? requestBody.contentLength() : 0;
if (contentLength > 0) {
var BufferObj = Buffer.$new();
requestBody.writeTo(BufferObj);
try {
console.log("\nrequest body String:\n", BufferObj.readString(), "\n");
} catch (error) {
try {
console.log("\nrequest body ByteString:\n", ByteString.of(BufferObj.readByteArray()).hex(), "\n");
} catch (error) {
console.log("error 1:", error);
}
}
}
} catch (error) {
console.log("error 2:", error);
}
var response = chain.proceed(request);
try {
console.log("MyInterceptor.intercept onLeave:", response, "\nresponse headers:\n", response.headers());
var responseBody = response.body();
var contentLength = responseBody ? responseBody.contentLength() : 0;
if (contentLength > 0) {
console.log("\nresponsecontentLength:", contentLength, "responseBody:", responseBody, "\n");
var ContentType = response.headers().get("Content-Type");
console.log("ContentType:", ContentType);
if (ContentType.indexOf("video") == -1) {
if (ContentType.indexOf("application") == 0) {
var source = responseBody.source();
if (ContentType.indexOf("application/zip") != 0) {
try {
console.log("\nresponse.body StringClass\n", source.readUtf8(), "\n");
} catch (error) {
try {
console.log("\nresponse.body ByteString\n", source.readByteString().hex(), "\n");
} catch (error) {
console.log("error 4:", error);
}
}
}
}
}
}
} catch (error) {
console.log("error 3:", error);
}
return response;
}
}
});
var ArrayList = Java.use("java.util.ArrayList");
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
console.log(OkHttpClient);
OkHttpClient.$init.overload('okhttp3.OkHttpClient$Builder').implementation = function (Builder) {
console.log("OkHttpClient.$init:", this, Java.cast(Builder.interceptors(), ArrayList));
this.$init(Builder);
};
var MyInterceptorObj = MyInterceptor.$new();
var Builder = Java.use("okhttp3.OkHttpClient$Builder");
console.log(Builder);
Builder.build.implementation = function () {
this.interceptors().clear();
//var MyInterceptorObj = MyInterceptor.$new();
this.interceptors().add(MyInterceptorObj);
var result = this.build();
return result;
};
Builder.addInterceptor.implementation = function (interceptor) {
this.interceptors().clear();
//var MyInterceptorObj = MyInterceptor.$new();
this.interceptors().add(MyInterceptorObj);
return this;
//return this.addInterceptor(interceptor);
};
console.log("hook_okhttp3...");
});
}
参考文章
https://www.jianshu.com/p/b833fba1bffe
https://bbs.pediy.com/thread-217424.htm
https://bbs.pediy.com/thread-252129.htm