In this tutorial we show how to do function tracing on your Android device.
2308 |
2309 |
Setting up your Android device
2310 |
2311 |
Before you start, you will need to root your device in case you haven’t done so
2312 | already. Also note that most of our testing has involved Android 4.4, and while
2313 | we do support 4.2 all the way through 6.0, there’s for now limited support for
2314 | ART and we would recommend that you start out with a Dalvik-powered ARM device
2315 | or emulator for the time being.
2316 |
2317 |
You will also need the adb tool from the Android SDK.
2318 |
2319 |
First off, download the latest frida-server for Android from our releases
2320 | page and get it running on your
2321 | device:
For the last step, make sure you start frida-server as root, i.e. if you are
2329 | doing this on a rooted device, you might need to su and run it from that
2330 | shell.
2331 |
2332 |
Next, make sure adb can see your device:
2333 |
2334 |
$ adb devices -l
2335 |
2336 |
This will also ensure that the adb daemon is running on your desktop, which
2337 | allows Frida to discover and communicate with your device regardless of whether
2338 | you’ve got it hooked up through USB or WiFi.
2339 |
2340 |
A quick smoke-test
2341 |
2342 |
Now, on your desktop it’s time to make sure the basics are working. Run:
2343 |
2344 |
$ frida-ps -U
2345 |
2346 |
This should give you a process list along the lines of:
Now just play around with the Chrome app and you should start seeing open()
2369 | calls flying in:
2370 |
2371 |
1392 ms open()
2372 | 1403 ms open()
2373 | 1420 ms open()
2374 |
2375 |
You can now live-edit the aforementioned JavaScript files as you read
2376 | man open, and start diving deeper and deeper into your Android apps.
2377 |
2378 |
Building your own tools
2379 |
2380 |
While the CLI tools like frida, frida-trace, etc., are definitely
2381 | quite useful, there might be times when you’d like to build your own tools
2382 | harnessing the powerful Frida APIs. For that we would
2383 | recommend reading the chapters on Functions and
2384 | Messages, and anywhere you see frida.attach() just
2385 | substitute that with frida.get_usb_device().attach().
hexdump(target[, options]): generate a hexdump from the provided
2341 | ArrayBuffer or NativePointertarget, optionally with options for
2342 | customizing the output.
0123456789 A B C D E F 0123456789ABCDEF
2358 | 00000000 7f 45 4c 46010101000000000000000000 .ELF............
2359 | 0000001003002800010000000000000034000000 ..(.........4...
2360 | 0000002034 a8 0400000000053400200008002800 4.......4. ...(.
2361 | 00000030 1e 00 1d 00060000003400000034000000 ........4...4...
2362 |
2363 |
2364 |
2365 |
int64(v): short-hand for new Int64(v)
2366 |
2367 |
2368 |
uint64(v): short-hand for new UInt64(v)
2369 |
2370 |
2371 |
ptr(s): short-hand for new NativePointer(s)
2372 |
2373 |
2374 |
NULL: short-hand for ptr("0")
2375 |
2376 |
2377 |
recv([type, ]callback): request callback to be called on the next
2378 | message received from your Frida-based application. Optionally type may
2379 | be specified to only receive a message where the type field is set to
2380 | type.
2381 |
2382 |
This will only give you one message, so you need to call recv() again
2383 | to receive the next one.
2384 |
2385 |
2386 |
send(message[, data]): send the JavaScript object message to your
2387 | Frida-based application (it must be serializable to JSON). If you also have
2388 | some raw binary data that you’d like to send along with it, e.g. you dumped
2389 | some memory using Memory#readByteArray, then you may pass this through the
2390 | optional data argument. This requires it to either be an ArrayBuffer or an
2391 | array of integers between 0 and 255.
2392 |
2393 |
2394 |
2395 |
2396 |
Performance considerations
2397 |
2398 | While send() is asynchronous, the total overhead of sending a single
2399 | message is not optimized for high frequencies, so that means Frida leaves
2400 | it up to you to batch multiple values into a single send()-call,
2401 | based on whether low delay or high throughput is desired.
2402 |
2403 |
2404 |
2405 |
2406 |
2407 |
setTimeout(fn, delay): call fn after delay milliseconds. Returns an
2408 | id that can be passed to clearTimeout to cancel it.
2409 |
2410 |
2411 |
clearTimeout(id): cancel id returned by call to setTimeout
2412 |
2413 |
2414 |
setInterval(fn, delay): call fn every delay milliseconds. Returns an
2415 | id that can be passed to clearInterval to cancel it.
2416 |
2417 |
2418 |
clearInterval(id): cancel id returned by call to setInterval
2419 |
2420 |
2421 |
2422 |
console
2423 |
2424 |
2425 |
2426 |
console.log(line), console.warn(line), console.error(line):
2427 | write line to the console of your Frida-based application. The exact
2428 | behavior depends on where frida-core
2429 | is integrated.
2430 | For example, this output goes to stdout or stderr when using Frida
2431 | through frida-python,
2432 | qDebug when using
2433 | frida-qml, etc.
2434 |
2435 |
Arguments that are ArrayBuffer objects will be substituted by the result of
2436 | hexdump() with default options.
2437 |
2438 |
2439 |
2440 |
rpc
2441 |
2442 |
2443 |
rpc.exports: empty object that you can either replace or insert into to
2444 | expose an RPC-style API to your application. The key specifies the method
2445 | name and the value is your exported function. This function may either
2446 | return a plain value for returning that to the caller immediately, or a
2447 | Promise for returning asynchronously.
In the example above we used script.on('message', on_message) to monitor for any messages from the injected process, JavaScript side. There are other notifications that you can watch for as well on both the script and session. If you want to be notified when the target process exits, use session.on('detached', your_function).
2529 |
2530 |
Frida
2531 |
2532 |
2533 |
Frida.version: property containing the current Frida version
2534 |
2535 |
2536 |
Process
2537 |
2538 |
2539 |
2540 |
Process.arch: property containing the string ia32, x64, arm
2541 | or arm64
2542 |
2543 |
2544 |
Process.platform: property containing the string windows,
2545 | darwin, linux or qnx
2546 |
2547 |
2548 |
Process.pageSize: property containing the size of a virtual memory page
2549 | (in bytes) as a JavaScript number. This is used to make your scripts more
2550 | portable.
2551 |
2552 |
2553 |
Process.pointerSize: property containing the size of a pointer
2554 | (in bytes) as a JavaScript number. This is used to make your scripts more
2555 | portable.
2556 |
2557 |
2558 |
Process.isDebuggerAttached(): returns a boolean indicating whether a
2559 | debugger is currently attached
2560 |
2561 |
2562 |
Process.getCurrentThreadId(): get this thread’s OS-specific id as a
2563 | JavaScript number
2564 |
2565 |
2566 |
Process.enumerateThreads(callbacks): enumerate all threads,
2567 | where callbacks is an object specifying:
2568 |
2569 |
2570 |
onMatch: function (thread): called with thread object containing:
2571 |
2572 |
id: OS-specific id
2573 |
state: string specifying either running, stopped, waiting,
2574 | uninterruptible or halted
2575 |
context: object with the keys pc and sp, which are
2576 | NativePointer objects specifying EIP/RIP/PC and ESP/RSP/SP,
2577 | respectively, for ia32/x64/arm. Other processor-specific keys
2578 | are also available, e.g. eax, rax, r0, x0, etc.
2579 |
2580 |
2581 |
This function may return the string stop to cancel the enumeration
2582 | early.
2583 |
2584 |
onComplete: function (): called when all threads have been enumerated
2585 |
2586 |
2587 |
2588 |
Process.enumerateThreadsSync(): synchronous version of
2589 | enumerateThreads() that returns the threads in an array.
2590 |
2591 |
2592 |
Process.findModuleByAddress(address),
2593 | Process.getModuleByAddress(address),
2594 | Process.findModuleByName(name),
2595 | Process.getModuleByName(name):
2596 | return an object with details about the module whose address or name
2597 | matches the one specified. In the event that no such module could be found,
2598 | the find-prefixed functions return null whilst the get-prefixed
2599 | functions throw an exception. See Process.enumerateModules() for
2600 | details about which fields are included.
2601 |
2602 |
2603 |
Process.enumerateModules(callbacks): enumerate modules loaded right now,
2604 | where callbacks is an object specifying:
2605 |
2606 |
2607 |
onMatch: function (module): called with module object containing:
2608 |
2609 |
name: canonical module name as a string
2610 |
base: base address as a NativePointer
2611 |
size: size in bytes
2612 |
path: full filesystem path as a string
2613 |
2614 |
2615 |
This function may return the string stop to cancel the enumeration
2616 | early.
2617 |
2618 |
onComplete: function (): called when all modules have been enumerated
2619 |
2620 |
2621 |
2622 |
Process.enumerateModulesSync(): synchronous version of
2623 | enumerateModules() that returns the modules in an array.
2624 |
2625 |
2626 |
Process.findRangeByAddress(address), getRangeByAddress(address):
2627 | return an object with details about the range containing address. In the
2628 | event that no such range could be found, findRangeByAddress() returns
2629 | null whilst getRangeByAddress() throws an exception. See
2630 | Process.enumerateRanges() for details about which fields are included.
2631 |
2632 |
2633 |
Process.enumerateRanges(protection|specifier, callbacks): enumerate memory
2634 | ranges satisfying protection given as a string of the form: rwx, where
2635 | rw- means “must be at least readable and writable”. Alternatively you may
2636 | provide a specifier object with a protection key whose value is as
2637 | aforementioned, and a coalesce key set to true if you’d like neighboring
2638 | ranges with the same protection to be coalesced (the default is false;
2639 | i.e. keeping the ranges separate). callbacks is an object specifying:
2640 |
2641 |
2642 |
onMatch: function (range): called with range object containing:
2643 |
2644 |
base: base address as a NativePointer
2645 |
size: size in bytes
2646 |
protection: protection string (see above)
2647 |
2648 |
file: (when available) file mapping details as an object
2649 | containing:
2650 |
2651 |
2652 |
path: full filesystem path as a string
2653 |
offset: offset in bytes
2654 |
2655 |
2656 |
2657 |
2658 |
This function may return the string stop to cancel the enumeration
2659 | early.
2660 |
2661 |
onComplete: function (): called when all memory ranges have been
2662 | enumerated
2663 |
2664 |
2665 |
2666 |
Process.enumerateRangesSync(protection|specifier): synchronous version of
2667 | enumerateRanges() that returns the ranges in an array.
2668 |
2669 |
2670 |
Process.enumerateMallocRanges(callbacks): just like enumerateRanges(),
2671 | but for individual memory allocations known to the system heap.
2672 |
2673 |
2674 |
Process.enumerateMallocRangesSync(protection): synchronous version of
2675 | enumerateMallocRanges() that returns the ranges in an array.
2676 |
2677 |
2678 |
2679 |
Module
2680 |
2681 |
2682 |
2683 |
Module.enumerateImports(name, callbacks): enumerate imports of module with
2684 | the name as seen in Process#enumerateModules. callbacks is an object
2685 | specifying:
2686 |
2687 |
2688 |
onMatch: function (imp): called with imp object containing:
2689 |
2690 |
type: string specifying either function or variable
2691 |
name: import name as a string
2692 |
module: module name as a string
2693 |
address: absolute address as a NativePointer
2694 |
2695 |
2696 |
Only the name field is guaranteed to be present for all imports. The
2697 | platform-specific backend will do its best to resolve the other fields
2698 | even beyond what the native metadata provides, but there is no guarantee
2699 | that it will succeed. This function may return the string stop to
2700 | cancel the enumeration early.
2701 |
2702 |
onComplete: function (): called when all imports have been
2703 | enumerated
2704 |
2705 |
2706 |
2707 |
Module.enumerateImportsSync(name): synchronous version of
2708 | enumerateImports() that returns the imports in an array.
2709 |
2710 |
2711 |
Module.enumerateExports(name, callbacks): enumerate exports of module with
2712 | the name as seen in Process#enumerateModules. callbacks is an object
2713 | specifying:
2714 |
2715 |
2716 |
onMatch: function (exp): called with exp object containing:
2717 |
2718 |
type: string specifying either function or variable
2719 |
name: export name as a string
2720 |
address: absolute address as a NativePointer
2721 |
2722 |
2723 |
This function may return the string stop to cancel the enumeration
2724 | early.
2725 |
2726 |
onComplete: function (): called when all exports have been
2727 | enumerated
2728 |
2729 |
2730 |
2731 |
Module.enumerateExportsSync(name): synchronous version of
2732 | enumerateExports() that returns the exports in an array.
2733 |
2734 |
2735 |
Module.enumerateRanges(name, protection, callbacks): just like
2736 | Process#enumerateRanges, except it’s scoped to the specified module
2737 | name.
2738 |
2739 |
2740 |
Module.enumerateRangesSync(name, protection): synchronous version of
2741 | enumerateRanges() that returns the ranges in an array.
2742 |
2743 |
2744 |
Module.findBaseAddress(name): returns the base address of the name
2745 | module, or null if the module isn’t loaded
2746 |
2747 |
2748 |
Module.findExportByName(module|null, exp): returns the absolute address of
2749 | the export named exp in module. If the module isn’t known you may pass
2750 | null instead of its name, but this can be a costly search and should be
2751 | avoided.
2752 |
2753 |
2754 |
2755 |
Memory
2756 |
2757 |
2758 |
2759 |
Memory.scan(address, size, pattern, callbacks): scan memory for
2760 | occurences of pattern in the memory range given by address and size.
2761 |
2762 |
2763 |
2764 |
pattern must be of the form “13 37 ?? ff” to match 0x13 followed by
2765 | 0x37 followed by any byte followed by 0xff
2766 |
2767 |
2768 |
callbacks is an object with:
2769 |
2770 |
2771 |
2772 |
onMatch: function (address, size): called with address
2773 | containing the address of the occurence as a NativePointer and
2774 | size specifying the size as a JavaScript number.
2775 |
2776 |
This function may return the string stop to cancel the memory
2777 | scanning early.
2778 |
2779 |
2780 |
onError: function (reason): called with reason when there was a
2781 | memory access error while scanning
2782 |
2783 |
2784 |
onComplete: function (): called when the memory range has been
2785 | fully scanned
2786 |
2787 |
2788 |
2789 |
2790 |
2791 |
2792 |
Memory.scanSync(address, size, pattern): synchronous version of scan()
2793 | that returns the matches in an array.
2794 |
2795 |
2796 |
Memory.alloc(size): allocate size bytes of memory on the heap. The
2797 | returned object is a NativePointer and the heap memory will be released
2798 | when all JavaScript handles to it are gone. This means you need to keep
2799 | a reference to it while the pointer is being used by code outside the
2800 | JavaScript runtime.
2801 |
2802 |
2803 |
Memory.copy(dst, src, n): just like memcpy.
2804 |
2805 |
2806 |
Memory.dup(address, size): short-hand for Memory.alloc() followed by
2807 | Memory.copy().
2808 |
2809 |
2810 |
Memory.protect(address, size, protection): update protection on a region
2811 | of memory, where protection is a string of the same format as
2812 | Process.enumerateRanges().
2813 |
2814 |
For example:
2815 |
2816 |
2817 |
2818 |
Memory.protect(ptr("0x1234"),4096,'rw-');
2819 |
2820 |
2821 |
2822 |
Memory.readPointer(address): read a pointer from address and return
2823 | it as a NativePointer.
2824 |
2825 |
A JavaScript exception will be thrown if address isn’t readable.
2826 |
2827 |
2828 |
Memory.writePointer(address, ptr): write ptr to address.
2829 |
2830 |
A JavaScript exception will be thrown if address isn’t writable.
2831 |
2832 |
2833 |
Memory.readS8(address), Memory.readU8(address),
2834 | Memory.readS16(address), Memory.readU16(address),
2835 | Memory.readS32(address), Memory.readU32(address),
2836 | Memory.readShort(address), Memory.readUShort(address),
2837 | Memory.readInt(address), Memory.readUInt(address),
2838 | Memory.readFloat(address), Memory.readDouble(address):
2839 | read a signed or unsigned 8/16/32/etc. or float/double value from
2840 | address and return it as a JavaScript number.
2841 |
2842 |
A JavaScript exception will be thrown if address isn’t readable.
2843 |
2844 |
2845 |
Memory.writeS8(address, value), Memory.writeU8(address, value),
2846 | Memory.writeS16(address, value), Memory.writeU16(address, value),
2847 | Memory.writeS32(address, value), Memory.writeU32(address, value),
2848 | Memory.writeShort(address, value), Memory.writeUShort(address, value),
2849 | Memory.writeInt(address, value), Memory.writeUInt(address, value),
2850 | Memory.writeFloat(address, value), Memory.writeDouble(address, value):
2851 | write the JavaScript number value to the signed or unsigned
2852 | 8/16/32/etc. or float/double value at address.
2853 |
2854 |
A JavaScript exception will be thrown if address isn’t writable.
2855 |
2856 |
2857 |
Memory.readS64(address), Memory.readU64(address),
2858 | Memory.readLong(address), Memory.readULong(address):
2859 | read a signed or unsigned 64-bit, or long-sized, value from address` and
2860 | return it as an Int64/UInt64 object.
2861 |
2862 |
A JavaScript exception will be thrown if address isn’t readable.
2863 |
2864 |
2865 |
Memory.writeS64(address, value), Memory.writeU64(address, value),
2866 | Memory.writeLong(address, value), Memory.writeULong(address, value):
2867 | write the Int64/UInt64 value to the signed or unsigned 64-bit, or
2868 | long-sized, value at address.
2869 |
2870 |
A JavaScript exception will be thrown if address isn’t writable.
2871 |
2872 |
2873 |
Memory.readByteArray(address, length): read length bytes from address
2874 | and return it as an ArrayBuffer. This buffer may be efficiently transferred
2875 | to your Frida-based application by passing it as the second argument to
2876 | send().
2877 |
2878 |
A JavaScript exception will be thrown if any of the length bytes read from
2879 | address isn’t readable.
2880 |
2881 |
2882 |
Memory.writeByteArray(address, bytes): write bytes to address, where
2883 | the former is either an ArrayBuffer, typically returned from
2884 | Memory.readByteArray(), or an array of integers between 0 and 255. For
2885 | example: [ 0x13, 0x37, 0x42 ].
2886 |
2887 |
A JavaScript exception will be thrown if any of the bytes written to
2888 | address isn’t writable.
2889 |
2890 |
2891 |
Memory.readCString(address[, size = -1]),
2892 | Memory.readUtf8String(address[, size = -1]),
2893 | Memory.readUtf16String(address[, length = -1]),
2894 | Memory.readAnsiString(address[, size = -1]):
2895 | read the bytes at address as an ASCII, UTF-8, UTF-16 or ANSI string.
2896 | Supply the optional size argument if you know the size of the string
2897 | in bytes, or omit it or specify -1 if the string is NUL-terminated.
2898 | Likewise you may supply the optional length argument if you know the
2899 | length of the string in characters.
2900 |
2901 |
A JavaScript exception will be thrown if any of the size / length bytes
2902 | read from address isn’t readable.
2903 |
2904 |
Note that readAnsiString() is only available (and relevant) on Windows.
2905 |
2906 |
2907 |
Memory.writeUtf8String(address, str),
2908 | Memory.writeUtf16String(address, str),
2909 | Memory.writeAnsiString(address, str):
2910 | encode and write the JavaScript string to address (with NUL-terminator).
2911 |
2912 |
A JavaScript exception will be thrown if any of the bytes written to
2913 | address isn’t writable.
2914 |
2915 |
Note that writeAnsiString() is only available (and relevant) on Windows.
2916 |
2917 |
2918 |
Memory.allocUtf8String(str),
2919 | Memory.allocUtf16String(str),
2920 | Memory.allocAnsiString(str):
2921 | allocate, encode and write out str as a UTF-8/UTF-16/ANSI string on the
2922 | heap. The returned object is a NativePointer. See Memory#alloc for
2923 | details about its lifetime.
2924 |
2925 |
2926 |
2927 |
MemoryAccessMonitor
2928 |
2929 |
2930 |
MemoryAccessMonitor is only available on Windows for now
2931 |
2932 | We would love to support this on the other platforms too, so if you find
2933 | this useful and would like to help out, please get in touch.
2934 |
2935 |
2936 |
2937 |
2938 |
2939 |
MemoryAccessMonitor.enable(ranges, callbacks): monitor one or more memory
2940 | ranges for access, and notify on the first access of each contained memory
2941 | page. ranges is either a single range object or an array of such objects,
2942 | each of which contains:
2943 |
2944 |
2945 |
base: base address as a NativePointer
2946 |
size: size in bytes
2947 |
2948 |
2949 |
callbacks is an object specifying:
2950 |
2951 |
2952 |
onAccess: function (details): called synchronously with details
2953 | object containing:
2954 |
2955 |
operation: the kind of operation that triggered the access, as a
2956 | string specifying either read, write or execute
2957 |
from: address of instruction performing the access as a
2958 | NativePointer
2959 |
address: address being accessed as a NativePointer
2960 |
rangeIndex: index of the accessed range in the ranges provided to
2961 | MemoryAccessMonitor.enable()
2962 |
pageIndex: index of the accessed memory page inside the specified
2963 | range
2964 |
pagesCompleted: overall number of pages which have been accessed
2965 | so far (and are no longer being monitored)
2966 |
pagesTotal: overall number of pages that were initially monitored
2967 |
2968 |
2969 |
2970 |
2971 |
2972 |
MemoryAccessMonitor.disable(): stop monitoring the remaining memory ranges
2973 | passed to MemoryAccessMonitor.enable()
2974 |
2975 |
2976 |
2977 |
Thread
2978 |
2979 |
2980 |
2981 |
Thread.backtrace([context, backtracer]): generate a backtrace for the
2982 | current thread, returned as an array of NativePointer objects.
2983 |
2984 |
If you call this from Interceptor’s onEnter or onLeave callbacks you
2985 | should provide this.context for the optional context argument, as it
2986 | will give you a more accurate backtrace. Omitting context means the
2987 | backtrace will be generated from the current stack location, which may
2988 | not give you a very good backtrace due to V8’s stack frames.
2989 | The optional backtracer argument specifies the kind of backtracer to use,
2990 | and must be either Backtracer.FUZZY or Backtracer.ACCURATE, where the
2991 | latter is the default if not specified. The accurate kind of backtracers
2992 | rely on debugger-friendly binaries or presence of debug information to do a
2993 | good job, whereas the fuzzy backtracers perform forensics on the stack in
2994 | order to guess the return addresses, which means you will get false
2995 | positives, but it will work on any binary.
Thread.sleep(delay): suspend execution of the current thread for delay
3011 | seconds specified as a JavaScript number. For example 0.05 to sleep for
3012 | 50 ms.
3013 |
3014 |
3015 |
Int64
3016 |
3017 |
3018 |
3019 |
new Int64(v): create a new Int64 from v, which is either a JavaScript
3020 | Number or a string containing a value in decimal, or hexadecimal if prefixed
3021 | with “0x”. You may use the int64(v) short-hand for brevity.
3022 |
3023 |
3024 |
add(rhs), sub(rhs),
3025 | and(rhs), or(rhs),
3026 | xor(rhs):
3027 | make a new Int64 with this Int64 plus/minus/and/or/xor rhs, which may
3028 | either be a JavaScript number or another Int64
3029 |
3030 |
3031 |
shr(n), shl(n):
3032 | make a new Int64 with this Int64 shifted right/left by n bits
3033 |
3034 |
3035 |
compare(rhs): returns an integer comparison result just like
3036 | String#localeCompare()
3037 |
3038 |
3039 |
toNumber(): cast this Int64 to a JavaScript Number
3040 |
3041 |
3042 |
toString([radix = 10]): convert to a string of optional radix (defaults to
3043 | 10)
3044 |
3045 |
3046 |
3047 |
UInt64
3048 |
3049 |
3050 |
3051 |
new UInt64(v): create a new UInt64 from v, which is either a JavaScript
3052 | Number or a string containing a value in decimal, or hexadecimal if prefixed
3053 | with “0x”. You may use the uint64(v) short-hand for brevity.
3054 |
3055 |
3056 |
add(rhs), sub(rhs),
3057 | and(rhs), or(rhs),
3058 | xor(rhs):
3059 | make a new UInt64 with this UInt64 plus/minus/and/or/xor rhs, which may
3060 | either be a JavaScript number or another UInt64
3061 |
3062 |
3063 |
shr(n), shl(n):
3064 | make a new UInt64 with this UInt64 shifted right/left by n bits
3065 |
3066 |
3067 |
compare(rhs): returns an integer comparison result just like
3068 | String#localeCompare()
3069 |
3070 |
3071 |
toNumber(): cast this UInt64 to a JavaScript Number
3072 |
3073 |
3074 |
toString([radix = 10]): convert to a string of optional radix (defaults to
3075 | 10)
3076 |
3077 |
3078 |
3079 |
NativePointer
3080 |
3081 |
3082 |
3083 |
new NativePointer(s): create a new NativePointer from the string s
3084 | containing a memory address in either decimal, or hexadecimal if prefixed
3085 | with “0x”. You may use the ptr(s) short-hand for brevity.
3086 |
3087 |
3088 |
isNull(): returns a boolean allowing you to conveniently check if a
3089 | pointer is NULL
3090 |
3091 |
3092 |
add(rhs), sub(rhs),
3093 | and(rhs), or(rhs),
3094 | xor(rhs):
3095 | make a new NativePointer with this NativePointer plus/minus/and/or/xor
3096 | rhs, which may either be a JavaScript number or another NativePointer
3097 |
3098 |
3099 |
shr(n), shl(n):
3100 | make a new NativePointer with this NativePointer shifted right/left by n
3101 | bits
3102 |
3103 |
3104 |
equals(rhs): returns a boolean indicating whether rhs is equal to
3105 | this one; i.e. it has the same pointer value
3106 |
3107 |
3108 |
compare(rhs): returns an integer comparison result just like
3109 | String#localeCompare()
3110 |
3111 |
3112 |
toInt32(): cast this NativePointer to a signed 32-bit integer
3113 |
3114 |
3115 |
toString([radix = 16]): convert to a string of optional radix (defaults to
3116 | 16)
3117 |
3118 |
3119 |
toMatchPattern(): returns a string containing a Memory.scan()-compatible
3120 | match pattern for this pointer’s raw value
3121 |
3122 |
3123 |
3124 |
NativeFunction
3125 |
3126 |
3127 |
3128 |
new NativeFunction(address, returnType, argTypes[, abi]): create a new
3129 | NativeFunction to call the function at address (specified with a
3130 | NativePointer), where returnType specifies the return type, and the
3131 | argTypes array specifies the argument types. You may optionally also
3132 | specify abi if not system default. For variadic functions, add a '...'
3133 | entry to argTypes between the fixed arguments and the variadic ones.
3134 |
3135 |
Structs & Classes by Value
3136 |
3137 |
As for structs or classes passed by value, instead of a string provide an
3138 | array containing the struct’s field types following each other. You may nest
3139 | these as deep as desired for representing structs inside structs. Note that
3140 | the returned object is also a NativePointer, and can thus be passed to
3141 | Interceptor#attach.
3142 |
3143 |
This must match the struct/class exactly, so if you have a struct with three
3144 | ints, you must pass ['int', 'int', 'int'].
3145 |
3146 |
For a class that has virtual methods, the first parameter will be a pointer
3147 | to the vtable.
3148 |
3149 |
For C++ scenarios involving a return value that is larger than
3150 | Process.pointerSize, a NativePointer to preallocated space must be passed
3151 | in as the first parameter. (This scenario is common in WebKit, for example.)
new NativeCallback(func, returnType, argTypes[, abi]): create a new
3210 | NativeCallback implemented by the JavaScript function func, where
3211 | returnType specifies the return type, and the argTypes array specifies
3212 | the argument types. You may also specify the abi if not system default.
3213 | See NativeFunction for details about supported types and abis.
3214 | Note that the returned object is also a NativePointer, and can thus be
3215 | passed to Interceptor#replace.
3216 |
3217 |
3218 |
Socket
3219 |
3220 |
3221 |
3222 |
Socket.type(handle): inspect the OS socket handle and return its type
3223 | as a string which is either tcp, udp, tcp6, udp6, unix:stream,
3224 | unix:dgram, or null if invalid or unknown.
3225 |
3226 |
3227 |
Socket.localAddress(handle),
3228 | Socket.peerAddress(handle):
3229 | inspect the OS socket handle and return its local or peer address, or
3230 | null if invalid or unknown.
3231 |
3232 |
The object returned has the fields:
3233 |
3234 |
3235 |
ip: (IP sockets) IP address as a string.
3236 |
port: (IP sockets) Port number as a JavaScript number.
3237 |
path: (UNIX sockets) UNIX path as a string.
3238 |
3239 |
3240 |
3241 |
3242 |
Stream
3243 |
3244 |
3245 |
3246 |
new UnixInputStream(fd[, options]),
3247 | new UnixOutputStream(fd[, options]),
3248 | new Win32InputStream(handle[, options]),
3249 | new Win32OutputStream(handle[, options]): create a new stream object
3250 | from the file descriptor fd (UNIX) or file HANDLEhandle (Windows).
3251 | You may also supply an options object with autoClose set to true to
3252 | make the stream close the underlying OS resource when the stream is
3253 | released, either through close() or future garbage-collection.
3254 |
3255 |
All methods of the returned object are fully asynchronous and return a
3256 | Promise object.
3257 |
3258 |
3259 |
close(): close the stream, releasing resources related to it. Once the
3260 | stream is closed, all other operations will fail. Closing a stream multiple
3261 | times is allowed and will not result in an error.
3262 |
3263 |
3264 |
InputStream#read(size): read up to size bytes from the stream. The
3265 | returned Promise receives an ArrayBuffer up to size bytes long. End of
3266 | stream is signalled through an empty buffer.
3267 |
3268 |
3269 |
InputStream#readAll(size): keep reading from the stream until exactly
3270 | size bytes have been consumed. The returned Promise receives an
3271 | ArrayBuffer that is exactly size bytes long. Premature error or end of
3272 | stream results in the Promise getting rejected with an error, where the
3273 | Error object has a partialData property containing the incomplete data.
3274 |
3275 |
3276 |
OutputStream#write(data): try to write data to the stream. The data
3277 | value is either an ArrayBuffer or an array of integers between 0 and 255.
3278 | The returned Promise receives a Number specifying how many bytes of
3279 | data were written to the stream.
3280 |
3281 |
3282 |
OutputStream#writeAll(data): keep writing to the stream until all of
3283 | data has been written. The data value is either an ArrayBuffer or an
3284 | array of integers between 0 and 255. Premature error or end of stream
3285 | results in an error, where the Error object has a partialSize property
3286 | specifying how many bytes of data were written to the stream before the
3287 | error occurred.
3288 |
3289 |
3290 |
3291 |
File
3292 |
3293 |
3294 |
3295 |
new File(filePath, mode): open or create the file at filePath with
3296 | the mode string specifying how it should be opened. For example "wb"
3297 | to open the file for writing in binary mode (this is the same format as
3298 | fopen() from the C standard library).
3299 |
3300 |
3301 |
write(data): synchronously write data to the file, where data is
3302 | either a string or a buffer as returned by Memory#readByteArray
3303 |
3304 |
3305 |
flush(): flush any buffered data to the underlying file
3306 |
3307 |
3308 |
close(): close the file. You should call this function when you’re done
3309 | with the file. Any remaining buffered data will automatically be flushed
3310 | before closure.
3311 |
3312 |
3313 |
3314 |
Interceptor
3315 |
3316 |
3317 |
3318 |
Interceptor.attach(target, callbacks): intercept calls to function at
3319 | target. This is a NativePointer specifying the address of the function
3320 | you would like to intercept calls to. Note that on 32-bit ARM this address
3321 | must have its least significant bit set to 0 for ARM functions, and 1 for
3322 | Thumb functions. Frida takes care of this detail for you if you get the
3323 | address from a Frida API (for example Module.findExportByName()).
3324 |
3325 |
The callbacks argument is an object containing one or more of:
3326 |
3327 |
3328 |
3329 |
onEnter: function (args): callback function given one argument
3330 | args that can be used to read or write arguments as an array of
3331 | NativePointer objects.
3332 |
3333 |
3334 |
onLeave: function (retval): callback function given one argument
3335 | retval that is a NativePointer-derived object containing the raw
3336 | return value.
3337 | You may call retval.replace(1337) to replace the return value with
3338 | the integer 1337, or retval.replace(ptr("0x1234")) to replace with
3339 | a pointer.
3340 | Note that this object is recycled across onLeave calls, so do not
3341 | store and use it outside your callback. Make a deep copy if you need
3342 | to store the contained value, e.g.: ptr(retval.toString()).
3343 |
3344 |
3345 |
3346 |
You may also intercept arbitrary instructions by passing a function instead
3347 | of the callbacks object. This function has the same signature as
3348 | onEnter, but the args argument passed to it will only give you sensible
3349 | values if the intercepted instruction is at the beginning of a function or
3350 | at a point where registers/stack have not yet deviated from that point.
3351 |
3352 |
Returns a listener object that you can call detach() on.
3353 |
3354 |
Note that these functions will be invoked with this bound to a
3355 | per-invocation (thread-local) object where you can store arbitrary data,
3356 | which is useful if you want to read an argument in onEnter and act on it
3357 | in onLeave.
Additionally, the object contains some useful properties:
3377 |
3378 |
3379 |
3380 |
returnAddress: return address as a NativePointer
3381 |
3382 |
3383 |
context: object with the keys pc and sp, which are
3384 | NativePointer objects specifying EIP/RIP/PC and ESP/RSP/SP,
3385 | respectively, for ia32/x64/arm. Other processor-specific keys
3386 | are also available, e.g. eax, rax, r0, x0, etc.
3387 | You may also update register values by assigning to these keys.
3388 |
3389 |
3390 |
errno: (UNIX) current errno value (you may replace it)
3391 |
3392 |
3393 |
lastError: (Windows) current OS error value (you may replace it)
3394 |
3395 |
3396 |
threadId: OS thread ID
3397 |
3398 |
3399 |
depth: call depth of relative to other invocations
3400 |
3401 |
3402 |
3403 |
3404 |
3405 |
3406 |
Performance considerations
3407 |
3408 | The callbacks provided have a significant impact on performance. If you only
3409 | need to inspect arguments but do not care about the return value, or the
3410 | other way around, make sure you omit the callback that you don't need; i.e.
3411 | avoid putting your logic in onEnter and leaving onLeave in
3412 | there as an empty callback.
3413 |
3414 |
3415 | On an iPhone 5S the base overhead when providing just onEnter might be
3416 | something like 6 microseconds, and 11 microseconds with both onEnter
3417 | and onLeave provided.
3418 |
3419 |
3420 | Also be careful about intercepting calls to functions that are called a
3421 | bazillion times per second; while send() is asynchronous, the total
3422 | overhead of sending a single message is not optimized for high frequencies,
3423 | so that means Frida leaves it up to you to batch multiple values into a
3424 | single send()-call, based on whether low delay or high throughput
3425 | is desired.
3426 |
3427 |
3428 |
3429 |
3430 |
3431 |
Interceptor.detachAll(): detach all previously attached callbacks.
3432 |
3433 |
3434 |
Interceptor.replace(target, replacement): replace function at target
3435 | with implementation at replacement. This is typically used if you want
3436 | to fully or partially replace an existing function’s implementation. Use
3437 | NativeCallback to implement a replacement in JavaScript. Note that
3438 | replacement will be kept alive until Interceptor#revert is called.
3439 | If you want to chain to the original implementation you can synchronously
3440 | call target through a NativeFunction inside your implementation, which
3441 | will bypass and go directly to the original implementation.
Interceptor.revert(target): revert function at target to the previous
3459 | implementation.
3460 |
3461 |
3462 |
Stalker
3463 |
3464 |
3465 |
3466 |
Stalker.follow([threadId, options]): start stalking threadId (or the
3467 | current thread if omitted), optionally with options for enabling events.
3468 |
3469 |
For example:
3470 |
3471 |
3472 |
3473 |
Stalker.follow(Process.getCurrentThreadId(),{
3474 | events:{
3475 | call:true,// CALL instructions: yes please
3476 | ret:false,// RET instructions: no thanks
3477 | exec:false// all instructions: no thanks
3478 | },
3479 | onReceive:function(events){
3480 | // Called with `events` containing a binary blob which is one or more
3481 | // GumEvent structs. See `gumevent.h` for the format. This is obviously a
3482 | // terrible API that is subject to change once a better trade-off between
3483 | // ease-of-use and performance has been found.
3484 | },
3485 | onCallSummary:function(summary){
3486 | // Called with `summary` being a key-value mapping of call target to number
3487 | // of calls, in the current time window. You would typically implement this
3488 | // instead of `onReceive` for efficiency.
3489 | }
3490 | });
3491 |
3492 |
3493 |
Performance considerations
3494 |
3495 | The callbacks provided have a significant impact on performance. If you only
3496 | need periodic call summaries but do not care about the raw events, or the
3497 | other way around, make sure you omit the callback that you don't need; i.e.
3498 | avoid putting your logic in onCallSummary and leaving
3499 | onReceive in there as an empty callback.
3500 |
3501 |
3502 |
3503 |
3504 |
3505 |
Stalker.unfollow([threadId]): stop stalking threadId (or the current
3506 | thread if omitted).
3507 |
3508 |
3509 |
Stalker.garbageCollect(): free accumulated memory at a safe point after
3510 | Stalker#unfollow. This is needed to avoid race-conditions where the
3511 | thread just unfollowed is executing its last instructions.
3512 |
3513 |
3514 |
Stalker.addCallProbe(address, callback): call callback (see
3515 | Interceptor#attach#onEnter for signature) synchronously when a CALL is
3516 | made to address. Returns an id that can be passed to
3517 | Stalker#removeCallProbe later.
3518 |
3519 |
3520 |
Stalker.removeCallProbe: remove a call probe added by
3521 | Stalker#addCallProbe.
3522 |
3523 |
3524 |
Stalker.trustThreshold: an integer specifying how many times a piece of
3525 | code needs to be executed before it is assumed it can be trusted to not
3526 | mutate.
3527 | Specify -1 for no trust (slow), 0 to trust code from the get-go, and N to
3528 | trust code after it has been executed N times. Defaults to 1.
3529 |
3530 |
3531 |
Stalker.queueCapacity: an integer specifying the capacity of the event
3532 | queue in number of events. Defaults to 16384 events.
3533 |
3534 |
3535 |
Stalker.queueDrainInterval: an integer specifying the time in milliseconds
3536 | between each time the event queue is drained. Defaults to 250 ms, which
3537 | means that the event queue is drained four times per second.
3538 |
3539 |
3540 |
3541 |
ApiResolver
3542 |
3543 |
3544 |
3545 |
new ApiResolver(type): create a new resolver of the given type, allowing
3546 | you to quickly find functions by name, with globs permitted. Precisely which
3547 | resolvers are available depends on the current platform and runtimes loaded
3548 | in the current process. As of the time of writing, the available resolvers
3549 | are:
3550 |
3551 |
3552 |
module: Resolves exported and imported functions of shared libraries
3553 | currently loaded. Always available.
3554 |
objc: Resolves Objective-C methods of classes currently loaded.
3555 | Available on macOS and iOS in processes that have the Objective-C
3556 | runtime loaded. Use ObjC.available to check at runtime, or
3557 | wrap your new ApiResolver('objc') call in a try-catch.
3558 |
3559 |
3560 |
The resolver will load the minimum amount of data required on creation, and
3561 | lazy-load the rest depending on the queries it receives. It is thus
3562 | recommended to use the same instance for a batch of queries, but recreate it
3563 | for future batches to avoid looking at stale data.
3564 |
3565 |
3566 |
enumerateMatches(query, callbacks): perform the resolver-specific query
3567 | string, where callbacks is an object specifying:
3568 |
3569 |
3570 |
3571 |
onMatch: function (match): called for each match, where match is an
3572 | object with name and address keys.
3573 |
3574 |
3575 |
onComplete: function (): called when all matches have been enumerated.
enumerateMatchesSync(query): synchronous version of enumerateMatches()
3615 | that returns the matches in an array.
3616 |
3617 |
3618 |
DebugSymbol
3619 |
3620 |
3621 |
3622 |
DebugSymbol.fromAddress(address), DebugSymbol.fromName(name):
3623 | look up debug information for address/name and return it as an object
3624 | containing:
3625 |
3626 |
3627 |
address: Address that this symbol is for, as a NativePointer.
3628 |
name: Name of the symbol, as a string.
3629 |
moduleName: Module name owning this symbol, as a string.
3630 |
fileName: File name owning this symbol, as a string.
3631 |
lineNumber: Line number in fileName, as a JavaScript number.
3632 |
3633 |
3634 |
You may also call toString() on it, which is very useful when combined
3635 | with Thread.backtrace():
DebugSymbol.getFunctionByName(name): resolves a function name and
3652 | returns its address as a NativePointer. Returns the first if more than
3653 | one function is found. Throws an exception if the name cannot be resolved.
3654 |
3655 |
3656 |
DebugSymbol.findFunctionsNamed(name): resolves a function name and returns
3657 | its addresses as an array of NativePointer objects.
3658 |
3659 |
3660 |
DebugSymbol.findFunctionsMatching(glob): resolves function names matching
3661 | glob and returns their addresses as an array of NativePointer objects.
3662 |
3663 |
3664 |
3665 |
Instruction
3666 |
3667 |
3668 |
3669 |
Instruction.parse(target): parse the instruction at the target address
3670 | in memory, represented by a NativePointer.
3671 | Note that on 32-bit ARM this address must have its least significant bit
3672 | set to 0 for ARM functions, and 1 for Thumb functions. Frida takes care
3673 | of this detail for you if you get the address from a Frida API (for
3674 | example Module.findExportByName()).
3675 |
3676 |
The object returned has the fields:
3677 |
3678 |
3679 |
address: Address (EIP) of this instruction, as a NativePointer.
3680 |
next: Pointer to the next instruction, so you can parse() it.
3681 |
size: Size of this instruction.
3682 |
mnemonic: String representation of instruction mnemonic.
3683 |
opStr: String representation of instruction operands.
3684 |
toString(): Convert to a human-readable string.
3685 |
3686 |
3687 |
3688 |
3689 |
ObjC
3690 |
3691 |
3692 |
3693 |
ObjC.available: a boolean specifying whether the current process has an
3694 | Objective-C runtime loaded. Do not invoke any other ObjC properties or
3695 | methods unless this is the case.
3696 |
3697 |
3698 |
ObjC.api: an object mapping function names to NativeFunction instances
3699 | for direct access to a big portion of the Objective-C runtime API.
3700 |
3701 |
3702 |
ObjC.classes: an object mapping class names to ObjC.Object JavaScript
3703 | bindings for each of the currently registered classes. You can interact with objects by using dot notation and replacing colons with underscores, i.e.: [NSString stringWithString:@"Hello World"] becomes var NSString = ObjC.classes.NSString; NSString.stringWithString_("Hello World");. Note the underscore after the method name. Refer to iOS Examples section for more details.
3704 |
3705 |
3706 |
ObjC.protocols: an object mapping protocol names to ObjC.Protocol
3707 | JavaScript bindings for each of the currently registered protocols.
3708 |
3709 |
3710 |
ObjC.mainQueue: the GCD queue of the main thread
3711 |
3712 |
3713 |
ObjC.schedule(queue, work): schedule the JavaScript function work on
3714 | the GCD queue specified by queue. An NSAutoreleasePool is created just
3715 | before calling work, and cleaned up on return.
new ObjC.Object(handle[, protocol]): create a JavaScript binding given
3727 | the existing object at handle (a NativePointer). You may also specify
3728 | the protocol argument if you’d like to treat handle as an object
3729 | implementing a certain protocol only.
$kind: string specifying either instance, class or meta-class
3745 |
$super: an ObjC.Object instance used for chaining up to super-class
3746 | method implementations
3747 |
$superClass: super-class as an ObjC.Object instance
3748 |
$class: class of this object as an ObjC.Object instance
3749 |
$className: string containing the class name of this object
3750 |
$protocols: object mapping protocol name to ObjC.Protocol instance
3751 | for each of the protocols that this object conforms to
3752 |
$methods: array containing native method names exposed by this object’s
3753 | class and parent classes
3754 |
$ownMethods: array containing native method names exposed by this object’s
3755 | class, not including parent classes
3756 |
$ivars: object mapping each instance variable name to its current
3757 | value, allowing you to read and write each through access and assignment
3758 |
3759 |
3760 |
There is also an equals(other) method for checking whether two instances
3761 | refer to the same underlying object.
3762 |
3763 |
3764 |
3765 |
3766 |
new ObjC.Protocol(handle): create a JavaScript binding given the existing
3767 | protocol at handle (a NativePointer).
3768 |
3769 |
3770 |
new ObjC.Block(target): create a JavaScript binding given the existing
3771 | block at target (a NativePointer), or, to define a new block, target
3772 | should be an object specifying the type signature and JavaScript function to
3773 | call whenever the block is invoked. The function is specified with an
3774 | implementation key, and the signature is specified either through a
3775 | types key, or through the retType and argTypes keys. See
3776 | ObjC.registerClass() for details.
3777 |
3778 |
The most common use-case is hooking an existing block, which for a block
3779 | expecting two arguments would look something like:
ObjC.implement(method, fn): create a JavaScript implementation compatible
3801 | with the signature of method, where the JavaScript function fn is used
3802 | as the implementation. Returns a NativeCallback that you may assign to an
3803 | ObjC method’s implementation property.
ObjC.registerProxy(properties): create a new class designed to act as a
3834 | proxy for a target object, where properties is an object specifying:
3835 |
3836 |
3837 |
protocols: (optional) Array of protocols this class conforms to.
3838 |
methods: (optional) Object specifying methods to implement.
3839 |
events: (optional) Object specifying callbacks for getting notified
3840 | about events. For now there’s just one event:
3841 |
3842 |
forward: function (name): Called with name specifying the
3843 | method name that we’re about to forward a call to. This might be
3844 | where you’d start out with a temporary callback that just logs the
3845 | names to help you decide which methods to override.
ObjC.registerClass(properties): create a new Objective-C class, where
3887 | properties is an object specifying:
3888 |
3889 |
3890 |
name: (optional) String specifying the name of the class; omit this
3891 | if you don’t care about the globally visible name and would like the
3892 | runtime to auto-generate one for you.
3893 |
super: (optional) Super-class, or null to create a new root class;
3894 | omit to inherit from NSObject.
3895 |
protocols: (optional) Array of protocols this class conforms to.
3896 |
methods: (optional) Object specifying methods to implement.
3897 |
3898 |
3899 |
3900 |
3901 |
constMyConnectionDelegateProxy=ObjC.registerClass({
3902 | name:'MyConnectionDelegateProxy',
3903 | super:ObjC.classes.NSObject,
3904 | protocols:[ObjC.protocols.NSURLConnectionDataDelegate],
3905 | methods:{
3906 | '- init':function(){
3907 | constself=this.super.init();
3908 | if(self!==null){
3909 | ObjC.bind(self,{
3910 | foo:1234
3911 | });
3912 | }
3913 | returnself;
3914 | },
3915 | '- dealloc':function(){
3916 | ObjC.unbind(this.self);
3917 | this.super.dealloc();
3918 | },
3919 | '- connection:didReceiveResponse:':function(conn,resp){
3920 | /* this.data.foo === 1234 */
3921 | },
3922 | /*
3923 | * But those previous methods are declared assuming that
3924 | * either the super-class or a protocol we conform to has
3925 | * the same method so we can grab its type information.
3926 | * However, if that's not the case, you would write it
3927 | * like this:
3928 | */
3929 | '- connection:didReceiveResponse:':{
3930 | retType:'void',
3931 | argTypes:['object','object'],
3932 | implementation:function(conn,resp){
3933 | }
3934 | },
3935 | /* Or grab it from an existing class: */
3936 | '- connection:didReceiveResponse:':{
3937 | types:ObjC.classes
3938 | .Foo['- connection:didReceiveResponse:'].types,
3939 | implementation:function(conn,resp){
3940 | }
3941 | },
3942 | /* Or from an existing protocol: */
3943 | '- connection:didReceiveResponse:':{
3944 | types:ObjC.protocols.NSURLConnectionDataDelegate
3945 | .methods['- connection:didReceiveResponse:'].types,
3946 | implementation:function(conn,resp){
3947 | }
3948 | },
3949 | /* Or write the signature by hand if you really want to: */
3950 | '- connection:didReceiveResponse:':{
3951 | types:'v32@0:8@16@24',
3952 | implementation:function(conn,resp){
3953 | }
3954 | }
3955 | }
3956 | });
3957 |
3958 | constproxy=MyConnectionDelegateProxy.alloc().init();
3959 | /* use `proxy`, and later: */
3960 | proxy.release();
3961 |
3962 |
3963 |
3964 |
ObjC.registerProtocol(properties): create a new Objective-C protocol,
3965 | where properties is an object specifying:
3966 |
3967 |
3968 |
name: (optional) String specifying the name of the protocol; omit this
3969 | if you don’t care about the globally visible name and would like the
3970 | runtime to auto-generate one for you.
3971 |
protocols: (optional) Array of protocols this protocol incorporates.
3972 |
methods: (optional) Object specifying methods to declare.
3973 |
3974 |
3975 |
3976 |
3977 |
constMyDataDelegate=ObjC.registerProtocol({
3978 | name:'MyDataDelegate',
3979 | protocols:[ObjC.protocols.NSURLConnectionDataDelegate],
3980 | methods:{
3981 | /* You must specify the signature: */
3982 | '- connection:didStuff:':{
3983 | retType:'void',
3984 | argTypes:['object','object']
3985 | },
3986 | /* Or grab it from a method of an existing class: */
3987 | '- connection:didStuff:':{
3988 | types:ObjC.classes
3989 | .Foo['- connection:didReceiveResponse:'].types
3990 | },
3991 | /* Or from an existing protocol method: */
3992 | '- connection:didStuff:':{
3993 | types:ObjC.protocols.NSURLConnectionDataDelegate
3994 | .methods['- connection:didReceiveResponse:'].types
3995 | },
3996 | /* Or write the signature by hand if you really want to: */
3997 | '- connection:didStuff:':{
3998 | types:'v32@0:8@16@24'
3999 | },
4000 | /* You can also make a method optional (default is required): */
4001 | '- connection:didStuff:':{
4002 | retType:'void',
4003 | argTypes:['object','object'],
4004 | optional:true
4005 | }
4006 | }
4007 | });
4008 |
4009 |
4010 |
4011 |
ObjC.bind(obj, data): bind some JavaScript data to an Objective-C
4012 | instance; see ObjC.registerClass() for an example.
4013 |
4014 |
4015 |
ObjC.unbind(obj): unbind previous associated JavaScript data from an
4016 | Objective-C instance; see ObjC.registerClass() for an example.
4017 |
4018 |
4019 |
ObjC.getBoundData(obj): look up previously bound data from an Objective-C
4020 | object.
4021 |
4022 |
4023 |
ObjC.choose(specifier, callbacks): enumerate live instances of classes
4024 | matching specifier by scanning the heap. specifier is either a class
4025 | selector or an object specifying a class selector and desired options.
4026 | The class selector is an ObjC.Object of a class, e.g.
4027 | ObjC.classes.UIButton.
4028 | When passing an object as the specifier you should provide the class
4029 | field with your class selector, and the subclasses field with a
4030 | boolean indicating whether you’re also interested in subclasses matching the
4031 | given class selector. The default is to also include subclasses.
4032 | The callbacks argument is an object specifying:
4033 |
4034 |
4035 |
4036 |
onMatch: function (instance): called once for each live instance found
4037 | with a ready-to-use instance just as if you would have called
4038 | new ObjC.Object(ptr("0x1234")) knowing that this particular
4039 | Objective-C instance lives at 0x1234.
4040 |
4041 |
This function may return the string stop to cancel the enumeration
4042 | early.
4043 |
4044 |
4045 |
onComplete: function (): called when all instances have been enumerated
4046 |
4047 |
4048 |
4049 |
4050 |
ObjC.chooseSync(specifier): synchronous version of choose() that returns
4051 | the instances in an array.
4052 |
4053 |
4054 |
ObjC.selector(name): convert the JavaScript string name to a selector
4055 |
4056 |
4057 |
ObjC.selectorAsString(sel): convert the selector sel to a JavaScript
4058 | string
4059 |
4060 |
4061 |
4062 |
Java
4063 |
4064 |
4065 |
4066 |
Java.available: a boolean specifying whether the current process has the
4067 | a Java VM loaded, i.e. Dalvik or ART. Do not invoke any other Java
4068 | properties or methods unless this is the case.
4069 |
4070 |
4071 |
Java.enumerateLoadedClasses(callbacks): enumerate classes loaded right
4072 | now, where callbacks is an object specifying:
4073 |
4074 |
4075 |
4076 |
onMatch: function (className): called for each loaded class with
4077 | className that may be passed to use() to get a JavaScript wrapper.
4078 |
4079 |
4080 |
onComplete: function (): called when all classes have been enumerated.
4081 |
4082 |
4083 |
4084 |
4085 |
Java.enumerateLoadedClassesSync(): synchronous version of
4086 | enumerateLoadedClasses() that returns the class names in an array.
4087 |
4088 |
4089 |
Java.perform(fn): ensure that the current thread is attached to the VM
4090 | and call fn. (This isn’t necessary in callbacks from Java.)
Java.use(className): dynamically get a JavaScript wrapper for
4104 | className that you can instantiate objects from by calling $new() on
4105 | it to invoke a constructor. Call $dispose() on an instance to clean it
4106 | up explicitly (or wait for the JavaScript object to get garbage-collected,
4107 | or script to get unloaded). Static and non-static methods are available,
4108 | and you can even replace a method implementation and throw an exception
4109 | from it:
Java.scheduleOnMainThread(fn): run fn on the main thread of the VM.
4123 |
4124 |
4125 |
Java.choose(className, callbacks): enumerate live instances of the
4126 | className class by scanning the Java heap, where callbacks is an
4127 | object specifying:
4128 |
4129 |
4130 |
4131 |
onMatch: function (instance): called once for each live instance found
4132 | with a ready-to-use instance just as if you would have called
4133 | Java.cast() with a raw handle to this particular instance.
4134 |
4135 |
This function may return the string stop to cancel the enumeration
4136 | early.
4137 |
4138 |
4139 |
onComplete: function (): called when all instances have been enumerated
4140 |
4141 |
4142 |
4143 |
4144 |
Java.cast(handle, klass): create a JavaScript wrapper given the existing
4145 | instance at handle of given class klass (as returned from
4146 | Java.use()). Such a wrapper also has a class property for getting a
4147 | wrapper for its class, and a $className property for getting a string
4148 | representation of its class-name.
WeakRef.bind(value, fn): monitor value and call the fn callback as
4160 | soon as value has been garbage-collected, or the script is about to get
4161 | unloaded. Returns an id that you can pass to WeakRef.unbind() for
4162 | explicit cleanup.
4163 |
4164 |
This API is useful if you’re building a language-binding, where you need to
4165 | free native resources when a JS value is no longer needed.
4166 |
4167 |
4168 |
WeakRef.unbind(id): stop monitoring the value passed to
4169 | WeakRef.bind(value, fn), and call the fn callback immediately.