[Xcode Template] MobileSubstrate Dylib Template for Xcode

Discussion in 'iOS Development' started by SkylarEC, Mar 23, 2009.

  1. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,658
    Likes Received:
    126
    Well, if you're anything like me, then you are absolutely sick of compiling MobileSubstrate plugins on your phone. There are reasons, and they all are bothersome. In fact, MobileSubstrate plugins are the last thing I was stuck compiling on my phone.

    So, I fixed that. By adding the SpringBoard headers to the appropriate places on my computer and adding libsubstrate to my build environment. [Of course, I also compiled it on my computer so I could compile and run MS plugins for the simulator]

    Which in itself would have been fine, except for the fact that Xcode doesn't want to compile dylibs for the iPhone. It will actively refuse to if you select "Build a dylib" and change the SDK to any iPhone SDK. Instead, you have to tell Xcode that you're compiling an application and set the dylib flags yourself. Then, take the application you've created, rename the binary, and discard the rest of the .app. Doing all that just was a waste of time.

    So, I put together a little template in xcode that will do most of what I want for me. I won't go on and on, as this is just a template, but it is a fantastic starting point for building a dylib, as templates should be. This will build the dylib and sets your first hook into SpringBoard.

    Unfortunately, you still have to rename the binary and discard the rest of the package (as xcode won't compile any other way). Also, don't forget to run ldid on the resulting dylib.

    Template: http://www.touchrepo.com/SampleCode/XcodeTemplates/MobileSubstrateDylib.zip
    EDIT: place the contents of that zip here:
    Place the contents of that zip in /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Project Templates/Application



    Note, this does require set up. The template assumes that your SpringBoard headers are all in order and are set up and ready to go in the standard header location. If they are not, then take this time to add the SpringBoard headers to /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.0.sdk/usr/include/SpringBoard/ etc, all the way up to the 2.2.1 SDK (for 3.0, class-dump the 3.0 SpringBoard and place those in the 3.0.sdk's include directory). Do the same for all the Simulator SDKs if you wish to also compile MS plugins for the Simulator. The smart coder would use symlinks whenever possible here.

    Next, you will need to get a copy of libsubstrate from off of your phone. Copy that to /Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/ If you have also compiled libsubstrate for yourself (for the simulator), place that in the Simulator's equivalent location.


    Once your headers and libraries are in place, go ahead select a "New Project" in Xcode and compile. You should now have an app. Again, append a dylib to that binary and discard the rest of the app bundle.

    Place the dylib on your phone in /Library/MobileSubstrate/DynamicLibraries, run ldid -S your.dylib, and respring!

    Enjoy!
  2. Cyanidepoison

    Cyanidepoison Active Member

    Joined:
    Jan 18, 2008
    Messages:
    1,098
    Likes Received:
    2
    You sir, win.

    I had quite a system down on Linux for this, but now that I'm using the iPhone SDK, this makes it a lot simpler.
  3. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,658
    Likes Received:
    126
    [After a deleted conversation between me and Gojohnnyboi, I decided to share this script that will convert the app the template builds into a dylib for you. It also will pseudosign your dylib and install it on your phone. I left it out for a few reasons: I don't want to assume that everybody wants to pseudosign their dylib, xcode signs it just fine; I don't want to assume everyone wants to install the dylib onto their phones at the time of build; and people will sometimes want to build dylibs for the Simulator.

    That said, if you want to use the script, just attach it to the build phase in Xcode, and it will run automatically when you build.]



    So just append a script to the built process. Something like this (courtesy of WiFone):

    Code:
    ## NB: change DEVICE_IP to IP of device; make sure it is active on the same local WiFi network (WLAN).
    DEVICE_IP="192.168.1.13"
    
    if [ -f "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/${EXECUTABLE_NAME}" ]
     then
       ## Pseudo-codesign with ldid-osx:
    #	[ if [ -f /usr/bin/ldid ]
    	  ldid -S "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/${EXECUTABLE_NAME}"
    #    fi ]
    
       ## Rename executable so that it has a .dylib extension, and move it to the folder above the .app folder:
    	mv "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/${EXECUTABLE_NAME}" "${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}.dylib"
    
    	## Remove the .app folder
    	rm -Rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app"
    	
    	## Install .dylib on device (NB: check if device's IP address is correct!)
    	## Remove the previous version (if exists):
    	ssh root@$DEVICE_IP rm -f /Library/MobileSubstrate/DynamicLibraries/${EXECUTABLE_NAME}.dylib
    	## Copy new version to device:
    	scp ${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}.dylib root@$DEVICE_IP:/Library/MobileSubstrate/DynamicLibraries/
    #	scp -r "$CONFIGURATION_BUILD_DIR/$EXECUTABLE_NAME.app" root@$DEVICE_IP:/Applications/
    	## Respring device to test new version:
    	ssh root@$DEVICE_IP killall SpringBoard
    
    fi

    [EDIT: The post form here on has been deleted. --Editor]
  4. CuriousG

    CuriousG New Member

    Joined:
    Apr 3, 2009
    Messages:
    6
    Likes Received:
    0
    Nice work...

    Thanks for the great work on the template SkylarEC. I have a couple of (probably very basic) questions.

    Question 1:
    I haven't installed SDK 3.0 yet, but it seems like this was built using XCode with SDK 3.0 installed, which is why I am seeing "Unknown SDK 3.0" in the build configurations. Is that a correct assumption?

    Question 2:
    On my Touch, I have the following files:

    • /usr/lib/libsubstrate.dylib
    • /Library/MobileSubstrate/MobileSubstrate.dylib

    They are different sizes, so I think they must serve different purposes or might be different versions of Substrate that got left on. Any thoughts on that? Which one should I put into /Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/?

    Question 3:
    Finally, if I wanted to build a plug-in for another app, say for example, MobileMail, I would do a class-dump of that app and put the resulting headers into: /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.*.sdk/usr/include/MobileMail/. Is that correct? They require the sub-directory for the app too, correct?

    Sorry for the basic questions, even though I've been a developer for quite a while, the iPhone (and Mac even) is a new platform for me and MobileSubstrate adds a whole new level of complexity to things.

    Thanks!

    - George
  5. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,658
    Likes Received:
    126
    George, thanks. To answer your questions:

    1. I did build this with the 3.0 SDK, which is why it shows up as such. You can just select another firmware build form the menu, and it should build just fine.
    2. MobileSubstrate is what actually plugs your plugin into whichever application. Libsubstrate is the library that contains the functions you use to hook other messages. You will want to copy libsubstrate into your usr/lib area.
    3. Your assumption is correct. You will need to class-dump whichever application you'd like your dylib to be injected into. And yes, you'd set up those headers the same way you've set up the SpringBoard headers.
  6. lolwut?

    lolwut? Banned

    Joined:
    Apr 5, 2009
    Messages:
    73
    Likes Received:
    0
    Device:
    iPod touch
    And how exactly do I get the iPhone 2.1 springboard headers?

    EDIT:
    Ah, don't worry, found your post.
    EDIT2:
    Except that causes my SSH connection to stop, plus I just realised I'm getting class dumps for 2.2, when I'm using the 2.1 SDK...
  7. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,658
    Likes Received:
    126
    The fact that it's killing SSH is unusual. Are you sure you don't have autilock turned on? Also, make sure your device in't unplugged Either of those two scnarios would cause the WiFi to die off.

    If you absolutely can not class dump on your device, then use the class dumps from the Simulator. Those headed are uually just as good (most times, exactly the same).

    Ad far as the class dump of 2.1 v. 2.2 goes, I wouldn't worry too much. Either one will do. Clearly, you will want a separate class dump of 3.0; but that is a whole other matter.
  8. lolwut?

    lolwut? Banned

    Joined:
    Apr 5, 2009
    Messages:
    73
    Likes Received:
    0
    Device:
    iPod touch
    Turns out even though SSH cut out everytime I tried it, it still dumped springboard fine.
    Plus, removing the making a new folder part of the code made it work without cutting out :S

    I put in the dump, but it tells me it can't find UIApplication.h, so I found that on my iPod and add that in, and it gives me a bunch of new errors related to that. Any help?

    EDIT:
    Ok, I tried GJB's tutorial source code, and I get one error, which is "UIControl.h: No such file or directory." but like with the UIApplication error, if I add in UIControl I get 12 errors about it.

    EDIT2:
    I've figured out that the errors are because the SDK is finding one UIControl in UIKit and another in include/Springboard, but I still don't know how to fix the error.

    EDIT3:
    Rargh, I deleted the UIKit.h from the files and added in UIControl to the Springboard folder, but now I can't use AlertView because that's from UIKit, and I can't find the .h file anywhere.

    EDIT4:
    Phew, I finally got it by just including <UIKit/UIAlert.h> instead of all of UIKit.

    EDIT5:
    And then it fails when I try to build under release, great.
    SO MANY EDITS.

    EDIT6:
    Well, I guess it doesn't really matter, building it under debug mode and putting it on my iPod works fine.
  9. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,658
    Likes Received:
    126
    When you class-dump something, the required headers have quotation marks, meaning the compiler will look in the same directory as the current header for the required header. To fix, you will need to go through all the headers that you dumped and replace "SomeHeader.h" with <SomeHeader.h>. Alternativly, just tell the compiler that it is an forward class by simly @class SomeObject (of course, you will still need to remove the reference from the heder). Usually though, you want to avoid the forward class references if you are referring to what your object is a subclass of. Warnings will abound if you don't.
  10. lolwut?

    lolwut? Banned

    Joined:
    Apr 5, 2009
    Messages:
    73
    Likes Received:
    0
    Device:
    iPod touch
    Yeah, I've fixed it, only problem is it will only compile under Debug.

    I'm having trouble with the whole coding side of dylibs...
    I used GJB's code and tried to adapt it to get used to it, so I changed:
    to:

    (and a few other little things)

    but when I put it on my device I tap the status bar and nothing happens.
    Am I doing it wrong? (Sorry for all the questions -.-)

Share This Page