Cycript allows developers to explore and modify running applications on either iOS or Mac OS X using a hybrid of Objective-C++ and JavaScript syntax through an interactive console that features syntax highlighting and tab completion.
(It also runs standalone on Android and Linux and provides access to Java, but without injection.)
current version: 0.9.594
bash# cycript -p SpringBoard
cy#
cy# [UIApp description]
@"<SpringBoard: 0x10ed05e40>"
cy# [for (x of [1,2,3]) x+1]
[2,3,4]
cy# choose(CALayer)[0]
#"<CALayer: 0x115807910>"
cy# @[0,1] instanceof Array
true
cy# var a = malloc(128)
0x1147c9d00
cy# ({m: 4, b: 5}).<TAB><TAB>
b m
cy# [&](int a)->int{return a}
0x111001000
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.
cy# fopen("/etc/passwd", "r");
(typedef void*)(0x7fff72c14280)
cy# log
[["/var/passwd-fake","r",(typedef void*)(0x7fff72c14280)]]
To learn more, we recommend: