Basic Concept

Ok, hooking into SpringBoard is actually very easy. What you do is have SpringBoard open a dynamic library that you create, which calls the initializing function within your dylib(specified when linking). From here you take whatever Class from SpringBoard you wish to override a method from that is in memory, and you "redirect" the method to another that you create. 


YES, this is the EXACT SAME WAY that WinterBoard works, meaning you can do just about anything with and / or to SpringBoard, or any objective-c class in memory for that matter.




So, how do I load it?

Well, saurik, creator of WinterBoard and Cydia, has whipped up a magical piece of code called MobileSubstrate. MobileSubstrate loads any dylibs that you place in /Library/MobileSubstrate/DynamicLibraries, and provides you with a method for redirecting the methods in memory, almost automatically. Note that the way in which i will be using here, requires at least a basic understanding of C.


Setting up your cross-compiler

If you have not already, you will need to build the iPhone Toolchain, as the Apple iPhone SDK doesn't allow (at least not without extensive modification of XCode) you to build dynamic libraries for the iPhone platform. 

Instructions on how to do so are posted here (at least until somebody takes the time to build an automatic toolchain installer):

http://www.saurik.com/id/4


Getting the SpringBoard info.

So you may (and should) be asking yourself, how the hell should I know what classes SpringBoard has, and what their methods are? Well, this knowledge can easily be gained by doing the following, depending on your current operating system.

Mac OS X :

1. Download "class-dump" from the internet.
2. With the iPhone 2.1 SDK final installed on your machine, run this command:

Code:
class-dump -H /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.1.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard
3. Move the "SpringBoard" folder containing the dumped headers to your compiler's default include directory, or the one that you are specifying with the -I argument to your compiler.


Example (Using MobileSubstrate)

You will need to get the header for using substrate as well as the mobilesubstrate dynamic library as well. I've uploaded them and you may download them at the bottom of the thread. Place that in the /usr/lib directory of your compilers sysroot

This example does nothing but override the "launch" method of SBApplicationIcon, so when the user clicks an icon, it does not allow them to open it, it simply shows an alert.


ExampleHookProtocol.h

Code:
/*
 *  ExampleHookProtocol.h
 *  
 *
 *  Created by John on 10/4/08.
 *  Copyright 2008 Gojohnnyboi. All rights reserved.
 *
 */

#import 
#import 
#import 
#import 
#import "substrate.h"

// We import our headers, "SpringBoard" being the dumped headers placed in your include directory.

@protocol ExampleHook

// When we redirect the "launch" method, we will specify this prefix, which
// will allow us to call the original method if desired.
- (void)__OriginalMethodPrefix_launch;

@end
ExampleHookLibrary.h (Our header file)


Code:
/*
 *  ExampleHookLibrary.h
 *  
 *
 *  Created by John on 10/4/08.
 *  Copyright 2008 Gojohnnyboi. All rights reserved.
 *
 */

#import "ExampleHookProtocol.h"

// Our method to override the launch of the icon
static void __$ExampleHook_AppIcon_Launch(SBApplicationIcon *_SBApplicationIcon);

// Our intiialization point that will be called when the dylib is loaded
extern "C" void ExampleHookInitialize();
ExampleHookLibrary.mm (Our main code file, [.mm allows all versions of C])

Code:
/*
 *  ExampleHookLibrary.mm
 *  
 *
 *  Created by John on 10/4/08.
 *  Copyright 2008 Gojohnnyboi. All rights reserved.
 *
 */

#import "ExampleHookLibrary.h"

static void __$ExampleHook_AppIcon_Launch(SBApplicationIcon *_SBApplicationIcon) {
 
 UIAlertView* __launchView = [[UIAlertView alloc] init];
 __launchView.title = @"No way muchacho";
 __launchView.message = @"You can't touch dis!";
 [__launchView addButtonWithTitle:@"Dismiss"];
 [__launchView show];
 
 // If at any point we wanted to have it actually launch we should do:
 // [_SBApplicationIcon __OriginalMethodPrefix_launch];
}

extern "C" void ExampleHookInitialize() {
 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
 // Get the SBApplicationIcon class
 Class _$SBAppIcon = objc_getClass("SBApplicationIcon");
 
 // MSHookMessage is what we use to redirect the methods to our own
 MSHookMessage(_$SBAppIcon, @selector(launch), (IMP) &__$ExampleHook_AppIcon_Launch, "__OriginalMethodPrefix_");
 
 // We just redirected SBApplicationIcon's "launch" to our custom method, and now we are done.
 
 [pool release];
}
Makefile (Very VERY important to this [you can use g++ directly if you know how, but for you who don't i will post this makefile as an example])

Code:
Compiler=arm-apple-darwin9-g++
IP=root@192.168.1.102
Sysroot=/Users/John/Desktop/Toolchain/sys

LDFLAGS= -lobjc \
    -framework Foundation \
    -framework UIKit \
    -framework CoreFoundation \
    -multiply_defined suppress \
    -L$(Sysroot)/usr/lib \
    -F$(Sysroot)/System/Library/Frameworks \
    -F$(Sysroot)/System/Library/PrivateFrameworks \
    -dynamiclib \
    -init _ExampleHookInitialize \
    -Wall \
    -Werror \
    -lsubstrate \
    -lobjc \
    -ObjC++ \
    -fobjc-exceptions \
    -march=armv6 \
    -mcpu=arm1176jzf-s \
    -fobjc-call-cxx-cdtors

CFLAGS= -dynamiclib

Objects= ExampleHookLibrary.o

Target=ExampleHook.dylib

all: $(Target) install

install:
  scp $(Target) $(IP):/var/root
  ssh $(IP) chmod 755 $(Target) 
  ssh $(IP) mv $(Target) /Library/MobileSubstrate/DynamicLibraries
  ssh $(IP) killall SpringBoard

$(Target): $(Objects)
  $(Compiler) $(LDFLAGS) -o $@ $^
  ldid -S $(Target)

%.o: %.mm
  $(Compiler) -c $(CFLAGS) $< -o $@

clean:
  rm -f *.o $(Target)

If you do not have ldid for your compiling platform, i suggest getting it from cydia or via apt itself


Code:
apt-get install ldid -y
Also, make sure that the mobile substrate library (libsubstrate.dylib) is in your sysroot in /usr/lib so that the linking will not fail.

This compiles perfectly, as shown here:


Code:
johns-imac:ExampleHook John$ make
arm-apple-darwin9-g++ -c -dynamiclib ExampleHookLibrary.mm -o ExampleHookLibrary.o
arm-apple-darwin9-g++ -lobjc -framework Foundation -framework UIKit -framework CoreFoundation -framework GraphicsServices -framework CoreGraphics -framework TelephonyUI -multiply_defined suppress -L/Users/John/Desktop/Toolchain/sys/usr/lib -F/Users/John/Desktop/Toolchain/sys/System/Library/Frameworks -F/Users/John/Desktop/Toolchain/sys/System/Library/PrivateFrameworks -dynamiclib -init _ExampleHookInitialize -Wall -Werror -lsubstrate -lobjc -ObjC++ -fobjc-exceptions -march=armv6 -mcpu=arm1176jzf-s -fobjc-call-cxx-cdtors -o ExampleHook.dylib ExampleHookLibrary.o
ldid -S ExampleHook.dylib

And here's a screenshot of what happens when you press the icon.