The definition of gdb is doable through the related transition stack question - it uses kstat to determine if the process is being debugged. This will determine if the debugger is connected to the process.
There is also a piece of code - Using the SEC_IS_BEING_DEBUGGED_RETURN_NIL macro in an iOS application - this allows you to make a macro that runs a debugger attached to a check in a variety of places in your code (this is C / Objective-C).
As for detecting Cycript, when it runs against a process, it injects dylib into the process to process messages between the cycript command line and the process - the library has a part of the name that resembles cynject . This name is not like any libraries that are present in a typical iOS application. This needs to be detected with a small loop ( C ):
BOOL hasCynject() { int max = _dyld_image_count(); for (int i = 0; i < max; i++) { const char *name = _dyld_get_image_name(i); if (name != NULL) { if (strstr(name, "cynject") == 0) return YES; } } }
Again, give it a better name than would be appropriate, and also confuse the line you are testing.
These are just the approaches that can be taken - unfortunately, they will protect you in some way at runtime, if someone wants to specify an IDA or some other disassembler, then you will not be protected.
The reason that the check for the debugger is implemented as a macro is because you will place the code in different places in the code, and as a result, someone trying to fix it will have to fix the application in a variety of places.
source share