views:

704

answers:

5

What would be the best way of inserting functionality into a binary application (3d party, closed source).

The target application is on OSX and seems to have been compiled using gcc 3+. I can see the listing of functions implemented in the binary and have debugged and isolated one particular function which I would like to remotely call.

Specifically, I would like to call this function - let's call it void zoomByFactor(x,y) - when I receive certain data from a complex HIDevice.

I can easily modify or inject instructions into the binary file itself (ie. the patching does not need to occur only in RAM).

What would you recommend as a way of "nicely" doing this?

Edit:

I do indeed need to entire application. So I can't ditch it and use a library. (For those who need an ethical explanation: this is a proprietary piece of CAD software whose company website hasn't been updated since 2006. I have paid for this product (quite a lot of money for what it is, really) and have project data which I can not easily migrate away from it. The product suits me just fine as it is, but I want to use a new HID which I recently got. I've examined the internals of the application, and I'm fairly confident that I can call the correct function with the relevant data and get it to work properly).

Here's what I've done so far, and it is quite gheto.

I've already modified parts of the application through this process:

xxd -g 0 binary > binary.hex
cat binary.hex | awk 'substitute work' > modified.hex
xxd -r modified.hex > newbinary
chmod 777 newbinary

I'm doing this kind of jumping through hoops because the binary is almost 100 megs large.

The jist of what I'm thinking is that I'd jmp somewhere in the main application loop, launch a thread, and return to the main function.

Now, the questions are: where can I insert the new code? do I need to modify symbol tables? alternatively, how could I make a dylib load automatically so that the only "hacking" I need to do is inserting a call to a normally loaded dylib into the main function?

A: 

Interesting problem. If I understand you correctly, you'd like to add the ability to remotely call functions in a running executable.

If you don't really need the whole application, you might be able to strip out the main function and turn it into a library file that you can link against. It'll be up to you to figure out how to make sure all the required initialization occurs.

Another approach could be to act like a virus. Inject a function that handles the remote calls, probably in another thread. You'll need to launch this thread by injecting some code into the main function, or wherever else is appropriate. Most likely you'll run into major issues with initialization, thread safety, and/or maintaining proper program state.

The best option, if its available, is to get the vendor of your application to expose a plugin API that lets you do this cleanly and reliably in a supported manner.

If you go with either hack-the-binary route, it'll be time consuming and brittle, but you'll learn a lot in the process.

Mr Fooz
+4  A: 

In MacOS X releases prior to 10.5 you'd do this using an Input Manager extension. Input Manager was intended to handle things like input for non-roman languages, where the extension could popup a window to input the appropriate glyphs and then pass the completed text to the app. The application only needed to make sure it was Unicode-clean, and didn't have to worry about the exact details of every language and region.

Input Manager was wildly abused to patch all sorts of unrelated functionality into applications, and often destabilized the app. It was also becoming an attack vector for trojans, such as "Oompa-Loompa". MacOS 10.5 tightens restrictions on Input Managers: it won't run them in a process owned by root or whell, nor in a process which has modified its uid. Most significantly, 10.5 won't load an Input Manager into a 64 bit process and has indicated that even 32 bit use is unsupported and will be removed in a future release.

So if you can live with the restrictions, an Input Manager can do what you want. Future MacOS releases will almost certainly introduce another (safer, more limited) way to do this, as the functionality really is needed for language input support.

DGentry
Are you meaning that I should pretend to be an input manager so that I can freeload the TextInput system's injection methods? The program is not a Cocoa app, so I'm wondering if I'll even be able to load an InputManager.
That is what I meant. However if the program is not a Cocoa app, you're right that you cannot insert hooks that way. Oh well.
DGentry
+3  A: 

For those interested in what I've ended up doing, here's a summary:

I've looked at several possibilities. They fall into runtime patching, and static binary file patching.

As far as file patching is concerned, I essentially tried two approaches:

  1. modifying the assembly in the code segments (__TEXT) of the binary.

  2. modifying the load commands in the mach header.

The first method requires there to be free space, or methods you can overwrite. It also suffers from extremely poor maintainability. Any new binaries will require hand patching them once again, especially if their source code has even slightly changed.

The second method was to try and add a LC_ LOAD_ DYLIB entry into the mach header. There aren't many mach-o editors out there, so it's hairy, but I actually modified the structures so that my entry was visible by otool -l. However, this didn't actually work as there was a dyld: bad external relocation length at runtime. I'm assuming I need to muck around with import tables etc. And this is way too much effort to get right without an editor.

Second path was to inject code at runtime. There isn't much out there to do this. Even for apps you have control over (ie. a child application you launch). Maybe there's a way to fork() and get the initialization process launched, but I never go that.

There is SIMBL, but this requires your app to be Cocoa because SIMBL will pose as a system wide InputManager and selectively load bundles. I dismissed this because my app was not Cocoa, and besides, I dislike system wide stuff.

Next up was mach_ inject and the mach_star project. There is also a newer project called PlugSuit hosted at google which seems to be nothing more than a thin wrapper around mach_inject.

Mach_inject provides an API to do what the name implies. I did find a problem in the code though. On 10.5.4, the mmap method in the mach_inject.c file requires there to be a MAP_ SHARED or'd with the MAP_READ or else the mmap will fail.

Aside from that, the whole thing actually works as advertised. I ended up using mach_ inject_ bundle to do what I had intended to do with the static addition of a DYLIB to the mach header: namely launching a new thread on module init that does its dirty business.

Anyways, I've made this a wiki. Feel free to add, correct or update information. There's practically no information available on this kind of work on OSX. The more info, the better.

There's info out therehttp://rentzsch.com/papers/overridingMacOSX
Azeem.Butt
A: 

On Windows, this is simple to do, is actually very widely done and is known as DLL/code injection.

There is a commercial SDK for OSX which allows doing this: Application Enhancer (free for non-commercial use).

CyberShadow
+1  A: 

I believe you could also use the DYLD_INSERT_LIBRARIES method.

This post is also related to what you were trying to do;

karlphillip