Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Hooking Functions (Part 2)

DZone's Guide to

Hooking Functions (Part 2)

As this series on hooking functions continues, see a live example of function interposing, which is a good way to inject code into a running process.

· Security Zone ·
Free Resource

Discover how to provide active runtime protection for your web applications from known and unknown vulnerabilities including Remote Code Execution Attacks.

In the first part of this series, we wrote a small library with malloc(.) and free(.) functions that we used to intercept normal memory allocation and management. We went over the compiled library, looked at the new loader sections introduced, and looked over the interposing commands in the disassembly.

Now we're going to write a simple program to see the interposing library in action.

First, you can't interpose functions with system binaries. If you try to interpose, say, /bin/ls or /usr/bin/size, you won't be able to. I expect this has something to do with system integrity protections introduced in new versions of MacOS, though I haven't tried it with SIP off yet (if you do, let me know how it goes). So we'll need to create our own program. This'll suffice:

#include <stdlib.h>

#define MALLOC_SIZE     1337
#define OK              0

int main(void) {
    void* ptr = malloc(MALLOC_SIZE);
    free(ptr);
    return OK;
}


Super simple. All we're doing is allocating some memory, freeing it, and returning. So why the odd value to allocate? Well, as you'll see in the output when you run this, the loader and the runtime allocates a bunch of memory, freeing much of that memory, prior to main(.) even being called.

So, let's run this mess and hook memory allocation. Let's compile everything, run it, and examine the output:

$ clang -dynamiclib -o libInterposeMalloc.dylib interpose_malloc.c
$ clang -o simple_main simple_main.c
$ DYLD_INSERT_LIBRARIES=./libInterposeMalloc.dylib ./simple_main 2>interpose_out.txt
$ less interpose_out.txt
simple_main(55286,0x7fff7a12d000) malloc: [+] 0x7fcef0c00020 8
simple_main(55286,0x7fff7a12d000) malloc: [+] 0x7fcef0c00030 16
simple_main(55286,0x7fff7a12d000) malloc: [-] 0x7fcef0c00020
simple_main(55286,0x7fff7a12d000) malloc: [+] 0x7fcef0c000a0 32
simple_main(55286,0x7fff7a12d000) malloc: [-] 0x7fcef0c000c0
...
simple_main(55286,0x7fff7a12d000) malloc: [+] 0x7fcef0c00020 14
simple_main(55286,0x7fff7a12d000) malloc: [-] 0x7fcef0c011b0
simple_main(55286,0x7fff7a12d000) malloc: [+] 0x7fcef2002000 1337
simple_main(55286,0x7fff7a12d000) malloc: [-] 0x7fcef2002000
(END)


And there it is, at the very end — you can see the memory allocation and free that we created in our program — an allocation of 1337 bytes, at 0x7fcef2002000, followed by an immedate free at the same address. Take a look at all the memory allocated prior to main even being called — there's an impressive amount of work that goes on prior to your function even being executed.

Now this seems like a pretty straightforward way to inject code into a running process. It is, and it's been used in past jailbreaks as well. This is in some ways a similar approach to DLL side-loading or hijacking, except we're only hijacking specific functions in a library. Other library hijacking methods require similar filesystem access, in that you're dropping libraries on the system in some way, compiling source code, serializing downloaded binary data, or something like that.

This approach requires similar access — you need to be able to get access to the shell environment to insert an environment variable prior to execution, and you need to download your code to a known location, or, failing that, to a location that you can somehow resolve dynamically at run time. Remember, the download location only needs to be readable by the targeted user; it doesn't need to be in the user home directory. And in many cases, you may not need access to the user's home directory to insert environment variables either, as many systems are configured with system-wide environment definitions.

So that's it! Function interposing in the wild. Enjoy!

Find out how Waratek’s award-winning application security platform can improve the security of your new and legacy applications and platforms with no false positives, code changes or slowing your application.

Topics:
function hooking ,macos ,function interposing ,security

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}