sensepost / objection

📱 objection - runtime mobile exploration
GNU General Public License v3.0
7.24k stars 829 forks source link

Unable to set return value on overloaded Android methods #206

Closed aph3rson closed 2 weeks ago

aph3rson commented 5 years ago

Attempting to set the return value of an overloaded method in an Android app, I get a Frida exception.

First, here's the attempt to patch the method without declaring an overloaded method:

> objection --gadget "[snip]" explore --startup-command "android hooking set return_value android.telephony.TelephonyManager.getSimSerialNumber null --dump-args --dump-backtrace --dump-return"

Using USB device `Google Pixel XL`
Agent injected and responds ok!
Running a startup command... android hooking set return_value android.telephony.TelephonyManager.getSimSerialNumber null --dump-args --dump-backtrace --dump-return
(agent) Attempting to modify return value for class android.telephony.TelephonyManager and method getSimSerialNumber.
Traceback (most recent call last):
  File "C:\Python37\Scripts\objection-script.py", line 11, in <module>
    load_entry_point('objection==1.5.2', 'console_scripts', 'objection')()
  File "c:\python37\lib\site-packages\click\core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "c:\python37\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\python37\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python37\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python37\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\python37\lib\site-packages\objection\console\cli.py", line 125, in explore
    r.run_command(command)
  File "c:\python37\lib\site-packages\objection\console\repl.py", line 185, in run_command
    exec_method(arguments)
  File "c:\python37\lib\site-packages\objection\commands\android\hooking.py", line 214, in set_method_return_value
    api.android_hooking_set_method_return(class_name, retval)
  File "c:\python37\lib\site-packages\frida\core.py", line 322, in method
    return script._rpc_request('call', js_name, args)
  File "c:\python37\lib\site-packages\frida\core.py", line 250, in _rpc_request
    raise result[2]
frida.core.RPCException: Error: getSimSerialNumber(): has more than one overload, use .overload(<signature>) to choose from:
        .overload()
        .overload('int')
    at throwOverloadError (frida/node_modules/frida-java/lib/class-factory.js:2233)
    at frida/node_modules/frida-java/lib/class-factory.js:1468
    at /script1.js:5070
    at /script1.js:5155
    at frida/node_modules/frida-java/lib/vm.js:42
    at M (frida/node_modules/frida-java/index.js:347)
    at frida/node_modules/frida-java/index.js:299
    at frida/node_modules/frida-java/lib/vm.js:42
    at frida/node_modules/frida-java/index.js:279
Asking jobs to stop...
Unloading objection agent...

After that, I attempt to declare an overload per the documentation (note that I'm running in Powershell, and a backtick is an escape character):

> objection --gadget "[snip]" explore --startup-command "android hooking set return_value android.telephony.TelephonyManager.getSimSerialNumber() null --dump-args --dump-backtrace --dump-return"

Using USB device `Google Pixel XL`
Agent injected and responds ok!
Running a startup command... android hooking set return_value android.telephony.TelephonyManager.getSimSerialNumber() null --dump-args --dump-backtrace --dump-return
(agent) Attempting to modify return value for class android.telephony.TelephonyManager and method getSimSerialNumber().
Traceback (most recent call last):
  File "C:\Python37\Scripts\objection-script.py", line 11, in <module>
    load_entry_point('objection==1.5.2', 'console_scripts', 'objection')()
  File "c:\python37\lib\site-packages\click\core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "c:\python37\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\python37\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python37\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python37\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\python37\lib\site-packages\objection\console\cli.py", line 125, in explore
    r.run_command(command)
  File "c:\python37\lib\site-packages\objection\console\repl.py", line 185, in run_command
    exec_method(arguments)
  File "c:\python37\lib\site-packages\objection\commands\android\hooking.py", line 214, in set_method_return_value
    api.android_hooking_set_method_return(class_name, retval)
  File "c:\python37\lib\site-packages\frida\core.py", line 322, in method
    return script._rpc_request('call', js_name, args)
  File "c:\python37\lib\site-packages\frida\core.py", line 250, in _rpc_request
    raise result[2]
frida.core.RPCException: TypeError: cannot read property 'argumentTypes' of undefined
    at [anon] (duk_hobject_props.c:2384)
    at /script1.js:5070
    at /script1.js:5155
    at frida/node_modules/frida-java/lib/vm.js:42
    at M (frida/node_modules/frida-java/index.js:347)
    at frida/node_modules/frida-java/index.js:299
    at frida/node_modules/frida-java/lib/vm.js:42
    at frida/node_modules/frida-java/index.js:279
    at /script1.js:5159
    at /script1.js:2107
    at /script1.js:5160
    [...]
Asking jobs to stop...
Unloading objection agent...
aph3rson commented 5 years ago

I did some simple debugging - it looks like single/double quotes are stripped from the args parameter that set_method_return_value ingests. I'd imagine this is being done by the REPL.

aph3rson commented 5 years ago

Coming back around to this - the problem is in the use of shlex.split by get_tokens - before that call, the document has the proper quotes included, but they're no longer present after.

https://github.com/sensepost/objection/blob/0f784eabd4aac12c7cb5f274026a8637a30cae50/objection/utils/helpers.py#L75-L96

aph3rson commented 5 years ago

Adding posix=True to the shlex call keeps the quotes in place. However, it looks like there's a further problem with the splitClassMethod agent method - it's splitting based on the last period in the string to determine a method, whereas overloaded methods will have parentheses to show which overload to use.

https://github.com/sensepost/objection/blob/fa6a8b8f9b68d6be41b51acb512e6d08754a2f1e/agent/src/android/hooking.ts#L12-L20

aph3rson commented 5 years ago

Alright, I've gotten as far as modifying the splitClassMethod to now extract an overload signature if it's passed in to the REPL. However, I'm stuck on mapping the argument types via methodInstance.argumentTypes with the overload - I've tried putting it in an eval() line similar to the following: eval("methodInstance." + overload + ".argumentTypes.map((arg) => arg.className)"), but am getting parse errors for some reason.

leonjza commented 5 years ago

Thanks so much for looking into this and updating the ticket as you go along. You rock! I'll also take a peek at this one asap.

aph3rson commented 5 years ago

I'm relatively sure I've gotten this - I'm doing some testing on my side before I fork and file a PR.

aph3rson commented 5 years ago

PR #239 has been opened which should fix this issue.

pich4ya commented 5 years ago

I faced the identical problem here. Tested on objection 1.6.6.


a.b.c.d on (Android: 8.0.0) [net] # android hooking set return_value a.b.c.XXX true
(agent) Attempting to modify return value for class a.b.c and method XXX.
A Frida agent exception has occurred.
Error: XXX(): has more than one overload, use .overload(<signature>) to choose from:
    .overload()
    .overload()
    at throwOverloadError (frida/node_modules/frida-java/lib/class-factory.js:2159)
    at frida/node_modules/frida-java/lib/class-factory.js:1393
    at /script1.js:5143
    at /script1.js:5232
    at frida/node_modules/frida-java/lib/vm.js:42
    at frida/node_modules/frida-java/index.js:281
    at /script1.js:5236
    at /script1.js:2108
    at /script1.js:5237```
aph3rson commented 5 years ago

The PR I filed hasn't yet been merged - you can try adding my fork as an alternate remote, and rebasing my issue branch onto your fork's master.

leonjza commented 5 years ago

Sorry about the delay in this one. Things are a little hectic at the moment, but I should finally get to it post DEF CON (with a new release).

leonjza commented 4 years ago

Left a comment suggesting an alternative implementation for #239. Once we got that sorted I think we can land it. Thanks so much for the help @aph3rson ! :)

IPMegladon commented 2 weeks ago

Done in 4cfacc46c696f72a08.