You can do it with MadCodeHook. Use the HookCode
function, give it the address of the function you want to replace and the address of the function you want to be called instead. It will give you back a function pointer that you can use for calling the original and for unhooking afterward. In essence, it implements the middle three steps of Barry's description.
I think MadCodeHook is free for personal use. If you're looking for something freer than that, you can try to find an old version of the Tnt Unicode controls. It used the same hooking technique to inject Unicode support into some of the VCL's code. You'll need an old version because more recent releases aren't free anymore. Find the OverwriteProcedure
function in TntSystem.pas, which is also where you'll find examples of how to use it.
Code-hooking is nice because it doesn't require you to recompile the RTL and VCL, and it doesn't involve conditional compilation to control which functions are in scope. You can hook the code from your unit-test setup procedure, and the original code will never know the difference. It will think it's calling the original FileExists
function (because it is), but when it gets there, it will immediately jump to your mocked version instead.