Arbitrary native code is just fine - all you need to do is catch it when it returns back into the CLR. Native code can't (legally) have access to any managed memory that isn't already pinned. Since you (by you, I mean the CLR) control the call point to native code, you control the return point too - you can patch the instructions after the call if necessary.