IOS中大多数情况,开发者都会使用OC提供的api函数,CFNetworkCopySystemProxySettings来进行代理检测;
CFNetworkCopySystemProxySettings
检测函数直接会检测这些ip和端口等:
采用直接附加页面进程:
frida -UF -l 通杀代理抓包.js
上通杀脚本:
javascript">var _imports = Process.findModuleByName("XXX").enumerateImports();
var _CFNetworkCopySystemProxySettings = null;
for (var i = 0; i < _imports.length; i++) {
//查找CFNetworkCopySystemProxySettings系统代理函数
if (_imports[i].name.indexOf("CFNetworkCopySystemProxySettings") !== -1) {
console.log(_imports[i].name, _imports[i].address);
_CFNetworkCopySystemProxySettings = _imports[i].address;
}
}
if (_CFNetworkCopySystemProxySettings) {
Interceptor.attach(_CFNetworkCopySystemProxySettings, {
onEnter: function (agrgs) {
}, onLeave: function (retval) {
console.log("retval: ", ObjC.Object(retval));
//将返回值全部nop
retval.replace(0);
}
})
}
NSURL URLWithString:
> frida-trace -U -f 包名 -m "+[NSURL URIWithString:]"
更改url得传入得参数,及堆栈打印,也叫url定位
/*
* Auto-generated by Frida. Please modify to match the signature of +[NSURL URLWithString:].
* This stub is currently auto-generated from manpages when available.
*
* For full API reference, see: https://frida.re/docs/javascript-api/
*/
{
/**
* Called synchronously when about to call +[NSURL URLWithString:].
*
* @this {object} - Object allowing you to store state for use in onLeave.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {array} args - Function arguments represented as an array of NativePointer objects.
* For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8.
* It is also possible to modify arguments by assigning a NativePointer object to an element of this array.
* @param {object} state - Object allowing you to keep state across function calls.
* Only one JavaScript function will execute at a time, so do not worry about race-conditions.
* However, do not use this to store function arguments across onEnter/onLeave, but instead
* use "this" which is an object for keeping state local to an invocation.
*/
onEnter(log, args, state) {
console.log('CCCryptorCreate called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
log(`+[NSURL URLWithString:]` + ObjC.Object(args[2]));
},
/**
* Called synchronously when about to return from +[NSURL URLWithString:].
*
* See onEnter for details.
*
* @this {object} - Object allowing you to access state stored in onEnter.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {NativePointer} retval - Return value represented as a NativePointer object.
* @param {object} state - Object allowing you to keep state across function calls.
*/
onLeave(log, retval, state) {
}
}
双向证书:
资源路径操作,可以入手关键函数;
> frida-trace -UF -m "-[NSBundle pathForResource*]"
javascript">/*
* Auto-generated by Frida. Please modify to match the signature of -[NSBundle pathForResource:ofType:].
* This stub is currently auto-generated from manpages when available.
*
* For full API reference, see: https://frida.re/docs/javascript-api/
*/
{
/**
* Called synchronously when about to call -[NSBundle pathForResource:ofType:].
*
* @this {object} - Object allowing you to store state for use in onLeave.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {array} args - Function arguments represented as an array of NativePointer objects.
* For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8.
* It is also possible to modify arguments by assigning a NativePointer object to an element of this array.
* @param {object} state - Object allowing you to keep state across function calls.
* Only one JavaScript function will execute at a time, so do not worry about race-conditions.
* However, do not use this to store function arguments across onEnter/onLeave, but instead
* use "this" which is an object for keeping state local to an invocation.
*/
onEnter(log, args, state) {
console.log('NSBundle pathForResource called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
log(`-[NSBundle pathForResource:${ObjC.Object(args[2])} ofType:${ObjC.Object(args[3])}]`);
},
/**
* Called synchronously when about to return from -[NSBundle pathForResource:ofType:].
*
* See onEnter for details.
*
* @this {object} - Object allowing you to access state stored in onEnter.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {NativePointer} retval - Return value represented as a NativePointer object.
* @param {object} state - Object allowing you to keep state across function calls.
*/
onLeave(log, retval, state) {
}
}
HOOK抓包
基于底层ssl库来实现:
javascript">//请求
var ssl_write = Module.findExportByName("libboringssl.dylib", "SSL_write");
console.log("ssl_write", ssl_write); //ssl input len
Interceptor.attach(ssl_write, {
onEnter: function (args) {
console.log("=================================================");
console.log("CurrentThreadId: ", Process.getCurrentThreadId(), ", ssl_write onEnter args[1]: ", hexdump(args[1], {length: args[2].toInt32()}));
}, onLeave: function (retval) {
}
});
//返回响应
var ssl_read = Module.findExportByName("libboringssl.dylib", "SSL_read");
console.log("ssl_read", ssl_read); //ssl output len
Interceptor.attach(ssl_read, {
onEnter: function (args) {
this.args1 = args[1];
this.args2 = args[2];
}, onLeave: function (retval) {
console.log("=================================================");
console.log("CurrentThreadId: ", Process.getCurrentThreadId(), ", ssl_read onLeave args[1]: ",
this.args1.readByteArray(this.args2.toInt32())
);
}
});
r0Capture 肉师傅的安卓应用层抓包通杀脚本
这个在之前安卓也说过,ios和安卓都通用的;
详见:https://codeooo.blog.csdn.net/article/details/127123371
javascript">function initializeGlobals() {
var resolver = new ApiResolver("module");
var exps = [
[Process.platform == "darwin" ? "*libboringssl*" : "*libssl*", ["SSL_read", "SSL_write", "SSL_get_fd", "SSL_get_session", "SSL_SESSION_get_id"]], // for ios and Android
[Process.platform == "darwin" ? "*libsystem*" : "*libc*", ["getpeername", "getsockname", "ntohs", "ntohl"]]
];
源码里三目运算符,也说明了,ios用 libboringssl 动态库 , 安卓 libssl库;
同时还hook了,”SSL_read", “SSL_write” ,等等~
javascript">Interceptor.attach(addresses["SSL_read"],
{
onEnter: function (args) {
var message = getPortsAndAddresses(SSL_get_fd(args[0]), true);
message["ssl_session_id"] = getSslSessionId(args[0]);
message["function"] = "SSL_read";
message["stack"] = SSLstackread;
this.message = message;
this.buf = args[1];
},
onLeave: function (retval) {
retval |= 0; // Cast retval to 32-bit integer.
if (retval <= 0) {
return;
}
send(this.message, Memory.readByteArray(this.buf, retval));
}
});
Interceptor.attach(addresses["SSL_write"],
{
onEnter: function (args) {
var message = getPortsAndAddresses(SSL_get_fd(args[0]), false);
message["ssl_session_id"] = getSslSessionId(args[0]);
message["function"] = "SSL_write";
message["stack"] = SSLstackwrite;
send(message, Memory.readByteArray(args[1], parseInt(args[2])));
},
onLeave: function (retval) {
}
});