Example

Say we have a program that opens /etc/passwd to check our password. We would prefer that it uses /var/passwd-fake. First, we need the address of fopen.

cy# fopen = dlsym(RTLD_DEFAULT, "fopen") (typedef void*)(0x7fff900c34ec)

We can't work with this function without a type signature, though, so let's cast it to a Functor. With Cycript we can use high-level C typedef syntax.

cy# fopen = (typedef void *(char *, char *))(fopen) (extern "C" void *fopen(char *, char *))

Next, let's @import Substrate, so we can use MS.hookFunction to modify fopen: we will swap in our fake passwd file, as well as log all the arguments.

cy# @import com.saurik.substrate.MS cy# var oldf = {} cy# var log = [] cy# MS.hookFunction(fopen, function(path, mode) { if (path == "/etc/passwd") path = "/var/passwd-fake"; var file = (*oldf)(path, mode); log.push([path.toString(), mode.toString(), file]); return file; }, oldf)

In addition to our nefarious modification, this let's us see all of the calls to fopen, as well as track what the returned FILE * values were. Let's try it out.