stalkerHookUnnameNative
- 函数:
stalkerHookUnnameNative
- 作用:实现Frida的Stalker去hook某个位置的代码的通用逻辑
- (调用)举例
- libmetasec_ml.so的ms_bd_c_l_a
FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)
- libmetasec_ml.so的ms_bd_c_l_a
- 最新代码
- 详见:FridaUtil.js
stalkerHookUnnameNative
的代码
// Frida Stalker hoo unknown name native function
static stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap){
console.log("Frida Stalker hook: module: baseAddress=" + moduleBaseAddress + ", isShowOpcode=" + FridaUtil.isShowOpcode)
var functionSizeHexStr = JsUtil.intToHexStr(functionSize)
var funcRelativeStartAddrHexStr = JsUtil.intToHexStr(funcRelativeStartAddr)
var funcRelativeEndAddr = funcRelativeStartAddr + functionSize
var funcRelativeEndAddrHexStr = JsUtil.intToHexStr(funcRelativeEndAddr)
console.log("function: relativeStartAddr=" + funcRelativeStartAddrHexStr + ", size=" + functionSize + "=" + functionSizeHexStr + ", relativeEndAddr=" + funcRelativeEndAddrHexStr)
const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr)
// var funcRealEndAddr = funcRealStartAddr + functionSize
const funcRealEndAddr = funcRealStartAddr.add(functionSize)
console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr)
var curTid = null
console.log("curTid=" + curTid)
Interceptor.attach(funcRealStartAddr, {
onEnter: function(args) {
JsUtil.logStr("Trigged addr: relative [" + funcRelativeStartAddrHexStr + "] = real [" + funcRealStartAddr + "]")
for(var i = 0; i < argNum; i++) {
var curArg = args[i]
console.log("arg[" + i + "]=" + curArg)
}
var curTid = Process.getCurrentThreadId()
console.log("curTid=" + curTid)
Stalker.follow(curTid, {
events: {
call: false, // CALL instructions: yes please
ret: true, // RET instructions
exec: false, // all instructions: not recommended as it's
block: false, // block executed: coarse execution trace
compile: false // block compiled: useful for coverage
},
// onReceive: Called with `events` containing a binary blob comprised of one or more GumEvent structs. See `gumevent.h` for details about the format. Use `Stalker.parse()` to examine the data.
onReceive(events) {
var parsedEvents = Stalker.parse(events)
// var parsedEventsStr = JSON.stringify(parsedEventsStr)
// console.log(">>> into onReceive: parsedEvents=" + parsedEvents + ", parsedEventsStr=" + parsedEventsStr);
console.log(">>> into onReceive: parsedEvents=" + parsedEvents);
},
// transform: (iterator: StalkerArm64Iterator) => {
transform: function (iterator) {
// https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html
// console.log("iterator=" + iterator)
var instruction = iterator.next()
const startAddress = instruction.address
// console.log("+++ into iterator: startAddress=" + startAddress)
// const isAppCode = startAddress.compare(funcRealStartAddr) >= 0 && startAddress.compare(funcRealEndAddr) === -1
// const isAppCode = (startAddress.compare(funcRealStartAddr) >= 0) && (startAddress.compare(funcRealEndAddr) < 0)
const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
var isAppCode = gt_realStartAddr && lt_realEndAddr
console.log("+++ into iterator: startAddress=" + startAddress + ", isAppCode=" + isAppCode)
// // for debug
// isAppCode = true
// console.log("isAppCode=" + isAppCode + ", gt_realStartAddr=" + gt_realStartAddr + ", lt_realEndAddr=" + lt_realEndAddr)
do {
if (isAppCode) {
// is origal function code = which we focus on
// FridaUtil.printInstructionInfo(instruction)
var curRealAddr = instruction.address
// console.log("curRealAddr=" + curRealAddr)
// const isAppCode = curRealAddr.compare(funcRealStartAddr) >= 0 && curRealAddr.compare(funcRealEndAddr) === -1
// console.log(curRealAddr + ": isAppCode=" + isAppCode)
var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
var curOffsetInt = curOffsetHexPtr.toInt32()
console.log("current: realAddr=" + curRealAddr + " -> offset: hex=" + curOffsetHexPtr + "=" + curOffsetInt)
// var instructionStr = instruction.mnemonic + " " + instruction.opStr
var instructionStr = instruction.toString()
// console.log("\t" + curRealAddr + ": " + instructionStr);
// console.log("\t" + curRealAddr + " <+" + curOffsetHexPtr + ">: " + instructionStr)
// console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr)
var opcodeStr = ""
if (FridaUtil.isShowOpcode) {
opcodeStr = " " + FridaUtil.genInstructionOpcodeStr(instruction)
}
var instructionFullLogStr = "\t" + curRealAddr + " <+" + curOffsetInt + ">" + opcodeStr + ": " + instructionStr
console.log(instructionFullLogStr)
// 0x252c0edf8 <+356>: br x10
// 0x252c0edf8 <+356> 40 01 1F D6: br x10
if (curOffsetInt in hookFuncMap){
console.log("offset: " + curOffsetHexPtr + "=" + curOffsetInt)
// let curHookFunc = hookFuncMap.get(curOffsetInt)
var curHookFunc = hookFuncMap[curOffsetInt]
// console.log("curOffsetInt=" + curOffsetInt + " -> curHookFunc=" + curHookFunc)
// putCallout -> https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html#putCallout
// StalkerScriptCallout -> https://www.radare.org/doc/frida/types/StalkerScriptCallout.html
// CpuContext -> https://www.radare.org/doc/frida/types/CpuContext.html
// Arm64CpuContext -> https://www.radare.org/doc/frida/interfaces/Arm64CpuContext.html
// work: normal
iterator.putCallout(curHookFunc)
// var extraDataDict = {
// "curOffsetInt": curOffsetInt
// }
// Not work: abnormal
// iterator.putCallout((context) => {
// // iterator.putCallout((context, extraDataDict) => {
// // console.log("match offset: " + curOffsetHexPtr + ", curRealAddr=" + curRealAddr)
// // curHookFunc(context, curOffsetInt, moduleBaseAddress)
// // context.curOffsetInt = curOffsetInt
// // context.curOffsetHexPtr = curOffsetHexPtr
// // context.moduleBaseAddress = moduleBaseAddress
// // context[curOffsetInt] = curOffsetInt
// // context[curOffsetHexPtr] = curOffsetHexPtr
// // context[moduleBaseAddress] = moduleBaseAddress
// // curHookFunc(context, extraDataDict)
// curHookFunc(context)
// })
}
}
iterator.keep()
} while ((instruction = iterator.next()) !== null)
}
});
// function needDebug(context) {
// console.log("into needDebug")
// // console.log("into needDebug: context=" + context)
// // var contextStr = JSON.stringify(context, null, 2)
// // console.log("context=" + contextStr)
// // var x9Value1 = context.x9
// // var x9Value2 = context["x9"]
// // console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
// }
},
onLeave: function(retval) {
console.log("addr: relative [" + funcRelativeStartAddrHexStr + "] real [" + funcRealStartAddr + "] -> retval=" + retval)
if (curTid != null) {
Stalker.unfollow(curTid)
console.log("Stalker.unfollow curTid=", curTid)
}
}
})
}