чат 1 [✅ ДОРАБОТКИ ЧАТА 1: Мониторинг процессов 1. 📌 CPU и memory — надёжная обработка:Добавим pidusage для более стабильного CPU/memory:
bash
КопироватьРедактировать
npm install pidusage

js
КопироватьРедактировать
// server.js (добавим в /processes)const pidusage = require('pidusage'); // ...const processesWithStats = await Promise.all(processes.map(async proc => { let stats = {}; try { stats = await pidusage(proc.pid); } catch (_) {} return { pid: proc.pid, name: proc.name, ppid: proc.ppid, cpu: stats.cpu ?? 0, memory: stats.memory ?? 0, cmd: proc.cmd }; })); const analyzed = processesWithStats.map(proc => ({ ...proc, analysis: ai.analyzeProcess(proc) })); res.json(analyzed);
2. 📌 Расширенный анализ в ai.js
js
КопироватьРедактировать
const path = require('path'); function analyzeProcess(proc) { const flags = []; const exePath = proc.cmd?.split(' ')[0] || ''; const exeDir = path.dirname(exePath).toLowerCase(); if (knownMalware.has(proc.name.toLowerCase())) { flags.push('Известное вредоносное'); } if (proc.cpu > 30) { flags.push(`Высокая загрузка CPU: ${proc.cpu.toFixed(1)}%`); } if (proc.memory > 300 * 1024 * 1024) { flags.push(`Высокая память: ${(proc.memory / 1048576).toFixed(1)}MB`); } if (exeDir.includes('temp')) { flags.push('Запуск из TEMP'); } if (exeDir.includes('system32')) { flags.push('Запуск из system32'); } if (proc.ppid === 4 || proc.name.toLowerCase().includes('system')) { flags.push('Запущен от SYSTEM'); } // (будет позже: число потоков, подпись EXE, сетевые подключения)return flags.length ? flags : ['Подозрений нет']; }
🧠 ДОБАВЛЕНИЕ SQLite ХРАНИЛИЩА
bash
КопироватьРедактировать
npm install sqlite3
Создание db.sqlite и сохранение анализа:
js
КопироватьРедактировать
// db.jsconst sqlite3 = require('sqlite3').verbose(); const db = new sqlite3.Database('./db.sqlite'); db.serialize(() => { db.run(` CREATE TABLE IF NOT EXISTS process_analysis ( pid INTEGER, name TEXT, score INTEGER, flags TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP ) `); }); function saveAnalysis(proc) { const score = proc.analysis.length; const flags = proc.analysis.join('; '); db.run( `INSERT INTO process_analysis (pid, name, score, flags) VALUES (?, ?, ?, ?)`, [proc.pid, proc.name, score, flags] ); } module.exports = { saveAnalysis };
В server.js:
js
КопироватьРедактировать
const db = require('./db'); // ... analyzed.forEach(db.saveAnalysis);
🎯 HTML-ИНТЕРФЕЙС (3 ВКЛАДКИ)Да, предлагаю следующую структуру index.html:
html
КопироватьРедактировать
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>AI Antivirus</title> <style>body { font-family: sans-serif; margin: 0; background: #f5f5f5; } .tabs { display: flex; background: #333; } .tab { padding: 10px 20px; color: #fff; cursor: pointer; } .tab:hover, .tab.active { background: #444; } .content { padding: 20px; display: none; } .content.active { display: block; } </style> </head> <body> <div class="tabs"> <div class="tab active" data-tab="proc">Процессы</div> <div class="tab" data-tab="files">Файлы</div> <div class="tab" data-tab="train">Обучение</div> </div> <div id="proc" class="content active"> <button onclick="loadProcesses()">Обновить</button> <table id="procTable" border="1" cellpadding="4"></table> </div> <div id="files" class="content"> <p>Форма загрузки и список отсканированных файлов будет тут.</p> </div> <div id="train" class="content"> <p>Обучение ИИ: истории verdict'ов и обратная связь.</p> </div> <script src="script.js"></script> </body> </html>
public/script.js
js
КопироватьРедактировать
// script.jsfunction switchTab(tabId) { document.querySelectorAll('.tab').forEach(el => el.classList.toggle('active', el.dataset.tab === tabId) ); document.querySelectorAll('.content').forEach(el => el.classList.toggle('active', el.id === tabId) ); } document.querySelectorAll('.tab').forEach(el => el.addEventListener('click', () => switchTab(el.dataset.tab)) ); async function loadProcesses() { const res = await fetch('/processes'); const data = await res.json(); const table = document.getElementById('procTable'); table.innerHTML = `<tr><th>PID</th><th>Имя</th><th>CPU</th><th>Память</th><th>Анализ</th></tr>` + data.map(p => `<tr> <td>${p.pid}</td><td>${p.name}</td> <td>${p.cpu.toFixed(1)}%</td> <td>${(p.memory / 1048576).toFixed(1)} MB</td> <td>${p.analysis.join('<br>')}</td> </tr>`).join(''); }
  • 📍Что дальше:Добавить анализ количества потоков через ps-node или wmic (Win) / /proc (Linux).
  • Интеграция формы загрузки файлов.
  • Обучение ИИ по сохранённым анализам в db.sqlite.
  • Добавить логотип, темную тему, оформление.
Подтвердите, если готов перейти ко вкладке "Файлы" или расширить признаки/базу.
4o

] ЧАТ 2 [✅ Правки по текущему коду 1. 🧱 extractFeatures(filepath) — улучшение обработки .exe
js
КопироватьРедактировать
async function extractFeatures(filepath) { const stat = await fs.stat(filepath); const size = stat.size; const buffer = await fs.readFile(filepath); const entropy = await calculateEntropy(buffer); let fileText = ''; try { fileText = buffer.toString('utf8', 0, 10000).replace(/[^\x20-\x7E]/g, ''); } catch (e) { fileText = ''; } const badStrings = await getBadStrings(); // теперь вынесены отдельноconst hasBadStrings = badStrings.some(str => fileText.includes(str.toLowerCase())); return { filepath, size, entropy, hasBadStrings }; }
2. 📁 getBadStrings() — отдельный конфиг или из БДСоздаём bad_strings.txt или табличку malware_signatures:
Вариант 1: из файла
js
КопироватьРедактировать
const path = require('path'); async function getBadStrings() { const content = await fs.readFile(path.join(__dirname, 'malware_signatures.txt'), 'utf8'); return content.split('\n').map(s => s.trim()).filter(Boolean); }
Вариант 2: из SQLite (предпочтительно, если всё в БД)
js
КопироватьРедактировать
async function getBadStringsFromDB(db) { const rows = await db.all('SELECT signature FROM malware_signatures'); return rows.map(row => row.signature.toLowerCase()); }
🧠 Следующий шаг: Сохранение результатов в SQLite 1. 📦 Таблица file_scan_resultsДобавь в инициализацию базы (db.js или в server.js при старте):
sql
КопироватьРедактировать
CREATE TABLE IF NOT EXISTS file_scan_results ( path TEXT, size INTEGER, entropy REAL, has_bad_strings BOOLEAN, verdict TEXT, scanned_at TEXT );
Node.js-версия:
js
КопироватьРедактировать
db.run(`CREATE TABLE IF NOT EXISTS file_scan_results ( path TEXT, size INTEGER, entropy REAL, has_bad_strings BOOLEAN, verdict TEXT, scanned_at TEXT )`);
2. 💾 Сохраняем после анализа файлаВ server.js или ai.js, после предсказания:
js
КопироватьРедактировать
const verdict = await aiAnalyzeFile(features); const stmt = db.prepare(` INSERT INTO file_scan_results (path, size, entropy, has_bad_strings, verdict, scanned_at) VALUES (?, ?, ?, ?, ?, ?) `); stmt.run( features.filepath, features.size, features.entropy, features.has_bad_strings, verdict, new Date().toISOString() ); stmt.finalize();
🔜 Общая следующая задача: вкладочный интерфейсХорошая идея — интерфейс с вкладками:
Пример public/index.html
html
КопироватьРедактировать
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>AI Antivirus</title> <style>body { font-family: sans-serif; margin: 0; background: #111; color: white; } .tabs { display: flex; background: #222; } .tab { padding: 1em; cursor: pointer; border-bottom: 2px solid transparent; } .tab.active { border-color: #00f2ff; } .tab-content { display: none; padding: 1em; } .tab-content.active { display: block; } </style> </head> <body> <div class="tabs"> <div class="tab active" data-tab="processes">Процессы</div> <div class="tab" data-tab="files">Файлы</div> <div class="tab" data-tab="training">Обучение</div> </div> <div class="tab-content active" id="processes"> <button onclick="updateProcesses()">Обновить</button> <div id="processTable">[Таблица процессов]</div> </div> <div class="tab-content" id="files"> <form onsubmit="scanFiles(event)"> <input type="text" placeholder="Введите путь..." id="scanPath" /> <button>Сканировать</button> </form> <div id="fileScanResults">[Список результатов]</div> </div> <div class="tab-content" id="training"> <div id="trainingData">[История и обратная связь]</div> </div> <script src="script.js"></script> </body> </html>
Пример public/script.js
js
КопироватьРедактировать
document.querySelectorAll('.tab').forEach(tab => { tab.addEventListener('click', () => { document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active')); tab.classList.add('active'); document.getElementById(tab.dataset.tab).classList.add('active'); }); }); async function scanFiles(event) { event.preventDefault(); const path = document.getElementById('scanPath').value; const res = await fetch('/scan-files', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path }) }); const { files } = await res.json(); const results = await Promise.all(files.map(async file => { const response = await fetch('/analyze-file', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filepath: file }) }); const { verdict } = await response.json(); return `<li>${file} — <strong>${verdict}</strong></li>`; })); document.getElementById('fileScanResults').innerHTML = `<ul>${results.join('')}</ul>`; }
  • ✅ Твоя текущая задача: Защита toString через try/catch
  • Сделать список расширений настраиваемым
  • Вредоносные строки — вынести в файл/БД
  • Сохранять результаты анализа файлов в file_scan_results
  • 🚀 Следующее: Добавить отображение истории сканирования (вкладка "Файлы")
  • Добавить обратную связь в "Обучение"
  • Выгрузку процессов и сканирование по API на вкладке "Процессы"
Если хочешь, могу написать готовые getScanHistory() и POST /feedback-file для обучения.
  • Продолжим?] ЧАТ 3 [✅ ЧТО ДЕЛАЕМ СЕЙЧАС: 🔹 Добавим SQLite и сохраним результаты загрузкиТаблица uploads
  • Сохраняем после анализа: sha256, extension, size_kb, verdict, uploaded_at
📁 db.js — модуль работы с SQLiteСоздай файл db.js:
js
КопироватьРедактировать
const sqlite3 = require('sqlite3').verbose(); const db = new sqlite3.Database('./db.sqlite'); // Создание таблицы db.run(` CREATE TABLE IF NOT EXISTS uploads ( id INTEGER PRIMARY KEY AUTOINCREMENT, sha256 TEXT, extension TEXT, size_kb REAL, verdict TEXT, uploaded_at TEXT ) `); function logUpload({ sha256, extension, size_kb, verdict }) { const uploaded_at = new Date().toISOString(); db.run( `INSERT INTO uploads (sha256, extension, size_kb, verdict, uploaded_at) VALUES (?, ?, ?, ?, ?)`, [sha256, extension, size_kb, verdict, uploaded_at] ); } function getUploads(callback) { db.all(`SELECT * FROM uploads ORDER BY uploaded_at DESC LIMIT 100`, callback); } module.exports = { logUpload, getUploads };
🧠 ai.js — доработаем хэши и вернём всё для записи в БД
js
КопироватьРедактировать
const crypto = require('crypto'); const fs = require('fs'); const path = require('path'); function calcHash(filePath, algo = 'sha256') { return new Promise((resolve, reject) => { const hash = crypto.createHash(algo); const stream = fs.createReadStream(filePath); stream.on('data', data => hash.update(data)); stream.on('end', () => resolve(hash.digest('hex'))); stream.on('error', reject); }); } async function extractFeatures(filePath) { try { const stats = fs.statSync(filePath); const size_kb = stats.size / 1024; const extension = path.extname(filePath).toLowerCase(); const [sha256, sha1, md5] = await Promise.all([ calcHash(filePath, 'sha256'), calcHash(filePath, 'sha1'), calcHash(filePath, 'md5') ]); return { size_kb, extension, sha256, sha1, md5 }; } catch (err) { throw new Error(`Ошибка чтения файла: ${err.message}`); } } async function analyze({ size_kb }) { return size_kb > 10000 ? 'Вредоносный' : 'Безопасный'; } module.exports = { extractFeatures, analyze };
🌐 server.js — обновим POST /upload, подключим db.js
js
КопироватьРедактировать
const express = require('express'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const ai = require('./ai'); const db = require('./db'); const app = express(); const MAX_FILE_SIZE = 20 * 1024 * 1024; // 20MBconst upload = multer({ dest: 'uploads/', limits: { fileSize: MAX_FILE_SIZE }, fileFilter: (req, file, cb) => { const allowed = ['.exe', '.dll', '.js']; if (allowed.includes(path.extname(file.originalname).toLowerCase())) cb(null, true); else cb(new Error('Формат не поддерживается')); } }); app.use(express.static('public')); app.use(express.json()); // Загрузка и анализ app.post('/upload', upload.single('file'), async (req, res) => { try { const filePath = req.file.path; const features = await ai.extractFeatures(filePath); const verdict = await ai.analyze(features); db.logUpload({ sha256: features.sha256, extension: features.extension, size_kb: features.size_kb, verdict }); res.json({ verdict, ...features }); } catch (err) { res.status(500).json({ error: err.message }); } }); // Получение последних загрузок app.get('/uploads', (req, res) => { db.getUploads((err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); // Старт app.listen(3000, () => console.log('🚀 Server on http://localhost:3000'));
  • 💡 Хочешь — сделаю HTML-интерфейс с 3 вкладками:📄 Процессы — (пока пусто или заглушка)
  • 📦 Файлы — форма + таблица анализа
  • 🧠 Обучение — список verdict'ов, кнопка обучения
Нажми «да» — и я пришлю тебе базовый HTML с вкладками и JS-обработкой.
Готов?] ЧАТ 4 [✅ ЗАДАЧА 1: Логирование обратной связи 1.1. Расширим db.sqliteДобавь таблицу feedback_logs:
sql
КопироватьРедактировать
CREATE TABLE IF NOT EXISTS feedback_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, sha256 TEXT, verdict TEXT, score REAL, user_correct BOOLEAN, timestamp TEXT DEFAULT CURRENT_TIMESTAMP );
Можешь выполнить это в server.js после подключения к БД:
js
КопироватьРедактировать
db.run(` CREATE TABLE IF NOT EXISTS feedback_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, sha256 TEXT, verdict TEXT, score REAL, user_correct BOOLEAN, timestamp TEXT DEFAULT CURRENT_TIMESTAMP ) `);
1.2. Сохраняем обратную связь в /feedbackВ server.js, маршрут /feedback:
js
КопироватьРедактировать
app.post('/feedback', (req, res) => { const { verdict, score, userCorrect, sha256 } = req.body; // Обновляем модельupdateModel({ score, userCorrect }); // Логируем обратную связь db.run( `INSERT INTO feedback_logs (sha256, verdict, score, user_correct) VALUES (?, ?, ?, ?)`, [sha256 || '', verdict, score, userCorrect ? 1 : 0], (err) => { if (err) return res.status(500).send("DB error"); res.sendStatus(200); } ); });
✅ ЗАДАЧА 2: История обратной связи 2.1. Добавим GET /feedback-history
js
КопироватьРедактировать
app.get('/feedback-history', (req, res) => { db.all(`SELECT * FROM feedback_logs ORDER BY timestamp DESC LIMIT 50`, (err, rows) => { if (err) return res.status(500).send("DB error"); res.json(rows); }); });
2.2. В public/script.jsДобавим функцию loadHistory():
js
КопироватьРедактировать
async function loadHistory() { const res = await fetch('/feedback-history'); const data = await res.json(); const table = data.map(fb => ` <tr> <td>${fb.sha256}</td> <td>${fb.verdict}</td> <td>${fb.score.toFixed(2)}</td> <td>${fb.user_correct ? '✅' : '❌'}</td> <td>${fb.timestamp}</td> </tr> `).join(''); document.getElementById('history').innerHTML = ` <h2>История обратной связи</h2> <table border="1" cellpadding="5"><tr> <th>SHA256</th><th>Вердикт</th><th>Score</th><th>Оценка</th><th>Время</th> </tr>${table}</table> `; }
И вызываем её после загрузки страницы:
js
КопироватьРедактировать
window.onload = loadHistory;
✅ ЗАДАЧА 3: Интерфейс с 3 вкладкамиВот базовая HTML-структура с вкладками:
html
КопироватьРедактировать
<!-- В index.html --><body> <nav> <button onclick="showTab('processes')">Процессы</button> <button onclick="showTab('files')">Файлы</button> <button onclick="showTab('training')">Обучение</button> </nav> <div id="processes" class="tab" style="display:none;"> <h2>Мониторинг процессов</h2> <p>Скоро тут будет таблица...</p> </div> <div id="files" class="tab" style="display:none;"> <h2>Сканирование файлов</h2> <form id="uploadForm">...</form> <div id="result"></div> </div> <div id="training" class="tab" style="display:none;"> <h2>История обучения</h2> <div id="history">Загрузка...</div> </div> <script>function showTab(id) { document.querySelectorAll('.tab').forEach(tab => tab.style.display = 'none'); document.getElementById(id).style.display = 'block'; } showTab('files'); // по умолчанию</script> </body>
  • 🚀 Дальнейшие шаги Визуально оформить вкладки (Tailwind или CSS)
  • Добавить sha256 хеш файла в анализ
  • Перевести "score" в список признаков для будущей модели
  • Интеграция анализа процессов (из чатов 1–2)
  • Экспорт логов для обучения
Хочешь — могу собрать всё в один архив или подготовить готовый GitHub-проект. Продолжим с SHA256, весами или внешним стилем?] ЧАТ 5 [небыло задач] ЧАТ 6 [небыло задач]