-->

Import ChatKit (i.e., Private Framework) OR using

2019-05-21 06:43发布

问题:

First - I know private frameworks/APIs won't get me to the AppStore, this is for private use/research only.

I can't get my project to compile with ChatKit.framework.

Basically I need to somehow init a CKDBMessage object and get stuff from it.

The first approach I tried is to be able to call this:

    CKDBMessage* msg = [[CKDBMessage alloc] initWithRecordID:lastID];
    NSLog(@"GOT SMS: %@", msg.text);

I couldn't get it to compile with any combination of these solutions:

  • Simply add only CKDBMessage.h to my project
  • Add all the headers of ChatKit.framework
  • Add also ChatKit.framework file itself

I have the headers and the framework file in Headers folder and I tried adding any/all of these build settings, both on recursive/non-recursive:

  • Framework Search Paths -> $(PROJECT_DIR)/Headers
  • Header Search Paths ->
    • $(SRCROOT)/Headers/ChatKit.framework/Headers
    • $(SRCROOT)/Headers
  • User Header Search Paths ->
    • $(SRCROOT)/Headers
    • $(SRCROOT)/Headers/ChatKit.framework/Headers

Always Search User Paths is always on YES

The second thing I tried was to do everything at runtime, this is what I have:

Class CKDBMessage = NSClassFromString(@"CKDBMessage");// objc_getClass("CKDBMessage");

SEL sel = @selector(initWithRecordID:);

NSMethodSignature *signature = [CKDBMessage methodSignatureForSelector:sel];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.selector = sel;
[invocation setArgument:&lastID atIndex:2];
[invocation invoke];

NSObject * msgWeak = [CKDBMessage alloc];
[invocation getReturnValue:&msgWeak];
NSObject *msg = msgWeak;

NSString *text = [msg performSelector:@selector(text)];

NSLog(@"text: %@", text);

Here I crash at invocationWithMethodSignature: because NSClassFromString returns nil instead of the class...

Any ideas on any of the two approaches?

This is for nonjailbroken, iOS8(.2), using Xcode6

回答1:

Well not many people viewed this, but for the sake of our wiki community, I managed to solve this by adding the CKDBMessage.h file to my project (actually I added all the headers of ChatKit but I don't think it's necessary), than I loaded the framework dynamically with dlopen like so:

dlopen("/System/Library/PrivateFrameworks/ChatKit.framework/ChatKit", RTLD_LAZY)

So my full solution is:

dlopen("/System/Library/PrivateFrameworks/ChatKit.framework/ChatKit", RTLD_LAZY);

Class CKDBMessageClass = NSClassFromString(@"CKDBMessage");
CKDBMessage *msg = [[CKDBMessageClass alloc] initWithRecordID:lastID];

NSString *text = msg.text;
NSLog(@"text: %@", text);

Getting the ID of the last message involves another framework: IMDPersistence:

//SomeFile.h
// ...
//declare the function:
static int (*IMDMessageRecordGetMessagesSequenceNumber)();

// SomeFile.m
// ...
//open IMDPersistence framework
void *libHandleIMD = dlopen("/System/Library/PrivateFrameworks/IMDPersistence.framework/IMDPersistence", RTLD_LAZY);

//make/get symbol from framework + name
IMDMessageRecordGetMessagesSequenceNumber = (int (*)())dlsym(libHandleIMD, "IMDMessageRecordGetMessagesSequenceNumber");

// get id of last SMS from symbol
int lastID = IMDMessageRecordGetMessagesSequenceNumber();

Now you can use lastID to get the message contents...



回答2:

Currently, I am using XCode 10. here we can see one MessagesKit.framework in PrivateFrameworks path. MessagesKit.framework contains SOMessageHelper file where we can see sendSMS function.

Function :

(void)sendMessageText:(id)arg1 toRecipient:(id)arg2 withCompletionBlock:(CDUnknownBlockType)arg3;