(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.outgoingXPCMessagesFunctionPointer = void 0;
const systemFunctions_1 = require("./lib/systemFunctions");
exports.outgoingXPCMessagesFunctionPointer = [
    systemFunctions_1.xpcConnectionSendMessage,
    systemFunctions_1.xpcConnectionSendMessageWithReply,
    systemFunctions_1.xpcConnectionSendMessageWithReplySync,
    systemFunctions_1.xpcConnectionSendNotification
];

},{"./lib/systemFunctions":7}],2:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.installHooks = void 0;
const types_1 = require("./lib/types");
const helpers_1 = require("./lib/helpers");
const systemFunctions_1 = require("./lib/systemFunctions");
const formatters_1 = require("./lib/formatters");
const consts_1 = require("./consts");
const parsers_1 = require("./lib/parsers");
/**
 * TODO:
 *  - Add `bplist16` serialization.
 *  - Add option to fetch the process' name in the connection description.
 * 	- Handle peer connections more explicitly; they have no name.
 * 	- Add option to filter services by pid.
 */
function installHooks(os, filter, shouldParse) {
    const pointers = [];
    if (filter.type & types_1.FilterType.Outgoing) {
        pointers.push(...consts_1.outgoingXPCMessagesFunctionPointer);
    }
    if (filter.type & types_1.FilterType.Incoming) {
        pointers.push(systemFunctions_1.xpcConnectionCallEventHandler);
    }
    for (let pointer of pointers) {
        Interceptor.attach(pointer.ptr, {
            onEnter: function (args) {
                _onEnterHandler(pointer.name, args, filter.connectionNamePattern, shouldParse);
            }
        });
    }
}
exports.installHooks = installHooks;
const _onEnterHandler = function (symbol, args, connectionNamePattern, shouldParse) {
    const p_connection = new NativePointer(args[0]);
    const connectionName = systemFunctions_1.xpcConnectionGetName.call(p_connection).readCString();
    if (connectionNamePattern != '*' && !helpers_1.wildcardMatch(connectionName, connectionNamePattern)) {
        return;
    }
    const ts = Date.now(); // Resolution isn't high enough, will have to use a dict of stacks in Python
    /*
     * Send a message to the application as soon as a new function is traced,
     * then collect/parse data (connection & dict objects, etc.) and send them to the app.
     * The app then will output full invocation data in sync, using the timestamp.
    */
    send({
        type: 'agent:trace:symbol',
        message: { timestamp: ts, symbol: symbol }
    });
    let connectionDesc = helpers_1.objcObjectDebugDesc((p_connection));
    // connectionDesc = formatConnectionDescription(connectionDesc);  // This is buggy, fix it later
    const p_message = new NativePointer(args[1]);
    let messageDesc = helpers_1.objcObjectDebugDesc(p_message);
    if (shouldParse) {
        const messageType = helpers_1.objcObjectDebugDesc(systemFunctions_1.xpcGetType.call(p_message));
        if (messageType == 'OS_xpc_dictionary') {
            const parsingResult = parsers_1.parseBPListKeysRecursively(p_message);
            if (parsingResult.length > 0) {
                messageDesc = formatters_1.formatMessageDescription(messageDesc, parsingResult);
            }
        } // Parse `OS_xpc_data` as well?
    }
    send({
        type: 'agent:trace:data',
        message: {
            timestamp: ts,
            data: { conn: connectionDesc, message: messageDesc }
        }
    });
};

},{"./consts":1,"./lib/formatters":4,"./lib/helpers":5,"./lib/parsers":6,"./lib/systemFunctions":7,"./lib/types":8}],3:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const setup_1 = require("./rpc/setup");
rpc.exports = {
    setUp: (os, filter, shouldParse) => setup_1.setUp(os, filter, shouldParse),
};

},{"./rpc/setup":9}],4:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatMessageDescription = exports.formatConnectionDescription = void 0;
function formatConnectionDescription(connectionDesc) {
    var s = connectionDesc;
    s = s.replace(/{ /g, '\n{\n\t')
        .replace(/, /g, ',\n\t')
        .replace(/<connection.*/s, '')
        .replace(/}/g, '\n}');
    return s;
}
exports.formatConnectionDescription = formatConnectionDescription;
function formatMessageDescription(messageDesc, parsingResult) {
    var s = messageDesc;
    for (let result of parsingResult) {
        s = s.replace(new RegExp(`(${result.key}.*\n)`), `$1Parsed ${result.format} data for key '${result.key}': \n${result.data}\n`);
    }
    return s;
}
exports.formatMessageDescription = formatMessageDescription;

},{}],5:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isBPListData = exports.objcObjectDebugDesc = exports.wildcardMatch = void 0;
function wildcardMatch(target, pattern) {
    /**
     * Matches a wildcard pattern, .e.g. 'com.apple.*', with `target`.
     */
    pattern = pattern.replace('*', '\.\*');
    pattern = '\^' + pattern;
    let exp = new RegExp(pattern);
    return exp.test(target);
}
exports.wildcardMatch = wildcardMatch;
function objcObjectDebugDesc(ptr) {
    return (new ObjC.Object(ptr)).toString();
}
exports.objcObjectDebugDesc = objcObjectDebugDesc;
function isBPListData(bytesPtr) {
    return bytesPtr.readCString(6) == 'bplist';
}
exports.isBPListData = isBPListData;

},{}],6:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseBPListKeysRecursively = void 0;
const helpers_1 = require("../lib/helpers");
const systemFunctions_1 = require("../lib/systemFunctions");
function parseBPListKeysRecursively(xpcDict) {
    const objType = helpers_1.objcObjectDebugDesc(systemFunctions_1.xpcGetType.call(xpcDict));
    if (objType != 'OS_xpc_dictionary') {
        throw Error("Bad object type " + objType);
    }
    const parsingResult = [];
    /**
     * See: https://developer.apple.com/documentation/xpc/1505404-xpc_dictionary_apply?language=objc
     */
    const block_impl = function (key, value) {
        const valueType = helpers_1.objcObjectDebugDesc(systemFunctions_1.xpcGetType.call(value));
        switch (valueType) {
            case 'OS_xpc_dictionary':
                parsingResult.push(...parseBPListKeysRecursively(value));
                break;
            case 'OS_xpc_data':
                const bytesPtr = systemFunctions_1.xpcDataGetBytesPtr.call(value);
                if (helpers_1.isBPListData(bytesPtr)) {
                    const length = systemFunctions_1.xpcDataGetLength.call(value);
                    const r = parseBPList(bytesPtr, length);
                    r.key = key.readCString();
                    parsingResult.push(r);
                }
                break;
            default:
                break;
        }
        return true;
    };
    const applierBlock = new ObjC.Block({
        implementation: block_impl,
        retType: 'bool',
        argTypes: ['pointer', 'pointer']
    });
    systemFunctions_1.xpcDictionaryApply.call(xpcDict, applierBlock.handle);
    return parsingResult;
}
exports.parseBPListKeysRecursively = parseBPListKeysRecursively;
function parseBPList(bytesPtr, length) {
    /**
     * Parse binary plist data after detecting its format
     */
    const bplistFmt = bytesPtr.readCString(8);
    if (bplistFmt == 'bplist15') {
        return {
            key: null,
            data: helpers_1.objcObjectDebugDesc(systemFunctions_1.__CFBinaryPlistCreate15.call(bytesPtr, length, ptr(0x0))),
            format: 'bplist15'
        };
    }
    else if (bplistFmt == 'bplist00') {
        return parseBPlist00(bytesPtr, length);
    } // Add bplist16 serialization
}
function parseBPlist00(bytesPtr, length) {
    const data = ObjC.classes.NSData.dataWithBytes_length_(bytesPtr, length);
    const format = Memory.alloc(8);
    format.writeU64(0xaaaaaaaa);
    const plist = ObjC.classes.NSPropertyListSerialization.propertyListWithData_options_format_error_(data, 0, format, ptr(0x0));
    return {
        key: null,
        data: helpers_1.objcObjectDebugDesc(plist),
        format: 'bplist00'
    };
}

},{"../lib/helpers":5,"../lib/systemFunctions":7}],7:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.__CFBinaryPlistCreate15 = exports.xpcConnectionCallEventHandler = exports.xpcConnectionSendNotification = exports.xpcConnectionSendMessageWithReplySync = exports.xpcConnectionSendMessageWithReply = exports.xpcConnectionSendMessage = exports.xpcDataGetLength = exports.xpcDataGetBytesPtr = exports.xpcGetType = exports.xpcDictionaryApply = exports.xpcConnectionGetName = void 0;
const libXPCDylib = 'libxpc.dylib';
const p_xpc_connection_get_name = Module.getExportByName(libXPCDylib, 'xpc_connection_get_name');
const p_xpc_dictionary_apply = Module.getExportByName(libXPCDylib, 'xpc_dictionary_apply');
const p_xpc_get_type = Module.getExportByName(libXPCDylib, 'xpc_get_type');
const p_xpc_data_get_bytes_ptr = Module.getExportByName(libXPCDylib, 'xpc_data_get_bytes_ptr');
const p_xpc_data_get_length = Module.getExportByName(libXPCDylib, 'xpc_data_get_length');
const p_xpc_connection_send_message = Module.getExportByName(libXPCDylib, 'xpc_connection_send_message');
const p_xpc_connection_send_message_with_reply = Module.getExportByName(libXPCDylib, 'xpc_connection_send_message_with_reply');
const p_xpc_connection_send_message_with_reply_sync = Module.getExportByName(libXPCDylib, 'xpc_connection_send_message_with_reply_sync');
const p_xpc_connection_send_notification = Module.getExportByName(libXPCDylib, 'xpc_connection_send_notification');
const p__xpc_Connection_call_event_handler = DebugSymbol.fromName('_xpc_connection_call_event_handler').address;
const p___CFBinaryPlistCreate15 = DebugSymbol.fromName('__CFBinaryPlistCreate15').address;
exports.xpcConnectionGetName = {
    name: 'xpc_connection_get_name',
    ptr: p_xpc_connection_get_name,
    call: new NativeFunction(p_xpc_connection_get_name, 'pointer', ['pointer'])
};
exports.xpcDictionaryApply = {
    name: 'xpc_dictionary_apply',
    ptr: p_xpc_dictionary_apply,
    call: new NativeFunction(p_xpc_dictionary_apply, 'pointer', ['pointer', 'pointer'])
};
exports.xpcGetType = {
    name: 'xpc_get_type',
    ptr: p_xpc_get_type,
    call: new NativeFunction(p_xpc_get_type, 'pointer', ['pointer'])
};
exports.xpcDataGetBytesPtr = {
    name: 'xpc_data_get_bytes_ptr',
    ptr: p_xpc_data_get_bytes_ptr,
    call: new NativeFunction(p_xpc_data_get_bytes_ptr, 'pointer', ['pointer'])
};
exports.xpcDataGetLength = {
    name: 'xpc_data_get_length',
    ptr: p_xpc_data_get_length,
    call: new NativeFunction(p_xpc_data_get_length, 'uint32', ['pointer'])
};
exports.xpcConnectionSendMessage = {
    name: 'xpc_connection_send_message',
    ptr: p_xpc_connection_send_message,
    call: new NativeFunction(p_xpc_connection_send_message, 'void', ['pointer', 'pointer'])
};
exports.xpcConnectionSendMessageWithReply = {
    name: 'xpc_connection_send_message_with_reply',
    ptr: p_xpc_connection_send_message_with_reply,
    call: new NativeFunction(p_xpc_connection_send_message_with_reply, 'void', ['pointer', 'pointer', 'pointer', 'pointer'])
};
exports.xpcConnectionSendMessageWithReplySync = {
    name: 'xpc_connection_send_message_with_reply_sync',
    ptr: p_xpc_connection_send_message_with_reply_sync,
    call: new NativeFunction(p_xpc_connection_send_message_with_reply_sync, 'void', ['pointer', 'pointer', 'pointer', 'pointer'])
};
exports.xpcConnectionSendNotification = {
    name: 'xpc_connection_send_notification',
    ptr: p_xpc_connection_send_notification,
    call: new NativeFunction(p_xpc_connection_send_notification, 'void', ['pointer', 'pointer'])
};
exports.xpcConnectionCallEventHandler = {
    name: '_xpc_connection_call_event_handler',
    ptr: p__xpc_Connection_call_event_handler,
    call: new NativeFunction(p__xpc_Connection_call_event_handler, 'void', ['pointer', 'pointer'])
};
exports.__CFBinaryPlistCreate15 = {
    name: '__CFBinaryPlistCreate15',
    ptr: p___CFBinaryPlistCreate15,
    call: new NativeFunction(p___CFBinaryPlistCreate15, 'pointer', ['pointer', 'uint64', 'pointer'])
};

},{}],8:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FilterType = void 0;
var FilterType;
(function (FilterType) {
    FilterType[FilterType["Incoming"] = 1] = "Incoming";
    FilterType[FilterType["Outgoing"] = 2] = "Outgoing";
    FilterType[FilterType["All"] = 3] = "All";
})(FilterType = exports.FilterType || (exports.FilterType = {}));

},{}],9:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setUp = void 0;
const hooking_1 = require("../hooking");
function setUp(os, filter, shouldParse) {
    hooking_1.installHooks(os, filter, shouldParse);
}
exports.setUp = setUp;

},{"../hooking":2}]},{},[3])
//# sourceMappingURL=data:application/json;charset=utf-8;base64, 
