3

I am writing a hook which logs all darwin notifications in the system. I hook into below functions:

CFNotificationCenterPostNotification
CFNotificationCenterPostNotificationWithOptions
NSNotificationCenter::postNotification
NSNotificationCenter::postNotificationName

I see lot of logs. Example when I unlock the screen it shows me SBDeviceLockStateChangedNotification.

But I am expecting events like - "com.apple.springboard.lockcomplete" or other events like here

Not sure why I am not able to capture darwin-like notifications. Any help appreciated. Here's the code for review

#include <notify.h>
#include <substrate.h>
#include <sqlite3.h>
#include <string.h>
#import <CoreFoundation/CFNotificationCenter.h>
//#include "CPDistributedMessagingCenter.h"
#import <CoreFoundation/CoreFoundation.h>
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
//#import <SpringBoard/SpringBoard.h>


// init CFNotificationCenterPostNotification hook
void (*orig_CFNotificationCenterPostNotification) (
                                                   CFNotificationCenterRef center,
                                                   CFStringRef name,
                                                   const void *object,
                                                   CFDictionaryRef userInfo,
                                                   Boolean deliverImmediately
                                                   );

void replaced_CFNotificationCenterPostNotification (
                                                    CFNotificationCenterRef center,
                                                    CFStringRef name,
                                                    const void *object,
                                                    CFDictionaryRef userInfo,
                                                    Boolean deliverImmediately
                                                    ){
    NSLog(@"CFNotificationCenterPostNotification: %@", name );

    orig_CFNotificationCenterPostNotification(center,name,object,userInfo,deliverImmediately);

}

void (*orig_CFNotificationCenterPostNotificationWithOptions) (
                                                      CFNotificationCenterRef center,
                                                      CFStringRef name,
                                                      const void *object,
                                                      CFDictionaryRef userInfo,
                                                      CFOptionFlags options
                                                      );
void replaced_CFNotificationCenterPostNotificationWithOptions (
                                                      CFNotificationCenterRef center,
                                                      CFStringRef name,
                                                      const void *object,
                                                      CFDictionaryRef userInfo,
                                                      CFOptionFlags options
                                                      )
{
    NSLog(@"CFNotificationCenterPostNotificationWithOptions: %@", name );

    orig_CFNotificationCenterPostNotificationWithOptions(center,name,object,userInfo,options);

}

%hook SpringBoard

-(void)applicationDidFinishLaunching:(id)application {
    %orig;

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Welcome"
                                                    message:@"Welcome to my iPhone!"
                                                   delegate:nil
                                          cancelButtonTitle:@"Thanks"
                                          otherButtonTitles:nil];
    [alert show];
    //[alert release];
}
%end
%hook NSNotificationCenter
- (void)postNotification:(NSNotification *)notification{

        NSLog(@"NSNotificationCenterpostNotification: %@",[notification name]);

    %orig;
}
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo{

        NSLog(@"NSNotificationCenterpostNotificationName: %@",aName);

    %orig;
}

%end
__attribute__((constructor)) void notificationinit() {

%init;

    MSHookFunction(CFNotificationCenterPostNotification, replaced_CFNotificationCenterPostNotification, &orig_CFNotificationCenterPostNotification);

    MSHookFunction(CFNotificationCenterPostNotificationWithOptions, replaced_CFNotificationCenterPostNotificationWithOptions, &orig_CFNotificationCenterPostNotificationWithOptions);

}
Community
  • 1
  • 1
TorukMakto
  • 2,066
  • 2
  • 24
  • 38

1 Answers1

5

So, a few thoughts:

  1. First, can you explain why you want to use method swizzling, or hooking to detect these notifications? Are you trying to actually intercept the notifications, process them in your software, and stop them from being delivered to the rest of the system? If that's what you want, then I understand your approach. If you simply want to receive these notifications, then I would recommend the normal approach of just registering for Darwin events (all of them, or by name). See here for an example.

  2. Is this just a problem with the com.apple.springboard.lockcomplete event? Because that event is not generated when you unlock the device. It's only posted when locking. To detect the unlock event, you can see this answer.

  3. If you're still having trouble, perhaps this is because events can be posted in multiple ways. You may be hooking CFNotificationCenterPostNotification() and CFNotificationCenterPostNotificationWithOptions(), but they are not the only ways to post events. The low level notify_post() API can also be used. My guess is that CFNotificationCenterPostNotification() will actually use the notify_post() call to post the event. So, it's possible that if you're trying to detect an event, especially an undocumented one, that iOS is posting the event directly with notify_post(), which would explain why you're not seeing it.

Hope this helps.

Community
  • 1
  • 1
Nate
  • 31,017
  • 13
  • 83
  • 207
  • Nate - Thank you so much for detailed answer. 1) I just want to receive every darwin notification. However the example you mentioned gets me only notifications when my app is in foreground. (Or I am be goofing up). 2) & 3) notify_post did the trick. Now I am able to hook into notify_post and capture every notification in the system. Appreciate your help and time. – TorukMakto Jul 19 '13 at 10:26
  • btw, the purpose was not to stop them but log them and build a database of all possible notifications so that when there is a requirement, we can go through master list and figure out how it can be achieved... – TorukMakto Jul 19 '13 at 10:28
  • 1
    @Bugivore, I'm not on my Mac right now, so I can't run. You should be able to receive notifications while your app is in the background. You may need to perform some steps to keep your app fully *alive* while in the background however. For a normal UIApplication, iOS disables quite a lot of functionality in the background. You can get around this by making your app a daemon, or by using undocumented background modes in your Info.plist (`continuous` and `unboundedTaskCompletion`). I need to go to sleep now, but I can post more on this tomorrow. Or, you can search through my old posts ... – Nate Jul 19 '13 at 10:41
  • 1
    @Bugivore, if you take a look [at this old answer of mine](http://stackoverflow.com/a/15798083/119114), it shows you how to modify an app to "stay alive" in the background for as long as you want. It's possible that this might be necessary to keep delivering notifications to your app after it goes into the background. Note that I also mention "Launch Daemons", which are like non-graphical background services that run all the time. Depending on what you're trying to do, this also might be a good solution. – Nate Jul 21 '13 at 21:52