frida / frida-core

Frida core library intended for static linking into bindings
https://frida.re
Other
609 stars 193 forks source link

Tracing Functions #111

Closed JohnWickJM closed 7 years ago

JohnWickJM commented 7 years ago

Could you assist with clarifying the following:

  1. If you are tracing for example the writeToFile method of NSData and you wanted to see the data that is being written how would you achieve that from within frida? Hooking [NSData writeToFile:atomically:] and printing arg[2] prints the name of the file as expected but can you print the data being written? Update: So it would be in arg[0] and I could access like so, correct?:
var wFile = ObjC.classes.NSData["- writeToFile:atomically:"];
Interceptor.attach(wFile.implementation, {
  onEnter: function(args) {
    var data = new ObjC.Object(args[0]);
    Memory.readUtf8String(data.bytes(), data.length());
    console.log("\n[writeToFile plainText:@\"" + data + "\"]");
  }});
  1. Having traced each function call for example with - frida-trace -m "-[NSData writeToFile:atomically:]" -U -f app:
   255 ms  -[NSData writeToFile:0x1246da5f0 atomically:0x1 ]
   268 ms  -[NSData writeToFile:0x12477fae0 atomically:0x1 ]
   289 ms  -[NSData writeToFile:0x1247847f0 atomically:0x1 ]

Can you break on each instance from within frida? I know you can do a backtrace to see who called the method etc...How do you use the values listed above from within frida?

I know you can achieve most of this from within lldb, just wondering what the approach would be from frida..

oleavr commented 7 years ago
  1. Yes, self is in args[0], the selector is in args[1], and actual method arguments (if any) follow from there. Your example would almost work, except:

    • You're not assigning the return value of Memory.readUtf8String() to a variable.
    • Is it safe to assume it's a string? Better use Memory.readByteArray() and use console.log(hexdump(buffer, { ansi: true })); (But if you're building an application/tool you probably don't want to use console.log(), but rather send() structured data to your application. That way you can even batch events to improve performance – see the send() documentation for details.)
  2. You can do this, but frida-trace doesn't support this yet. You can implement your own breakpoints by using a blocking recv(), i.e. send('breakpoint-x'); recv('breakpoing-x-resume', function () {}).wait();. See the Messages tutorial. It's also very easy to eval() code and build your own REPL/introspection. (But if you're interested in contributing this kind of improvements to frida-trace, that would rock! It's still a tiny tool, less than 1000 LOC, and quite barebones in terms of functionality. It was built quickly to showcase what kind of tools can be built on top of Frida.)