请大神帮忙看看~万分感谢!
对象(实例)函数原型:
id __cdecl -[APPProcessor reqDataWithBizDict:actDict:zipType:info:newApiVer:](
APPProcessor \*self,
SEL a2,
id a3,
id a4,
signed \__int64 \*a5,
APTaskInfoData \*a6,
bool a7)
frida hook后的参数情况:
对应上面的reqDataWithBizDict: id a3
a3={
"external_info" = "\_input_charset=\\"utf-8\\"&body=\\"\\\\"extInfo\\":{\\"ap_link_token\\":\\"EP11bad44220dd0b2d10fc93d0666e38c48_1761914117465\\"}}\\"";
},type: __NSSingleEntryDictionaryI
对应上面的actDict: id a4
a4={
action = {
method = main;
type = test;
};
},type: __NSSingleEntryDictionaryI
对应上面的zipType: signed __int64 *a5,应该是数据压缩类型:0或者1
a5 0x16fdf26d8
16fdf26d8 00 00 00 00 00 00 00 00 20 35 b3 85 02 00 00 00 … 5…
16fdf26e8 40 28 df 6f 01 00 00 00 d0 27 df 6f 01 00 00 00 @(.o…'.o…
16fdf26f8 e0 70 a4 99 01 00 00 00 30 77 6c 73 62 74 77 73 .p…0wlsbtws
16fdf2708 6c 36 75 61 39 61 6f 34 77 30 62 30 76 76 6f 32 l6ua9ao4w0b0vvo2
对应上面的info:APTaskInfoData *a6,应该是任务的相关信息:”0wlsbtwsl6ua9ao4w0b0vvo2”
a6 0x16fdf2700
16fdf2700 30 77 6c 73 62 74 77 73 6c 36 75 61 39 61 6f 34 0wlsbtwsl6ua9ao4
16fdf2710 77 30 62 30 76 76 6f 32 00 00 00 00 00 00 00 00 w0b0vvo2…
16fdf2720 00 00 00 00 8c f6 27 41 f8 48 80 03 01 00 00 00 …'A.H…
16fdf2730 00 f2 0a 31 01 00 00 00 30 77 6c 73 62 74 77 73 …1…0wlsbtws
APTaskInfoData 是结构体
00000000 struct APTaskInfoData // sizeof=0x2
00000000 {
00000000 __int16 field_0;/////////////////////////”0wlsbtwsl6ua9ao4w0b0vvo2”
00000002 };
对应上面的newApiVer:bool 类型:true或者false
arg7 0x0
以下是frida 主动调用函数代码:
function hook_nativelib()
{
const NSDictionary = ObjC.classes.NSDictionary;
const NSString = ObjC.classes.NSString;
//参数a2对应上面的a3
// 1. 定义 external_info 的值(注意转义特殊字符,保持原字符串格式)
const externalInfoValue = “_input_charset=\“utf-8\”&body=\”\\“extInfo\”:{\“ap_link_token\”:\“EP11bad44220dd0b2d10fc93d0666e38c48_1761914117465\”}}\“”;
// 2. 将键和值转换为 Objective-C 的 NSString 对象(NSDictionary 要求键值为对象类型)
const key = NSString.stringWithString_(“external_info”);
const value = NSString.stringWithString_(externalInfoValue);
// 3. 用 dictionaryWithObject:forKey: 构造单键值对字典(自动为 __NSSingleEntryDictionaryI 类型)
const singleEntryDict = NSDictionary.dictionaryWithObject_forKey_(value, key);
const a2 = singleEntryDict;
//参数a3对应上面的a4
// 1. 构建内层 action 字典(包含 method 和 type 两个键值对)
const methodKey = NSString.stringWithString_(“method”);
const methodValue = NSString.stringWithString_(“main”);
const typeKey = NSString.stringWithString_(“type”);
const typeValue = NSString.stringWithString_(“test”);
// 内层字典有两个键值对,使用多键构造方法
const innerValues = [methodValue, typeValue];
const innerKeys = [methodKey, typeKey];
const actionDict = NSDictionary.dictionaryWithObjects_forKeys_count_(innerValues, innerKeys, innerValues.length);
// 2. 构建外层字典(仅包含 action 一个键值对,类型为 __NSSingleEntryDictionaryI)
const outerKey = NSString.stringWithString_(“action”);
// 单键值对通过 dictionaryWithObject:forKey: 构造,系统会自动返回 __NSSingleEntryDictionaryI 类型
const outerDict = NSDictionary.dictionaryWithObject_forKey_(actionDict, outerKey);
const a3 = outerDict;
//参数a4对应上面的a5
// 1. 分配 8 字节内存(存储 int64_t)
const a4 = Memory.alloc(8); // 64位整数占8字节,直接指定大小更清晰
// 2. 向内存写入 64 位有符号整数(小端序,符合大多数系统架构)
a4.writeS64(0); // 设置 zipType 的值(根据实际需求调整)
参数a5对应上面的a6
// 构造结构体并赋值字符串
const a5 = Memory.alloc(30); // 分配 30 字节内存(对应 var0[30])
// 要赋值的字符串(注意长度不能超过 30 字节,超出部分会被截断)
const str = “0wlsbtwsl6ua9ao4w0b0vvo2”;
// 将字符串写入结构体的 var0 数组(自动处理 null 终止)
Memory.writeUtf8String(a5, str);
//const immediateRead = Memory.readUtf8String(a5);
//console.log(“a5”, immediateRead);
//参数a6对应上面的a7
//const a6 = 0x0;
const a6 = false;
//开始调用
if (ObjC.available) {
// 1. 获取目标类
const APPProcessor = ObjC.classes.APPProcessor;
if (!APPProcessor) {
console.log("未找到 APPProcessor 类");
return;
}
// 2. 创建/获取 APPProcessor 实例(根据实际情况调整,若为单例则用单例方法)
let processorInstance;
try {
// 若支持 alloc + init 初始化
processorInstance = APPProcessor.alloc().init();
// 若为单例(例如 sharedProcessor),则替换为:
// processorInstance = APPProcessor.sharedProcessor();
} catch (err) {
console.log("实例化 APPProcessor 失败:", err.message);
return;
}
if (!processorInstance) {
console.log("未获取到 APPProcessor 实例");
return;
}
if (processorInstance.isKindOfClass\_(ObjC.classes.APPProcessor)) {
console.log("实例有效");
} else {
console.log("实例无效,类型:", processorInstance.$className); // 若为 nil,$className 可能为 null
}
try {
const result = processorInstance.reqDataWithBizDict_actDict_zipType_info_newApiVer\_(a2,a3,a4,a5,a6);///////////////////////////////////////////////////////////////////////////////////////////////////////调用函数
console.log("调用结果:", result);
} catch (err) {
if (err === null) {);///////////////////////////////////////////////////////////////////////////////////////////////////////返回异常
// 极少数情况:异常未被正确转换,直接返回 null(旧版 Frida 可能出现));///////////////////////////////////////////////////////////////////////////////////////////////////////返回异常
console.log("调用失败:底层异常err 为 null");
} else if (typeof err === "object") {
// 处理 JS 原生 Error 或 Objective-C 桥接异常
console.log("错误名称:", err.name || "未知错误");
console.log("错误信息:", err.message || "无详细信息");
if (err.stack) {
console.log("调用栈:", err.stack);
}
} else {
// 其他类型异常(如字符串、数字,极少出现)
console.log("异常:", err);
}
}
}
}
function main()
{
hook_nativelib();
}
setImmediate(main);
调用结果:
frida ios主动调用 结果:实例有效
调用失败:底层异常err 为 null