libInFieldCollection.dylib的vsPHbdGf
代码fridaStalker_vsPHbdGf.js
贴出之前的某个Frida的Stalker的完整调试代码:
/Users/crifan/dev/dev_root/iosReverse/iOSModifyActivation/subBin/libInFieldCollection_dylib/dynamicDebug/frida/frida_stalker/fridaStalker_vsPHbdGf.js
/**
* Function: frida Stakler to hook libInFieldCollection.dylib funtion vsPHbdGf
* Author: Crifan Li
* Update: 20241217
* Usage:
* cd /Users/crifan/dev/dev_root/iosReverse/iOSModifyActivation/subBin/libInFieldCollection_dylib/dynamicDebug/frida/frida_stalker
* frida -U -n mobileactivationd -l fridaStalker_vsPHbdGf.js
*/
// https://github.com/crifan/JsFridaUtil/blob/main/JsUtil.js
// pure JavaScript utils
class JsUtil {
constructor() {
console.log("JsUtil constructor")
}
static {
}
/*---------- Number(Int) ----------*/
static intToHexStr(intValue, prefix="0x", isUpperCase=true){
// var hexStr = prefix + intValue.toString(16)
// var hexStr = prefix + String(intValue).padStart(2, "0")
// var hexStr = prefix + intValue.toString(16).padStart(2, "0")
var intHexStr = intValue.toString(16)
// console.log("intHexStr=" + intHexStr)
var padding0HexStr = intHexStr.padStart(2, "0")
// console.log("padding0HexStr=" + padding0HexStr)
if (isUpperCase) {
padding0HexStr = padding0HexStr.toUpperCase()
// console.log("padding0HexStr=" + padding0HexStr)
}
var fullHexStr = prefix + padding0HexStr
// console.log("fullHexStr=" + fullHexStr)
return fullHexStr
}
/*---------- Log ----------*/
// Generate single line log string
// input: logStr="Called: -[NSURLRequest initWithURL:]"
// output: "=============================== Called: -[NSURLRequest initWithURL:] ==============================="
static generateLineStr(logStr, isWithSpace=true, delimiterChar="=", lineWidth=80){
// console.log("logStr=" + logStr, ", isWithSpace=" + isWithSpace + ", delimiterChar=" + delimiterChar + ", lineWidth=" + lineWidth)
var lineStr = ""
var realLogStr = ""
if (isWithSpace) {
realLogStr = " " + logStr + " "
} else {
realLogStr = logStr
}
var realLogStrLen = realLogStr.length
if ((realLogStrLen % 2) > 0){
realLogStr += " "
realLogStrLen = realLogStr.length
}
var leftRightPaddingStr = ""
var paddingLen = lineWidth - realLogStrLen
if (paddingLen > 0) {
var leftRightPaddingLen = paddingLen / 2
leftRightPaddingStr = JsUtil.times(delimiterChar, leftRightPaddingLen)
}
lineStr = leftRightPaddingStr + realLogStr + leftRightPaddingStr
// console.log("lineStr:\n" + lineStr)
return lineStr
}
static logStr(curStr, isWithSpace=true, delimiterChar="=", lineWidth=80){
// let delimiterStr = "--------------------"
// console.log(delimiterStr + " " + curStr + " " + delimiterChar)
var lineStr = JsUtil.generateLineStr(curStr, isWithSpace, delimiterChar, lineWidth)
console.log(lineStr)
}
/*---------- Object: Dict/List/... ----------*/
// convert Object(dict/list/...) to JSON string
// function toJsonStr(curObj, singleLine=false, space=2){
static toJsonStr(curObj, singleLine=false, space=2){
// console.log("toJsonStr: singleLine=" + singleLine)
// var jsonStr = JSON.stringify(curObj, null, 2)
var jsonStr = JSON.stringify(curObj, null, space)
if(singleLine) {
// jsonStr = jsonStr.replace(/\\n/g, '')
jsonStr = jsonStr.replace(/\n/g, '')
}
return jsonStr
// return curObj.toString()
}
/*---------- List ----------*/
// check whether is item inside the list
// eg: curItem="abc", curList=["abc", "def"] => true
static isItemInList(curItem, curList){
// method1:
return curList.includes(curItem)
// // method2:
// return curList.indexOf(curItem) > -1
}
static sortByKey(curList, keyName){
if (null != curList){
curList.sort(function(objA, objB) {
var valueA = objA[keyName]
var valueB = objB[keyName]
var valudDiff = valueA - valueB
// console.log("valueA=" + valueA + ", valueB=" + valueB + " -> valudDiff=" + valudDiff)
return valudDiff
})
}
}
/*---------- String ----------*/
/** Function that count occurrences of a substring in a string;
* @param {String} string The string
* @param {String} subString The sub string to search for
* @param {Boolean} [allowOverlapping] Optional. (Default:false)
*
* @author Vitim.us https://gist.github.com/victornpb/7736865
* @see Unit Test https://jsfiddle.net/Victornpb/5axuh96u/
* @see https://stackoverflow.com/a/7924240/938822
*/
static occurrences(string, subString, allowOverlapping) {
// console.log("string=" + string + ",subString=" + subString + ", allowOverlapping=" + allowOverlapping)
string += "";
subString += "";
if (subString.length <= 0) return (string.length + 1);
var n = 0,
pos = 0,
step = allowOverlapping ? 1 : subString.length;
while (true) {
pos = string.indexOf(subString, pos);
// console.log("pos=" + pos)
if (pos >= 0) {
++n;
pos += step;
} else break;
}
return n;
}
// String multiple
// eg: str="=", num=5 => "====="
static times(str, num){
return new Array(num + 1).join(str)
}
// check string is empty or null
static strIsEmpty(curStr){
var isNull = null == curStr
var isEmp = "" === curStr
return isNull || isEmp
}
/*---------- Byte ----------*/
// byte decimaal to byte hex
// eg:
// 8 => 8
// -60 => c4
// function byteDecimalToByteHex(byteDecimal) {
static byteDecimalToByteHex(byteDecimal) {
// var digitCount = 6
var digitCount = 2
var minusDigitCount = 0 - digitCount
// return (byteDecimal + Math.pow(16, 6)).toString(16).substr(-6)
// var hexStr = (byteDecimal + Math.pow(16, 2)).toString(16).substr(-2)
// return (byteDecimal + Math.pow(16, digitCount)).toString(16).substr(minusDigitCount)
var hexStr = (byteDecimal + Math.pow(16, digitCount)).toString(16).substr(minusDigitCount)
// console.log("typeof hexStr=" + (typeof hexStr))
// console.log("hexStr=" + hexStr)
var hexValue = parseInt(hexStr, 16)
// console.log("typeof hexValue=" + (typeof hexValue))
// console.log("hexValue=" + hexValue)
return hexValue
}
/*---------- Object ----------*/
// check is js string
static isJsStr(curObj){
// console.log("curObj=" + curObj)
var curObjType = (typeof curObj)
// console.log("curObjType=" + curObjType)
var isStr = curObjType === "string"
// console.log("isStr=" + isStr)
return isStr
}
/*---------- Pointer ----------*/
// check pointer is valid or not
// example
// 0x103e79560 => true
// 0xc => false
static isValidPointer(curPtr){
let MinValidPointer = 0x10000
var isValid = curPtr > MinValidPointer
// console.log("curPtr=" + curPtr, " -> isValid=" + isValid)
return isValid
}
}
// https://github.com/crifan/JsFridaUtil/blob/main/frida/FridaUtil.js
// Frida Common Util
class FridaUtil {
// for Stalker onEnter transform, is show opcode string or not
static isShowOpcode = true
constructor() {
console.log("FridaUtil constructor")
console.log("FridaUtil Process.platform=" + Process.platform)
}
static isiOS(){
var platform = Process.platform
// console.log("platform=" + platform)
var isJavaAvailable = Java.available
// console.log("isJavaAvailable=" + isJavaAvailable)
var isDarwin = platform === "darwin"
// console.log("isDarwin=" + isDarwin)
var isiOSOS = (!isJavaAvailable) && isDarwin
// console.log("isiOSOS=" + isiOSOS)
return isiOSOS
}
static isAndroid(){
var platform = Process.platform
// console.log("platform=" + platform)
var isJavaAvailable = Java.available
// console.log("isJavaAvailable=" + isJavaAvailable)
var isLinux = platform === "linux"
// console.log("isLinux=" + isLinux)
var isAndroidOS = isJavaAvailable && isLinux
// console.log("isAndroidOS=" + isAndroidOS)
return isAndroidOS
}
// Frida pointer to UTF-8 string
static ptrToUtf8Str(curPtr){
var curUtf8Str = curPtr.readUtf8String()
// console.log("curUtf8Str=" + curUtf8Str)
return curUtf8Str
}
// Frida pointer to C string
static ptrToCStr(curPtr){
// var curCStr = Memory.readCString(curPtr)
var curCStr = curPtr.readCString()
// var curCStr = curPtr.readUtf8String()
// console.log("curCStr=" + curCStr)
return curCStr
}
static genModuleInfoStr(foundModule){
// console.log("Module: name=" + foundModule.name + ", base=" + foundModule.base + ", size=" + foundModule.size + ", path=" + foundModule.path)
var endAddress = foundModule.base.add(foundModule.size)
var sizeHexStr = JsUtil.intToHexStr(foundModule.size)
// console.log("Module: name=" + foundModule.name + ", address=[" + foundModule.base + "-" + endAddress + "], size=" + sizeHexStr + "=" + foundModule.size + ", path=" + foundModule.path)
var moduleInfoStr = "Module: address=[" + foundModule.base + "-" + endAddress + "], name=" + foundModule.name + ", size=" + sizeHexStr + "=" + foundModule.size + ", path=" + foundModule.path
return moduleInfoStr
}
// print module basic info: name, base, size, path
static printModuleBasicInfo(foundModule){
var moduleInfoStr = FridaUtil.genModuleInfoStr(foundModule)
console.log(moduleInfoStr)
}
// print module symbols
static printModuleSymbols(foundModule){
var curSymbolList = foundModule.enumerateSymbols()
console.log("Symbol: length=" + curSymbolList.length + ", list=" + curSymbolList)
for(var i = 0; i < curSymbolList.length; i++) {
console.log("---------- Symbol [" + i + "]----------")
var curSymbol = curSymbolList[i]
var sectionStr = JSON.stringify(curSymbol.section)
console.log("name=" + curSymbol.name + ", address=" + curSymbol.address + "isGlobal=" + curSymbol.isGlobal + ", type=" + curSymbol.type + ", section=" + sectionStr)
}
}
// print module exports
static printModuleExports(foundModule){
var curExportList = foundModule.enumerateExports()
console.log("Export: length=" + curExportList.length + ", list=" + curExportList)
for(var i = 0; i < curExportList.length; i++) {
console.log("---------- Export [" + i + "]----------")
var curExport = curExportList[i]
console.log("type=" + curExport.type + ", name=" + curExport.name + ", address=" + curExport.address)
}
}
// print module info
static printModuleInfo(moduleName){
const foundModule = Module.load(moduleName)
// const foundModule = Module.ensureInitialized()
console.log("foundModule=" + foundModule)
if (null == foundModule) {
return
}
FridaUtil.printModuleBasicInfo(foundModule)
FridaUtil.printModuleSymbols(foundModule)
FridaUtil.printModuleExports(foundModule)
}
// print process basic info
static printProcessBasicInfo(){
console.log(
"Process: id=" + Process.id
+ ", currentThreadId=" + Process.getCurrentThreadId()
+ ", currentDir=" + Process.getCurrentDir()
+ ", homeDir=" + Process.getHomeDir()
+ ", tmpDir=" + Process.getTmpDir()
+ ", arch=" + Process.arch
+ ", platform=" + Process.platform
+ ", pageSize=" + Process.pageSize
+ ", pointerSize=" + Process.pointerSize
+ ", codeSigningPolicy=" + Process.codeSigningPolicy
+ ", isDebuggerAttached=" + Process.isDebuggerAttached()
)
}
// print all loaded modules basic info of current process
// Note: similar to `image list` in lldb
static printAllLoadedModules(isSort=true){
FridaUtil.printProcessBasicInfo()
var moduleList = []
Process.enumerateModules({
onMatch: function(module){
// console.log('Module name: ' + module.name + " - " + "Base Address: " + module.base.toString());
// FridaUtil.printModuleBasicInfo(module)
moduleList.push(module)
},
onComplete: function(){}
})
if (isSort) {
// moduleList.sort(function(moduleA, moduleB) {
// // var isLarge = moduleA.base > moduleB.base
// // console.log("moduleA.base=" + moduleA.base + ", moduleB.base=" + moduleB.base + " -> isLarge=" + isLarge)
// var addrDiff = moduleA.base - moduleB.base
// console.log("moduleA.base=" + moduleA.base + ", moduleB.base=" + moduleB.base + " -> addrDiff=" + addrDiff)
// return addrDiff
// })
JsUtil.sortByKey(moduleList, "base")
}
for(var i = 0; i < moduleList.length; i++) {
var curModule = moduleList[i]
// var prefixStr = "\t"
var prefixStr = " "
console.log(prefixStr + FridaUtil.genModuleInfoStr(curModule))
}
}
static printModuleInfoAndStalkerExclude(moduleName){
var foundModule = Process.getModuleByName(moduleName)
console.log("moduleName=" + moduleName + " -> foundModule=" + foundModule)
if (null != foundModule) {
Stalker.exclude(foundModule)
// console.log("Stalker.exclude for module:")
// FridaUtil.printModuleBasicInfo(foundModule)
console.log("Stalker.exclude for: " + FridaUtil.genModuleInfoStr(foundModule))
}
}
// print function call and stack, output content type is: address
static printFunctionCallStack_addr(curContext, prefix=""){
var backtracerType = Backtracer.ACCURATE
// var backtracerType = Backtracer.FUZZY
if (!JsUtil.strIsEmpty(prefix)){
prefix = prefix + " "
}
// const linePrefix = "\n"
// const linePrefix = "\n\t"
const linePrefix = "\n "
// const linePrefix = "\n "
// const linePrefix = "\n"
console.log(prefix + 'Stack:' + linePrefix +
Thread.backtrace(curContext, backtracerType)
.map(DebugSymbol.fromAddress).join(linePrefix) + '\n');
}
static dumpMemory(toDumpPtr, byteLen=128){
var buf = toDumpPtr.readByteArray(byteLen)
var dumpHexStr = hexdump(
buf,
{
offset: 0,
length: byteLen,
header: true,
ansi: true
}
)
console.log("dumpHexStr=\n" + dumpHexStr)
}
// convert ByteArray to Opcode string
static byteArrayToOpcodeStr(byteArr){
var byteStrList = []
for(var i = 0; i < byteArr.length; i++) {
var curByte = byteArr[i]
// console.log("curByte=" + curByte)
var curByteStr = JsUtil.intToHexStr(curByte, "", true)
// console.log("curByteStr=" + curByteStr)
byteStrList.push(curByteStr)
}
// console.log("byteStrList=" + byteStrList)
var opcodeStr = byteStrList.join(" ")
// console.log("byteArr=" + byteArr + " -> opcodeStr=" + opcodeStr)
return opcodeStr
}
// read byte array from address
// Note: curAddress is NativePointer
static readAddressByteArray(curAddress, byteSize){
// console.log("curAddress=" + curAddress + ", byteSize=" + byteSize)
// var instructionByteArrBuffer = curAddress.readByteArray(byteSize)
var curByteArray = []
for(var i = 0; i < byteSize; i++){
var curAddr = curAddress.add(i)
// console.log("curAddr=" + curAddr)
var byteU8 = curAddr.readU8()
// console.log("byteU8=" + byteU8)
curByteArray.push(byteU8)
}
// console.log("curByteArray=" + curByteArray)
return curByteArray
}
static genInstructionOpcodeStr(instruction){
var instructionByteArr = FridaUtil.readAddressByteArray(instruction.address, instruction.size)
// console.log("instructionByteArr=" + instructionByteArr)
// var instructionOpcodeStr = hexdump(
// instructionByteArr,
// {
// offset: 0,
// length: curInstructionSize,
// header: false,
// ansi: false
// }
// )
var instructionOpcodeStr = FridaUtil.byteArrayToOpcodeStr(instructionByteArr)
// console.log("instructionOpcodeStr=" + instructionOpcodeStr)
return instructionOpcodeStr
}
static printInstructionInfo(instruction){
// Instruction: address=0x252c0edf8,toString()=br x10,next=0x4,size=4,mnemonic=br,opStr=x10,operands=[{"type":"reg","value":"x10","access":"r"}],regsAccessed={"read":["x10"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c0edf8","next":"0x4","size":4,"mnemonic":"br","opStr":"x10","operands":[{"type":"reg","value":"x10","access":"r"}],"regsAccessed":{"read":["x10"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
console.log("Instruction: address=" + instruction.address
+ ",toString()=" + instruction.toString()
+ ",toJSON()=" + JSON.stringify(instruction.toJSON())
// + ",next=" + instruction.next
// + ",size=" + instruction.size
// + ",mnemonic=" + instruction.mnemonic
// + ",opStr=" + instruction.opStr
// + ",operands=" + JSON.stringify(instruction.operands)
// + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
// + ",regsRead=" + JSON.stringify(instruction.regsRead)
// + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
// + ",groups=" + JSON.stringify(instruction.groups)
)
}
// 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)
}
}
})
}
}
/*******************************************************************************
* Other Util
*******************************************************************************/
// function logMain(mainStr){
// const mainDelimiter = "========================================"
// console.log(mainDelimiter + " " + mainStr + " " + mainDelimiter)
// }
// function logSub(subStr){
// const subDelimiter = "------------------------------"
// console.log(subDelimiter + " " + subStr + " " + subDelimiter)
// }
/*******************************************************************************
* Main Hook
*******************************************************************************/
function stalkerHookNative_vsPHbdGf(){
// console.log("into stalkerHookNative_vsPHbdGf:")
// logSub("into stalkerHookNative_vsPHbdGf")
JsUtil.logStr("into stalkerHookNative_vsPHbdGf", true, "-")
var libraryName = "libInFieldCollection.dylib"
// for debug
// libraryName = "mobileactivationd"
const moduleBaseAddress = Module.findBaseAddress(libraryName)
console.log("libraryName=" + libraryName + " -> moduleBaseAddress=" + moduleBaseAddress)
if (null == moduleBaseAddress) {
console.error("Failed to find library " + libraryName)
return
}
var funcName = "vsPHbdGf"
// for debug
// -[MACollectionInterface copyIngestData:] __text 00000001000067B4 00000D84 00000270 R . . . . . B T .
// funcName = "-[MACollectionInterface copyIngestData:]"
// funcName = "DERDecodeItem"
// funcName = "mach_msg"
var origFuncPtr = Module.findExportByName(libraryName, funcName)
console.log("origFuncPtr=" + origFuncPtr)
if (null == origFuncPtr) {
console.error("Failed to find function " + funcName + "in lib " + libraryName)
return
}
var funcRelativeStartAddr = origFuncPtr - moduleBaseAddress
console.log("funcRelativeStartAddr=" + funcRelativeStartAddr + "=" + JsUtil.intToHexStr(funcRelativeStartAddr))
// for debug
/*
[iPhone::mobileactivationd ]-> ============ Trigged addr: relative [0x13c94] = real [0x1c280ec94] ============
...
+++ into iterator: startAddress=0x1c2813d78, isAppCode=true
current: realAddr=0x1c2813d78 -> offset: hex=0x50e4=20708
0x1c2813d78 <+20708>: str x0, [sp, #0xc8]
current: realAddr=0x1c2813d7c -> offset: hex=0x50e8=20712
0x1c2813d7c <+20712>: bl #0x1c2842d88
*/
// // use later address as start address, try to avoid only hook part code == not hook all code
// funcRelativeStartAddr = funcRelativeStartAddr + 0x50e4
var functionSize = 0x61FC
// for debug: make larger, tyr to support hook more code
// var functionSize = 0x10000
// CollectPCRT == void __fastcall vsPHbdGf(__int64 a1, __int64 a2)
var argNum = 2
console.log("functionSize=" + functionSize + "=" + JsUtil.intToHexStr(functionSize) + ", argNum=" + argNum)
// try exclude not-concern functions inside common libs
// // var moduleName_libObjc = "/usr/lib/libobjc.A.dylib"
// var moduleName_libObjc = "libobjc.A.dylib"
// // FridaUtil.printModuleInfo(moduleName_libObjc)
// var module_libObjc = Process.getModuleByName(moduleName_libObjc)
// console.log("module_libObjc=" + module_libObjc)
// if (null != module_libObjc) {
// FridaUtil.printModuleBasicInfo(module_libObjc)
// Stalker.exclude(module_libObjc)
// }
// // var moduleName_system =
// var moduleName_system = "libSystem.B.dylib"
// // FridaUtil.printModuleInfo(moduleName_system)
// var module_system = Process.getModuleByName(moduleName_system)
// console.log("module_system=" + module_system)
// if (null != module_system) {
// FridaUtil.printModuleBasicInfo(module_system)
// Stalker.exclude(module_system)
// }
// var moduleName_MobileGestalt = "libMobileGestalt.dylib"
// var module_MobileGestalt = Process.getModuleByName(moduleName_MobileGestalt)
// console.log("module_MobileGestalt=" + module_MobileGestalt)
// if (null != module_MobileGestalt) {
// FridaUtil.printModuleBasicInfo(module_MobileGestalt)
// }
// var moduleName_IOKit = "IOKit"
// var module_IOKit = Process.getModuleByName(moduleName_IOKit)
// console.log("module_IOKit=" + module_IOKit)
// if (null != module_IOKit) {
// FridaUtil.printModuleBasicInfo(module_IOKit)
// }
// var moduleName_Foundation = "Foundation"
// var module_Foundation = Process.getModuleByName(moduleName_Foundation)
// console.log("module_Foundation=" + module_Foundation)
// if (null != module_Foundation) {
// FridaUtil.printModuleBasicInfo(module_Foundation)
// }
// var moduleName_CoreFoundation = "CoreFoundation"
// var module_CoreFoundation = Process.getModuleByName(moduleName_CoreFoundation)
// console.log("module_CoreFoundation=" + module_CoreFoundation)
// if (null != module_CoreFoundation) {
// FridaUtil.printModuleBasicInfo(module_CoreFoundation)
// }
// FridaUtil.printModuleInfoAndStalkerExclude("libobjc.A.dylib") // /usr/lib/libobjc.A.dylib
// FridaUtil.printModuleInfoAndStalkerExclude("libSystem.B.dylib") // /usr/lib/libSystem.B.dylib
// FridaUtil.printModuleInfoAndStalkerExclude("libsystem_malloc.dylib") // /usr/lib/system/libsystem_malloc.dylib
FridaUtil.printAllLoadedModules()
var toExcludeModuleList = [
"libobjc.A.dylib", // /usr/lib/libobjc.A.dylib
"libSystem.B.dylib", // /usr/lib/libSystem.B.dylib
"libsystem_malloc.dylib", // /usr/lib/system/libsystem_malloc.dylib
"libsystem_m.dylib", // /usr/lib/system/libsystem_m.dylib
"libsystem_networkextension.dylib", // /usr/lib/system/libsystem_networkextension.dylib
"libsystem_notify.dylib", // /usr/lib/system/libsystem_notify.dylib
"libsystem_sandbox.dylib", // /usr/lib/system/libsystem_sandbox.dylib
"libsystem_kernel.dylib", // /usr/lib/system/libsystem_kernel.dylib
"libsystem_platform.dylib", // /usr/lib/system/libsystem_platform.dylib
"libsystem_pthread.dylib", // /usr/lib/system/libsystem_pthread.dylib
"libsystem_symptoms.dylib", // /usr/lib/system/libsystem_symptoms.dylib
"libsystem_trace.dylib", // /usr/lib/system/libsystem_trace.dylib
"libunwind.dylib", // /usr/lib/system/libunwind.dylib
"libxpc.dylib", // /usr/lib/system/libxpc.dylib
// Module: address=[0x19a60a000-0x19a60f000], name=libcache.dylib, size=0x5000=20480, path=/usr/lib/system/libcache.dylib
"libcache.dylib",
// Module: address=[0x19a60f000-0x19a61b000], name=libcommonCrypto.dylib, size=0xc000=49152, path=/usr/lib/system/libcommonCrypto.dylib
"libcommonCrypto.dylib",
// Module: address=[0x19a61b000-0x19a620000], name=libcompiler_rt.dylib, size=0x5000=20480, path=/usr/lib/system/libcompiler_rt.dylib
"libcompiler_rt.dylib",
// Module: address=[0x19a620000-0x19a629000], name=libcopyfile.dylib, size=0x9000=36864, path=/usr/lib/system/libcopyfile.dylib
"libcopyfile.dylib",
// Module: address=[0x19a629000-0x19a68d000], name=libcorecrypto.dylib, size=0x64000=409600, path=/usr/lib/system/libcorecrypto.dylib
"libcorecrypto.dylib",
// Module: address=[0x19a68d000-0x19a6fd000], name=libdispatch.dylib, size=0x70000=458752, path=/usr/lib/system/libdispatch.dylib
"libdispatch.dylib",
// Module: address=[0x19a6fd000-0x19a727000], name=libdyld.dylib, size=0x2a000=172032, path=/usr/lib/system/libdyld.dylib
"libdyld.dylib",
// Module: address=[0x22ab49000-0x22abcb000], name=libsystem_c.dylib, size=0x82000=532480, path=/usr/lib/system/libsystem_c.dylib
"libsystem_c.dylib",
// Module: address=[0x22af96000-0x22b2f5000], name=CoreFoundation, size=0x35f000=3534848, path=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
"CoreFoundation",
// Module: address=[0x101720000-0x10172c000], name=MAMock.dylib, size=0xc000=49152, path=/Library/MobileSubstrate/DynamicLibraries/MAMock.dylib
"MAMock.dylib",
// // Module: address=[0x22b61f000-0x22b654000], name=libMobileGestalt.dylib, size=0x35000=217088, path=/usr/lib/libMobileGestalt.dylib
// "libMobileGestalt.dylib",
]
for(var i = 0; i < toExcludeModuleList.length; i++) {
// console.log("---------- Module [" + i + "]----------")
var curModule = toExcludeModuleList[i]
FridaUtil.printModuleInfoAndStalkerExclude(curModule)
}
let hookFuncMap = {
0x164: // +356
function (context) {
var contextStr = JSON.stringify(context)
console.log("[0x164] contextStr=" + contextStr)
var x10 = context.x10
console.log("[0x164] x10=" + x10)
},
0x1DC: // +476
function (context) {
var contextStr = JSON.stringify(context)
console.log("[0x1DC] contextStr=" + contextStr)
var x10 = context.x10
console.log("[0x1DC] x10=" + x10)
},
}
FridaUtil.isShowOpcode = false
FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)
}
function hookNative(){
// console.log("into hookNative:")
// logMain("into hookNative")
JsUtil.logStr("into hookNative")
stalkerHookNative_vsPHbdGf()
}
hookNative()
输出日志
部分调试输出日志:
➜ frida_stalker frida -U -n mobileactivationd -l fridaStalker_vsPHbdGf.js
____
/ _ | Frida 16.5.9 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to iPhone (id=9bad8d3c9530bd2fc62072c30ee3accf3cdc45d6)
Attaching...
=============================== into hookNative ===============================
----------------------- into stalkerHookNative_vsPHbdGf -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative ===============================
----------------------- into stalkerHookNative_vsPHbdGf -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative ===============================
----------------------- into stalkerHookNative_vsPHbdGf -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative ===============================
----------------------- into stalkerHookNative_vsPHbdGf -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative ===============================
----------------------- into stalkerHookNative_vsPHbdGf -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=0x252bfb000
origFuncPtr=0x252c0ec94
funcRelativeStartAddr=81044
functionSize=25084=0x61fc, argNum=2
Process: id=9871, currentThreadId=11303, currentDir=/, homeDir=/var/mobile, tmpDir=/var/tmp, arch=arm64, platform=darwin, pageSize=16384, pointerSize=8, codeSigningPolicy=optional, isDebuggerAttached=false
Module: address=[0x100620000-0x10082c000], name=mobileactivationd, size=0x20c000=2146304, path=/usr/libexec/mobileactivationd
Module: address=[0x100884000-0x100888000], name=MobileSubstrate.dylib, size=0x4000=16384, path=/Library/MobileSubstrate/MobileSubstrate.dylib
Module: address=[0x1008cc000-0x1008d0000], name=SubstrateInserter.dylib, size=0x4000=16384, path=/usr/lib/substrate/SubstrateInserter.dylib
Module: address=[0x100a00000-0x100a18000], name=SubstrateLoader.dylib, size=0x18000=98304, path=/usr/lib/substrate/SubstrateLoader.dylib
Module: address=[0x100a44000-0x100a9c000], name=dyld, size=0x58000=360448, path=/usr/lib/dyld
Module: address=[0x100b44000-0x100b50000], name=MAMock.dylib, size=0xc000=49152, path=/Library/MobileSubstrate/DynamicLibraries/MAMock.dylib
Module: address=[0x100d00000-0x100e14000], name=libsubstrate.dylib, size=0x114000=1130496, path=/usr/lib/libsubstrate.dylib
Module: address=[0x22a217000-0x22a219000], name=libSystem.B.dylib, size=0x2000=8192, path=/usr/lib/libSystem.B.dylib
Module: address=[0x22a219000-0x22a26f000], name=libc++.1.dylib, size=0x56000=352256, path=/usr/lib/libc++.1.dylib
Module: address=[0x22a26f000-0x22a282000], name=libc++abi.dylib, size=0x13000=77824, path=/usr/lib/libc++abi.dylib
Module: address=[0x22a282000-0x22aa0a000], name=libobjc.A.dylib, size=0x788000=7897088, path=/usr/lib/libobjc.A.dylib
Module: address=[0x22aa0a000-0x22aa0f000], name=libcache.dylib, size=0x5000=20480, path=/usr/lib/system/libcache.dylib
Module: address=[0x22aa0f000-0x22aa1b000], name=libcommonCrypto.dylib, size=0xc000=49152, path=/usr/lib/system/libcommonCrypto.dylib
Module: address=[0x22aa1b000-0x22aa20000], name=libcompiler_rt.dylib, size=0x5000=20480, path=/usr/lib/system/libcompiler_rt.dylib
...
Module: address=[0x22cbc2000-0x22cbc3000], name=vecLib, size=0x1000=4096, path=/System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/vecLib
...
Module: address=[0x252bfb000-0x252c51000], name=libInFieldCollection.dylib, size=0x56000=352256, path=/usr/lib/libInFieldCollection.dylib
Module: address=[0x252c62000-0x252c70000], name=libMobileGestaltExtensions.dylib, size=0xe000=57344, path=/usr/lib/libMobileGestaltExtensions.dylib
...
Module: address=[0x256365000-0x2563fa000], name=SampleAnalysis, size=0x95000=610304, path=/System/Library/PrivateFrameworks/SampleAnalysis.framework/SampleAnalysis
---------- Module [0]----------
moduleName=libobjc.A.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22a282000-0x22aa0a000], name=libobjc.A.dylib, size=0x788000=7897088, path=/usr/lib/libobjc.A.dylib
---------- Module [1]----------
moduleName=libSystem.B.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22a217000-0x22a219000], name=libSystem.B.dylib, size=0x2000=8192, path=/usr/lib/libSystem.B.dylib
---------- Module [2]----------
moduleName=libsystem_malloc.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ac81000-0x22aca4000], name=libsystem_malloc.dylib, size=0x23000=143360, path=/usr/lib/system/libsystem_malloc.dylib
---------- Module [3]----------
moduleName=libsystem_m.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ac53000-0x22ac81000], name=libsystem_m.dylib, size=0x2e000=188416, path=/usr/lib/system/libsystem_m.dylib
---------- Module [4]----------
moduleName=libsystem_networkextension.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aca4000-0x22acb0000], name=libsystem_networkextension.dylib, size=0xc000=49152, path=/usr/lib/system/libsystem_networkextension.dylib
---------- Module [5]----------
moduleName=libsystem_notify.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acb0000-0x22acb7000], name=libsystem_notify.dylib, size=0x7000=28672, path=/usr/lib/system/libsystem_notify.dylib
---------- Module [6]----------
moduleName=libsystem_sandbox.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acd3000-0x22acd6000], name=libsystem_sandbox.dylib, size=0x3000=12288, path=/usr/lib/system/libsystem_sandbox.dylib
---------- Module [7]----------
moduleName=libsystem_kernel.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ac28000-0x22ac53000], name=libsystem_kernel.dylib, size=0x2b000=176128, path=/usr/lib/system/libsystem_kernel.dylib
---------- Module [8]----------
moduleName=libsystem_platform.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acb7000-0x22acc2000], name=libsystem_platform.dylib, size=0xb000=45056, path=/usr/lib/system/libsystem_platform.dylib
---------- Module [9]----------
moduleName=libsystem_pthread.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acc2000-0x22acd3000], name=libsystem_pthread.dylib, size=0x11000=69632, path=/usr/lib/system/libsystem_pthread.dylib
---------- Module [10]----------
moduleName=libsystem_symptoms.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acd6000-0x22acde000], name=libsystem_symptoms.dylib, size=0x8000=32768, path=/usr/lib/system/libsystem_symptoms.dylib
---------- Module [11]----------
moduleName=libsystem_trace.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acde000-0x22acf4000], name=libsystem_trace.dylib, size=0x16000=90112, path=/usr/lib/system/libsystem_trace.dylib
---------- Module [12]----------
moduleName=libunwind.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acf4000-0x22acfa000], name=libunwind.dylib, size=0x6000=24576, path=/usr/lib/system/libunwind.dylib
---------- Module [13]----------
moduleName=libxpc.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acfa000-0x22ad28000], name=libxpc.dylib, size=0x2e000=188416, path=/usr/lib/system/libxpc.dylib
---------- Module [14]----------
moduleName=libcache.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa0a000-0x22aa0f000], name=libcache.dylib, size=0x5000=20480, path=/usr/lib/system/libcache.dylib
---------- Module [15]----------
moduleName=libcommonCrypto.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa0f000-0x22aa1b000], name=libcommonCrypto.dylib, size=0xc000=49152, path=/usr/lib/system/libcommonCrypto.dylib
---------- Module [16]----------
moduleName=libcompiler_rt.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa1b000-0x22aa20000], name=libcompiler_rt.dylib, size=0x5000=20480, path=/usr/lib/system/libcompiler_rt.dylib
---------- Module [17]----------
moduleName=libcopyfile.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa20000-0x22aa29000], name=libcopyfile.dylib, size=0x9000=36864, path=/usr/lib/system/libcopyfile.dylib
---------- Module [18]----------
moduleName=libcorecrypto.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa29000-0x22aa8d000], name=libcorecrypto.dylib, size=0x64000=409600, path=/usr/lib/system/libcorecrypto.dylib
---------- Module [19]----------
moduleName=libdispatch.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa8d000-0x22aafd000], name=libdispatch.dylib, size=0x70000=458752, path=/usr/lib/system/libdispatch.dylib
---------- Module [20]----------
moduleName=libdyld.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aafd000-0x22ab27000], name=libdyld.dylib, size=0x2a000=172032, path=/usr/lib/system/libdyld.dylib
---------- Module [21]----------
moduleName=libsystem_c.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ab49000-0x22abcb000], name=libsystem_c.dylib, size=0x82000=532480, path=/usr/lib/system/libsystem_c.dylib
---------- Module [22]----------
moduleName=CoreFoundation -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22af96000-0x22b2f5000], name=CoreFoundation, size=0x35f000=3534848, path=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
---------- Module [23]----------
moduleName=MAMock.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x100b44000-0x100b50000], name=MAMock.dylib, size=0xc000=49152, path=/Library/MobileSubstrate/DynamicLibraries/MAMock.dylib
Frida Stalker hook: module: baseAddress=0x252bfb000
function: relativeStartAddr=0x13c94, size=25084=0x61fc, relativeEndAddr=0x19e90
funcRealStartAddr=0x252c0ec94, funcRealEndAddr=0x252c14e90
curTid=null
[iPhone::mobileactivationd ]-> ============ Trigged addr: relative [0x13c94] = real [0x252c0ec94] ============
arg[0]=0x16f866988
arg[1]=0x16f866984
curTid=21011
+++ into iterator: startAddress=0x10f3c1768, isAppCode=false
+++ into iterator: startAddress=0x10f3c1778, isAppCode=false
...
+++ into iterator: startAddress=0x11074c030, isAppCode=false
+++ into iterator: startAddress=0x252c0eca4, isAppCode=true
Instruction: address=0x252c0eca4,toString()=stp x20, x19, [sp, #0x40],next=0x4,size=4,mnemonic=stp,opStr=x20, x19, [sp, #0x40],operands=[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],regsAccessed={"read":["x20","x19","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0eca4","next":"0x4","size":4,"mnemonic":"stp","opStr":"x20, x19, [sp, #0x40]","operands":[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],"regsAccessed":{"read":["x20","x19","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0eca4 -> offset: hex=0x10=16
0x252c0eca4 <+16>: stp x20, x19, [sp, #0x40]
Instruction: address=0x252c0eca8,toString()=stp x29, x30, [sp, #0x50],next=0x4,size=4,mnemonic=stp,opStr=x29, x30, [sp, #0x50],operands=[{"type":"reg","value":"fp","access":"r"},{"type":"reg","value":"lr","access":"r"},{"type":"mem","value":{"base":"sp","disp":80},"access":"rw"}],regsAccessed={"read":["fp","lr","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0eca8","next":"0x4","size":4,"mnemonic":"stp","opStr":"x29, x30, [sp, #0x50]","operands":[{"type":"reg","value":"fp","access":"r"},{"type":"reg","value":"lr","access":"r"},{"type":"mem","value":{"base":"sp","disp":80},"access":"rw"}],"regsAccessed":{"read":["fp","lr","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0eca8 -> offset: hex=0x14=20
0x252c0eca8 <+20>: stp x29, x30, [sp, #0x50]
Instruction: address=0x252c0ecac,toString()=add x29, sp, #0x50,next=0x4,size=4,mnemonic=add,opStr=x29, sp, #0x50,operands=[{"type":"reg","value":"fp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"80","access":"r"}],regsAccessed={"read":["sp"],"written":["fp"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecac","next":"0x4","size":4,"mnemonic":"add","opStr":"x29, sp, #0x50","operands":[{"type":"reg","value":"fp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"80","access":"r"}],"regsAccessed":{"read":["sp"],"written":["fp"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecac -> offset: hex=0x18=24
0x252c0ecac <+24>: add x29, sp, #0x50
Instruction: address=0x252c0ecb0,toString()=sub sp, sp, #1, lsl #12,next=0x4,size=4,mnemonic=sub,opStr=sp, sp, #1, lsl #12,operands=[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1","shift":{"type":"lsl","value":12},"access":"r"}],regsAccessed={"read":["sp"],"written":["sp"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecb0","next":"0x4","size":4,"mnemonic":"sub","opStr":"sp, sp, #1, lsl #12","operands":[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1","shift":{"type":"lsl","value":12},"access":"r"}],"regsAccessed":{"read":["sp"],"written":["sp"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecb0 -> offset: hex=0x1c=28
0x252c0ecb0 <+28>: sub sp, sp, #1, lsl #12
Instruction: address=0x252c0ecb4,toString()=sub sp, sp, #0xf00,next=0x4,size=4,mnemonic=sub,opStr=sp, sp, #0xf00,operands=[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"3840","access":"r"}],regsAccessed={"read":["sp"],"written":["sp"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecb4","next":"0x4","size":4,"mnemonic":"sub","opStr":"sp, sp, #0xf00","operands":[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"3840","access":"r"}],"regsAccessed":{"read":["sp"],"written":["sp"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecb4 -> offset: hex=0x20=32
0x252c0ecb4 <+32>: sub sp, sp, #0xf00
Instruction: address=0x252c0ecb8,toString()=str x1, [sp, #0x88],next=0x4,size=4,mnemonic=str,opStr=x1, [sp, #0x88],operands=[{"type":"reg","value":"x1","access":"r"},{"type":"mem","value":{"base":"sp","disp":136},"access":"rw"}],regsAccessed={"read":["x1","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecb8","next":"0x4","size":4,"mnemonic":"str","opStr":"x1, [sp, #0x88]","operands":[{"type":"reg","value":"x1","access":"r"},{"type":"mem","value":{"base":"sp","disp":136},"access":"rw"}],"regsAccessed":{"read":["x1","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecb8 -> offset: hex=0x24=36
0x252c0ecb8 <+36>: str x1, [sp, #0x88]
Instruction: address=0x252c0ecbc,toString()=str x0, [sp, #0xa8],next=0x4,size=4,mnemonic=str,opStr=x0, [sp, #0xa8],operands=[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":168},"access":"rw"}],regsAccessed={"read":["x0","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecbc","next":"0x4","size":4,"mnemonic":"str","opStr":"x0, [sp, #0xa8]","operands":[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":168},"access":"rw"}],"regsAccessed":{"read":["x0","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecbc -> offset: hex=0x28=40
0x252c0ecbc <+40>: str x0, [sp, #0xa8]
Instruction: address=0x252c0ecc0,toString()=add x28, sp, #0x428,next=0x4,size=4,mnemonic=add,opStr=x28, sp, #0x428,operands=[{"type":"reg","value":"x28","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1064","access":"r"}],regsAccessed={"read":["sp"],"written":["x28"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecc0","next":"0x4","size":4,"mnemonic":"add","opStr":"x28, sp, #0x428","operands":[{"type":"reg","value":"x28","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1064","access":"r"}],"regsAccessed":{"read":["sp"],"written":["x28"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecc0 -> offset: hex=0x2c=44
0x252c0ecc0 <+44>: add x28, sp, #0x428
Instruction: address=0x252c0ecc4,toString()=add x23, sp, #0x315,next=0x4,size=4,mnemonic=add,opStr=x23, sp, #0x315,operands=[{"type":"reg","value":"x23","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"789","access":"r"}],regsAccessed={"read":["sp"],"written":["x23"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecc4","next":"0x4","size":4,"mnemonic":"add","opStr":"x23, sp, #0x315","operands":[{"type":"reg","value":"x23","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"789","access":"r"}],"regsAccessed":{"read":["sp"],"written":["x23"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecc4 -> offset: hex=0x30=48
0x252c0ecc4 <+48>: add x23, sp, #0x315
Instruction: address=0x252c0ecc8,toString()=add x26, sp, #0x158,next=0x4,size=4,mnemonic=add,opStr=x26, sp, #0x158,operands=[{"type":"reg","value":"x26","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"344","access":"r"}],regsAccessed={"read":["sp"],"written":["x26"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecc8","next":"0x4","size":4,"mnemonic":"add","opStr":"x26, sp, #0x158","operands":[{"type":"reg","value":"x26","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"344","access":"r"}],"regsAccessed":{"read":["sp"],"written":["x26"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecc8 -> offset: hex=0x34=52
...
0x252c0edf0 <+348>: add x10, x8, x10
Instruction: address=0x252c0edf4,toString()=add w8, w9, #1,next=0x4,size=4,mnemonic=add,opStr=w8, w9, #1,operands=[{"type":"reg","value":"w8","access":"w"},{"type":"reg","value":"w9","access":"r"},{"type":"imm","value":"1","access":"r"}],regsAccessed={"read":["w9"],"written":["w8"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0edf4","next":"0x4","size":4,"mnemonic":"add","opStr":"w8, w9, #1","operands":[{"type":"reg","value":"w8","access":"w"},{"type":"reg","value":"w9","access":"r"},{"type":"imm","value":"1","access":"r"}],"regsAccessed":{"read":["w9"],"written":["w8"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0edf4 -> offset: hex=0x160=352
0x252c0edf4 <+352>: add w8, w9, #1
Instruction: address=0x252c0edf8,toString()=br x10,next=0x4,size=4,mnemonic=br,opStr=x10,operands=[{"type":"reg","value":"x10","access":"r"}],regsAccessed={"read":["x10"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c0edf8","next":"0x4","size":4,"mnemonic":"br","opStr":"x10","operands":[{"type":"reg","value":"x10","access":"r"}],"regsAccessed":{"read":["x10"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
current: realAddr=0x252c0edf8 -> offset: hex=0x164=356
0x252c0edf8 <+356>: br x10
offset: 0x164=356
[0x164] contextStr={"pc":"0x252c0edf8","sp":"0x16f864a10","nzcv":536870912,"x0":"0x58eef7c8","x1":"0x16f866984","x2":"0x16f8669c8","x3":"0x1","x4":"0x100c71750","x5":"0x8","x6":"0x64","x7":"0x0","x8":"0x7","x9":"0x6","x10":"0x252c0ee00","x11":"0x6","x12":"0x2668d857","x13":"0x0","x14":"0x10082738d","x15":"0x2648f095a","x16":"0x252c4ea00","x17":"0xa711087f","x18":"0x0","x19":"0x16f8669c8","x20":"0x100827377","x21":"0x100834018","x22":"0x0","x23":"0x16f864d25","x24":"0x399258cb","x25":"0x0","x26":"0x16f864b68","x27":"0x176dc56e","x28":"0x16f864e38","fp":"0x16f866960","lr":"0x11074c00c","q0":{},"q1":{},"q2":{},"q3":{},"q4":{},"q5":{},"q6":{},"q7":{},"q8":{},"q9":{},"q10":{},"q11":{},"q12":{},"q13":{},"q14":{},"q15":{},"q16":{},"q17":{},"q18":{},"q19":{},"q20":{},"q21":{},"q22":{},"q23":{},"q24":{},"q25":{},"q26":{},"q27":{},"q28":{},"q29":{},"q30":{},"q31":{},"d0":6.0132879286022618e-154,"d1":1.9999992847442624,"d2":7.9499288951273454e-275,"d3":0,"d4":0,"d5":0,"d6":0,"d7":0,"d8":0,"d9":0,"d10":0,"d11":0,"d12":0,"d13":0,"d14":0,"d15":0,"d16":-1.0855813867524649e+251,"d17":0.000002084565455e-308,"d18":3.0554698911305689e-152,"d19":0.000001322084152e-308,"d20":3.7696966457559071e-175,"d21":1.0004894955531618e+128,"d22":9.5944260775693913e+225,"d23":-6.8154492514793903e-236,"d24":-2.1930923744387854e+50,"d25":0,"d26":0,"d27":0,"d28":0,"d29":0,"d30":0,"d31":0,"s0":1.3563115067909484e-19,"s1":1.9999998807907104,"s2":3.8204714345426298e-37,"s3":0,"s4":0,"s5":0,"s6":0,"s7":0,"s8":0,"s9":0,"s10":0,"s11":0,"s12":0,"s13":0,"s14":0,"s15":0,"s16":1.5548730664783592e-21,"s17":-1.3084408235578860e+36,"s18":-8.6088756618229034e-23,"s19":-5.408784745233076e-20,"s20":4.2151578028428229e+37,"s21":18362722504671230,"s22":3.372155249992253e+28,"s23":-7.6784630118876258e-30,"s24":-3715189.5,"s25":0,"s26":0,"s27":0,"s28":0,"s29":0,"s30":0,"s31":0}
[0x164] x10=0x252c0ee00
+++ into iterator: startAddress=0x252c0ee00, isAppCode=true
Instruction: address=0x252c0ee00,toString()=mov w25, #0xddc9,next=0x4,size=4,mnemonic=mov,opStr=w25, #0xddc9,operands=[{"type":"reg","value":"w25","access":"w"},{"type":"imm","value":"56777","access":""}],regsAccessed={"read":[],"written":["w25"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ee00","next":"0x4","size":4,"mnemonic":"mov","opStr":"w25, #0xddc9","operands":[{"type":"reg","value":"w25","access":"w"},{"type":"imm","value":"56777","access":""}],"regsAccessed":{"read":[],"written":["w25"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ee00 -> offset: hex=0x16c=364
0x252c0ee00 <+364>: mov w25, #0xddc9
Instruction: address=0x252c0ee04,toString()=movk w25, #0x6c8d, lsl #16,next=0x4,size=4,mnemonic=movk,opStr=w25, #0x6c8d, lsl #16,operands=[{"type":"reg","value":"w25","access":"rw"},{"type":"imm","value":"27789","shift":{"type":"lsl","value":16},"access":"r"}],regsAccessed={"read":["w25"],"written":["w25"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ee04","next":"0x4","size":4,"mnemonic":"movk","opStr":"w25, #0x6c8d, lsl #16","operands":[{"type":"reg","value":"w25","access":"rw"},{"type":"imm","value":"27789","shift":{"type":"lsl","value":16},"access":"r"}],"regsAccessed":{"read":["w25"],"written":["w25"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ee04 -> offset: hex=0x170=368
...
0x252c13cd8 <+20548>: add x8, x8, x9
Instruction: address=0x252c13cdc,toString()=br x8,next=0x4,size=4,mnemonic=br,opStr=x8,operands=[{"type":"reg","value":"x8","access":"r"}],regsAccessed={"read":["x8"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c13cdc","next":"0x4","size":4,"mnemonic":"br","opStr":"x8","operands":[{"type":"reg","value":"x8","access":"r"}],"regsAccessed":{"read":["x8"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
current: realAddr=0x252c13cdc -> offset: hex=0x5048=20552
0x252c13cdc <+20552>: br x8
+++ into iterator: startAddress=0x252c13ce4, isAppCode=true
Instruction: address=0x252c13ce4,toString()=mov w22, #0xf6e,next=0x4,size=4,mnemonic=mov,opStr=w22, #0xf6e,operands=[{"type":"reg","value":"w22","access":"w"},{"type":"imm","value":"3950","access":""}],regsAccessed={"read":[],"written":["w22"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13ce4","next":"0x4","size":4,"mnemonic":"mov","opStr":"w22, #0xf6e","operands":[{"type":"reg","value":"w22","access":"w"},{"type":"imm","value":"3950","access":""}],"regsAccessed":{"read":[],"written":["w22"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13ce4 -> offset: hex=0x5050=20560
0x252c13ce4 <+20560>: mov w22, #0xf6e
Instruction: address=0x252c13ce8,toString()=movk w22, #0x327e, lsl #16,next=0x4,size=4,mnemonic=movk,opStr=w22, #0x327e, lsl #16,operands=[{"type":"reg","value":"w22","access":"rw"},{"type":"imm","value":"12926","shift":{"type":"lsl","value":16},"access":"r"}],regsAccessed={"read":["w22"],"written":["w22"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13ce8","next":"0x4","size":4,"mnemonic":"movk","opStr":"w22, #0x327e, lsl #16","operands":[{"type":"reg","value":"w22","access":"rw"},{"type":"imm","value":"12926","shift":{"type":"lsl","value":16},"access":"r"}],"regsAccessed":{"read":["w22"],"written":["w22"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13ce8 -> offset: hex=0x5054=20564
...
0x252c13d70 <+20700>: sub w25, w8, #0x2a
Instruction: address=0x252c13d74,toString()=bl #0x252c42e9c,next=0x4,size=4,mnemonic=bl,opStr=#0x252c42e9c,operands=[{"type":"imm","value":"9978523292","access":"r"}],regsAccessed={"read":[],"written":["lr"]},regsRead=[],regsWritten=["lr"],groups=["call","jump","branch_relative"],toJSON()={"address":"0x252c13d74","next":"0x4","size":4,"mnemonic":"bl","opStr":"#0x252c42e9c","operands":[{"type":"imm","value":"9978523292","access":"r"}],"regsAccessed":{"read":[],"written":["lr"]},"regsRead":[],"regsWritten":["lr"],"groups":["call","jump","branch_relative"]}
current: realAddr=0x252c13d74 -> offset: hex=0x50e0=20704
0x252c13d74 <+20704>: bl #0x252c42e9c
+++ into iterator: startAddress=0x252c42e9c, isAppCode=false
+++ into iterator: startAddress=0x22ac914c0, isAppCode=false
+++ into iterator: startAddress=0x22ac914dc, isAppCode=false
+++ into iterator: startAddress=0x22ac914f0, isAppCode=false
+++ into iterator: startAddress=0x252c13d78, isAppCode=true
Instruction: address=0x252c13d78,toString()=str x0, [sp, #0xc8],next=0x4,size=4,mnemonic=str,opStr=x0, [sp, #0xc8],operands=[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":200},"access":"rw"}],regsAccessed={"read":["x0","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13d78","next":"0x4","size":4,"mnemonic":"str","opStr":"x0, [sp, #0xc8]","operands":[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":200},"access":"rw"}],"regsAccessed":{"read":["x0","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13d78 -> offset: hex=0x50e4=20708
0x252c13d78 <+20708>: str x0, [sp, #0xc8]
Instruction: address=0x252c13d7c,toString()=bl #0x252c42d88,next=0x4,size=4,mnemonic=bl,opStr=#0x252c42d88,operands=[{"type":"imm","value":"9978523016","access":"r"}],regsAccessed={"read":[],"written":["lr"]},regsRead=[],regsWritten=["lr"],groups=["call","jump","branch_relative"],toJSON()={"address":"0x252c13d7c","next":"0x4","size":4,"mnemonic":"bl","opStr":"#0x252c42d88","operands":[{"type":"imm","value":"9978523016","access":"r"}],"regsAccessed":{"read":[],"written":["lr"]},"regsRead":[],"regsWritten":["lr"],"groups":["call","jump","branch_relative"]}
current: realAddr=0x252c13d7c -> offset: hex=0x50e8=20712
0x252c13d7c <+20712>: bl #0x252c42d88
+++ into iterator: startAddress=0x252c42d88, isAppCode=false
+++ into iterator: startAddress=0x22ab7145c, isAppCode=false
+++ into iterator: startAddress=0x22ab71478, isAppCode=false
+++ into iterator: startAddress=0x22ab7147c, isAppCode=false
+++ into iterator: startAddress=0x22ab71490, isAppCode=false
+++ into iterator: startAddress=0x22ab714a0, isAppCode=false
+++ into iterator: startAddress=0x22ab714cc, isAppCode=false
+++ into iterator: startAddress=0x22ab714d0, isAppCode=false
+++ into iterator: startAddress=0x22ab714f8, isAppCode=false
+++ into iterator: startAddress=0x22ab7151c, isAppCode=false
+++ into iterator: startAddress=0x252c13d80, isAppCode=true
Instruction: address=0x252c13d80,toString()=mov w5, #0x87f,next=0x4,size=4,mnemonic=mov,opStr=w5, #0x87f,operands=[{"type":"reg","value":"w5","access":"w"},{"type":"imm","value":"2175","access":""}],regsAccessed={"read":[],"written":["w5"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13d80","next":"0x4","size":4,"mnemonic":"mov","opStr":"w5, #0x87f","operands":[{"type":"reg","value":"w5","access":"w"},{"type":"imm","value":"2175","access":""}],"regsAccessed":{"read":[],"written":["w5"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13d80 -> offset: hex=0x50ec=20716
0x252c13d80 <+20716>: mov w5, #0x87f
Instruction: address=0x252c13d84,toString()=movk w5, #0xa711, lsl #16,next=0x4,size=4,mnemonic=movk,opStr=w5, #0xa711, lsl #16,operands=[{"type":"reg","value":"w5","access":"rw"},{"type":"imm","value":"42769","shift":{"type":"lsl","value":16},"access":"r"}],regsAccessed={"read":["w5"],"written":["w5"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13d84","next":"0x4","size":4,"mnemonic":"movk","opStr":"w5, #0xa711, lsl #16","operands":[{"type":"reg","value":"w5","access":"rw"},{"type":"imm","value":"42769","shift":{"type":"lsl","value":16},"access":"r"}],"regsAccessed":{"read":["w5"],"written":["w5"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13d84 -> offset: hex=0x50f0=20720
...