Is there an elegant way (Objective C or C) for my app (jailbroken iOS) to check whether a specific dynamic library is available or not in iOS, other than checking if the actual dylib file exists at a specific path with an NSFileManager or calling dlopen? (e.g., an object that has info about available dynamic libraries that I can access.)
Update: I know I can also make it a requirement in my project settings (Xcode), but then the app just crashes on startup if the dylib isn't available, without any feedback (if there's a way to catch this and do an alert before crashing, that would be an acceptable solution, too).
If you are using weak linking for your dylib, it should be pretty easy to detect if the library is present by checking for a particular symbol.
Say you have a void foo( void ); function in that library.
You can declare that prototype as extern in your own code, and use the weak_import attribute:
extern void foo( void ) __attribute__( ( weak_import ) );
This way, if the symbol is not found (because its not anymore in the library, or because the whole library is not available), the linker will set the address of the symbol to NULL.
You can then simply and elegantly check for that symbol:
if( foo == NULL )
{
/* Alerts the user */
}
else
{
/* It's safe to use foo() */
}
For further reading: Framework Programming Guide
It's my personal opinion that your approach is off. When installing a jailbroken app, most end-users will install it through Cydia/Installer/Icy, which is a wrapper for APT.
When you do finally push your package up to those stores, you can specify package 'dependencies', which will make it so that your app will not be able to be installed at all, let alone be run, without those packages installed.
It's up to you, however, to determine the package which contains the dylib you wish.
There are only a few edge-case scenarios which could cause a missing dylib once installed from APT, namely deleting the libraries, messing with MobileSubstrate settings, and someone downloading your app outside of APT.
However, in this case, the users shouldn't expect your app to work perfectly, seeing as they have been messing around with developer-type things which they probably shouldn't be.
Related
I've been searching for 2 days to prevent my app from jailbreak device, and I got it, the problem is I still can hook my class use theOS and override the jailbreak check function.
Do you have any proven Idea maybe , framework , library or something else ?
You can use dyld for that.
_dyld_image_count returns a number of dynamic libraries loaded into your application address space. Then you can iterate over them using _dyld_get_image_name checking dynamic library path. That way you can determine whether CydiaSubstrate library or any dynamic library with unknown path been loaded into your application.
Of course with jailbreak even those functions can be hooked and I don't think you can do much about it. Arxan claims it can do something with it but even if it detects something you can always hook any function it uses for detection. CydiaSubstrate tweaks are always one step ahead because they're loaded before main is called. Thus it can hook everything it wants in constructor and you can't do anything about it.
Without jailbreak only way to load malicious library is to modify and resign your app so that it links against the library. Without jailbreak you can't hook C functions so _dyld_get_image_name will be able to detect that library.
I did quite a bit of googling for a definitive answer, but I could not find one.
We have cross-platform sources that need to be used by our iOS apps. I have already packaged them as static framework and got a test app to link successfully against and make a call into it.
The problem I am having is that it makes heavy use of global static constructors.
I am seeing erratic behavior with only a subset of objects getting instantiated but not all.
My questions:
Do static constructors even work within the context of an iOS static
lib?
How would one debug such a problem?
Thanks!
constructors in a static library get called erratically
The use of -all_load and -force_load does not make any difference in invocation of constructor attribute labeled functions
What you need to do is this:
make sure the constructors are global symbols. do this by exporting them via a symbols' file.
consider creating an init function and use the linker setting "initialization routine" to control the order of the instantiation of your global objects..
Do static constructors work within the context of an iOS static lib?
They only start to work once they're linked into an executable, but once that is accomplished they will work.
How do you debug such a problem
There are a few approaches
You have to presume no specific order of the invocation of the constructors.
Make sure the constructors are being linked into the executable (use nm to determine this)
You can try an -Wl,-all_load to get it to load all the components of all archives into the executable (or -Wl,-force_load,libstatic.a to just load for a specific static archive).
I have just finished porting a decent amount of c-sources to the iOS platform and packaged them as a universal static framework. I, then, added the framework (not the project) to a sample iOS app in order to test linkage and proper function. That's when I ran into a humbling problem.
In my attempt to solve the problem described here, I also came across some symbols that are composed through the heavy use of macros (i HATE those). Some of those macros use function attributes that are really extensions of gcc rather than of standard C.
Of course I can always add -std=gnu89, but even then, I am not sure it will resolve the original problem of undefined symbols in the static library.
Not only that, I am now worried that my port to iOS of those sources may not be an accurate port and may result in the type of bugs/issues that maybe related to compiler's codeine and/or optimization policies.
If you can share some of your experience/advice in how best to go about that port, I would really appreciate it.
Thanks!
From manual testing with clang 8.0, it seems that both __attribute__((constructor)) and __attribute__((__constructor__)) work for your purpose.
I've built a static library that I'm my iOS binary is linking in. Code stripping is off, etc. for the static library, and I can see the symbols in the archive (via nm).
So, I link that library into my application as a framework. But, I'm not actually calling that function directly. As a result, I can see the symbols that I'm calling directly in my binary, but not the ones that aren't called. But, since I actually want these symbols to be there at runtime, I'm compiling with -all_load.
But, this seems to place an unnecessary burden on the users of the library. Is there something I can add in the static library that enforces this, rather than relying on the user of the library?
Depending on what you are trying to accomplish, you can precisely control which symbols are dead-stripped and which are always loaded, even if the user of the library doesn't actually use them.
The easiest way is to create a library initialization function that references the exact symbols you don't want dead-stripped. This is precise, and saves you the burden of wrestling with the linker command-line options, which may insulate you from (unlikely) tool behavior changes down the road.
Frameworks have automatic initializers (quite handy) that can be called automatically when the framework is loaded at runtime, right after any static variables are initialized.
__attribute__((constructor))
static void MyModuleInitializer()
{
static BOOL initialized = NO;
if (!initialized) {
// References to symbols that should be kept around.
initialized = YES;
}
}
Just for grins, automatic finalizers are also supported using the __attribute__((destructor)) decorator.
I've tried to formulate the problem in an abstract way, but anyway I give details about the actual libraries in the end.
Dynamic library Addon is statically linked against other library WebRTC which has some code in assembly and this code is linked into WebRTC as object files together with WebRTC's own object files. Lets call this assembly code VP8. Functions of VP8 are marked extern inside WebRTC. Some function Encode() from Addon calls functions of WebRTC which eventually calls functions from VP8.
Now, the application Firefox which is going to load library Addon is quite complex and has its own version (means statically linked) of library WebRTC(let's call it WebRTC2), but an older one.
So, here is a problem: if a call of Encode() is made from the application Firefox, WebRTC functions get called (not WebRTC2, which is correct) BUT when WebRTC tries to call VP8 functions, they get called from the WebRTC2 version (means application's version of WebRTC), but not from WebRTC.
Is there are way to force WebRTC make calls only from local copy of VP8?
Application Firefox is a Firefox browser, WebRTC is a WebRTC library, VP8 is a VP8 codec library (inside WebRTC) and Addon is my Firefox C++ add-on.
UPDATE - DETAILED DESCRIPTION
Here is "unabstract" description of the problem:
So there is a C++ XPCOM add-on which is statically linked against latest version of WebRTC library.
At some point inside add-on a call for encoding a frame is made (method Encode of VP8Encoder class) and it crashes in Firefox all the time, while continue to work well on test programs using gtest framework.
The problem is that at some point inside WebRTC there is VP8 assembly code which is get called for encoding and functions of this assembly code are declared as extern in implementation files. Actually, it crashes on vp8_intra_pred_y_ve_sse2 function.
I've compared three assembly codes of this function: one is from my version of WebRTC (used in add-on), second - where debugger crashed and the third one - from source code of Mozilla's WebRTC.
It turned out that for some weird reason, Mozilla's code get called instead of add-on's WebRTC (they both have same names of course) and as Mozilla's WebRTC code is outdated, it crashes with EXC_BAD_ACCESS.
This probably won't be much help to you, but since no one else has responded, here I go ...
You didn't mention if you're running on Linux, Windows, or something else. My answer is for Linux. I believe Windows loads dynamic libraries differently.
I think what's happening is that you've statically linked against the WebRTC library stub interfaces and those stub interfaces are dynamically linking to the actual implementation, and then getting the first instance of the WebRTC library loaded into firefox instead of the second. Be sure that you're really linking against a statically compiled version of the WebRTC library.
The linux dlopen(3) man page has an interesting flag listed that seems like it would help if your library was the one loading the WebRTC library:
void *dlopen(const char *filename, int flag);
dlopen()
The function dlopen() loads the dynamic library file named by the null-
terminated string filename and returns an opaque "handle" for the
dynamic library. [...]
RTLD_DEEPBIND (since glibc 2.3.4)
Place the lookup scope of the symbols in this library ahead of
the global scope. This means that a self-contained library will
use its own symbols in preference to global symbols with the
same name contained in libraries that have already been loaded.
This flag is not specified in POSIX.1-2001.
Unfortunately, firefox is the one loading your library.
If your library was dynamically linked against WebRTC (which it seems to be) and you explicitly loaded the WebRTC library you want using dl_open() with the RTLD_DEEPBIND flag, than that would solve your problem.
This won't help you much since its not your code that's binding to vp8_intra_pred_y_ve_sse2, but its worth pointing out that gcc also has the dlsym() function which can take a couple of special flags:
void *dlsym(void *handle, const char *symbol);
dlsym()
The function dlsym() takes a "handle" of a dynamic library returned by
dlopen() and the null-terminated symbol name, returning the address
where that symbol is loaded into memory. [...]
There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The
former will find the first occurrence of the desired symbol using the
default library search order. The latter will find the next occurrence
of a function in the search order after the current library. This
allows one to provide a wrapper around a function in another shared
library.
You could use that in your code to at least debug what's going on by having it print out the values it gets for a lookup of vp8_intra_pred_y_ve_sse2.
Finally, the same man page notes that linux has a dlvsm() that takes a version string argument as well, allowing the XPCOM code to specify which version of the function it wants:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
void *dlvsym(void *handle, char *symbol, char *version);
If it were me, and I was forced to dynamically link the stuff, I'd go with the brute force approach. Go into the libraries and change the function names (in both libraries). Its not elegant, and it will be a headache whenever a new version of either library comes out, but its simple and direct.