2023-06-07 10:49:59 +07:00
|
|
|
#import <Foundation/Foundation.h>
|
2024-01-10 14:19:59 +07:00
|
|
|
#include <objc/message.h>
|
2023-06-21 17:28:42 +07:00
|
|
|
#include <stdio.h>
|
2023-06-07 10:49:59 +07:00
|
|
|
|
2024-02-09 14:01:34 +07:00
|
|
|
void* sel_lookUpByName(const char* name);
|
|
|
|
|
|
|
|
|
2023-06-15 10:46:10 +07:00
|
|
|
@interface Foo : NSObject
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Foo
|
|
|
|
- (void)bar {
|
2024-02-09 14:01:34 +07:00
|
|
|
NSLog(@"Invoke instance method %@", self);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)tobehijacked:(NSString*)input {
|
|
|
|
NSLog(@"Invoke tobehijacked method %@", input);
|
2023-06-15 10:46:10 +07:00
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface Bar : NSObject
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Bar
|
2023-06-26 15:19:59 +07:00
|
|
|
static int x;
|
|
|
|
|
2023-06-15 10:46:10 +07:00
|
|
|
+ (void)load {
|
2023-06-26 15:19:59 +07:00
|
|
|
x = 1;
|
2024-02-09 14:01:34 +07:00
|
|
|
printf("Invoke +load method\n");
|
2023-06-15 10:46:10 +07:00
|
|
|
}
|
2023-06-21 17:28:42 +07:00
|
|
|
|
2023-06-26 15:19:59 +07:00
|
|
|
- (void)dummy {
|
2024-02-09 14:01:34 +07:00
|
|
|
NSLog(@"Static value check after +load should be 1: x=%d", x);
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@interface FakeNSDateFormatter : NSDateFormatter {
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation FakeNSDateFormatter
|
|
|
|
- (NSDate*)dateFromString:(NSString*)dateString {
|
|
|
|
NSLog(@"Hijacked the NSDateFormatter");
|
|
|
|
return [super dateFromString:dateString];
|
2023-06-26 15:19:59 +07:00
|
|
|
}
|
|
|
|
@end
|
2023-06-21 17:28:42 +07:00
|
|
|
|
|
|
|
|
|
|
|
__attribute__((constructor)) static void
|
2023-06-26 15:19:59 +07:00
|
|
|
hmmge(int argc, char** argv) {
|
2024-02-09 14:01:34 +07:00
|
|
|
printf("Invoke C constructor\n");
|
|
|
|
printf("Checking for arguments to be passed correctly\n");
|
|
|
|
printf(" argc=%d\n", argc);
|
2023-06-26 15:19:59 +07:00
|
|
|
for (int i = 0; i < argc; i++) {
|
2024-02-09 14:01:34 +07:00
|
|
|
printf(" argv[%d]=%s\n", i, argv[i]);
|
2023-06-26 15:19:59 +07:00
|
|
|
}
|
2024-02-09 14:01:34 +07:00
|
|
|
NSLog(@"Using Objective-C in C constructor");
|
|
|
|
NSLog(@"Test static Objective-C class is initialized and +load completed");
|
2023-06-26 15:19:59 +07:00
|
|
|
Bar *bar = [[Bar alloc] init];
|
|
|
|
[bar dummy];
|
2023-06-21 17:28:42 +07:00
|
|
|
}
|
2023-06-15 10:46:10 +07:00
|
|
|
|
2024-02-09 14:01:34 +07:00
|
|
|
int main(int argc, const char * argv[], char* envp[]) {
|
2023-06-15 10:46:10 +07:00
|
|
|
@autoreleasepool {
|
2024-02-09 14:01:34 +07:00
|
|
|
NSLog(@"Invoke main()");
|
2024-01-10 14:19:59 +07:00
|
|
|
|
2024-02-09 14:01:34 +07:00
|
|
|
// Foo bar using Objective-C syntax
|
2023-06-15 10:46:10 +07:00
|
|
|
Foo *foo = [[Foo alloc] init];
|
|
|
|
[foo bar];
|
2024-01-10 14:19:59 +07:00
|
|
|
|
2024-02-09 14:01:34 +07:00
|
|
|
// Foo bar with selector and msgSend
|
|
|
|
NSLog(@"Directly call \"bar\" %p through objc_msgSend %p with object foo %p", @selector(bar), objc_msgSend, foo);
|
2024-01-10 14:19:59 +07:00
|
|
|
typedef void (*barfunc)(id, SEL);
|
2024-01-10 14:50:53 +07:00
|
|
|
barfunc bar_ = (barfunc)&objc_msgSend;
|
2024-01-10 14:19:59 +07:00
|
|
|
bar_(foo, @selector(bar));
|
2024-02-09 14:01:34 +07:00
|
|
|
|
|
|
|
NSString *dummyinput = @"dummy input";
|
|
|
|
[foo tobehijacked:dummyinput];
|
|
|
|
NSLog(@"The above invocation should be hijacked with input at %p", dummyinput);
|
|
|
|
|
|
|
|
NSString *dateString = @"2024-01-01T00:00:00.000Z";
|
|
|
|
|
|
|
|
// NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
|
|
|
// [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
|
|
|
|
// NSDate *date = [dateFormatter dateFromString:dateString];
|
|
|
|
|
|
|
|
// this is to test the idea for hooking,
|
|
|
|
// basically, we create a middle-class inherits the class to be used
|
|
|
|
//
|
|
|
|
// example using NSDateFormatter:
|
|
|
|
// - Create a FakeNSDateFormatter inherits NSDateFormatter
|
|
|
|
// - Have an overloaded function that calls [super inherited]
|
|
|
|
// - The internal struct class_t has superclass points to NSDateFormatter
|
|
|
|
// FakeNSDateFormatter *dateFormatter = [[FakeNSDateFormatter alloc] init];
|
|
|
|
// [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
|
|
|
|
// NSDate *date = [dateFormatter dateFromString:dateString];
|
|
|
|
// NSLog(@"Test hijacked/hooked Objective-C result %@", date);
|
|
|
|
|
|
|
|
NSLog(@"Selector \"dateFromString:\" using @selector %p", @selector(dateFromString:));
|
|
|
|
NSLog(@"Selector \"bar:\" using @selector %p", @selector(bar:));
|
|
|
|
NSLog(@"Selector \"dummy\" using @selector %p", @selector(dummy));
|
|
|
|
|
|
|
|
NSLog(@"[Bar dummy] implementation is at %p\n", [foo methodForSelector:@selector(bar:)]);
|
2023-06-15 10:46:10 +07:00
|
|
|
}
|
2023-06-26 15:19:59 +07:00
|
|
|
|
2024-02-09 14:01:34 +07:00
|
|
|
printf("Selector lookup 'dateFromString:' addr: %p\n", sel_lookUpByName("dateFromString:"));
|
|
|
|
printf("Selector lookup 'bar:' addr: %p\n", sel_lookUpByName("bar:"));
|
|
|
|
printf("Selector lookup 'dummy' addr: %p\n", sel_lookUpByName("dummy"));
|
|
|
|
|
|
|
|
printf("Test if arguments are passed correctly to main(argc, argv, env)\n");
|
|
|
|
printf(" argc=%d\n", argc);
|
2023-06-26 15:19:59 +07:00
|
|
|
for (int i = 0; i < argc; i++) {
|
2024-02-09 14:01:34 +07:00
|
|
|
printf(" argv[%d]=%s\n", i, argv[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*envp) {
|
|
|
|
printf(" env[]=%s\n", *envp);
|
|
|
|
envp++;
|
2023-06-26 15:19:59 +07:00
|
|
|
}
|
2023-06-15 10:46:10 +07:00
|
|
|
return 0;
|
2023-06-07 10:49:59 +07:00
|
|
|
}
|