macho/research/custom_loader/a.mm

124 lines
3.6 KiB
Plaintext

#import <Foundation/Foundation.h>
#include <objc/message.h>
#include <stdio.h>
void* sel_lookUpByName(const char* name);
@interface Foo : NSObject
@end
@implementation Foo
- (void)bar {
NSLog(@"Invoke instance method %@", self);
}
- (void)tobehijacked:(NSString*)input {
NSLog(@"Invoke tobehijacked method %@", input);
}
@end
@interface Bar : NSObject
@end
@implementation Bar
static int x;
+ (void)load {
x = 1;
printf("Invoke +load method\n");
}
- (void)dummy {
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];
}
@end
__attribute__((constructor)) static void
hmmge(int argc, char** argv) {
printf("Invoke C constructor\n");
printf("Checking for arguments to be passed correctly\n");
printf(" argc=%d\n", argc);
for (int i = 0; i < argc; i++) {
printf(" argv[%d]=%s\n", i, argv[i]);
}
NSLog(@"Using Objective-C in C constructor");
NSLog(@"Test static Objective-C class is initialized and +load completed");
Bar *bar = [[Bar alloc] init];
[bar dummy];
}
int main(int argc, const char * argv[], char* envp[]) {
@autoreleasepool {
NSLog(@"Invoke main()");
// Foo bar using Objective-C syntax
Foo *foo = [[Foo alloc] init];
[foo bar];
// Foo bar with selector and msgSend
NSLog(@"Directly call \"bar\" %p through objc_msgSend %p with object foo %p", @selector(bar), objc_msgSend, foo);
typedef void (*barfunc)(id, SEL);
barfunc bar_ = (barfunc)&objc_msgSend;
bar_(foo, @selector(bar));
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:)]);
}
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);
for (int i = 0; i < argc; i++) {
printf(" argv[%d]=%s\n", i, argv[i]);
}
while (*envp) {
printf(" env[]=%s\n", *envp);
envp++;
}
return 0;
}