---
title: 'Сканирование пользовательских папок в корпоративной сети: автоматизация аудита файлов'
summary: 'Практическое руководство по созданию Python-скрипта для поиска файлов с определёнными расширениями на рабочих станциях сотрудников через административные шары Windows. Описание архитектуры, безопасности и запуска.'
date: '2025-05-22'
draft: false
tags:
- аудит
- безопасность
- python
- windows
- сканирование
- администрирование
---
# Документация для сканера расширений файлов

- Внутри корпаративной сети пользователи частенько хранят что то не нужно, давйте выясним чем сотруднок занимаеться на рабочем месте и каким файлам пользуеться, а после проанализируем что там есть у него на ПК.
## Обзор

Скрипт представляет собой инструмент для сканирования сетевых компьютеров с целью поиска файлов с определенными расширениями в пользовательских директориях.
## Основные возможности

* **Сетевое сканирование**: Подключение к удаленным компьютерам через административные шары (C\$)
* **Поиск файлов**: Обнаружение файлов с заданными расширениями (.exe, .url, .lnk)
* **Фильтрация**: Исключение системных пользователей и нежелательных файлов
* **Логирование**: Детальное ведение журнала операций
* **Экспорт результатов**: Сохранение данных в CSV формате
## Конфигурация
### Основные параметры

```python
EXTENSIONS = (".exe", ".url", ".lnk") # Искомые расширения файлов
EXCLUDE_USERS = ("All Users", "Default", "Default User", "Public", "desktop.ini", "Administrator")
SEARCH_DIRS = ("Desktop", "Downloads", "Documents") # Сканируемые директории
EXCLUDE_FILENAME_KEYWORDS = ("putty", "telegram", "vmware", "anydesk") # Исключаемые ключевые слова
```
### Файлы конфигурации

* `hosts.txt` - список хостов для сканирования (по одному на строку)
* `found_files.csv` - результаты сканирования
* `failed_hosts.csv` - журнал неудачных подключений
* `scanner.log` - детальный лог операций
## Архитектура
### Основные функции
#### `read_hosts(file_path: str) -> List[str]`
Читает список хостов из файла, игнорируя комментарии (строки, начинающиеся с `#`)
#### `is_excluded_file(file: str) -> bool`
Проверяет, должен ли файл быть исключен из результатов на основе:
* Имени файла (`desktop.ini`, `Thumbs.db`)
* Ключевых слов в имени файла
#### `wait_for_access(path: str, timeout: int = 3) -> bool`
Проверяет доступность сетевого пути с таймаутом
#### `scan_host(host: str) -> List[List[str]]`
Основная функция сканирования:
1. Подключается к `\\{host}\c$\Users`
2. Перебирает пользовательские директории
3. Сканирует указанные поддиректории
4. Фильтрует файлы по расширениям и исключениям
5. Возвращает список найденных файлов
#### `write_results(rows: List[List[str]], header: List[str], file_path: str)`
Записывает результаты в CSV файл с разделителем `;`
#### `log_failed_host(host: str, reason: str)`
Записывает информацию о неудачных подключениях
## Структура данных
### Формат результатов CSV

| Поле      | Описание                  |
| --------- | ------------------------- |
| PC Name   | Имя компьютера            |
| User      | Имя пользователя          |
| Extension | Расширение файла          |
| File Path | Полный путь к файлу       |
| Scan Date | Дата и время сканирования |
### Формат журнала ошибок
| Поле      | Описание       |
| --------- | -------------- |
| Host      | Имя хоста      |
| Reason    | Причина ошибки |
| Timestamp | Время ошибки   |
## Безопасность и требования
### Системные требования

* **ОС**: Windows (для доступа к административным шарам)
* **Права**: Административные права на целевых машинах
* **Сеть**: Доступ к портам SMB (445/tcp)
* **Python**: 3.6+ с модулями `os`, `csv`, `pathlib`, `logging`, `datetime`, `typing`
### Рекомендации по безопасности

1. **Ограничение доступа**: Запускать только с учетных записей с минимально необходимыми правами
2. **Сетевая сегментация**: Использовать в изолированных сетевых сегментах
3. **Аудит**: Регулярно проверять логи на предмет подозрительной активности
4. **Шифрование логов**: При необходимости добавьте шифрование логов или безопасную транспортировку логов на удалённый сервер
## Развёртывание и запуск

1. Установите Python 3.8+:
- на MACOS:
```bash
brew install python # или иным способом в зависимости от ОС
```

- на Windows:
```bash
choco install python # или иным способом в зависимости от ОС
```

- на Linux:
```bash
sudo apt-get install python3 # или иным способом в зависимости от ОС
```

2. Подготовьте файл `hosts.txt`:
```text
PC-NAME-1
PC-NAME-2
```

3. Запустите скрипт:  
```bash
python3 main.py
```

```python
import os
import csv
import pathlib
import logging
from datetime import datetime
from typing import List

# Конфигурация
EXTENSIONS = (".exe", ".url", ".lnk")
EXCLUDE_USERS = ("All Users", "Default", "Default User", "Public", "desktop.ini", "Administrator")
SEARCH_DIRS = ("Desktop", "Downloads", "Documents")
EXCLUDE_FILENAME_KEYWORDS = ("putty", "telegram", "vmware", "anydesk")  # слова в имени файла, а не расширения
EXCLUDE_FILENAMES = ("desktop.ini", "Thumbs.db")
OUTPUT_FILE = "found_files.csv"
FAILED_FILE = "failed_hosts.csv"
HOSTS_FILE = "hosts.txt"
LOG_FILE = "scanner.log"

# Настройка логирования
logging.basicConfig(
	filename=LOG_FILE,
	level=logging.INFO,
	format='%(asctime)s [%(levelname)s] %(message)s',
	datefmt='%Y-%m-%d %H:%M:%S'
)

def read_hosts(file_path: str) -> List[str]:
	with open(file_path, "r", encoding="utf-8") as f:
		return [line.strip() for line in f if line.strip() and not line.strip().startswith("#")]

def is_excluded_file(file: str) -> bool:
	file_lower = file.lower()
	return (
		file in EXCLUDE_FILENAMES
		or any(keyword in file_lower for keyword in EXCLUDE_FILENAME_KEYWORDS)
	)

def wait_for_access(path: str, timeout: int = 3) -> bool:
	try:
		return os.path.exists(path)
	except Exception:
		return False

def scan_host(host: str) -> List[List[str]]:
	results = []
	base_users_path = f"\\\\{host}\\c$\\Users"
	try:
		if not wait_for_access(base_users_path):
			raise Exception("Недоступен путь к Users")
		logging.info(f"Подключение к: {host}")
		users = os.listdir(base_users_path)
		for user in users:
			if user in EXCLUDE_USERS:
				continue
			user_base = os.path.join(base_users_path, user)
			for sub_dir in SEARCH_DIRS:
				target_dir = os.path.join(user_base, sub_dir)
				if not os.path.exists(target_dir):
					continue
				for root, _, files in os.walk(target_dir):
					for file in files:
						if is_excluded_file(file):
							continue
						if not file.lower().endswith(EXTENSIONS):
							continue
						full_path = os.path.join(root, file)
						ext = pathlib.Path(file).suffix
						logging.info(f"[{host}] Обнаружен файл: {full_path}")
						results.append([
							host, user, ext, full_path, datetime.now().strftime("%Y-%m-%d %H:%M:%S")
						])
	except Exception as e:
		log_failed_host(host, str(e))
		logging.error(f"Ошибка при сканировании {host}: {e}")
	return results

def write_results(rows: List[List[str]], header: List[str], file_path: str):
	file_exists = os.path.exists(file_path)
	with open(file_path, mode="a", newline='', encoding="utf-8") as f:
		writer = csv.writer(f, delimiter=";")
		if not file_exists:
			writer.writerow(header)
		writer.writerows(rows)
	logging.info(f"Записано {len(rows)} строк в {file_path}")

def log_failed_host(host: str, reason: str):
	with open(FAILED_FILE, mode="a", newline='', encoding="utf-8") as f:
		writer = csv.writer(f, delimiter=";")
		writer.writerow([host, reason, datetime.now().strftime("%Y-%m-%d %H:%M:%S")])

def main():
	logging.info("=== Запуск сканирования ===")
	hosts = read_hosts(HOSTS_FILE)
	header = ["PC Name", "User", "Extension", "File Path", "Scan Date"]
	for host in hosts:
		print(f"Scanning: {host}")
		results = scan_host(host)
		if results:
			write_results(results, header, OUTPUT_FILE)
		else:
			logging.warning(f"Нет результатов или ошибка доступа: {host}")
	logging.info("=== Завершение сканирования ===")

if __name__ == "__main__":
	main()
```

## Полезные ресурсы

1. [Официальная документация Python](https://docs.python.org/3/)
2. [Работа с путями в Python](https://realpython.com/python-pathlib/)
3. [Примеры работы с CSV](https://pythonexamples.org/python-csv/)
4. [Сетевые пути Windows](https://learn.microsoft.com/ru-ru/windows/win32/fileio/naming-a-file)