Closed Techbrunch closed 4 years ago
I just fixed this in the latest release. The mono_aot_get_method
function was one of the signatures that I removed yesterday. I added it again and used some code from https://github.com/freehuntx/frida-mono-api/pull/6 (thanks to @alxbl) to prevent Fridax from crashing if some of the defined signatures do not exist in the Mono runtime.
By the way, please be aware of the fact that GetTasksAsync
returns a Task instead of a raw value. You will need some extra code to be able to read the results of that task. I think a colleague of mine has some code snippets of this in his notes, feel free to ping me for those notes.
@tijme Bad news but I don't think that this issue is resolved, you actually never removed the mono_aot_get_method
function from the signatures. It is now twice in the list and I'm still getting the same error.
I will debug this when I have the time. I think it could be due to the APK not being compiled AOT, but I'm not sure. It looks like somehow the mono_aot_get_method
method is not exported in your Mono runtime.
I think you need to use mono_compile_method
(source) to JIT-compile the method. This will return a pointer to the native code produced, which you can use to intercept. You can use this script as a reference, since it uses mono_compile_method
and I think it does exactly what you want. I'll try to make an example script when I have the time.
Would you mind sharing the APK that you compiled?
It could very well be that your APK is compiled with an older version of Xamarin/Mono. AOT compilation for Android was introduced in version 5.1 (source, search for AotAssemblies
).
Additionally, AOT compilation is not the default on Android.
Hum then that must be the issue:
AOT Compilation
The AOT Compilation option (on the Packaging Properties page) enables Ahead-of-Time (AOT) compilation of assemblies. When this option is enabled, Just In Time (JIT) startup overhead is minimized by precompiling assemblies before runtime. The resulting native code is included in the APK along with the uncompiled assemblies. This results in shorter application startup time, but at the expense of slightly larger APK sizes.
The AOT Compilation option requires an Enterprise license or higher. AOT compilation is available only when the project is configured for Release mode, and it is disabled by default. For more information about AOT Compilation, see AOT.
Is there another way to hook into functions if AOT Compilation is disabled ?
This is the last APK I compiled (just rename it to .apk):
Is there another way to hook into functions if AOT Compilation is disabled ?
As I stated, I think you need to use mono_compile_method (source) to JIT-compile the method. This will return a pointer to the native code produced, which you can use to intercept. You can use this script as a reference, since it uses mono_compile_method and I think it does exactly what you want.
When I have the time I will take a look and see if I can make an example script for this. Or just a method which allows you to intercept both JIT and AOT compiled methods. 👍
Thanks I'll look into that !
As I stated, I think you need to use mono_compile_method
That's correct.
Just as a heads up, in the code you merged from my PR, I have included a helper method to hook JITTed/unJITTed (non-AOT) methods. Like @tijme said, AOT must be hooked differently.
I'm not sure if you fully merged it or only took the bits that deal with mono runtime image name, but the PR adds MonoApiHelper.Intercept
which behaves like Interceptor
but takes a mono class definition, a method name and hooks. There's no documentation as of right now (we have an upcoming blog on hooking managed methods in Mono, but it's been backlogged since February. Once it's done I'll link it to you if interested.)
The method is at https://github.com/freehuntx/frida-mono-api/pull/6/files#diff-1620eb23fbd98d7f220961acb8cf39b3R98
Hope this can help a bit!
@tijme @alxbl It works like a charm thanks !
My script:
import { MonoApiHelper, MonoApi } from '../vendors/frida-mono-api'
import ClassHelper from '../libraries/class_helper'
// Intercept settings
var className = "CompanyName.ProjectName.Views.Web.Html.HtmlWebView";
// The root AppDomain is the initial domain created by the runtime when it is initialized. Programs execute on this AppDomain.
const domain = MonoApi.mono_get_root_domain()
// Get a reference to a certain class within the Xamarin application.
var classInformation = ClassHelper.getClassByName(className);
console.log('classInformation: ' + classInformation);
MonoApiHelper.Intercept(classInformation, 'GetElement', {
onEnter: function(args) {
console.log("Entered GetElement");
var arg0 = MonoApiHelper.StringToUtf8(args[0]);
console.log('Old arg0: ' + arg0)
var newArg0 = MonoApiHelper.StringNew(url.replace('old', 'new'), domain);
console.log('New arg0: ' + MonoApiHelper.StringToUtf8(newArg0))
args[0] = newArg0;
},
onLeave: function onLeave(log, retval, state) {
console.log("Left GetElement.");
}
})
console.log(`'modify_function_argument.js' attached and ready.`)
FYI: I was also able to patch the APK permanantly using Objection (https://github.com/sensepost/objection/pull/329#issuecomment-609438408)
@alxbl Looking forward to read the blog post, I might write one in the meantime.
I'm glad that it's working for you @Techbrunch. Thanks to @alxbl for writing this method. I've added an example script in the repo that looks like the script above.
https://github.com/NorthwaveNL/fridax/blob/master/examples/jit_modify_class_function_argument.js
@Techbrunch The blog is live now if you're still interested in reading it. It showcases how to bypass certificate pinning in Xamarin using Frida.
The work was done before Fridax released, but I added a reference to fridax at the end since I feel like this project's goal is a superset of what we were trying to achieve.
Cheers!
@alxbl Thanks, for the link. I was wondering how did you go about intercepting the traffic in the first place ? In my case I had to redirect inbound requests by modifying the host file on the phone as suggested by Burp documentation (https://portswigger.net/support/using-burp-suites-invisible-proxy-settings-to-test-a-non-proxy-aware-thick-client-application). I was wondering if you had a better solution ?
So, I replied in PM, but I'll leave the relevant part in this issue in case it can help others.
I setup MITMProxy in transparent mode, and then used USB reverse tunneling (adb reverse
) and iptables to force HTTP/S traffic through the reverse tunnel and through MITMProxy.
The commands:
# On the MITM with rooted Android phone plugged through USB
adb reverse tcp:8080 tcp:8080
# On the Phone (adb shell, su)
iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 127.0.0.1:8080
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 127.0.0.1:8080
By the way, please be aware of the fact that
GetTasksAsync
returns a Task instead of a raw value. You will need some extra code to be able to read the results of that task. I think a colleague of mine has some code snippets of this in his notes, feel free to ping me for those notes.
Hi, any chances to get those code snippets? :)
Hello,
I can't get the
modify_class_function_argument.js
script to work.I'm working with this app: https://github.com/xamarin/xamarin-forms-samples/tree/master/WebServices/TodoREST
I'm trying to intercerpt the
GetTasksAsync
function of theTodoItemManager
:Source for the class: https://github.com/xamarin/xamarin-forms-samples/blob/master/WebServices/TodoREST/TodoREST/Data/TodoItemManager.cs
I'm using this script:
The stacktrace I'm getting: