目录
1. 基础
1.1 字符串处理
const NSString = ObjC.classes.NSString
# 创建字符串
var mystr = NSString.stringWithString_("Example");
1.2 根据关键字搜索方法并Hook
var resolver = new ApiResolver('objc');
// enumerateMatches() 中参数为正则表达式,格式为 *[* *]
resolver.enumerateMatches('*[aa* bbb*]',{
onMatch: function(match){
console.log(match['name'] + ":" +match['address']);
var method = match['name'];
var implementation = match['address'];
if (method.indexOf(".cxx_destruct") == -1 ){
try{
Interceptor.attach(ptr(implementation), {
onEnter: function(args){
console.log("======onenter=======");
console.log("[*] Method Name: " + method);
// args[0]指向类本身
// args[1]指向selector
// oc的参数从args[2]开始
console.log("[*] args[2]: " + args[2]);
// 实体化为oc类
var arg2 = new ObjC.Object(args[2]);
console.log(arg2.toString());
},
onLeave: function(retval){
console.log("======onleave=======");
console.log("[*] Method Name: " + method);
console.log("\t[-] retval: " + retval);
}
});
} catch(err){
console.log("[!] Exception: " + err.message);
}
}
},
onComplete: function(){}
});
1.3 直接Hook类方法
var hook = ObjC.classes.DeviceManager['+ isDeviceJailed'];
Interceptor.attach(hook.implementation, {
onEnter: function (args) {
},
onLeave:function(retval){
retval.replace(0x0);
}
});
1.4 OC类常用参数
var cwObj = new ObjC.Object(args[0]);
console.log(`==> classname ${cwObj.$className}`); // 类名
console.log(`==> ownmethods ${cwObj.$ownMethods}`); // 类方法
console.log(`==> methods ${cwObj.$methods}`); // 类方法,包含父类方法
var ivars = cwObj.$ivars; // 类参数
console.log(`==> _movieURL ${ivars.param1}`);
1.5 直接调用OC类方法
类似字符串处理的方式
const UIImage = ObjC.classes.UIImage;
var path = 'path/myphoto.jpg'
var img = UIImage.imageWithContentsOfFile_(path); //UIImage
1.6 查看应用运行目录
这里使用基于frida的一个工具objection
objection -g [AppName] explore
env
2. 进阶
2.1 根据地址Hook方法
先获取当前运行的Module名称, 一般和ipa包的名字时一致的
var modules = Process.enumerateModules();
for(var i=0;i<modules.length;i++){
console.log(`== Name: ${modules[i].name} <${modules[i].base}>`);
}
利用目标函数的相对地址获取绝对地址并hook
/**
* 根据module名字和目标方法的偏移地址获得方法的绝对地址
*/
function get_func_addr(module, offset) {
// 根据名字获取module地址
var base_addr = Module.findBaseAddress(module);
console.log("base_addr: " + base_addr);
console.log(hexdump(ptr(base_addr), {
length: 16,
header: true,
ansi: true
}));
var func_addr = base_addr.add(offset);
if (Process.arch == 'arm')
return func_addr.add(1); //如果是32位地址+1
else
return func_addr;
}
// 获取目标函数的绝对地址
var func_addr = get_func_addr('Myapp', 0x387C04);
console.log('func_addr: ' + func_addr);
Interceptor.attach(ptr(func_addr), {
onEnter: function(args) {
console.log("====onEnter=====");
console.log("arg0: " + args[0]);
console.log(hexdump(ptr(args[0]), {
length: 64,
header: false,
ansi: false
}))
console.log("arg1: " + args[1]);
console.log("arg2: " + args[2]);
},
onLeave: function(retval) {
console.log("====onLeave=====");
console.log("arg0: " + retval);
console.log(hexdump(ptr(retval), {
length: 64,
header: true,
ansi: true
}))
}
});
2.1 Hook Native方法
const resolver = new ApiResolver('module');
resolver.enumerateMatches('exports:*CGGeometry*!*Rect*',{
onMatch: function(match){
console.log(match['name'] + ":" +match['address']);
var method = match['name'];
var implementation = match['address'];
if (method.indexOf(".cxx_destruct") == -1 ){
try{
Interceptor.attach(ptr(implementation), {
onEnter: function(args){
console.log("======onenter=======");
console.log("[*] Method Name: " + method);
console.log(args[0]);
console.log(hexdump(ptr(args[0]), {
length: 64,
header: true,
ansi: true
}))
},
onLeave: function(retval){
console.log("======onleave=======");
console.log("[*] Method Name: " + method);
console.log("\t[-] retval: " + retval);
}
});
} catch(err){
console.log("[!] Exception: " + err.message);
}
}
},
onComplete: function(){}
});
2.3 向内存中写入数据
var array = [0xaa, 0x12, 0x22];
// 直接写数据可能存在权限问题,先修改内存权限
Memory.protect(targetAddr, array.length, 'rw-');
// 写入数据
Memory.writeByteArray(targetAddr, array);
2.4 直接调用Native方法
/**
* 调用NativeFunction,利用CoreMedia中的方法,从CMSampleBuffer中提取ImageBuffer
*/
const CMSampleBufferGetImageBufferPtr = Module.getExportByName('CoreMedia','CMSampleBufferGetImageBuffer');
const CMSampleBufferGetImageBuffer = new NativeFunction(CMSampleBufferGetImageBufferPtr, 'pointer', ['pointer']);
var cvPixelBufferPtr = CMSampleBufferGetImageBuffer(bufferPtr);
2.5 对Native指针的操作
例如打印模板地址的字符串
// args[1] 目标地址
// args[2]要打印的字符串的长度
new NativePointer(args[1]).readCString(parseInt(args[2]))