Compare commits

..
93 Commits
Author SHA1 Message Date
87owo c14957afff Update and rename convert_full.py to convert.py 2026-01-04 22:34:35 +08:00
87owo 843a4998f1 Delete Engine/Model/convert.py 2026-01-04 20:45:08 +08:00
87owo 9637e74edc Add files via upload 2026-01-04 20:17:23 +08:00
87owo b1bdf4f671 Add files via upload 2026-01-04 18:55:43 +08:00
87owo 238ed8e364 Add files via upload 2026-01-04 18:55:04 +08:00
87owo 8aa1509863 Add files via upload 2026-01-04 13:41:45 +08:00
87owo aac182e30b Add files via upload 2026-01-04 13:40:19 +08:00
87owo ac7e953acc Add files via upload 2026-01-04 12:28:25 +08:00
87owo 6ae0f27e05 Add files via upload 2026-01-04 11:46:45 +08:00
87owo f6e5a92400 Add files via upload 2026-01-02 22:27:59 +08:00
87owo 5e5ff3428c Add files via upload 2026-01-02 22:26:42 +08:00
87owo 1cdbb9c402 Add files via upload 2026-01-02 22:25:22 +08:00
87owo 8caacd1870 Update README.md 2026-01-01 21:38:30 +08:00
87owo cfbc4c9c20 Update README.md 2026-01-01 21:29:21 +08:00
87owo 76dbf1c5d0 Add files via upload 2026-01-01 20:38:03 +08:00
87owo c0e7c4afa5 Add files via upload 2026-01-01 18:31:39 +08:00
87owo 9da0970d85 Delete ProtectRules.cpp 2026-01-01 18:31:01 +08:00
87owo d6f2ad32a7 Delete ProtectRegistry.cpp 2026-01-01 18:30:54 +08:00
87owo 8dbc87a331 Delete ProtectProcess.cpp 2026-01-01 18:30:45 +08:00
87owo 77eb1ce44e Delete ProtectFile.cpp 2026-01-01 18:30:37 +08:00
87owo e12f4ae61a Delete ProtectBoot.cpp 2026-01-01 18:30:29 +08:00
87owo c23a73625f Delete DriverEntry.cpp 2026-01-01 18:30:20 +08:00
87owo 3a66946686 Delete DriverCommon.h 2026-01-01 18:30:13 +08:00
87owo 7fef43701f Add files via upload 2026-01-01 18:29:52 +08:00
87owo 7f5eb34ac6 Add files via upload 2026-01-01 17:41:40 +08:00
87owo ba4369f829 Add files via upload 2026-01-01 03:39:49 +08:00
87owo 81af2e51fc Delete Plugins/Filter/ProtectScreen.c 2026-01-01 03:37:53 +08:00
87owo dff09064c8 Delete Plugins/Filter/ProtectRules.h 2026-01-01 03:37:45 +08:00
87owo ee0bb32cce Delete Plugins/Filter/ProtectRules.c 2026-01-01 03:37:35 +08:00
87owo 4a215c308b Delete Plugins/Filter/ProtectRegistry.c 2026-01-01 03:37:18 +08:00
87owo 79493a96ea Delete Plugins/Filter/ProtectRemote.c 2026-01-01 03:37:07 +08:00
87owo 3cca1c4671 Delete Plugins/Filter/ProtectProcess.c 2026-01-01 03:36:54 +08:00
87owo 72e9923d08 Delete Plugins/Filter/ProtectMatch.h 2026-01-01 03:36:43 +08:00
87owo 406e152891 Delete Plugins/Filter/ProtectMatch.c 2026-01-01 03:36:27 +08:00
87owo e9eb569d50 Delete Plugins/Filter/ProtectInject.c 2026-01-01 03:36:17 +08:00
87owo 640b389e44 Delete Plugins/Filter/ProtectImage.c 2026-01-01 03:36:07 +08:00
87owo 314e3349d6 Delete Plugins/Filter/ProtectFile.c 2026-01-01 03:35:56 +08:00
87owo 0ae4d72bc9 Delete Plugins/Filter/ProtectBoot.c 2026-01-01 03:35:45 +08:00
87owo 8920a5fb21 Delete Plugins/Filter/DriverPipe.c 2026-01-01 03:35:34 +08:00
87owo b338ff5dd9 Delete Plugins/Filter/DriverEntry.h 2026-01-01 03:35:25 +08:00
87owo 87e2fcb37c Delete Plugins/Filter/DriverEntry.c 2026-01-01 03:35:05 +08:00
87owo bab43e3b17 Add files via upload 2026-01-01 03:34:44 +08:00
87owo e602088330 Add files via upload 2025-12-29 20:14:49 +08:00
87owo 2f6db92077 Add files via upload 2025-12-29 20:14:14 +08:00
87owo cee33c0f77 Add files via upload 2025-12-28 14:58:49 +08:00
87owo 4fcdaa10b6 Add files via upload 2025-12-28 14:54:52 +08:00
87owo 949f74ab04 Add files via upload 2025-12-28 14:21:07 +08:00
87owo ef68a89b45 Add files via upload 2025-12-28 14:20:35 +08:00
87owo 10ecb35cca Add files via upload 2025-12-28 14:12:29 +08:00
87owo 696ac22f77 Add files via upload 2025-12-27 15:17:13 +08:00
87owo 8d13f98030 Add files via upload 2025-12-27 02:09:29 +08:00
87owo 1dddf13a9d Add files via upload 2025-12-27 02:08:10 +08:00
87owo 855472239a Delete Engine/Model/train_torch.py 2025-12-27 01:42:33 +08:00
87owo dc5d317623 Delete Engine/Model/train_tensorflow.py 2025-12-27 01:42:24 +08:00
87owo 91011e9e2a Add files via upload 2025-12-27 01:42:07 +08:00
87owo bb09b75d3b Add files via upload 2025-12-27 01:41:45 +08:00
87owo b2f9adad66 Add files via upload 2025-12-27 01:41:03 +08:00
87owo 0c2c84d2a9 Add files via upload 2025-12-26 15:13:42 +08:00
87owo 1733e7cc86 Add files via upload 2025-12-25 23:49:05 +08:00
87owo 831d9a9895 Add files via upload 2025-12-25 18:53:53 +08:00
87owo 70ba3a629d Update README.md 2025-12-25 03:14:28 +08:00
87owo 29e9702d21 Update README.md 2025-12-25 03:12:28 +08:00
87owo f8ef756bd4 Add files via upload 2025-12-25 01:23:41 +08:00
87owo 233b28e8a5 Add files via upload 2025-12-24 22:34:19 +08:00
87owo da77c17be5 Add files via upload 2025-12-24 14:33:17 +08:00
87owo 8dfa76822e Delete Engine/Model/train.py 2025-12-24 14:32:38 +08:00
87owo 4163991b66 Add files via upload 2025-12-24 14:32:18 +08:00
87owo 78323c9a08 Add files via upload 2025-12-24 14:31:06 +08:00
87owo eb517e86f3 Add files via upload 2025-12-24 14:30:13 +08:00
87owo e24f3823cb Add files via upload 2025-12-24 11:15:31 +08:00
87owo fd3e8ee28a Update README.md 2025-12-21 23:27:08 +08:00
87owo a980ea7bd6 Update README.md 2025-12-21 23:26:00 +08:00
87owo 20ce73c54f Update README.md 2025-12-21 23:17:32 +08:00
87owo d8f22f7f28 Update README.md 2025-12-21 23:16:03 +08:00
87owo 591055edaf Update README.md 2025-12-21 23:13:09 +08:00
87owo fbf0e06c04 Update LICENSE.txt 2025-12-19 22:46:40 +08:00
87owo 9daf327e80 Update README.md 2025-12-19 22:42:21 +08:00
87owo 4441978e10 Update LICENSE.txt 2025-12-19 22:38:14 +08:00
87owo d8eb770735 Update LICENSE.txt 2025-12-18 20:12:03 +08:00
87owo cefbf79c6e Update LICENSE.txt 2025-12-11 20:01:08 +08:00
87owo fc8762094e Update LICENSE.txt 2025-12-11 20:00:42 +08:00
87owo 801c3aadcc Update LICENSE.txt 2025-12-09 11:43:08 +08:00
87owo 4296f1ec43 Add files via upload 2025-11-27 15:28:31 +08:00
87owo a7f469747c Add files via upload 2025-11-27 14:57:17 +08:00
87owo 68d0352343 Add files via upload 2025-11-27 14:56:17 +08:00
87owo 01e6d09f7c Update train.py 2025-11-26 17:56:08 +08:00
87owo 6582abfd4a Update train.py 2025-11-26 17:26:31 +08:00
87owo f8f4b303d7 Update LICENSE.txt 2025-11-01 17:08:11 +08:00
87owo 79f05a23a8 Add files via upload 2025-10-08 11:51:18 +08:00
87owo 95845c5c85 Add files via upload 2025-10-08 11:05:43 +08:00
87owo cd1a24290e Add files via upload 2025-10-07 23:08:14 +08:00
87owo 21261bfb17 Add files via upload 2025-10-07 22:48:17 +08:00
87owo 79abf51cb8 Add files via upload 2025-10-07 22:25:51 +08:00
36 changed files with 2308 additions and 2819 deletions

No files matched your search

+16 -34
View File
@@ -9,43 +9,22 @@ def preprocess_image(file_data, size, channels=1):
arr = numpy.frombuffer(file_data, dtype=numpy.uint8)
img = numpy.zeros(wah*wah*channels, dtype=numpy.uint8)
img[:len(file_data)] = arr
if channels == 1:
image = Image.fromarray(img.reshape((wah, wah)), 'L')
else:
image = Image.fromarray(img.reshape((wah, wah, channels)), 'RGB')
image = Image.fromarray(img.reshape((wah, wah)), 'L')
return image.resize((width, height), Image.Resampling.NEAREST)
####################################################################################################
def is_text_file(content, sample_size=1024):
raw = content[:sample_size]
if not raw:
return False
text_char = set(range(32, 127)) | {9, 10, 13}
nontext = sum(b not in text_char for b in raw)
return nontext / len(raw) < 0.15
def get_type(file_path):
suffix = {
".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys",
".bat", ".cmd", ".js", ".php", ".ps1", ".vbs", ".wsf"}
match_data = {}
if not os.path.splitext(file_path)[-1].lower() in suffix:
return match_data
suffix = {".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".mui", ".cpl"}
try:
with pefile.PE(file_path, fast_load=True) as pe:
for section in pe.sections:
name = section.Name.rstrip(b'\x00').decode('latin1').lower()
if section.Characteristics & 0x00000020:
match_data[name] = section.get_data()
except pefile.PEFormatError:
file_content = None
if not os.path.splitext(file_path)[-1].lower() in suffix:
return file_content
with open(file_path, 'rb') as f:
file_content = f.read()
if is_text_file(file_content):
match_data[os.path.splitext(file_path)[-1].lower()] = file_content
return match_data
except:
pass
return file_content
####################################################################################################
@@ -54,20 +33,23 @@ def file_to_images(input_dir, output_dir):
for file in files:
try:
file_path = os.path.join(root, file)
for name, data in get_type(file_path).items():
print(name, file_path)
file_content = get_type(file_path)
if file_content:
print(file_path)
relative_path = os.path.relpath(root, input_dir)
output_path_dir = os.path.join(output_dir, relative_path)
if not os.path.exists(output_path_dir):
os.makedirs(output_path_dir)
image = preprocess_image(data, (224, 224))
image.save(os.path.join(output_path_dir, f"{name}_{file}.png"))
image = preprocess_image(file_content, (224, 224))
safe_name = os.path.basename(file_path).replace('/', '_').replace('\\', '_')
image.save(os.path.join(output_path_dir, f"{safe_name}.png"))
except Exception as e:
print(e)
####################################################################################################
input_directory = input('Enter the folder path: ')
output_directory = "./Image_File"
output_directory = "./Image_Output"
file_to_images(input_directory, output_directory)
input('Conversion Complete')
+1 -1
View File
@@ -30,5 +30,5 @@ def dedup_realtime(root):
####################################################################################################
if __name__ == "__main__":
dedup_realtime(r".\Image_File")
dedup_realtime(input("Input file path: "))
input('Deduplicate Complete')
+80 -49
View File
@@ -2,6 +2,7 @@ import tensorflow as tf
import os, tf2onnx, numpy, random
from PIL import Image
from tensorflow.keras import *
from collections import Counter
####################################################################################################
@@ -10,36 +11,10 @@ tf.keras.mixed_precision.set_global_policy('mixed_float16')
####################################################################################################
def get_file_list(directory):
file_paths, labels, class_indices = [], [], {}
for i, cls in enumerate(sorted([d for d in os.listdir(directory) if os.path.isdir(os.path.join(directory, d))])):
class_indices[cls] = i
cls_dir = os.path.join(directory, cls)
for root, _, files in os.walk(cls_dir):
for file in files:
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif')):
file_paths.append(os.path.join(root, file))
labels.append(i)
return file_paths, labels, class_indices
####################################################################################################
def parse_fn(filename, label, image_size, channels, num_classes):
img = tf.io.read_file(filename)
img = tf.image.decode_image(img, channels=channels, expand_animations=False)
img = tf.cond(
tf.reduce_all(tf.equal(tf.shape(img)[:2], image_size)),
lambda: tf.cast(img, tf.float32),
lambda: tf.image.resize(img, image_size))
img = tf.cast(img, tf.float32) / 255.0
label = tf.one_hot(label, depth=num_classes)
return img, label
####################################################################################################
def load_dataset(data_dir, image_size=(224, 224), val_split=0.00001, batch_size=128, color_mode="grayscale"):
def load_dataset(data_dir, image_size=(224, 224), val_split=0.00001, batch_size=256, color_mode="grayscale"):
channels = 1 if color_mode == "grayscale" else 3
file_paths, labels, class_indices = get_file_list(data_dir)
combined = list(zip(file_paths, labels))
random.shuffle(combined)
file_paths[:], labels[:] = zip(*combined)
@@ -64,11 +39,35 @@ def load_dataset(data_dir, image_size=(224, 224), val_split=0.00001, batch_size=
####################################################################################################
def parse_fn(filename, label, image_size, channels, num_classes):
img = tf.io.read_file(filename)
img = tf.image.decode_image(img, channels=channels, expand_animations=False)
img = tf.cond(tf.reduce_all(tf.equal(tf.shape(img)[:2], image_size)), lambda: tf.cast(img, tf.float32), lambda: tf.image.resize(img, image_size))
img = tf.cast(img, tf.float32) / 255.0
label = tf.one_hot(label, depth=num_classes)
return img, label
def get_file_list(directory):
file_paths, labels, class_indices = [], [], {}
for i, cls in enumerate(sorted([d for d in os.listdir(directory) if os.path.isdir(os.path.join(directory, d))])):
class_indices[cls] = i
cls_dir = os.path.join(directory, cls)
for root, _, files in os.walk(cls_dir):
for file in files:
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif')):
file_paths.append(os.path.join(root, file))
labels.append(i)
return file_paths, labels, class_indices
####################################################################################################
def multi_conv(x, strides):
convs = []
for k in [1, 3, 5, 7]:
for k in [(1, 7), (1, 1), (3, 3), (5, 5)]:
c = layers.DepthwiseConv2D(kernel_size=k, strides=strides, padding='same', activation='gelu')(x)
convs.append(c)
x = layers.Concatenate()(convs)
x = layers.BatchNormalization()(x)
return layers.Activation('gelu')(x)
@@ -78,12 +77,27 @@ def gated_conv(x, strides):
g = layers.DepthwiseConv2D(3, strides=strides, padding='same', activation='sigmoid')(x)
return layers.Multiply()([c, g])
def se_block(x, reduction):
def coordinate_attention(x, reduction):
input_shape = tf.shape(x)
h, w = input_shape[1], input_shape[2]
filters = x.shape[-1]
s = layers.Conv2D(filters // reduction, 1, padding='same', activation='gelu')(x)
s = layers.BatchNormalization()(s)
s = layers.Conv2D(filters, 1, padding='same', activation='sigmoid')(s)
return layers.multiply([x, s])
mip = max(8, filters // reduction)
x_h = layers.Lambda(lambda t: tf.reduce_mean(t, axis=2, keepdims=True))(x)
x_w = layers.Lambda(lambda t: tf.reduce_mean(t, axis=1, keepdims=True))(x)
x_w_t = layers.Permute((2, 1, 3))(x_w)
x_cat = layers.Concatenate(axis=1)([x_h, x_w_t])
x_cat = layers.Conv2D(mip, 1, padding='valid', use_bias=False)(x_cat)
x_cat = layers.BatchNormalization()(x_cat)
x_cat = layers.Activation('gelu')(x_cat)
x_cat_h, x_cat_w = layers.Lambda(lambda t: tf.split(t[0], [t[1], t[2]], axis=1))([x_cat, h, w])
x_h_sigmoid = layers.Conv2D(filters, 1, padding='valid', activation='sigmoid')(x_cat_h)
x_cat_w = layers.Permute((2, 1, 3))(x_cat_w)
x_w_sigmoid = layers.Conv2D(filters, 1, padding='valid', activation='sigmoid')(x_cat_w)
return layers.Multiply()([x, x_h_sigmoid, x_w_sigmoid])
def build_model(input_shape, num_classes):
i = layers.Input(shape=input_shape)
@@ -93,40 +107,57 @@ def build_model(input_shape, num_classes):
x = multi_conv(x, strides=2)
x = multi_conv(x, strides=2)
x = multi_conv(x, strides=2)
x = se_block(x, reduction=2)
x = coordinate_attention(x, reduction=4)
x = layers.GlobalMaxPooling2D()(x)
x = layers.Dense(x.shape[-1] // 2, activation='gelu', dtype='float32')(x)
o = layers.Dense(num_classes, activation='softmax', dtype='float32')(x)
return models.Model(i, o)
####################################################################################################
def lr_scheduler(epoch, lr):
return 1e-4 * (0.95 ** epoch)
def calculate_lr_cosine_sq(epoch, total_epochs=30, lr_start=5e-4, lr_end=5e-7):
cos_val = 0.5 * (1 + numpy.cos(epoch / total_epochs * numpy.pi))
return lr_end + (lr_start - lr_end) * (cos_val ** 2)
def lr_scheduler(epoch):
return calculate_lr_cosine_sq(epoch)
def categorical_focal_loss(gamma=2.0, alpha=0.25):
def focal_loss(y_true, y_pred):
y_pred = tf.clip_by_value(y_pred, tf.keras.backend.epsilon(), 1.0 - tf.keras.backend.epsilon())
cross_entropy = -y_true * tf.math.log(y_pred)
loss = alpha * tf.math.pow(1.0 - y_pred, gamma) * cross_entropy
return tf.reduce_sum(loss, axis=-1)
return focal_loss
class CustomModelCheckpoint(callbacks.Callback):
def on_epoch_end(self, epoch, logs=False):
models.save_model(self.model, f"PYAS_Model_Epoch_{epoch + 1}.h5")
spec = (tf.TensorSpec((None,) + train_ds.image_shape, tf.float32),)
model_proto, _ = tf2onnx.convert.from_keras(self.model, input_signature=spec, opset=18)
model_proto, _ = tf2onnx.convert.from_keras(self.model, input_signature=spec, opset=17)
with open(f"PYAS_Model_Epoch_{epoch + 1}.onnx", "wb") as f:
f.write(model_proto.SerializeToString())
####################################################################################################
train_ds, val_ds = load_dataset(r'.\Image_File')
train_ds, val_ds = load_dataset(r'.\Image_Full_Pefile')
for imgs, _ in train_ds.take(1):
train_ds.image_shape = imgs.shape[1:]
break
strategy = tf.distribute.MirroredStrategy(cross_device_ops=tf.distribute.HierarchicalCopyAllReduce())
with strategy.scope():
try:
model = models.load_model('PYAS_Model_Epoch_0.h5')
print("Load model from disk")
except:
print("Creating a new model")
model = build_model(train_ds.image_shape, len(train_ds.class_indices))
print(f"Total parameters: {model.count_params()}")
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
try:
model = models.load_model('PYAS_Model_Epoch_0.h5')
print("Load model from disk")
except:
print("Creating a new model")
model = build_model(train_ds.image_shape, len(train_ds.class_indices))
print(f"Total parameters: {model.count_params()}")
model.compile(optimizer='adam', loss=categorical_focal_loss(gamma=2.0, alpha=0.25),
metrics=['accuracy', metrics.Precision(name='precision'), metrics.Recall(name='recall'),
metrics.FalsePositives(name='fp'), metrics.TrueNegatives(name='tn')])
model.fit(train_ds, epochs=30, callbacks=[CustomModelCheckpoint(), callbacks.LearningRateScheduler(lr_scheduler)], validation_data=val_ds)
input('Training Complete')
+24 -15
View File
@@ -1,22 +1,31 @@
87owo software and source code Development License Agreement
Last updated: 2025-09-09
87owo Publicly Available Source Code License Agreement
Last updated: 2025-12-19
1. License and Ownership
– A single device key may be required to activate the software or source code.
– 87owo reserves all rights. Intellectual property rights are not transferred.
– All project script archives and executable files are proprietary.
- This software and its source code are source available for public view.
- Access or execution of certain features may require an activation key.
- 87owo reserves all legal rights, no intellectual property is transferred.
- All project archives, source code, and binaries remain fully proprietary.
2. Use and Prohibitions
– Reverse engineering, removal of licenses, or use for illegal purposes is prohibited.
– Personal internal use or modification of the source code is permitted.
– Redistribution, etc. requires prior authorization from the original author.
- You may view, download, and modify the code for local and personal use.
- Redistribution of any original or modified code requires prior consent.
- Commercial hosting or SaaS deployment is prohibited without permission.
- Reverse engineering, license removal, or illegal use is strictly barred.
3. Updates and Terms
– New versions and updates may include patches, enhancements, or modifications.
– Continued use constitutes your acceptance of these features or license.
3. Data and Privacy
- This project may collect operational data for optimization and analysis.
- All collected data is strictly anonymized to ensure the user's privacy.
- Transmission of information is encrypted to prevent unauthorized access.
4. Warranty and Liability
– This software or code is provided "as is" without warranty of any kind.
– In no event will we be liable for any direct or indirect damages.
4. Updates and Terms
- New releases may include critical patches, enhancements, or UI changes.
- Continued use of these services constitutes acceptance of updated terms.
- The author reserves the right to modify these license terms at any time.
© 2020–2025 87owo (PYAS Security). All rights reserved.
5. Warranty and Liability
- All services and assets are provided "as is" without any form of warranty.
- 87owo is not liable for any direct or indirect damages from software use.
- Users assume all risks regarding performance, data, and system integrity.
© 2020-2026 87owo (PYAS Security). All rights reserved.
+324 -152
View File
@@ -1,7 +1,7 @@
import os, gc, re, sys, time, json, shutil
import os, gc, re, sys, time, json, uuid, queue
import ctypes, ctypes.wintypes, threading
import requests, webbrowser, winreg, msvcrt
import traceback, hashlib
import traceback, hashlib, subprocess, shutil
from PYAS_Config import *
from PYAS_Engine import *
@@ -13,7 +13,7 @@ from PySide6.QtGui import *
####################################################################################################
class PROCESSENTRY32(ctypes.Structure):
class PROCESSENTRY32W(ctypes.Structure):
_fields_ = [
("dwSize", ctypes.wintypes.DWORD),
("cntUsage", ctypes.wintypes.DWORD),
@@ -22,8 +22,9 @@ class PROCESSENTRY32(ctypes.Structure):
("th32ModuleID", ctypes.wintypes.DWORD),
("cntThreads", ctypes.wintypes.DWORD),
("th32ParentProcessID", ctypes.wintypes.DWORD),
("pcPriClassBase", ctypes.wintypes.LONG),
("dwFlags", ctypes.wintypes.DWORD),
("szExeFile", ctypes.wintypes.CHAR * 260)]
("szExeFile", ctypes.wintypes.WCHAR * 260)]
class MIB_TCPROW_OWNER_PID(ctypes.Structure):
_fields_ = [
@@ -62,8 +63,7 @@ class PROCESS_BASIC_INFORMATION(ctypes.Structure):
("PebBaseAddress", ctypes.wintypes.LPVOID),
("Reserved2", ctypes.wintypes.LPVOID * 2),
("UniqueProcessId", ctypes.wintypes.LPVOID),
("Reserved3", ctypes.wintypes.LPVOID)
]
("Reserved3", ctypes.wintypes.LPVOID)]
class UNICODE_STRING(ctypes.Structure):
_fields_ = [
@@ -71,6 +71,22 @@ class UNICODE_STRING(ctypes.Structure):
("MaximumLength", ctypes.wintypes.USHORT),
("Buffer", ctypes.c_void_p)]
class FILTER_MESSAGE_HEADER(ctypes.Structure):
_fields_ = [
("ReplyLength", ctypes.wintypes.ULONG),
("MessageId", ctypes.c_uint64)]
class PYAS_MESSAGE(ctypes.Structure):
_fields_ = [
("MessageCode", ctypes.wintypes.ULONG),
("ProcessId", ctypes.wintypes.ULONG),
("Path", ctypes.wintypes.WCHAR * 1024)]
class PYAS_FULL_MESSAGE(ctypes.Structure):
_fields_ = [
("Header", FILTER_MESSAGE_HEADER),
("Data", PYAS_MESSAGE)]
####################################################################################################
class MainWindow_Controller(QMainWindow):
@@ -78,7 +94,10 @@ class MainWindow_Controller(QMainWindow):
scan_add_virus_signal = Signal(str)
scan_result_signal = Signal(str)
scan_reset_signal = Signal()
scan_update_signal = Signal(str, str)
scan_remove_signal = Signal(str)
progress_title_signal = Signal(str)
init_log_signal = Signal(str)
def __init__(self):
super().__init__()
@@ -89,11 +108,6 @@ class MainWindow_Controller(QMainWindow):
self.load_config()
self.init_interface()
self.init_windll()
self.backup_mbr()
self.relock_file()
self.init_whitelist()
self.init_thread()
self.init_connect()
self.show_startup()
####################################################################################################
@@ -107,9 +121,10 @@ class MainWindow_Controller(QMainWindow):
self.sign = sign_scanner()
self.sign.init_windll(["wintrust"])
self.model = model_scanner()
self.model.load_path(self.path_models)
self.rule = rule_scanner()
self.rule.load_path(self.path_rules)
self.cloud = cloud_scanner()
self.cloud_queue = queue.Queue()
self.init_cloud_worker()
self.mouse_flag = 0
self.mouse_pos = 0
@@ -129,11 +144,14 @@ class MainWindow_Controller(QMainWindow):
"traditional_switch", "simplified_switch", "english_switch",
]
self.pyas_default = {
"version": "3.3.6",
"product": "00000-00000-00000-00000-00000",
"version": "3.3.8",
"api_host": "https://pyas-security.com/",
"api_key": "",
"suffix": [".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".mui", ".cpl"],
"size": 256 * 1024 * 1024,
"sensitive": 95,
"language": "english_switch",
"theme": "white_switch",
"sensitive": 95,
"process_switch": True,
"document_switch": True,
"system_switch": True,
@@ -187,7 +205,7 @@ class MainWindow_Controller(QMainWindow):
####################################################################################################
def init_windll(self):
for name in ["ntdll", "Psapi", "user32", "kernel32", "advapi32", "iphlpapi", "shell32"]:
for name in ["ntdll", "Psapi", "user32", "kernel32", "advapi32", "iphlpapi", "shell32", "fltlib"]:
try:
setattr(self, name.lower(), ctypes.WinDLL(name, use_last_error=True))
except Exception as e:
@@ -200,8 +218,7 @@ class MainWindow_Controller(QMainWindow):
ctypes.wintypes.HANDLE, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD, ctypes.c_wchar_p,
ctypes.c_wchar_p, ctypes.POINTER(ctypes.wintypes.DWORD), ctypes.c_wchar_p, ctypes.c_wchar_p,
ctypes.c_wchar_p
]
ctypes.c_wchar_p]
self.advapi32.CreateServiceW.restype = ctypes.wintypes.HANDLE
self.advapi32.OpenServiceW.argtypes = [ctypes.wintypes.HANDLE, ctypes.c_wchar_p, ctypes.wintypes.DWORD]
@@ -225,6 +242,11 @@ class MainWindow_Controller(QMainWindow):
self.shell32.CommandLineToArgvW.argtypes = [ctypes.wintypes.LPCWSTR, ctypes.POINTER(ctypes.c_int)]
self.shell32.CommandLineToArgvW.restype = ctypes.POINTER(ctypes.wintypes.LPWSTR)
self.fltlib.FilterConnectCommunicationPort.argtypes = [ctypes.wintypes.LPCWSTR, ctypes.wintypes.DWORD, ctypes.c_void_p, ctypes.wintypes.DWORD, ctypes.c_void_p, ctypes.POINTER(ctypes.wintypes.HANDLE)]
self.fltlib.FilterConnectCommunicationPort.restype = ctypes.c_long
self.fltlib.FilterGetMessage.argtypes = [ctypes.wintypes.HANDLE, ctypes.c_void_p, ctypes.wintypes.DWORD, ctypes.c_void_p]
self.fltlib.FilterGetMessage.restype = ctypes.c_long
####################################################################################################
def save_config(self, file_path, config):
@@ -270,6 +292,16 @@ class MainWindow_Controller(QMainWindow):
self.pyas_config[key] = []
return self.pyas_config[key]
####################################################################################################
def init_engine_thread(self):
try:
self.rule.load_path(self.path_rules, callback=lambda x: self.init_log_signal.emit(os.path.basename(x)))
self.model.load_path(self.path_models, callback=lambda x: self.init_log_signal.emit(os.path.basename(x)))
self.init_log_signal.emit("引擎加載完成")
except Exception as e:
self.send_message(e, "warn", False)
####################################################################################################
def init_interface(self):
@@ -297,7 +329,7 @@ class MainWindow_Controller(QMainWindow):
def create_shadow(self):
shadow = QGraphicsDropShadowEffect(self)
shadow.setOffset(0, 0)
shadow.setBlurRadius(20)
shadow.setBlurRadius(15)
shadow.setColor(QColor(175, 175, 175))
return shadow
@@ -313,7 +345,10 @@ class MainWindow_Controller(QMainWindow):
self.scan_add_virus_signal.connect(self.slot_scan_add_virus)
self.scan_result_signal.connect(self.slot_scan_result)
self.scan_reset_signal.connect(self.slot_scan_reset)
self.scan_update_signal.connect(self.slot_scan_update)
self.scan_remove_signal.connect(self.slot_scan_remove)
self.progress_title_signal.connect(self.slot_progress_title)
self.init_log_signal.connect(self.slot_init_log)
for name, widget in self.widgets.items():
if hasattr(widget, "setCheckable") and widget.isCheckable():
@@ -572,12 +607,19 @@ class MainWindow_Controller(QMainWindow):
def show_startup(self):
try:
if self.singleton_mutex("pyas_security"):
self.backup_mbr()
self.relock_file()
self.init_whitelist()
self.init_thread()
self.init_connect()
param = ""
if self.args_pyas:
param = self.args_pyas[0].replace("/", "-")
if "-h" not in param:
self.show_button()
self.apply_settings()
self.start_daemon_thread(self.init_engine_thread)
else:
sys.exit(0)
except Exception as e:
@@ -614,20 +656,16 @@ class MainWindow_Controller(QMainWindow):
def reset_button(self):
if self.send_message("您確定要重置所有設定嗎?", "quest", True):
self.pyas_config = self.pyas_default.copy()
self.restart_button()
def restart_button(self):
self.save_config(self.file_config, self.pyas_config)
self.minimize_button()
while self.isVisible():
QApplication.processEvents()
os.execl(self.python, self.python, *sys.argv)
self.close_button()
def singleton_mutex(self, name):
mutex = self.kernel32.CreateMutexW(None, False, name)
if self.kernel32.GetLastError() == 183:
try:
self.h_mutex = self.kernel32.CreateMutexW(None, False, name)
if self.kernel32.GetLastError() == 183:
return False
return True
except Exception:
return False
return True
####################################################################################################
@@ -747,6 +785,23 @@ class MainWindow_Controller(QMainWindow):
self.widgets["method_button"].show()
self.send_message(msg, "notify", True)
@Slot(str)
def slot_init_log(self, text):
self.send_message(text, "load", True)
@Slot(str, str)
def slot_scan_update(self, old_text, new_text):
items = self.widgets["virus_list"].findItems(old_text, Qt.MatchExactly)
if items:
items[0].setText(new_text)
@Slot(str)
def slot_scan_remove(self, text):
items = self.widgets["virus_list"].findItems(text, Qt.MatchExactly)
if items:
row = self.widgets["virus_list"].row(items[0])
self.widgets["virus_list"].takeItem(row)
####################################################################################################
def init_scan(self):
@@ -794,10 +849,16 @@ class MainWindow_Controller(QMainWindow):
continue
self.scan_count += 1
state = self.scan_engine(norm_path)
if state:
suffix = self.pyas_config.get("suffix", [".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".mui"])
ext = os.path.splitext(file_path)[-1].lower()
if ext not in suffix:
continue
result = self.scan_engine(norm_path)
if result:
self.virus_results.append(norm_path)
self.scan_add_virus_signal.emit(f"[{state}] > {norm_path}")
self.scan_add_virus_signal.emit(f"[{result}] > {norm_path}")
self.start_daemon_thread(self.cloud_check, norm_path)
lang = self.pyas_config.get("language", "english_switch")
self.progress_title_signal.emit(self.trans(lang, "正在掃描"))
@@ -829,21 +890,83 @@ class MainWindow_Controller(QMainWindow):
def scan_engine(self, file_path):
try:
if self.sign.sign_verify(file_path):
return False
result = False
label, level = self.model.model_scan(file_path)
if label and level >= self.pyas_config.get("sensitive", 95):
return f"{label}.{level}"
if not self.sign.sign_verify(file_path):
result = f"{label}.{level}"
if self.pyas_config.get("extension_switch", False):
label, level = self.rule.yara_scan(file_path)
if label and level:
return f"{label}.{level}"
return False
types, detail = self.rule.yara_scan(file_path)
if types and detail:
result = f"{types}.{detail}"
return result
except Exception as e:
self.send_message(e, "warn", False)
return None
return False
####################################################################################################
def init_cloud_worker(self):
for _ in range(1):
t = threading.Thread(target=self.cloud_worker, daemon=True)
t.start()
def cloud_worker(self):
while True:
try:
file_path = self.cloud_queue.get()
self.perform_cloud_scan(file_path)
self.cloud_queue.task_done()
except Exception:
pass
def cloud_check(self, file_path, get_result=False):
if get_result:
return self.perform_cloud_scan(file_path, get_result=True)
self.cloud_queue.put(file_path)
def perform_cloud_scan(self, file_path, get_result=False):
was_locked = False
try:
if not os.path.exists(file_path):
return False
if file_path in self.virus_lock:
self.lock_file(file_path, False)
was_locked = True
size = os.path.getsize(file_path)
if size > self.pyas_config.get("size", 256 * 1024 * 1024):
if was_locked:
self.lock_file(file_path, True)
return False
api_host = self.pyas_config.get("api_host", "https://pyas-security.com/")
api_key = self.pyas_config.get("api_key", "")
success, sha256 = self.cloud.upload_file(file_path, api_host, api_key)
if was_locked:
self.lock_file(file_path, True)
was_locked = False
if success and sha256:
if get_result:
return self.cloud.get_result(sha256, api_host, api_key)
else:
self.send_message(f"雲端服務 | 通訊服務錯誤 | None | {file_path} | None", "warn", True)
except Exception as e:
self.send_message(e, "warn", False)
finally:
if 'was_locked' in locals() and was_locked:
try:
self.lock_file(file_path, True)
except Exception:
pass
return False
####################################################################################################
@@ -934,7 +1057,7 @@ class MainWindow_Controller(QMainWindow):
self.send_message(f"成功增加到白名單,共 {n} 個檔案", "info", True)
widget.takeItem(widget.row(item))
self.virus_results.remove(file_path)
except:
except Exception as e:
self.send_message(e, "warn", False)
elif act == quarantine_action:
@@ -945,7 +1068,7 @@ class MainWindow_Controller(QMainWindow):
self.send_message(f"成功增加到隔離區,共 {n} 個檔案", "info", True)
widget.takeItem(widget.row(item))
self.virus_results.remove(file_path)
except:
except Exception as e:
self.send_message(e, "warn", False)
count = len(self.virus_results)
@@ -956,7 +1079,7 @@ class MainWindow_Controller(QMainWindow):
def list_process(self):
pe = self.get_process_entry()
snapshot = self.kernel32.CreateToolhelp32Snapshot(0x00000002, 0)
result, success = [], self.kernel32.Process32First(snapshot, ctypes.byref(pe))
result, success = [], self.kernel32.Process32FirstW(snapshot, ctypes.byref(pe))
while success:
pid = pe.th32ProcessID
@@ -964,15 +1087,13 @@ class MainWindow_Controller(QMainWindow):
if pid > 4:
name, file_path = self.get_exe_info(pid)
if not name:
raw = bytes(pe.szExeFile).split(b"\x00", 1)[0]
if raw:
try:
name = raw.decode("mbcs", errors="replace") or None
except Exception:
name = None
try:
name = pe.szExeFile
except Exception:
name = None
result.append((pid, name, file_path))
success = self.kernel32.Process32Next(snapshot, ctypes.byref(pe))
success = self.kernel32.Process32NextW(snapshot, ctypes.byref(pe))
self.kernel32.CloseHandle(snapshot)
return result
@@ -1044,21 +1165,21 @@ class MainWindow_Controller(QMainWindow):
self.kill_process(pid)
elif act == white_action:
file_path = self.norm_path(path)
if file_path and self.send_message("您確定要增加到白名單嗎?", "quest"):
target_path = self.norm_path(file_path)
if target_path and self.send_message("您確定要增加到白名單嗎?", "quest"):
try:
n = self.manage_named_list("white_list", [file_path], action="add", with_hash=True)
n = self.manage_named_list("white_list", [target_path], action="add", with_hash=True)
self.send_message(f"成功增加到白名單,共 {n} 個檔案", "info", True)
except:
except Exception as e:
self.send_message(e, "warn", False)
elif act == quarantine_action:
file_path = self.norm_path(path)
if file_path and self.send_message("您確定要增加到隔離區嗎?", "quest"):
target_path = self.norm_path(file_path)
if target_path and self.send_message("您確定要增加到隔離區嗎?", "quest"):
try:
n = self.manage_named_list("quarantine", [file_path], action="add", with_hash=True, lock_func=self.lock_file)
n = self.manage_named_list("quarantine", [target_path], action="add", with_hash=True, lock_func=self.lock_file)
self.send_message(f"成功增加到隔離區,共 {n} 個檔案", "info", True)
except:
except Exception as e:
self.send_message(e, "warn", False)
def kill_process(self, pid):
@@ -1286,6 +1407,35 @@ class MainWindow_Controller(QMainWindow):
except Exception as e:
self.send_message(e, "warn", False)
####################################################################################################
def check_process_survival(self):
target_map = {
"explorer.exe": "explorer.exe"
}
try:
running = set()
pe = self.get_process_entry()
snapshot = self.kernel32.CreateToolhelp32Snapshot(0x00000002, 0)
if self.kernel32.Process32FirstW(snapshot, ctypes.byref(pe)):
while True:
try:
name = pe.szExeFile.lower()
running.add(name)
except:
pass
if not self.kernel32.Process32NextW(snapshot, ctypes.byref(pe)):
break
self.kernel32.CloseHandle(snapshot)
for name, cmd in target_map.items():
if name.lower() not in running:
subprocess.Popen(cmd, shell=True)
self.send_message(f"系統防護 | 系統進程重啟 | None | None | {name}", "notify", True)
except Exception as e:
self.send_message(e, "warn", False)
####################################################################################################
def popup_button(self):
@@ -1407,19 +1557,19 @@ class MainWindow_Controller(QMainWindow):
if name:
return name
snapshot = self.kernel32.CreateToolhelp32Snapshot(0x00000002, 0)
entry = PROCESSENTRY32()
entry.dwSize = ctypes.sizeof(PROCESSENTRY32)
entry = PROCESSENTRY32W()
entry.dwSize = ctypes.sizeof(PROCESSENTRY32W)
result = ""
if self.kernel32.Process32First(snapshot, ctypes.byref(entry)):
if self.kernel32.Process32FirstW(snapshot, ctypes.byref(entry)):
while True:
if entry.th32ProcessID == pid:
try:
result = entry.szExeFile.decode("mbcs").rstrip("\x00")
result = entry.szExeFile
except Exception:
result = ""
break
if not self.kernel32.Process32Next(snapshot, ctypes.byref(entry)):
if not self.kernel32.Process32NextW(snapshot, ctypes.byref(entry)):
break
self.kernel32.CloseHandle(snapshot)
return result
@@ -1521,7 +1671,15 @@ class MainWindow_Controller(QMainWindow):
def website_button(self):
try:
webbrowser.open("https://github.com/87owo/PYAS")
webbrowser.open("https://pyas-security.com/antivirus")
return True
except Exception as e:
self.send_message(e, "warn", False)
return False
def cloud_button(self):
try:
webbrowser.open("https://pyas-security.com/analyze")
return True
except Exception as e:
self.send_message(e, "warn", False)
@@ -1624,7 +1782,8 @@ class MainWindow_Controller(QMainWindow):
continue
if self.scan_engine(file_path):
self.kernel32.TerminateProcess(h, 0)
self.send_message(f"進程防護 | 靜態掃描攔截 | {pid} | {file_path} | None", "notify", True)
self.send_message(f"進程防護 | 靜態掃描攔截 | {pid} | None | {file_path}", "notify", True)
self.start_daemon_thread(self.cloud_check, file_path)
self.suspend_process(h, False)
self.kernel32.CloseHandle(h)
@@ -1650,10 +1809,10 @@ class MainWindow_Controller(QMainWindow):
def get_process_list(self):
exist_process, pe = set(), self.get_process_entry()
hSnapshot = self.kernel32.CreateToolhelp32Snapshot(0x00000002, 0)
if self.kernel32.Process32First(hSnapshot, ctypes.byref(pe)):
if self.kernel32.Process32FirstW(hSnapshot, ctypes.byref(pe)):
while True:
exist_process.add(pe.th32ProcessID)
if not self.kernel32.Process32Next(hSnapshot, ctypes.byref(pe)):
if not self.kernel32.Process32NextW(hSnapshot, ctypes.byref(pe)):
break
self.kernel32.CloseHandle(hSnapshot)
return exist_process
@@ -1665,8 +1824,8 @@ class MainWindow_Controller(QMainWindow):
return ""
def get_process_entry(self):
pe = PROCESSENTRY32()
pe.dwSize = ctypes.sizeof(PROCESSENTRY32)
pe = PROCESSENTRY32W()
pe.dwSize = ctypes.sizeof(PROCESSENTRY32W)
return pe
def get_exe_info(self, pid):
@@ -1760,17 +1919,27 @@ class MainWindow_Controller(QMainWindow):
bytes_returned = ctypes.wintypes.DWORD()
res = self.kernel32.ReadDirectoryChangesW(hDir, buffer, ctypes.sizeof(buffer), True,
0x0000001F, ctypes.byref(bytes_returned), None, None)
if not res:
continue
if res:
notify = FILE_NOTIFY_INFORMATION.from_buffer_copy(buffer)
raw_filename = notify.FileName[:notify.FileNameLength // 2]
file_path = self.norm_path(os.path.join(self.path_user, raw_filename))
notify = FILE_NOTIFY_INFORMATION.from_buffer_copy(buffer)
raw_filename = notify.FileName[:notify.FileNameLength // 2]
if not raw_filename:
continue
if notify.Action in [2, 3, 4] and not self.is_in_whitelist(file_path):
state = self.scan_engine(file_path)
if state:
self.add_to_quarantine([file_path])
self.send_message(f"檔案防護 | 靜態掃描攔截 | None | {file_path} | None", "notify", True)
file_path = self.norm_path(os.path.join(self.path_user, raw_filename), must_exist=True)
if file_path and notify.Action in [2, 3, 4] and not self.is_in_whitelist(file_path):
suffix = self.pyas_config.get("suffix", [".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".mui"])
ext = os.path.splitext(file_path)[-1].lower()
if ext not in suffix:
continue
state = self.scan_engine(file_path)
if state:
self.add_to_quarantine([file_path])
self.send_message(f"檔案防護 | 靜態掃描攔截 | None | None | {file_path}", "notify", True)
self.start_daemon_thread(self.cloud_check, file_path)
except Exception as e:
self.send_message(e, "warn", False)
self.kernel32.CloseHandle(hDir)
@@ -1847,97 +2016,100 @@ class MainWindow_Controller(QMainWindow):
self.repair_system_file_type()
self.repair_system_file_icon()
self.repair_system_image()
time.sleep(0.2)
self.check_process_survival()
time.sleep(0.5)
except Exception as e:
self.send_message(e, "warn", False)
####################################################################################################
def install_system_driver(self):
service_name = "PYAS_Driver"
scm = self.advapi32.OpenSCManagerW(None, None, 0xF003F)
if not scm:
try:
service_name = "PYAS_Driver"
bin_path = self.path_drivers
cmd = [
"sc", "create", service_name,
f"binPath={bin_path}",
"type=kernel",
"start=demand",
"error=normal",
"depend=FltMgr",
"group=\"FSFilter Activity Monitor\""]
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
key_path = r"SYSTEM\CurrentControlSet\Services\PYAS_Driver\Instances"
with winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, key_path) as key:
winreg.SetValueEx(key, "DefaultInstance", 0, winreg.REG_SZ, "PYAS Instance")
with winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, rf"{key_path}\PYAS Instance") as key:
winreg.SetValueEx(key, "Altitude", 0, winreg.REG_SZ, "320000")
winreg.SetValueEx(key, "Flags", 0, winreg.REG_DWORD, 0)
subprocess.run(["sc", "start", service_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
return True
except Exception as e:
self.send_message(e, "warn", False)
return False
svc = self.advapi32.CreateServiceW(scm, service_name, service_name, 0xF01FF,
0x00000001, 0x00000003, 0x00000001, self.path_drivers, None, None, None, None, None)
if not svc:
svc = self.advapi32.OpenServiceW(scm, service_name, 0xF01FF)
if not svc:
self.advapi32.CloseServiceHandle(scm)
return False
res = self.advapi32.StartServiceW(svc,0,None)
self.advapi32.CloseServiceHandle(svc)
self.advapi32.CloseServiceHandle(scm)
return bool(res)
def stop_system_driver(self):
service_name = "PYAS_Driver"
scm = self.advapi32.OpenSCManagerW(None, None, 0xF003F)
if not scm:
try:
service_name = "PYAS_Driver"
subprocess.run(["sc", "stop", service_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
subprocess.run(["sc", "delete", service_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
return True
except Exception:
return False
svc = self.advapi32.OpenServiceW(scm, service_name, 0xF01FF)
if not svc:
self.advapi32.CloseServiceHandle(scm)
return False
status = SERVICE_STATUS()
self.advapi32.ControlService(svc, 0x00000001, ctypes.byref(status))
self.advapi32.DeleteService(svc)
self.advapi32.CloseServiceHandle(svc)
self.advapi32.CloseServiceHandle(scm)
return True
####################################################################################################
def pipe_server_thread(self):
pipe_path = r"\\.\pipe\PYAS_Output_Pipe"
PIPE_BUF_SIZE = 65536
try:
port_name = "\\PYAS_Output_Pipe"
h_port = ctypes.wintypes.HANDLE()
while self.pyas_config.get("driver_switch", False):
try:
hPipe = self.kernel32.CreateNamedPipeW(pipe_path, 0x00000001, 0x00000004 | 0x00000002, 1, PIPE_BUF_SIZE, PIPE_BUF_SIZE, 0, None)
if hPipe == ctypes.c_void_p(-1).value:
time.sleep(0.2)
continue
while self.pyas_config.get("driver_switch", False):
hr = self.fltlib.FilterConnectCommunicationPort(port_name, 0, None, 0, None, ctypes.byref(h_port))
if hr == 0:
message = PYAS_FULL_MESSAGE()
while self.pyas_config.get("driver_switch", False):
if not self.kernel32.ConnectNamedPipe(hPipe, None) and self.kernel32.GetLastError() != 535:
time.sleep(0.2)
continue
while self.pyas_config.get("driver_switch", False):
hr_get = self.fltlib.FilterGetMessage(h_port, ctypes.byref(message), ctypes.sizeof(PYAS_FULL_MESSAGE), None)
if hr_get == 0:
code = message.Data.MessageCode
pid = message.Data.ProcessId
raw_path = self.get_exe_info(pid)[1]
target = message.Data.Path
buf = ctypes.create_string_buffer(PIPE_BUF_SIZE)
bytes_read = ctypes.c_ulong(0)
if not self.kernel32.ReadFile(hPipe, buf, PIPE_BUF_SIZE, ctypes.byref(bytes_read), None) or bytes_read.value == 0:
self.kernel32.DisconnectNamedPipe(hPipe)
time.sleep(0.2)
continue
rule_name = "Unknown"
if code == 2001:
rule_name = "FILE_BLOCK"
elif code == 3001:
rule_name = "REG_BLOCK"
elif code == 4001:
rule_name = "BOOT_BLOCK"
elif code == 5001:
rule_name = "RANSOM_BLOCK"
elif code == 6001:
rule_name = "INJECT_BLOCK"
msg = buf.raw[:bytes_read.value].decode("utf-8", errors="ignore")
parts = [p.strip() for p in msg.split("|", 3)]
if len(parts) == 4:
rules, pid, raw_path, target = parts
for old, new in self.block_replace.items():
rules = rules.replace(old, new)
self.send_message(f"驅動防護 | {rules} | {pid} | {raw_path} | {target}", "notify", True)
display_rule = self.block_replace.get(rule_name, rule_name)
self.send_message(f"驅動防護 | {display_rule} | {pid} | {raw_path} | {target}", "notify", True)
file_path = self.norm_path(self.device_path_to_drive(raw_path))
if not self.is_in_whitelist(file_path) and not self.sign.sign_verify(file_path):
try:
h = self.kernel32.OpenProcess(0x1F0FFF, False, int(pid.strip()))
if h:
self.kernel32.TerminateProcess(h, 0)
self.kernel32.CloseHandle(h)
except Exception as e:
self.send_message(e, "warn", False)
self.kernel32.DisconnectNamedPipe(hPipe)
self.kernel32.CloseHandle(hPipe)
except Exception as e:
self.send_message(e, "warn", False)
time.sleep(0.5)
if code in [4001, 5001]:
try:
h = self.kernel32.OpenProcess(0x1F0FFF, False, pid)
if h:
self.kernel32.TerminateProcess(h, 0)
self.kernel32.CloseHandle(h)
except:
pass
else:
break
self.kernel32.CloseHandle(h_port)
time.sleep(0.2)
except Exception as e:
self.send_message(e, "warn", False)
####################################################################################################
+8 -8
View File
@@ -24,7 +24,7 @@ translate_dict = {
"english_switch": {"開啟":"On","關閉":"Off","开启":"On","关闭":"Off",",":", ",
"立即刪除":"Delete Now","安全模式":"Safe Mode","官方網站":"Official Website ",
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","加載":"Load ",
"腳本":"Script ","鏈式":"Chain ","記憶體":"Memory ","正在加載":"Loading ","加載":"Load ",
"行為":"Behavior ","可疑":"Suspicious ","勒索":"Ransom ","主要":"Main ",
"許可條款":"License Terms ","惡意":"Malicious", "開發":"Developers ",
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ",
@@ -117,13 +117,13 @@ translate_dict = {
"_white": "_black"
},
"black_switch": {
"255, 255, 255": "55, 55, 55",
"245, 245, 245": "75, 75, 75",
"235, 235, 235": "65, 65, 65",
"240, 240, 240": "80, 80, 80",
"250, 250, 250": "90, 90, 90",
"220, 255, 220": "80, 80, 80",
"210, 255, 210": "90, 90, 90",
"255, 255, 255": "20, 20, 20",
"245, 245, 245": "40, 40, 40",
"235, 235, 235": "30, 30, 30",
"240, 240, 240": "70, 70, 70",
"250, 250, 250": "80, 80, 80",
"220, 255, 220": "70, 70, 70",
"210, 255, 210": "80, 80, 80",
"0, 0, 0": "255, 255, 255",
"_black": "_white"
}
+209 -92
View File
@@ -1,5 +1,6 @@
import os, yara, numpy, base64, onnxruntime
import ctypes, ctypes.wintypes, pefile
import os, yara, time, numpy, base64, requests
import ctypes, ctypes.wintypes, hashlib, onnxruntime
from PIL import Image
from io import BytesIO
@@ -45,61 +46,85 @@ class sign_scanner:
for name in path:
try:
setattr(self, name.lower(), ctypes.WinDLL(name, use_last_error=True))
except Exception as e:
self.send_message(e, "warn", False)
except Exception:
pass
self.WinVerifyTrust = self.wintrust.WinVerifyTrust
self.WinVerifyTrust.restype = ctypes.wintypes.LONG
self.WinVerifyTrust.argtypes = [ctypes.wintypes.HWND, ctypes.POINTER(GUID), ctypes.c_void_p]
def is_sign(self, file_path):
with pefile.PE(file_path, fast_load=True) as pe:
sec_dir = pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_SECURITY']]
return sec_dir.VirtualAddress != 0 and sec_dir.Size > 0
try:
self.WinVerifyTrust = self.wintrust.WinVerifyTrust
self.WinVerifyTrust.restype = ctypes.wintypes.LONG
self.WinVerifyTrust.argtypes = [ctypes.wintypes.HWND, ctypes.POINTER(GUID), ctypes.c_void_p]
except Exception:
pass
def sign_verify(self, file_path):
fi = WINTRUST_FILE_INFO(ctypes.sizeof(WINTRUST_FILE_INFO), file_path, None, None)
data = WINTRUST_DATA(ctypes.sizeof(WINTRUST_DATA), None, None, 2, 0, 1,
ctypes.pointer(fi), 1, None, None, 0, 0, None)
s = self.WinVerifyTrust(None, ctypes.byref(self.verify), ctypes.byref(data))
data.dwStateAction = 2
self.WinVerifyTrust(None, ctypes.byref(self.verify), ctypes.byref(data))
return s == 0
try:
fi = WINTRUST_FILE_INFO(ctypes.sizeof(WINTRUST_FILE_INFO), file_path, None, None)
data = WINTRUST_DATA(ctypes.sizeof(WINTRUST_DATA), None, None, 2, 0, 1,
ctypes.pointer(fi), 1, None, None, 0, 0, None)
s = self.WinVerifyTrust(None, ctypes.byref(self.verify), ctypes.byref(data))
data.dwStateAction = 2
self.WinVerifyTrust(None, ctypes.byref(self.verify), ctypes.byref(data))
return s == 0
except Exception:
return False
####################################################################################################
class rule_scanner:
def __init__(self):
self.rules = {}
self.rules = None
self.network = []
def load_path(self, path):
def load_path(self, path, callback=None):
yara_files = {}
for root, _, files in os.walk(path):
for file in files:
self.load_file(os.path.join(root, file))
full_path = os.path.join(root, file)
if callback:
callback(full_path)
ext = os.path.splitext(file)[1].lower()
if ext in ('.yara', '.yar'):
namespace = os.path.relpath(full_path, path).replace(os.sep, '_')
yara_files[namespace] = full_path
elif ext in ('.yc', '.yrc'):
self.load_compiled_rule(full_path)
elif ext in ('.ip', '.txt'):
self.load_network_list(full_path)
def load_file(self, file):
ext = os.path.splitext(file)[1].lower()
if yara_files:
self.compile_all_rules(yara_files)
def load_compiled_rule(self, file):
try:
if ext in ('.yara', '.yar'):
self.rules[file] = yara.compile(file)
elif ext in ('.yc', '.yrc'):
self.rules[file] = yara.load(file)
elif ext in ('.ip', '.txt'):
with open(file, "r", encoding="utf-8", errors="ignore") as f:
self.network.extend(line.strip() for line in f if line.strip())
self.rules = yara.load(file)
except Exception:
return False
pass
def load_network_list(self, file):
try:
with open(file, "r", encoding="utf-8", errors="ignore") as f:
self.network.extend(line.strip() for line in f if line.strip())
except Exception:
pass
def compile_all_rules(self, file_map):
try:
self.rules = yara.compile(filepaths=file_map)
except Exception:
pass
def yara_scan(self, file_path):
try:
for rules in self.rules.values():
matches = rules.match(filepath=file_path)
if matches:
rule_name = str(matches[0])
label = rule_name.split("_")[0]
level = rule_name.split("_")[-1]
return f"Rules/{label}", level
if not self.rules:
return False, False
matches = self.rules.match(filepath=file_path)
if matches:
rule_name = str(matches[0])
types = rule_name.split("_")[0]
label = rule_name.split("_")[1]
level = rule_name.split("_")[2]
return f"{types}/{label}", level
return False, False
except Exception:
return False, False
@@ -108,63 +133,81 @@ class rule_scanner:
class model_scanner:
def __init__(self):
self.model = None
self.suffix = {".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".bat", ".cmd", ".js", ".php", ".ps1", ".vbs", ".wsf"}
self.labels = ["Pefile/White", "Script/White", "Pefile/General", "Script/General"]
self.detect_set = {"Pefile/General", "Script/General"}
self.models = []
self.labels = ["Pefile/White", "Pefile/General"]
self.detect_set = {"Pefile/General"}
self.resize = (224, 224)
def load_path(self, path):
def load_path(self, path, callback=None):
for root, _, files in os.walk(path):
for file in files:
self.load_file(os.path.join(root, file))
full_path = os.path.join(root, file)
if callback:
callback(full_path)
self.load_file(full_path)
def load_file(self, file):
if file.lower().endswith('.onnx'):
try:
self.model = onnxruntime.InferenceSession(file)
session = onnxruntime.InferenceSession(file)
self.models.append(session)
except Exception:
return False
def model_scan(self, file_path, full_output=False):
if not self.model or not file_path.exists():
if not self.models:
return (False, False) if not full_output else ([], str(file_path), None)
sections = self.extract_sections(file_path)
if not sections:
return (False, False) if not full_output else ([], str(file_path), None)
images = [self.preprocess_image(data, self.resize) for data in sections.values()]
if not images:
data = self.get_data(file_path)
if not data:
return (False, False) if not full_output else ([], str(file_path), None)
arr = numpy.stack([numpy.asarray(img).astype('float32') / 255.0 for img in images])[:, :, :, None]
input_shape = self.model.get_inputs()[0].shape
if len(input_shape) == 4 and input_shape[1] in (1, 3):
arr = arr.transpose(0, 3, 1, 2)
image = self.preprocess_image(data, self.resize)
if not image:
return (False, False) if not full_output else ([], str(file_path), None)
input_name = self.model.get_inputs()[0].name
preds = self.model.run(None, {input_name: arr})[0]
exp = numpy.exp(preds - numpy.max(preds, axis=1, keepdims=True))
probs = exp / numpy.sum(exp, axis=1, keepdims=True)
max_overall = max(numpy.max(row) for row in probs)
arr = numpy.asarray(image).astype('float32') / 255.0
arr = numpy.expand_dims(arr, axis=0)
if arr.ndim == 3:
arr = numpy.expand_dims(arr, axis=-1)
results = []
for name, pred, img in zip(sections.keys(), probs, images):
best_malicious = None
for model in self.models:
input_meta = model.get_inputs()[0]
input_name = input_meta.name
input_shape = input_meta.shape
curr_arr = arr.copy()
if len(input_shape) == 4:
if input_shape[1] in (1, 3) and input_shape[3] not in (1, 3):
curr_arr = curr_arr.transpose(0, 3, 1, 2)
try:
probs = model.run(None, {input_name: curr_arr})[0]
pred = probs[0]
except Exception:
continue
idx = int(numpy.argmax(pred))
label = self.labels[idx]
conf = round((pred[idx] / max_overall) * 100, 2)
label = self.labels[idx] if idx < len(self.labels) else f"Class_{idx}"
conf = round(float(pred[idx]) * 100, 2)
if full_output:
results.append((name, label, conf, self.pil_to_base64(img)))
elif label in self.detect_set:
return label, int(conf)
results.append(("Whole File", label, conf, self.pil_to_base64(image)))
if label in self.detect_set:
if best_malicious is None or conf > best_malicious[1]:
best_malicious = (label, int(conf))
if full_output:
results.sort(key=lambda x: (x[1] not in self.detect_set, -x[2]))
malicious_count = sum(1 for _, lbl, _, _ in results if lbl in self.detect_set)
total = len(results)
status = f"{malicious_count}/{total}"
return results, str(file_path), status
return False, False
return results, str(file_path), f"{malicious_count}/{total}"
return best_malicious if best_malicious else (False, False)
def pil_to_base64(self, img):
buf = BytesIO()
@@ -180,26 +223,100 @@ class model_scanner:
image = Image.fromarray(imgbuf.reshape((wah, wah)), 'L')
return image.resize((width, height), Image.Resampling.NEAREST)
def is_text_file(self, content, sample_size=1024):
raw = content[:sample_size]
if not raw:
return False
text_char = set(range(32, 127)) | {9, 10, 13}
nontext = sum(b not in text_char for b in raw)
return nontext / len(raw) < 0.15
def extract_sections(self, file_path):
match_data = {}
def get_data(self, file_path):
try:
with pefile.PE(file_path, fast_load=True) as pe:
for section in pe.sections:
name = section.Name.rstrip(b'\x00').decode('latin1').lower()
if section.Characteristics & 0x00000020:
match_data[name] = section.get_data()
except Exception:
with open(file_path, 'rb') as f:
content = f.read()
ext = file_path.suffix.lower()
if ext in self.suffix or self.is_text_file(content):
match_data[ext] = content
return match_data
return f.read()
except Exception:
return None
####################################################################################################
class cloud_scanner:
def __init__(self):
pass
def calc_hash(self, file_path, block_size=65536):
try:
h = hashlib.sha256()
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(block_size), b""):
h.update(chunk)
return h.hexdigest()
except Exception:
return ""
def upload_file(self, file_path, api_host, api_key):
try:
sha256 = self.calc_hash(file_path)
if not sha256:
return False, None
base = api_host.rstrip('/')
base_headers = {"X-API-Key": api_key, "User-Agent": "PYAS-Client/1.0"}
def _req(m, ep, files=None, **k):
try:
return requests.request(m, f"{base}{ep}", headers=base_headers, files=files, timeout=120, **k)
except:
return None
r = _req("GET", f"/api/processing_status/{sha256}")
status = r.json().get('status') if r and r.status_code == 200 else 'missing'
if status in ['failed', 'error']:
status = 'missing'
if status == 'missing':
with open(file_path, 'rb') as f:
r = _req("POST", "/api/upload", files={'file': f})
if not r or r.status_code != 200:
return False, sha256
return True, sha256
except Exception:
return False, None
def get_result(self, sha256, api_host, api_key):
try:
if not sha256:
return False
base = api_host.rstrip('/')
headers = {"X-API-Key": api_key, "User-Agent": "PYAS-Client/1.0"}
def _req(m, ep, **k):
try:
return requests.request(m, f"{base}{ep}", headers=headers, timeout=10, **k)
except:
return None
for _ in range(30):
r = _req("GET", f"/api/processing_status/{sha256}")
st = r.json().get('status') if r else 'error'
if st == 'done':
break
if st in ['error', 'failed']:
return False
time.sleep(1)
r = _req("GET", f"/api/report/{sha256}")
if r and r.status_code == 200:
data = r.json().get('data', {})
res = data.get('detection', {}).get('results', {}).get('PYAS', {})
label = res.get('label', 'Unsupport')
sims = data.get('similar', [])
is_malicious = 'General' in label
sim_malicious_count = 0
valid_sim_count = 0
for s in sims:
if s.get('similarity', 0) > 80:
valid_sim_count += 1
if "General" in s.get('label'):
sim_malicious_count += 1
if is_malicious and (valid_sim_count == 0 or sim_malicious_count == valid_sim_count):
return True
except Exception:
pass
return False
+33 -30
View File
@@ -1437,8 +1437,8 @@ class Ui_main_window(object):
self.info_text.setHtml(QCoreApplication.translate("main_window", u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", None))
"</style></head><body style=\" font-family:'PMingLiU'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';\"><br /></p></body></html>", None))
self.sensitive_title.setText(QCoreApplication.translate("main_window", u"\u589e\u5f37\u6a21\u5f0f", None))
self.sensitive_text.setText(QCoreApplication.translate("main_window", u"\u6b64\u9078\u9805\u53ef\u4ee5\u589e\u5f37\u6383\u63cf\u5f15\u64ce", None))
self.sensitive_switch.setText(QCoreApplication.translate("main_window", u"\u95dc\u9589", None))
@@ -1477,39 +1477,42 @@ class Ui_main_window(object):
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'Microsoft YaHei'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">PYAS Security Software Development License Agreement</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Last updated: 2025-08-15</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">87owo Publicly Available Source Code License Agreement</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Last updated: 2025-12-19</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">1. License &amp; Ownership</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">1. License and Ownership</p>\n"
"<p style=\" margin-top:0px; ma"
"rgin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 A single device key may be required to activate the software or source code.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 Non exclusive, non transferable, and for personal, internal use only.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 87owo reserves all rights. Intellectual property rights are not transferred.</p>\n"
"rgin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - This software and its source code are source available for public view.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - Access or execution of certain features may require an activation key.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - 87owo reserves all legal rights, no intellectual property is transferred.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - All project archives, source code, and binaries remain fully proprietary.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">2. Use &amp; Prohibitions</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent"
":0; text-indent:0px;\"> \u2013 Private redistribution, sublicensing, or rental is prohibited.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 Private reverse engineering or removal of notices is prohibited.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 Any of the above requires prior authorization from the original author.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 Only personal internal use or modification of the source code is permitted.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 Use of the software or source code for any illegal purpose is prohibited.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin"
"-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">3. License Components</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 All project script archives and executable files are proprietary.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; mar"
"gin-right:0px; -qt-block-indent:0; text-indent:0px;\">2. Use and Prohibitions</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - You may view, download, and modify the code for local and personal use.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - Redistribution of any original or modified code requires prior consent.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - Commercial hosting or SaaS deployment is prohibited without permission.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - Reverse engineering, license removal, or illegal use is strictly barred.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-blo"
"ck-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">3. Data and Privacy</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - This project may collect operational data for optimization and analysis.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - All collected data is strictly anonymized to ensure the user's privacy.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - Transmission of information is encrypted to prevent unauthorized access.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">4. Updates &amp; Terms</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 Updates to new versions may include patches, enhancements, or modifications.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-lef"
"t:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 Continued use constitutes your acceptance of these features or terms.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; m"
"argin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">4. Updates and Terms</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - New releases may include critical patches, enhancements, or UI changes.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - Continued use of these services constitutes acceptance of updated terms.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - The author reserves the right to modify these license terms at any time.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">5. Warranty &amp; Liability</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 This software is provided &quot;as is,&quot; without warranty of any kind.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> \u2013 In no event shall there be any liability for consequential damages.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-in"
"dent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">\u00a9 2020\u20132025 87owo (PYAS Security). All rights reserved.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", None))
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">5. Warranty and Liabi"
"lity</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - All services and assets are provided &quot;as is&quot; without any form of warranty.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - 87owo is not liable for any direct or indirect damages from software use.</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> - Users assume all risks regarding performance, data, and system integrity.</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">\u00a9 2020-2026 87owo (PYAS Security). All rights reserved.</p></body></html>", None))
self.process_title.setText(QCoreApplication.translate("main_window", u"\u9032\u7a0b\u9632\u8b77", None))
self.process_text.setText(QCoreApplication.translate("main_window", u"\u6b64\u9078\u9805\u53ef\u4ee5\u6514\u622a\u9032\u7a0b\u75c5\u6bd2", None))
self.process_switch.setText(QCoreApplication.translate("main_window", u"\u95dc\u9589", None))
+1 -1
View File
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
pyinstaller_versionfile.create_versionfile(
output_file="versionfile.txt",
version='3.3.6',
version='3.3.8',
company_name="PYAS Security",
file_description="Python Antivirus Software",
internal_name="PYAS",
+142
View File
@@ -0,0 +1,142 @@
#pragma once
#include <fltKernel.h>
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <ntstrsafe.h>
constexpr auto PYAS_PORT_NAME = L"\\PYAS_Output_Pipe";
constexpr auto MAX_PATH_LEN = 1024;
constexpr auto PYAS_POOL_TAG = 'SAYP';
#ifndef PROCESS_TERMINATE
#define PROCESS_TERMINATE (0x0001)
#endif
#ifndef PROCESS_CREATE_THREAD
#define PROCESS_CREATE_THREAD (0x0002)
#endif
#ifndef PROCESS_VM_OPERATION
#define PROCESS_VM_OPERATION (0x0008)
#endif
#ifndef PROCESS_VM_READ
#define PROCESS_VM_READ (0x0010)
#endif
#ifndef PROCESS_VM_WRITE
#define PROCESS_VM_WRITE (0x0020)
#endif
#ifndef PROCESS_DUP_HANDLE
#define PROCESS_DUP_HANDLE (0x0040)
#endif
#ifndef PROCESS_CREATE_PROCESS
#define PROCESS_CREATE_PROCESS (0x0080)
#endif
#ifndef PROCESS_SET_INFORMATION
#define PROCESS_SET_INFORMATION (0x0200)
#endif
#ifndef PROCESS_QUERY_INFORMATION
#define PROCESS_QUERY_INFORMATION (0x0400)
#endif
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME (0x0800)
#endif
#ifndef PROCESS_QUERY_LIMITED_INFORMATION
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#endif
#ifndef PROCESS_SET_QUOTA
#define PROCESS_SET_QUOTA (0x0100)
#endif
#ifndef POOL_FLAG_NON_PAGED
#define POOL_FLAG_NON_PAGED 0x0000000000000040UI64
#endif
#ifndef FSCTL_MANAGE_BYPASS_IO
#define FSCTL_MANAGE_BYPASS_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 188, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef enum _FS_BPIO_OPERATIONS {
FS_BPIO_OP_ENABLE = 1,
FS_BPIO_OP_DISABLE = 2,
FS_BPIO_OP_QUERY = 3,
FS_BPIO_OP_VOLUME_STACK_PAUSE = 4,
FS_BPIO_OP_VOLUME_STACK_RESUME = 5,
FS_BPIO_OP_STREAM_PAUSE = 6,
FS_BPIO_OP_STREAM_RESUME = 7,
FS_BPIO_OP_GET_INFO = 8
} FS_BPIO_OPERATIONS;
typedef struct _FS_BPIO_INPUT {
FS_BPIO_OPERATIONS Operation;
ULONG InFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
} FS_BPIO_INPUT, * PFS_BPIO_INPUT;
typedef struct _FS_BPIO_OUTPUT {
FS_BPIO_OPERATIONS Operation;
ULONG OutFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
NTSTATUS Status;
} FS_BPIO_OUTPUT, * PFS_BPIO_OUTPUT;
#endif
typedef struct _PYAS_MESSAGE {
ULONG MessageCode;
ULONG ProcessId;
WCHAR Path[MAX_PATH_LEN];
} PYAS_MESSAGE, * PPYAS_MESSAGE;
typedef struct _DRIVER_DATA {
PDRIVER_OBJECT DriverObject;
PFLT_FILTER FilterHandle;
PFLT_PORT ServerPort;
PFLT_PORT ClientPort;
PEPROCESS PyasProcess;
ULONG PyasPid;
LARGE_INTEGER Cookie;
FAST_MUTEX PortMutex;
FAST_MUTEX TrackerMutex;
EX_RUNDOWN_REF PortRundown;
} DRIVER_DATA, * PDRIVER_DATA;
extern DRIVER_DATA GlobalData;
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreSetInfo(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_FileSystemControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectBoot_PreDeviceControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
NTSTATUS InitializeProcessProtection();
VOID UninitializeProcessProtection();
NTSTATUS InitializeRegistryProtection(PDRIVER_OBJECT DriverObject);
VOID UninitializeRegistryProtection();
VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo);
BOOLEAN IsProcessTrusted(HANDLE ProcessId);
BOOLEAN IsTargetProtected(HANDLE ProcessId);
BOOLEAN IsInstallerProcess(HANDLE ProcessId);
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes);
BOOLEAN CheckRegistryRule(PCUNICODE_STRING KeyName);
BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName);
BOOLEAN CheckProtectedPathRule(PCUNICODE_STRING FileName);
BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Buffer, ULONG Length, BOOLEAN IsWrite);
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path, USHORT PathSize);
FORCEINLINE PVOID PyasAllocate(SIZE_T Size) {
#if (NTDDI_VERSION >= NTDDI_WIN10_VB)
return ExAllocatePool2(POOL_FLAG_NON_PAGED, Size, PYAS_POOL_TAG);
#else
PVOID Buffer = ExAllocatePoolWithTag(NonPagedPoolNx, Size, PYAS_POOL_TAG);
if (Buffer) RtlZeroMemory(Buffer, Size);
return Buffer;
#endif
}
FORCEINLINE VOID PyasFree(PVOID Ptr) {
if (Ptr) ExFreePoolWithTag(Ptr, PYAS_POOL_TAG);
}
-299
View File
@@ -1,299 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectRules.h"
LARGE_INTEGER g_CmRegHandle;
PDEVICE_OBJECT g_ControlDeviceObject;
KSPIN_LOCK g_ProtectLock;
FAST_MUTEX HookMutex;
PDRIVER_OBJECT DiskDrvObj = NULL;
KEVENT g_LogDrainEvent;
BOOLEAN g_Unloading = FALSE;
BOOLEAN g_CmRegActive = FALSE;
EX_RUNDOWN_REF g_Rundown;
PDEVICE_OBJECT g_GuardDevice = NULL;
PDEVICE_OBJECT g_MbrFilterTargets[MAX_MBR_TARGETS] = { 0 };
ULONG g_MbrFilterCount = 0;
volatile LONG g_LogWorkCount = 0;
static UNICODE_STRING g_DeviceName;
static WCHAR g_DeviceNameBuf[64];
static UNICODE_STRING g_SymLink = RTL_CONSTANT_STRING(L"\\??\\PYAS_Driver");
static BOOLEAN g_SymLinkCreated = FALSE;
static NTSTATUS CombinedDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (DeviceObject == g_ControlDeviceObject) {
PIO_STACK_LOCATION s = IoGetCurrentIrpStackLocation(Irp);
if (s->MajorFunction == IRP_MJ_CREATE || s->MajorFunction == IRP_MJ_CLOSE || s->MajorFunction == IRP_MJ_CLEANUP) {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
{
PIO_STACK_LOCATION s = IoGetCurrentIrpStackLocation(Irp);
if (s->MajorFunction == IRP_MJ_PNP) {
PDEVICE_OBJECT lower = (PDEVICE_OBJECT)DeviceObject->DeviceExtension;
if (s->MinorFunction == IRP_MN_REMOVE_DEVICE) {
NTSTATUS st;
IoSkipCurrentIrpStackLocation(Irp);
st = lower ? IoCallDriver(lower, Irp) : STATUS_SUCCESS;
if (lower) IoDetachDevice(lower);
IoDeleteDevice(DeviceObject);
return st;
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver((PDEVICE_OBJECT)DeviceObject->DeviceExtension, Irp);
}
}
return BootProtectDispatch(DeviceObject, Irp);
}
static NTSTATUS AttachDiskFilters(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING name = RTL_CONSTANT_STRING(L"\\Driver\\Disk");
UNICODE_STRING sym = RTL_CONSTANT_STRING(L"IoDriverObjectType");
POBJECT_TYPE* pType = (POBJECT_TYPE*)MmGetSystemRoutineAddress(&sym);
if (!pType || !*pType)
return STATUS_NOT_SUPPORTED;
NTSTATUS status = ObReferenceObjectByName(&name, OBJ_CASE_INSENSITIVE, NULL, 0, *pType, KernelMode, NULL, (PVOID*)&DiskDrvObj);
if (!NT_SUCCESS(status))
return status;
ULONG done = 0;
status = IoEnumerateDeviceObjectList(DiskDrvObj, NULL, 0, &done);
if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS) {
ObDereferenceObject(DiskDrvObj);
DiskDrvObj = NULL;
return status;
}
PDEVICE_OBJECT* list = ExAllocatePool2(POOL_FLAG_NON_PAGED, done * sizeof(PDEVICE_OBJECT), 'dskT');
if (!list) {
ObDereferenceObject(DiskDrvObj);
DiskDrvObj = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoEnumerateDeviceObjectList(DiskDrvObj, list, done * sizeof(PDEVICE_OBJECT), &done);
if (!NT_SUCCESS(status)) {
ExFreePool2(list, 'dskT', NULL, 0);
ObDereferenceObject(DiskDrvObj);
DiskDrvObj = NULL;
return status;
}
for (ULONG i = 0; i < done && g_MbrFilterCount < MAX_MBR_TARGETS; ++i) {
PDEVICE_OBJECT lower = list[i], filter, attached = NULL;
status = IoCreateDevice(DriverObject, 0, NULL, lower->DeviceType, lower->Characteristics, FALSE, &filter);
if (!NT_SUCCESS(status))
continue;
filter->Flags |= (lower->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE));
status = IoAttachDeviceToDeviceStackSafe(filter, lower, &attached);
if (!NT_SUCCESS(status) || !attached) {
IoDeleteDevice(filter);
continue;
}
filter->StackSize = lower->StackSize + 1;
filter->AlignmentRequirement = lower->AlignmentRequirement;
filter->DeviceExtension = attached;
filter->Flags &= ~DO_DEVICE_INITIALIZING;
g_MbrFilterTargets[g_MbrFilterCount++] = filter;
}
for (ULONG i = 0; i < done; ++i)
ObDereferenceObject(list[i]);
ExFreePool2(list, 'dskT', NULL, 0);
return STATUS_SUCCESS;
}
static NTSTATUS AttachFsFilters(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING symDev = RTL_CONSTANT_STRING(L"IoDeviceObjectType");
POBJECT_TYPE* pDevType = (POBJECT_TYPE*)MmGetSystemRoutineAddress(&symDev);
if (!pDevType || !*pDevType)
return STATUS_NOT_SUPPORTED;
NTSTATUS status = STATUS_SUCCESS;
for (ULONG i = 0; g_AttachDisk[i] && g_MbrFilterCount < MAX_MBR_TARGETS; ++i) {
UNICODE_STRING name;
RtlInitUnicodeString(&name, g_AttachDisk[i]);
PDEVICE_OBJECT fsCtl = NULL;
status = ObReferenceObjectByName(&name, OBJ_CASE_INSENSITIVE, NULL, 0, *pDevType, KernelMode, NULL, (PVOID*)&fsCtl);
if (!NT_SUCCESS(status) || !fsCtl)
continue;
PDRIVER_OBJECT fsDrv = fsCtl->DriverObject;
if (fsDrv) {
ULONG need = 0;
status = IoEnumerateDeviceObjectList(fsDrv, NULL, 0, &need);
if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_SUCCESS) {
PDEVICE_OBJECT* list = (PDEVICE_OBJECT*)ExAllocatePool2(POOL_FLAG_NON_PAGED, need * sizeof(PDEVICE_OBJECT), 'fsTA');
if (list) {
status = IoEnumerateDeviceObjectList(fsDrv, list, need * sizeof(PDEVICE_OBJECT), &need);
if (NT_SUCCESS(status)) {
for (ULONG j = 0; j < need && g_MbrFilterCount < MAX_MBR_TARGETS; ++j) {
PDEVICE_OBJECT lower = list[j], filter, attached = NULL;
NTSTATUS s2 = IoCreateDevice(DriverObject, 0, NULL, lower->DeviceType, lower->Characteristics, FALSE, &filter);
if (!NT_SUCCESS(s2))
continue;
filter->Flags |= (lower->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE));
s2 = IoAttachDeviceToDeviceStackSafe(filter, lower, &attached);
if (!NT_SUCCESS(s2) || !attached) {
IoDeleteDevice(filter);
continue;
}
filter->StackSize = lower->StackSize + 1;
filter->AlignmentRequirement = lower->AlignmentRequirement;
filter->DeviceExtension = attached;
filter->Flags &= ~DO_DEVICE_INITIALIZING;
g_MbrFilterTargets[g_MbrFilterCount++] = filter;
}
}
ExFreePool2(list, 'fsTA', NULL, 0);
}
}
}
ObDereferenceObject(fsCtl);
}
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
KeInitializeSpinLock(&g_ProtectLock);
ExInitializeFastMutex(&HookMutex);
KeInitializeEvent(&g_LogDrainEvent, NotificationEvent, TRUE);
g_Unloading = FALSE;
g_CmRegActive = FALSE;
InterlockedExchange(&g_LogWorkCount, 0);
ExInitializeRundownProtection(&g_Rundown);
{
UNICODE_STRING guardName = RTL_CONSTANT_STRING(L"\\Device\\PYAS_Driver_Guard");
NTSTATUS gs = IoCreateDevice(DriverObject, 0, &guardName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_GuardDevice);
if (!NT_SUCCESS(gs))
return STATUS_DEVICE_BUSY;
}
{
LARGE_INTEGER t = KeQueryPerformanceCounter(NULL);
g_DeviceName.Buffer = g_DeviceNameBuf;
g_DeviceName.MaximumLength = sizeof(g_DeviceNameBuf);
RtlStringCchPrintfW(g_DeviceName.Buffer, RTL_NUMBER_OF(g_DeviceNameBuf), L"\\Device\\PYAS_Driver_%p_%I64x", DriverObject, t.QuadPart);
g_DeviceName.Length = (USHORT)(wcslen(g_DeviceName.Buffer) * sizeof(WCHAR));
}
NTSTATUS status = IoCreateDevice(DriverObject, 0, &g_DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_ControlDeviceObject);
if (!NT_SUCCESS(status))
return status;
DriverObject->DriverUnload = DriverUnload;
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
DriverObject->MajorFunction[i] = CombinedDispatch;
DriverObject->Flags |= 0x20;
g_ControlDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
IoDeleteSymbolicLink(&g_SymLink);
{
UINT i = 0;
for (; i < 50; ++i) {
status = IoCreateSymbolicLink(&g_SymLink, &g_DeviceName);
if (NT_SUCCESS(status))
break;
LARGE_INTEGER d = { 0 };
d.QuadPart = -10LL * 1000LL * 10LL;
KeDelayExecutionThread(KernelMode, FALSE, &d);
IoDeleteSymbolicLink(&g_SymLink);
}
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_ControlDeviceObject);
g_ControlDeviceObject = NULL;
if (g_GuardDevice) { IoDeleteDevice(g_GuardDevice); g_GuardDevice = NULL; }
return status;
}
}
g_SymLinkCreated = TRUE;
{
static WCHAR regAltBuf[32];
static UNICODE_STRING regAlt;
LARGE_INTEGER t = KeQueryPerformanceCounter(NULL);
RtlStringCchPrintfW(regAltBuf, RTL_NUMBER_OF(regAltBuf), L"385100.%I64x", t.QuadPart);
RtlInitUnicodeString(&regAlt, regAltBuf);
status = CmRegisterCallbackEx(RegistryProtectCallback, &regAlt, DriverObject, NULL, &g_CmRegHandle, NULL);
if (NT_SUCCESS(status))
g_CmRegActive = TRUE;
}
InitImageProtect();
InitInjectProtect();
InitRemoteProtect();
InitScreenProtect();
InitProcessProtect();
AttachFsFilters(DriverObject);
AttachDiskFilters(DriverObject);
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
g_Unloading = TRUE;
if (g_SymLinkCreated) {
IoDeleteSymbolicLink(&g_SymLink);
g_SymLinkCreated = FALSE;
}
if (g_CmRegActive) {
CmUnRegisterCallback(g_CmRegHandle);
g_CmRegActive = FALSE;
}
UninitInjectProtect();
UninitImageProtect();
UninitRemoteProtect();
UninitScreenProtect();
UninitProcessProtect();
ExWaitForRundownProtectionRelease(&g_Rundown);
if (InterlockedCompareExchange((volatile LONG*)&g_LogWorkCount, 0, 0) != 0) {
KeWaitForSingleObject(&g_LogDrainEvent, Executive, KernelMode, FALSE, NULL);
}
if (InterlockedCompareExchange(&g_LogWorkCount, 0, 0) != 0) {
KeResetEvent(&g_LogDrainEvent);
while (InterlockedCompareExchange(&g_LogWorkCount, 0, 0) != 0)
KeWaitForSingleObject(&g_LogDrainEvent, Executive, KernelMode, FALSE, NULL);
}
for (ULONG i = 0; i < g_MbrFilterCount; ++i) {
if (g_MbrFilterTargets[i]) {
IoDetachDevice((PDEVICE_OBJECT)g_MbrFilterTargets[i]->DeviceExtension);
IoDeleteDevice(g_MbrFilterTargets[i]);
g_MbrFilterTargets[i] = NULL;
}
}
g_MbrFilterCount = 0;
if (DiskDrvObj) {
ObDereferenceObject(DiskDrvObj);
DiskDrvObj = NULL;
}
if (g_ControlDeviceObject) {
IoDeleteDevice(g_ControlDeviceObject);
g_ControlDeviceObject = NULL;
}
if (g_GuardDevice) {
IoDeleteDevice(g_GuardDevice);
g_GuardDevice = NULL;
}
}
+141
View File
@@ -0,0 +1,141 @@
#include "DriverCommon.h"
DRIVER_DATA GlobalData;
static NTSTATUS InstanceSetup(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_SETUP_FLAGS Flags, DEVICE_TYPE VolumeDeviceType, FLT_FILESYSTEM_TYPE VolumeFilesystemType) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(VolumeDeviceType);
UNREFERENCED_PARAMETER(VolumeFilesystemType);
return STATUS_SUCCESS;
}
static NTSTATUS InstanceQueryTeardown(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
return STATUS_SUCCESS;
}
static VOID InstanceTeardownStart(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
static VOID InstanceTeardownComplete(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_TEARDOWN_FLAGS Flags) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
static NTSTATUS DriverUnload(FLT_FILTER_UNLOAD_FLAGS Flags) {
UNREFERENCED_PARAMETER(Flags);
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
UninitializeRegistryProtection();
UninitializeProcessProtection();
ExWaitForRundownProtectionRelease(&GlobalData.PortRundown);
if (GlobalData.ServerPort) {
FltCloseCommunicationPort(GlobalData.ServerPort);
}
if (GlobalData.FilterHandle) {
FltUnregisterFilter(GlobalData.FilterHandle);
}
return STATUS_SUCCESS;
}
static NTSTATUS PortConnect(PFLT_PORT ClientPort, PVOID ServerPortCookie, PVOID ConnectionContext, ULONG SizeOfContext, PVOID* ConnectionPortCookie) {
UNREFERENCED_PARAMETER(ServerPortCookie);
UNREFERENCED_PARAMETER(ConnectionContext);
UNREFERENCED_PARAMETER(SizeOfContext);
UNREFERENCED_PARAMETER(ConnectionPortCookie);
ExAcquireFastMutex(&GlobalData.PortMutex);
GlobalData.ClientPort = ClientPort;
GlobalData.PyasPid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
GlobalData.PyasProcess = PsGetCurrentProcess();
ExReInitializeRundownProtection(&GlobalData.PortRundown);
ExReleaseFastMutex(&GlobalData.PortMutex);
return STATUS_SUCCESS;
}
static VOID PortDisconnect(PVOID ConnectionCookie) {
UNREFERENCED_PARAMETER(ConnectionCookie);
ExAcquireFastMutex(&GlobalData.PortMutex);
GlobalData.ClientPort = NULL;
GlobalData.PyasPid = 0;
if (GlobalData.PyasProcess) {
GlobalData.PyasProcess = NULL;
}
ExReleaseFastMutex(&GlobalData.PortMutex);
ExWaitForRundownProtectionRelease(&GlobalData.PortRundown);
}
CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE, 0, ProtectFile_PreCreate, NULL },
{ IRP_MJ_WRITE, 0, ProtectFile_PreWrite, NULL },
{ IRP_MJ_SET_INFORMATION, 0, ProtectFile_PreSetInfo, NULL },
{ IRP_MJ_FILE_SYSTEM_CONTROL, 0, ProtectFile_FileSystemControl, NULL },
{ IRP_MJ_DEVICE_CONTROL, 0, ProtectBoot_PreDeviceControl, NULL },
{ IRP_MJ_OPERATION_END }
};
CONST FLT_REGISTRATION FilterRegistration = {
sizeof(FLT_REGISTRATION),
FLT_REGISTRATION_VERSION,
0,
NULL,
Callbacks,
DriverUnload,
InstanceSetup,
InstanceQueryTeardown,
InstanceTeardownStart,
InstanceTeardownComplete,
NULL,
NULL,
NULL
};
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status = STATUS_SUCCESS;
PSECURITY_DESCRIPTOR sd = NULL;
OBJECT_ATTRIBUTES oa = { 0 };
UNICODE_STRING name = { 0 };
RtlZeroMemory(&GlobalData, sizeof(GlobalData));
GlobalData.DriverObject = DriverObject;
ExInitializeFastMutex(&GlobalData.PortMutex);
ExInitializeFastMutex(&GlobalData.TrackerMutex);
ExInitializeRundownProtection(&GlobalData.PortRundown);
status = FltRegisterFilter(DriverObject, &FilterRegistration, &GlobalData.FilterHandle);
if (!NT_SUCCESS(status)) return status;
status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);
if (NT_SUCCESS(status)) {
RtlInitUnicodeString(&name, PYAS_PORT_NAME);
InitializeObjectAttributes(&oa, &name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd);
status = FltCreateCommunicationPort(GlobalData.FilterHandle, &GlobalData.ServerPort, &oa, NULL, PortConnect, PortDisconnect, NULL, 1);
FltFreeSecurityDescriptor(sd);
}
if (!NT_SUCCESS(status)) {
FltUnregisterFilter(GlobalData.FilterHandle);
return status;
}
InitializeProcessProtection();
InitializeRegistryProtection(DriverObject);
PsSetLoadImageNotifyRoutine(ImageLoadNotify);
return FltStartFiltering(GlobalData.FilterHandle);
}
-187
View File
@@ -1,187 +0,0 @@
#pragma once
#include <ntifs.h>
#include <ntstrsafe.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <fltKernel.h>
#define PIPE_NAME L"\\??\\pipe\\PYAS_Output_Pipe"
#ifndef POOL_FLAG_NON_PAGED
#define POOL_FLAG_NON_PAGED 0x00000001
#endif
#ifndef PROCESS_TERMINATE
#define PROCESS_TERMINATE 0x0001
#endif
#ifndef PROCESS_CREATE_THREAD
#define PROCESS_CREATE_THREAD 0x0002
#endif
#ifndef PROCESS_VM_OPERATION
#define PROCESS_VM_OPERATION 0x0008
#endif
#ifndef PROCESS_VM_WRITE
#define PROCESS_VM_WRITE 0x0020
#endif
#ifndef PROCESS_VM_READ
#define PROCESS_VM_READ 0x0010
#endif
#ifndef PROCESS_DUP_HANDLE
#define PROCESS_DUP_HANDLE 0x0040
#endif
#ifndef PROCESS_CREATE_PROCESS
#define PROCESS_CREATE_PROCESS 0x0080
#endif
#ifndef PROCESS_SET_QUOTA
#define PROCESS_SET_QUota 0x0100
#endif
#ifndef PROCESS_SET_INFORMATION
#define PROCESS_SET_INFORMATION 0x0200
#endif
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME 0x0800
#endif
#ifndef PROCESS_QUERY_LIMITED_INFORMATION
#define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
#endif
#ifndef PROCESS_SET_LIMITED_INFORMATION
#define PROCESS_SET_LIMITED_INFORMATION 0x2000
#endif
#ifndef THREAD_TERMINATE
#define THREAD_TERMINATE 0x0001
#endif
#ifndef THREAD_SUSPEND_RESUME
#define THREAD_SUSPEND_RESUME 0x0002
#endif
#ifndef THREAD_SET_CONTEXT
#define THREAD_SET_CONTEXT 0x0010
#endif
#ifndef THREAD_IMPERSONATE
#define THREAD_IMPERSONATE 0x0100
#endif
#ifndef THREAD_DIRECT_IMPERSONATION
#define THREAD_DIRECT_IMPERSONATION 0x0200
#endif
#ifndef JOB_OBJECT_ASSIGN_PROCESS
#define JOB_OBJECT_ASSIGN_PROCESS 0x0001
#endif
#ifndef JOB_OBJECT_TERMINATE
#define JOB_OBJECT_TERMINATE 0x0008
#endif
#ifndef FILE_DISPOSITION_DELETE
#define FILE_DISPOSITION_DELETE 0x00000001
#endif
#ifndef UINT
typedef unsigned int UINT;
#endif
#define MAX_MBR_TARGETS 64
extern POBJECT_TYPE* PsJobType;
extern volatile LONG g_LogWorkCount;
extern BOOLEAN g_Unloading;
extern KEVENT g_LogDrainEvent;
extern KSPIN_LOCK g_ProtectLock;
extern LARGE_INTEGER g_CmRegHandle;
extern POBJECT_TYPE* IoDriverObjectType;
extern POBJECT_TYPE* IoFileObjectType;
extern FAST_MUTEX HookMutex;
extern EX_RUNDOWN_REF g_Rundown;
extern PDEVICE_OBJECT g_GuardDevice;
extern PDRIVER_OBJECT g_DriverObject;
extern PFLT_FILTER g_FilterHandle;
NTSYSAPI PCSTR NTAPI PsGetProcessImageFileName(PEPROCESS Process);
typedef PVOID(NTAPI* _pyas_ExAllocatePool2)(ULONG, SIZE_T, ULONG);
typedef VOID(NTAPI* _pyas_ExFreePool2)(PVOID, ULONG, PVOID, ULONG);
typedef PVOID(NTAPI* _pyas_ExAllocatePoolWithTag)(POOL_TYPE, SIZE_T, ULONG);
typedef VOID(NTAPI* _pyas_ExFreePoolWithTag)(PVOID, ULONG);
static __forceinline PVOID PYAS_ExAllocatePool2(ULONG f, SIZE_T s, ULONG t) {
static _pyas_ExAllocatePool2 p2 = 0;
if (!p2) {
UNICODE_STRING n = RTL_CONSTANT_STRING(L"ExAllocatePool2");
p2 = (_pyas_ExAllocatePool2)MmGetSystemRoutineAddress(&n);
}
if (p2)
return p2(f, s, t);
static _pyas_ExAllocatePoolWithTag p1 = 0;
if (!p1) {
UNICODE_STRING n = RTL_CONSTANT_STRING(L"ExAllocatePoolWithTag");
p1 = (_pyas_ExAllocatePoolWithTag)MmGetSystemRoutineAddress(&n);
}
if (p1)
return p1((f & POOL_FLAG_NON_PAGED) ? NonPagedPoolNx : PagedPool, s, t);
return NULL;
}
static __forceinline VOID PYAS_ExFreePool2(PVOID a, ULONG t, PVOID h, ULONG f) {
UNREFERENCED_PARAMETER(h);
UNREFERENCED_PARAMETER(f);
static _pyas_ExFreePool2 p2 = 0;
if (!p2) {
UNICODE_STRING n = RTL_CONSTANT_STRING(L"ExFreePool2");
p2 = (_pyas_ExFreePool2)MmGetSystemRoutineAddress(&n);
}
if (p2) {
p2(a, t, h, f);
return;
}
static _pyas_ExFreePoolWithTag p1 = 0;
if (!p1) {
UNICODE_STRING n = RTL_CONSTANT_STRING(L"ExFreePoolWithTag");
p1 = (_pyas_ExFreePoolWithTag)MmGetSystemRoutineAddress(&n);
}
if (p1) {
p1(a, t);
return;
}
}
#define ExAllocatePool2 PYAS_ExAllocatePool2
#define ExFreePool2 PYAS_ExFreePool2
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
VOID SendPipeLog(PCSTR msg, SIZE_T len);
VOID UninitImageProtect(VOID);
VOID UninitInjectProtect(VOID);
VOID UninitRemoteProtect(VOID);
VOID UninitScreenProtect(VOID);
VOID UninitProcessProtect(VOID);
VOID UninitFileProtect(VOID);
VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2);
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_writes_bytes_opt_(ProcessInformationLength) PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
NTSTATUS ObReferenceObjectByName(
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN PACCESS_STATE PassedAccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID* Object
);
NTSTATUS BootProtectDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
);
NTSTATUS RegistryProtectCallback(PVOID ctx, PVOID arg1, PVOID arg2);
NTSTATUS InitImageProtect(VOID);
NTSTATUS InitInjectProtect(VOID);
NTSTATUS InitRemoteProtect(VOID);
NTSTATUS InitScreenProtect(VOID);
NTSTATUS InitProcessProtect(VOID);
NTSTATUS InitFileProtect(VOID);
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath);
-80
View File
@@ -1,80 +0,0 @@
#include <ntifs.h>
#include <ntstrsafe.h>
#include "DriverEntry.h"
extern PDEVICE_OBJECT g_ControlDeviceObject;
typedef struct _PIPE_LOG_CTX {
PIO_WORKITEM Item;
SIZE_T Len;
PCHAR Buf;
}PIPE_LOG_CTX, * PPIPE_LOG_CTX;
static VOID PipeLogWork(PDEVICE_OBJECT DeviceObject, PVOID Context)
{
UNREFERENCED_PARAMETER(DeviceObject);
PPIPE_LOG_CTX ctx = (PPIPE_LOG_CTX)Context;
HANDLE h = NULL;
UNICODE_STRING name;
OBJECT_ATTRIBUTES oa = { 0 };
IO_STATUS_BLOCK iosb;
RtlInitUnicodeString(&name, PIPE_NAME);
InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
if (NT_SUCCESS(ZwCreateFile(&h, FILE_GENERIC_WRITE, &oa, &iosb, NULL, 0, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0))) {
ZwWriteFile(h, NULL, NULL, NULL, &iosb, ctx->Buf, (ULONG)(ctx->Len > 0xFFFFFFFF ? 0xFFFFFFFF : ctx->Len), NULL, NULL);
ZwClose(h);
}
IoFreeWorkItem(ctx->Item);
ExFreePool2(ctx->Buf, 'golP', NULL, 0);
ExFreePool2(ctx, 'golP', NULL, 0);
if (InterlockedDecrement(&g_LogWorkCount) == 0) {
KeSetEvent(&g_LogDrainEvent, IO_NO_INCREMENT, FALSE);
}
}
VOID SendPipeLog(PCSTR msg, SIZE_T len)
{
if (!msg || len == 0)
return;
if (!g_ControlDeviceObject)
return;
if (g_Unloading)
return;
PPIPE_LOG_CTX ctx = (PPIPE_LOG_CTX)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(PIPE_LOG_CTX), 'golP');
if (!ctx)
return;
ctx->Len = len;
ctx->Buf = (PCHAR)ExAllocatePool2(POOL_FLAG_NON_PAGED, ctx->Len, 'golP');
if (!ctx->Buf) {
ExFreePool2(ctx, 'golP', NULL, 0);
return;
}
RtlCopyMemory(ctx->Buf, msg, ctx->Len);
ctx->Item = IoAllocateWorkItem(g_ControlDeviceObject);
if (!ctx->Item) {
ExFreePool2(ctx->Buf, 'golP', NULL, 0);
ExFreePool2(ctx, 'golP', NULL, 0);
return;
}
InterlockedIncrement(&g_LogWorkCount);
IoQueueWorkItem(ctx->Item, PipeLogWork, DelayedWorkQueue, ctx);
}
VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
{
ANSI_STRING a1 = { 0 }, a2 = { 0 };
CHAR buf[1024] = { 0 };
if (s1)
RtlUnicodeStringToAnsiString(&a1, s1, TRUE);
if (s2)
RtlUnicodeStringToAnsiString(&a2, s2, TRUE);
RtlStringCchPrintfA(buf, RTL_NUMBER_OF(buf), "%s | %u | %s | %s", tag, upid, a1.Buffer ? a1.Buffer : "", a2.Buffer ? a2.Buffer : "");
SendPipeLog(buf, strlen(buf));
RtlFreeAnsiString(&a1);
RtlFreeAnsiString(&a2);
}
+40 -15
View File
@@ -1,27 +1,52 @@
[Version]
Signature = "$WINDOWS NT$"
Class = System
ClassGuid = {4d36e97d-e325-11ce-bfc1-08002be10318}
Class = ActivityMonitor
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}
Provider = %ManufacturerName%
DriverVer = 12/29/2025,1.0.0.0
CatalogFile = PYAS_Driver.cat
PnpLockdown = 1
DriverVer =
[DestinationDirs]
DefaultDestDir = 13
[DefaultInstall.ntamd64]
CopyFiles = @PYAS_Driver.sys
AddService = PYAS_Driver,0x00000002
[SourceDisksFiles]
PYAS_Driver.sys = 1
DefaultDestDir = 12
PYAS_Driver.DriverFiles = 12
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
PYAS_Driver.sys = 1,,
[DefaultInstall.NTamd64]
OptionDesc = %ServiceDescription%
CopyFiles = PYAS_Driver.DriverFiles
[DefaultInstall.NTamd64.Services]
AddService = %ServiceName%,,PYAS_Driver.Service
[PYAS_Driver.DriverFiles]
PYAS_Driver.sys
[PYAS_Driver.Service]
DisplayName = %ServiceName%
Description = %ServiceDescription%
ServiceBinary = %12%\PYAS_Driver.sys
Dependencies = FltMgr
ServiceType = 2
StartType = 3
ErrorControl = 1
LoadOrderGroup = "FSFilter Activity Monitor"
AddReg = PYAS_Driver.AddReg
[PYAS_Driver.AddReg]
HKR,"Parameters","DebugFlags",0x00010001,0x0
HKR,"Parameters","SupportedFeatures",0x00010001,0x3
HKR,"Parameters\Instances","DefaultInstance",0x00000000,"PYAS Instance"
HKR,"Parameters\Instances\PYAS Instance","Altitude",0x00000000,"320000"
HKR,"Parameters\Instances\PYAS Instance","Flags",0x00010001,0x0
[Strings]
ManufacturerName = "PYAS_Driver"
DiskName = "PYAS_Driver"
ServiceName="PYAS_Driver"
ServiceDisplayName="PYAS_Driver"
ManufacturerName = "PYAS Security"
DiskName = "PYAS_Driver Source Disk"
ServiceName = "PYAS_Driver"
ServiceDescription = "PYAS Security Driver"
+35
View File
@@ -0,0 +1,35 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36518.9 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PYAS_Driver", "PYAS_Driver.vcxproj", "{699C79A8-A904-1976-F72A-CDD7E811CFD2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Debug|ARM64.ActiveCfg = Debug|ARM64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Debug|ARM64.Build.0 = Debug|ARM64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Debug|ARM64.Deploy.0 = Debug|ARM64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Debug|x64.ActiveCfg = Debug|x64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Debug|x64.Build.0 = Debug|x64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Debug|x64.Deploy.0 = Debug|x64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Release|ARM64.ActiveCfg = Release|ARM64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Release|ARM64.Build.0 = Release|ARM64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Release|ARM64.Deploy.0 = Release|ARM64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Release|x64.ActiveCfg = Release|x64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Release|x64.Build.0 = Release|x64
{699C79A8-A904-1976-F72A-CDD7E811CFD2}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D166699A-50D5-470E-9559-39B8E842528D}
EndGlobalSection
EndGlobal
+128
View File
@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{699C79A8-A904-1976-F72A-CDD7E811CFD2}</ProjectGuid>
<TemplateGuid>{dd38f7fc-d7bd-488b-9242-7d8754cde80d}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">x64</Platform>
<RootNamespace>PYAS_Driver</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<ClCompile>
<LanguageStandard>stdcpp20</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)fltmgr.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)fltmgr.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Include="PYAS_Driver.inf" />
</ItemGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="DriverCommon.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="DriverEntry.cpp" />
<ClCompile Include="ProtectBoot.cpp" />
<ClCompile Include="ProtectFile.cpp" />
<ClCompile Include="ProtectProcess.cpp" />
<ClCompile Include="ProtectRegistry.cpp" />
<ClCompile Include="ProtectRules.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Inf Include="PYAS_Driver.inf">
<Filter>Driver Files</Filter>
</Inf>
</ItemGroup>
<ItemGroup>
<ClInclude Include="DriverCommon.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ProtectRules.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ProtectFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ProtectBoot.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ProtectRegistry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ProtectProcess.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DriverEntry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
-173
View File
@@ -1,173 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static VOID GetExeNameForLog(HANDLE pid, PUNICODE_STRING exe)
{
if (!exe || !exe->Buffer || exe->MaximumLength == 0)
return;
exe->Length = 0;
if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
if (GetProcessImagePathByPid(pid, exe))
return;
}
PEPROCESS eproc = PsGetCurrentProcess();
PCSTR n = PsGetProcessImageFileName(eproc);
size_t l = n ? strlen(n) : 0;
for (size_t i = 0; i < l && i < (exe->MaximumLength / sizeof(WCHAR)) - 1; i++)
exe->Buffer[i] = (WCHAR)n[i];
exe->Buffer[l] = 0;
exe->Length = (USHORT)(l * sizeof(WCHAR));
}
static BOOLEAN QueryDevName(PDEVICE_OBJECT dev, PUNICODE_STRING out)
{
if (!dev || !out || !out->Buffer || out->MaximumLength == 0)
return FALSE;
ULONG need = 0;
NTSTATUS s = ObQueryNameString(dev, NULL, 0, &need);
if (s != STATUS_INFO_LENGTH_MISMATCH || need == 0)
return FALSE;
POBJECT_NAME_INFORMATION oni = (POBJECT_NAME_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, need, 'nOmD');
if (!oni)
return FALSE;
BOOLEAN ok = FALSE;
s = ObQueryNameString(dev, oni, need, &need);
if (NT_SUCCESS(s) && oni->Name.Buffer && oni->Name.Length && oni->Name.Length < out->MaximumLength) {
RtlCopyMemory(out->Buffer, oni->Name.Buffer, oni->Name.Length);
out->Length = (USHORT)oni->Name.Length;
out->Buffer[out->Length / sizeof(WCHAR)] = 0;
ok = TRUE;
}
ExFreePool2(oni, 'nOmD', NULL, 0);
return ok;
}
static BOOLEAN IsDASDRoot(PFILE_OBJECT fo)
{
if (!fo)
return TRUE;
if (fo->FileName.Length == 0 && fo->RelatedFileObject == NULL)
return TRUE;
return FALSE;
}
static BOOLEAN IsDangerousDiskIo(PIO_STACK_LOCATION s)
{
if (!s)
return FALSE;
if (s->MajorFunction == IRP_MJ_DEVICE_CONTROL || s->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) {
ULONG code = s->Parameters.DeviceIoControl.IoControlCode;
if (code == IOCTL_SCSI_PASS_THROUGH || code == IOCTL_SCSI_PASS_THROUGH_DIRECT)
return TRUE;
if (code == IOCTL_DISK_SET_DRIVE_LAYOUT || code == IOCTL_DISK_SET_DRIVE_LAYOUT_EX)
return TRUE;
if (code == IOCTL_DISK_DELETE_DRIVE_LAYOUT)
return TRUE;
if (code == IOCTL_DISK_FORMAT_TRACKS || code == IOCTL_DISK_FORMAT_TRACKS_EX)
return TRUE;
if (code == IOCTL_DISK_SET_PARTITION_INFO || code == IOCTL_DISK_SET_PARTITION_INFO_EX)
return TRUE;
return FALSE;
}
if (s->MajorFunction == IRP_MJ_SCSI)
return TRUE;
if (s->MajorFunction == IRP_MJ_WRITE || s->MajorFunction == IRP_MJ_FLUSH_BUFFERS)
return TRUE;
return FALSE;
}
NTSTATUS BootProtectDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PDEVICE_OBJECT lower = (PDEVICE_OBJECT)DeviceObject->DeviceExtension;
if (!lower) {
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
if (!ExAcquireRundownProtection(&g_Rundown)) {
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(lower, Irp);
}
if (g_Unloading) {
IoSkipCurrentIrpStackLocation(Irp);
NTSTATUS rs = IoCallDriver(lower, Irp);
ExReleaseRundownProtection(&g_Rundown);
return rs;
}
PIO_STACK_LOCATION s = IoGetCurrentIrpStackLocation(Irp);
if (s->MajorFunction == IRP_MJ_POWER) {
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
NTSTATUS ps = PoCallDriver(lower, Irp);
ExReleaseRundownProtection(&g_Rundown);
return ps;
}
HANDLE pid = PsGetCurrentProcessId();
ULONG upid = (ULONG)(ULONG_PTR)pid;
if (upid == 0 || upid == 4) {
IoSkipCurrentIrpStackLocation(Irp);
NTSTATUS ns = IoCallDriver(lower, Irp);
ExReleaseRundownProtection(&g_Rundown);
return ns;
}
BOOLEAN blocked = FALSE;
WCHAR eb[512] = { 0 };
UNICODE_STRING exe = { 0 };
exe.Buffer = eb;
exe.MaximumLength = sizeof(eb);
if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
GetExeNameForLog(pid, &exe);
if (IsWhitelist(&exe)) {
IoSkipCurrentIrpStackLocation(Irp);
NTSTATUS ns2 = IoCallDriver(lower, Irp);
ExReleaseRundownProtection(&g_Rundown);
return ns2;
}
}
if (lower->DeviceType == FILE_DEVICE_DISK) {
if (IsDangerousDiskIo(s)) {
BOOLEAN hit = FALSE;
WCHAR db[512] = { 0 };
UNICODE_STRING dev = { 0 };
dev.Buffer = db;
dev.MaximumLength = sizeof(db);
if (QueryDevName(lower, &dev)) {
if (MatchBlockFile(&dev))
hit = TRUE;
}
else {
hit = TRUE;
}
if (!hit && s->MajorFunction == IRP_MJ_WRITE && s->FileObject && IsDASDRoot(s->FileObject))
hit = TRUE;
if (hit) {
blocked = TRUE;
if (dev.Length == 0)
QueryDevName(lower, &dev);
LogAnsi3("BOOT_BLOCK", upid, &exe, dev.Length ? &dev : &exe);
}
}
}
if (blocked) {
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
ExReleaseRundownProtection(&g_Rundown);
return STATUS_ACCESS_DENIED;
}
IoSkipCurrentIrpStackLocation(Irp);
NTSTATUS rs2 = IoCallDriver(lower, Irp);
ExReleaseRundownProtection(&g_Rundown);
return rs2;
}
+34
View File
@@ -0,0 +1,34 @@
#include "DriverCommon.h"
#ifndef IOCTL_DISK_FORMAT_TRACKS
#define IOCTL_DISK_FORMAT_TRACKS CTL_CODE(IOCTL_DISK_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#endif
#ifndef IOCTL_DISK_FORMAT_TRACKS_EX
#define IOCTL_DISK_FORMAT_TRACKS_EX CTL_CODE(IOCTL_DISK_BASE, 0x000b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#endif
FLT_PREOP_CALLBACK_STATUS ProtectBoot_PreDeviceControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
ULONG IoControlCode = Data->Iopb->Parameters.DeviceIoControl.Common.IoControlCode;
if (IoControlCode == IOCTL_DISK_SET_DRIVE_LAYOUT_EX ||
IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT ||
IoControlCode == IOCTL_DISK_FORMAT_TRACKS ||
IoControlCode == IOCTL_DISK_FORMAT_TRACKS_EX) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
UNICODE_STRING MsgStr = RTL_CONSTANT_STRING(L"Disk_Wiper_Attempt");
SendMessageToUser(4001, (ULONG)(ULONG_PTR)Pid, MsgStr.Buffer, MsgStr.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
return FLT_PREOP_COMPLETE;
}
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
-279
View File
@@ -1,279 +0,0 @@
#include <ntifs.h>
#include <fltKernel.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
#pragma comment(lib, "FltMgr.lib")
PFLT_FILTER g_FilterHandle = NULL;
PDRIVER_OBJECT g_DriverObject = NULL;
EX_RUNDOWN_REF g_Rundown;
typedef struct _MINIFILTER_DATA {
PFLT_FILTER Filter;
} MINIFILTER_DATA, * PMINIFILTER_DATA;
static VOID GetExeNameForLog(HANDLE pid, PUNICODE_STRING exe)
{
if (!exe || !exe->Buffer || !exe->MaximumLength)
return;
exe->Length = 0;
if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
if (GetProcessImagePathByPid(pid, exe))
return;
}
PEPROCESS eproc = NULL;
NTSTATUS s = PsLookupProcessByProcessId(pid, &eproc);
if (NT_SUCCESS(s) && eproc) {
PCSTR n = PsGetProcessImageFileName(eproc);
size_t l = n ? strlen(n) : 0;
for (size_t i = 0; i < l && i < (exe->MaximumLength / sizeof(WCHAR)) - 1; i++)
exe->Buffer[i] = (WCHAR)n[i];
exe->Buffer[l] = 0;
exe->Length = (USHORT)(l * sizeof(WCHAR));
ObDereferenceObject(eproc);
return;
}
PCSTR n = NULL;
PEPROCESS cur = PsGetCurrentProcess();
if (cur)
n = PsGetProcessImageFileName(cur);
size_t l = n ? strlen(n) : 0;
for (size_t i = 0; i < l && i < (exe->MaximumLength / sizeof(WCHAR)) - 1; i++)
exe->Buffer[i] = (WCHAR)n[i];
exe->Buffer[l] = 0;
exe->Length = (USHORT)(l * sizeof(WCHAR));
}
static BOOLEAN PreOpCheck(ULONG* outUpid)
{
if (g_Unloading)
return FALSE;
if (!ExAcquireRundownProtection(&g_Rundown))
return FALSE;
HANDLE pid = PsGetCurrentProcessId();
ULONG upid = (ULONG)(ULONG_PTR)pid;
if (upid == 0 || upid == 4) {
ExReleaseRundownProtection(&g_Rundown);
return FALSE;
}
*outUpid = upid;
return TRUE;
}
static VOID PostOpRelease()
{
ExReleaseRundownProtection(&g_Rundown);
}
static BOOLEAN IsExeWhitelisted(ULONG pid)
{
WCHAR buffer[512] = { 0 };
UNICODE_STRING exe = { 0 };
exe.Buffer = buffer;
exe.MaximumLength = sizeof(buffer);
GetExeNameForLog((HANDLE)pid, &exe);
return IsWhitelist(&exe);
}
static BOOLEAN IsDeleteOrRename(PFLT_CALLBACK_DATA Data)
{
FILE_INFORMATION_CLASS infoClass = Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
if (infoClass == FileDispositionInformation) {
PFILE_DISPOSITION_INFORMATION di = (PFILE_DISPOSITION_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
return di && di->DeleteFile;
}
if (infoClass == FileDispositionInformationEx) {
PFILE_DISPOSITION_INFORMATION_EX dx = (PFILE_DISPOSITION_INFORMATION_EX)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
return dx && (dx->Flags & FILE_DISPOSITION_DELETE);
}
if (infoClass == FileRenameInformation || infoClass == FileRenameInformationEx)
return TRUE;
return FALSE;
}
static FLT_PREOP_CALLBACK_STATUS CheckAndBlockFile(PFLT_CALLBACK_DATA Data, ULONG upid, PUNICODE_STRING exe)
{
if (KeGetCurrentIrql() > APC_LEVEL)
return FLT_PREOP_SUCCESS_NO_CALLBACK;
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
if (!NT_SUCCESS(status))
return FLT_PREOP_SUCCESS_NO_CALLBACK;
status = FltParseFileNameInformation(nameInfo);
if (!NT_SUCCESS(status)) {
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
BOOLEAN hitFile = MatchBlockFile(&nameInfo->Name);
BOOLEAN hitRansom = MatchBlockRansom(&nameInfo->Name) && HasBlockedSuffix(&nameInfo->Name);
BOOLEAN blocked = hitFile || hitRansom;
if (blocked) {
LogAnsi3(hitFile && !hitRansom ? "FILE_BLOCK" : "RANSOM_BLOCK", upid, exe, &nameInfo->Name);
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
Data->IoStatus.Information = 0;
return FLT_PREOP_COMPLETE;
}
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
static FLT_PREOP_CALLBACK_STATUS FilePreOp(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
ULONG upid;
if (!PreOpCheck(&upid))
return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (KeGetCurrentIrql() > APC_LEVEL) {
PostOpRelease();
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
BOOLEAN checkFile = (Data->Iopb->MajorFunction == IRP_MJ_CREATE || Data->Iopb->MajorFunction == IRP_MJ_WRITE);
BOOLEAN checkSetInfo = (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION && IsDeleteOrRename(Data));
if (!checkFile && !checkSetInfo) {
PostOpRelease();
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
if (!NT_SUCCESS(status)) {
PostOpRelease();
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
status = FltParseFileNameInformation(nameInfo);
if (!NT_SUCCESS(status)) {
FltReleaseFileNameInformation(nameInfo);
PostOpRelease();
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
WCHAR exe_buffer[512] = { 0 };
UNICODE_STRING exe = { 0 };
exe.Buffer = exe_buffer;
exe.MaximumLength = sizeof(exe_buffer);
GetExeNameForLog(PsGetCurrentProcessId(), &exe);
BOOLEAN hitFile = MatchBlockFile(&nameInfo->Name);
BOOLEAN hitRansom = MatchBlockRansom(&nameInfo->Name) && HasBlockedSuffix(&nameInfo->Name);
BOOLEAN isExcept = IsWhitelistExcept(&exe);
if ((hitFile || hitRansom) && !isExcept) {
LogAnsi3(hitFile && !hitRansom ? "FILE_BLOCK" : "RANSOM_BLOCK", upid, &exe, &nameInfo->Name);
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
Data->IoStatus.Information = 0;
PostOpRelease();
return FLT_PREOP_COMPLETE;
}
if (isExcept && hitRansom) {
LogAnsi3("RANSOM_BLOCK", upid, &exe, &nameInfo->Name);
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
Data->IoStatus.Information = 0;
PostOpRelease();
return FLT_PREOP_COMPLETE;
}
if (IsWhitelist(&nameInfo->Name)) {
FltReleaseFileNameInformation(nameInfo);
PostOpRelease();
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FltReleaseFileNameInformation(nameInfo);
PostOpRelease();
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
static NTSTATUS FilterUnloadCallback(FLT_FILTER_UNLOAD_FLAGS Flags)
{
UNREFERENCED_PARAMETER(Flags);
g_Unloading = TRUE;
ExWaitForRundownProtectionRelease(&g_Rundown);
if (g_FilterHandle != NULL) {
FltUnregisterFilter(g_FilterHandle);
g_FilterHandle = NULL;
}
return STATUS_SUCCESS;
}
static NTSTATUS FilterInstanceSetup(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(VolumeDeviceType);
UNREFERENCED_PARAMETER(VolumeFilesystemType);
return STATUS_SUCCESS;
}
static VOID FilterInstanceTeardownStart(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
static VOID FilterInstanceTeardownComplete(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}
const FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE, 0, FilePreOp, NULL },
{ IRP_MJ_WRITE, 0, FilePreOp, NULL },
{ IRP_MJ_SET_INFORMATION, 0, FilePreOp, NULL },
{ IRP_MJ_OPERATION_END }
};
const FLT_REGISTRATION FilterRegistration = {
sizeof(FLT_REGISTRATION),
FLT_REGISTRATION_VERSION, 0, NULL, Callbacks, FilterUnloadCallback, FilterInstanceSetup, NULL,
FilterInstanceTeardownStart, FilterInstanceTeardownComplete, NULL, NULL, NULL, NULL
};
NTSTATUS InitFileProtect(VOID)
{
ExInitializeRundownProtection(&g_Rundown);
NTSTATUS status = FltRegisterFilter(g_DriverObject, &FilterRegistration, &g_FilterHandle);
if (!NT_SUCCESS(status))
return status;
status = FltStartFiltering(g_FilterHandle);
if (!NT_SUCCESS(status)) {
FltUnregisterFilter(g_FilterHandle);
g_FilterHandle = NULL;
}
return status;
}
VOID UninitFileProtect(VOID)
{
g_Unloading = TRUE;
ExWaitForRundownProtectionRelease(&g_Rundown);
if (g_FilterHandle != NULL) {
FltUnregisterFilter(g_FilterHandle);
g_FilterHandle = NULL;
}
}
+236
View File
@@ -0,0 +1,236 @@
#include "DriverCommon.h"
static BOOLEAN IsHoneyToken(PUNICODE_STRING Path) {
if (!Path || !Path->Buffer) return FALSE;
if (WildcardMatch(L"*PYAS_Honey*", Path->Buffer, Path->Length) ||
WildcardMatch(L"*Backup_Secret*", Path->Buffer, Path->Length)) {
return TRUE;
}
return FALSE;
}
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
UNICODE_STRING FileName = { 0 };
NTSTATUS status = STATUS_SUCCESS;
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
if (!NT_SUCCESS(status) || !nameInfo) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
status = FltParseFileNameInformation(nameInfo);
if (!NT_SUCCESS(status)) {
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FileName = nameInfo->Name;
if (!FileName.Buffer || FileName.Length == 0) {
goto cleanup;
}
HANDLE Pid = PsGetCurrentProcessId();
BOOLEAN Trusted = IsProcessTrusted(Pid);
if (IsHoneyToken(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
goto cleanup;
}
}
}
if (WildcardMatch(L"\\Device\\PhysicalDrive*", FileName.Buffer, FileName.Length) ||
(WildcardMatch(L"\\Device\\Harddisk*", FileName.Buffer, FileName.Length) && !WildcardMatch(L"*Volume*", FileName.Buffer, FileName.Length))) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &
(FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE | WRITE_DAC | WRITE_OWNER)) {
if (!Trusted && !IsInstallerProcess(Pid)) {
UNICODE_STRING MsgStr = RTL_CONSTANT_STRING(L"Disk_Wiper_Attempt");
SendMessageToUser(4001, (ULONG)(ULONG_PTR)Pid, MsgStr.Buffer, MsgStr.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
goto cleanup;
}
}
}
if (CheckProtectedPathRule(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE | WRITE_DAC | GENERIC_WRITE)) {
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
goto cleanup;
}
}
}
if (CheckFileExtensionRule(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (DELETE | FILE_DELETE_CHILD)) {
if (CheckRansomActivity(Pid, &FileName, NULL, 0, FALSE)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
goto cleanup;
}
}
}
}
cleanup:
if (nameInfo) {
FltReleaseFileNameInformation(nameInfo);
}
return callbackStatus;
}
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreSetInfo(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
FILE_INFORMATION_CLASS infoClass = Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
if (infoClass != FileDispositionInformation &&
infoClass != FileRenameInformation &&
infoClass != FileRenameInformationEx) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
if (!NT_SUCCESS(status) || !nameInfo) return FLT_PREOP_SUCCESS_NO_CALLBACK;
status = FltParseFileNameInformation(nameInfo);
if (!NT_SUCCESS(status) || !nameInfo->Name.Buffer) {
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
if (CheckFileExtensionRule(&nameInfo->Name) || CheckProtectedPathRule(&nameInfo->Name)) {
if (CheckRansomActivity(Pid, &nameInfo->Name, NULL, 0, FALSE)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
}
}
if (nameInfo) {
FltReleaseFileNameInformation(nameInfo);
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (Data->Iopb->IrpFlags & (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE)) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
ULONG WriteLength = Data->Iopb->Parameters.Write.Length;
if (WriteLength == 0) return FLT_PREOP_SUCCESS_NO_CALLBACK;
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
if (NT_SUCCESS(status) && nameInfo) {
status = FltParseFileNameInformation(nameInfo);
if (NT_SUCCESS(status) && nameInfo->Name.Buffer) {
if (CheckFileExtensionRule(&nameInfo->Name)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
PVOID SystemBuffer = NULL;
PMDL Mdl = Data->Iopb->Parameters.Write.MdlAddress;
if (!Mdl) {
if (Data->Iopb->Parameters.Write.WriteBuffer && KeGetCurrentIrql() <= APC_LEVEL) {
if (NT_SUCCESS(FltLockUserBuffer(Data))) {
Mdl = Data->Iopb->Parameters.Write.MdlAddress;
}
}
}
if (Mdl) {
SystemBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority | MdlMappingNoExecute);
}
if (SystemBuffer) {
if (CheckRansomActivity(Pid, &nameInfo->Name, SystemBuffer, WriteLength, TRUE)) {
if (!IsInstallerProcess(Pid)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
}
}
}
}
}
}
FltReleaseFileNameInformation(nameInfo);
}
return callbackStatus;
}
FLT_PREOP_CALLBACK_STATUS ProtectFile_FileSystemControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (Data->Iopb->Parameters.FileSystemControl.Common.FsControlCode != FSCTL_MANAGE_BYPASS_IO) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
PFS_BPIO_INPUT InputBuffer = (PFS_BPIO_INPUT)Data->Iopb->Parameters.FileSystemControl.Neither.InputBuffer;
if (!InputBuffer) return FLT_PREOP_SUCCESS_NO_CALLBACK;
__try {
if (InputBuffer->Operation == FS_BPIO_OP_ENABLE) {
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
if (NT_SUCCESS(FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo)) && nameInfo) {
if (NT_SUCCESS(FltParseFileNameInformation(nameInfo))) {
if (CheckFileExtensionRule(&nameInfo->Name) || CheckProtectedPathRule(&nameInfo->Name)) {
Data->IoStatus.Status = STATUS_NOT_SUPPORTED;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
}
FltReleaseFileNameInformation(nameInfo);
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
-123
View File
@@ -1,123 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static BOOLEAN g_ImageNotifyEnabled = FALSE;
static BOOLEAN CheckVadExec(PVOID a)
{
MEMORY_BASIC_INFORMATION mbi = { 0 };
SIZE_T ret = 0;
NTSTATUS s = ZwQueryVirtualMemory(NtCurrentProcess(), a, MemoryBasicInformation, &mbi, sizeof(mbi), &ret);
if (!NT_SUCCESS(s))
return FALSE;
if (mbi.State != MEM_COMMIT)
return FALSE;
if (mbi.Type == SEC_IMAGE)
return FALSE;
if (mbi.Type != MEM_PRIVATE && mbi.Type != MEM_MAPPED)
return FALSE;
return (mbi.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0;
}
static BOOLEAN WalkForShellcode(ULONG h)
{
#define MAXWALK 20
PVOID frames[MAXWALK] = { 0 };
ULONG c = RtlWalkFrameChain(frames, MAXWALK, 1);
if (c == 0)
return FALSE;
ULONG limit = RTL_NUMBER_OF(frames);
ULONG count = c < limit ? c : limit;
ULONG d = h < count ? h : count;
for (ULONG i = 0; i < d; i++) {
PVOID p = frames[i];
if (p && CheckVadExec(p))
return TRUE;
}
for (ULONG i = 0; i < d; i++) {
ULONG idx = count - 1 - i;
if (idx >= d) {
PVOID p = frames[idx];
if (p && CheckVadExec(p))
return TRUE;
}
}
return FALSE;
}
static VOID ImageLoadNotify(IN PUNICODE_STRING FullImageName, IN HANDLE ProcessId, IN PIMAGE_INFO ImageInfo)
{
UNREFERENCED_PARAMETER(ImageInfo);
if (g_Unloading)
return;
if (ProcessId == (HANDLE)0 || ProcessId == (HANDLE)4)
return;
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
return;
if (!ExAcquireRundownProtection(&g_Rundown))
return;
WCHAR eb[512] = { 0 };
UNICODE_STRING exe = { 0 };
exe.Buffer = eb;
exe.MaximumLength = sizeof(eb);
exe.Length = 0;
if (!GetProcessImagePathByPid(ProcessId, &exe)) {
PEPROCESS eproc = PsGetCurrentProcess();
PCSTR n = PsGetProcessImageFileName(eproc);
size_t l = n ? strlen(n) : 0;
for (size_t i = 0; i < l && i < RTL_NUMBER_OF(eb) - 1; i++)
eb[i] = (WCHAR)n[i];
eb[l] = 0;
exe.Length = (USHORT)(l * sizeof(WCHAR));
}
if (exe.Length & 1) exe.Length--;
{
size_t elen = exe.Length / sizeof(WCHAR);
if ((elen >= 14 && _wcsnicmp(exe.Buffer + elen - 14, L"powershell.exe", 14) == 0) ||
(elen >= 8 && _wcsnicmp(exe.Buffer + elen - 8, L"pwsh.exe", 8) == 0)) {
ExReleaseRundownProtection(&g_Rundown);
return;
}
}
if (IsWhitelist(&exe)) {
ExReleaseRundownProtection(&g_Rundown);
return;
}
if (FullImageName && FullImageName->Buffer) {
if (MatchClrFromNonFramework(FullImageName)) {
LogAnsi3("CLR_BLOCK", (ULONG)(ULONG_PTR)ProcessId, &exe, FullImageName);
ExReleaseRundownProtection(&g_Rundown);
return;
}
}
if (WalkForShellcode(8)) {
UNICODE_STRING none = RTL_CONSTANT_STRING(L"None");
LogAnsi3("SHELLCODE_BLOCK", (ULONG)(ULONG_PTR)ProcessId, &exe, &none);
ExReleaseRundownProtection(&g_Rundown);
return;
}
ExReleaseRundownProtection(&g_Rundown);
}
NTSTATUS InitImageProtect(VOID)
{
NTSTATUS s = PsSetLoadImageNotifyRoutine(ImageLoadNotify);
if (NT_SUCCESS(s))
g_ImageNotifyEnabled = TRUE;
return s;
}
VOID UninitImageProtect(VOID)
{
if (g_ImageNotifyEnabled) {
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
g_ImageNotifyEnabled = FALSE;
}
}
-177
View File
@@ -1,177 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static PVOID g_ObRegHandle = NULL;
static POB_OPERATION_REGISTRATION g_ObOps = NULL;
static OB_CALLBACK_REGISTRATION g_ObReg = { 0 };
static OB_PREOP_CALLBACK_STATUS PreProcessCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION Info)
{
UNREFERENCED_PARAMETER(RegistrationContext);
if (g_Unloading)
return OB_PREOP_SUCCESS;
if (!Info || Info->KernelHandle)
return OB_PREOP_SUCCESS;
if (!Info->Object)
return OB_PREOP_SUCCESS;
if (Info->Operation != OB_OPERATION_HANDLE_CREATE && Info->Operation != OB_OPERATION_HANDLE_DUPLICATE)
return OB_PREOP_SUCCESS;
if (!ExAcquireRundownProtection(&g_Rundown))
return OB_PREOP_SUCCESS;
HANDLE cur = PsGetCurrentProcessId();
if (cur == (HANDLE)0 || cur == (HANDLE)4) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
HANDLE target = PsGetProcessId((PEPROCESS)Info->Object);
if (target == cur) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
ACCESS_MASK* desired = (Info->Operation == OB_OPERATION_HANDLE_CREATE) ? &Info->Parameters->CreateHandleInformation.DesiredAccess : &Info->Parameters->DuplicateHandleInformation.DesiredAccess;
ACCESS_MASK mask = PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE;
PCSTR tn = PsGetProcessImageFileName((PEPROCESS)Info->Object);
if (tn && (_stricmp(tn, "lsass.exe") == 0))
mask |= PROCESS_VM_READ;
if ((*desired & mask) == 0) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
BOOLEAN logok = (KeGetCurrentIrql() == PASSIVE_LEVEL);
WCHAR cbuf[512] = { 0 }, tbuf[512] = { 0 };
UNICODE_STRING cexe = { 0 }, texe = { 0 };
cexe.Buffer = cbuf; cexe.MaximumLength = sizeof(cbuf);
texe.Buffer = tbuf; texe.MaximumLength = sizeof(tbuf);
if (logok)
GetProcessImagePathByPid(cur, &cexe);
if (logok && IsWhitelist(&cexe)) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
ACCESS_MASK old = *desired;
*desired &= ~mask;
if ((*desired) != old && logok) {
GetProcessImagePathByPid(target, &texe);
if (cexe.Length == 0) {
PEPROCESS eproc = PsGetCurrentProcess();
PCSTR n = PsGetProcessImageFileName(eproc);
size_t l = n ? strlen(n) : 0;
for (size_t i = 0; i < l && i < RTL_NUMBER_OF(cbuf) - 1; i++)
cbuf[i] = (WCHAR)n[i];
cbuf[l] = 0;
cexe.Length = (USHORT)(l * sizeof(WCHAR));
}
LogAnsi3("INJECT_BLOCK", (ULONG)(ULONG_PTR)cur, &cexe, &texe);
}
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
static OB_PREOP_CALLBACK_STATUS PreThreadCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION Info)
{
UNREFERENCED_PARAMETER(RegistrationContext);
if (!Info || Info->KernelHandle)
return OB_PREOP_SUCCESS;
if (Info->Object == NULL)
return OB_PREOP_SUCCESS;
if (Info->Operation != OB_OPERATION_HANDLE_CREATE && Info->Operation != OB_OPERATION_HANDLE_DUPLICATE)
return OB_PREOP_SUCCESS;
if (!ExAcquireRundownProtection(&g_Rundown))
return OB_PREOP_SUCCESS;
HANDLE cur = PsGetCurrentProcessId();
if (cur == (HANDLE)0 || cur == (HANDLE)4) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
HANDLE owner = PsGetThreadProcessId((PETHREAD)Info->Object);
if (owner == cur) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
ACCESS_MASK tmask = THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_IMPERSONATE | THREAD_DIRECT_IMPERSONATION;
ACCESS_MASK* desired = (Info->Operation == OB_OPERATION_HANDLE_CREATE) ? &Info->Parameters->CreateHandleInformation.DesiredAccess : &Info->Parameters->DuplicateHandleInformation.DesiredAccess;
if ((*desired & tmask) == 0) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
BOOLEAN logok = (KeGetCurrentIrql() == PASSIVE_LEVEL);
WCHAR cbuf[512] = { 0 };
UNICODE_STRING cexe = { 0 };
cexe.Buffer = cbuf;
cexe.MaximumLength = sizeof(cbuf);
if (logok)
GetProcessImagePathByPid(cur, &cexe);
if (logok && IsWhitelist(&cexe)) {
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
ACCESS_MASK old = *desired;
*desired &= ~tmask;
if ((*desired) != old && logok) {
if (cexe.Length == 0) {
PEPROCESS eproc = PsGetCurrentProcess();
PCSTR n = PsGetProcessImageFileName(eproc);
size_t l = n ? strlen(n) : 0;
for (size_t i = 0; i < l && i < RTL_NUMBER_OF(cbuf) - 1; i++)
cbuf[i] = (WCHAR)n[i];
cbuf[l] = 0;
cexe.Length = (USHORT)(l * sizeof(WCHAR));
}
UNICODE_STRING tnone = RTL_CONSTANT_STRING(L"None");
LogAnsi3("THREAD_BLOCK", (ULONG)(ULONG_PTR)cur, &cexe, &tnone);
}
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
NTSTATUS InitInjectProtect(VOID)
{
static UNICODE_STRING obAlt;
RtlInitUnicodeString(&obAlt, L"385000");
g_ObOps = (POB_OPERATION_REGISTRATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(OB_OPERATION_REGISTRATION) * 2, 'bOpr');
if (!g_ObOps)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(g_ObOps, sizeof(OB_OPERATION_REGISTRATION) * 2);
g_ObOps[0].ObjectType = PsProcessType;
g_ObOps[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
g_ObOps[0].PreOperation = PreProcessCallback;
g_ObOps[1].ObjectType = PsThreadType;
g_ObOps[1].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
g_ObOps[1].PreOperation = PreThreadCallback;
RtlZeroMemory(&g_ObReg, sizeof(g_ObReg));
g_ObReg.Version = OB_FLT_REGISTRATION_VERSION;
g_ObReg.OperationRegistrationCount = 2;
g_ObReg.Altitude = obAlt;
g_ObReg.RegistrationContext = NULL;
g_ObReg.OperationRegistration = g_ObOps;
NTSTATUS s = ObRegisterCallbacks(&g_ObReg, &g_ObRegHandle);
if (!NT_SUCCESS(s)) {
ExFreePool2(g_ObOps, 'bOpr', NULL, 0);
g_ObOps = NULL;
RtlZeroMemory(&g_ObReg, sizeof(g_ObReg));
}
return s;
}
VOID UninitInjectProtect(VOID)
{
if (g_ObRegHandle) {
ObUnRegisterCallbacks(g_ObRegHandle);
g_ObRegHandle = NULL;
}
if (g_ObOps) {
ExFreePool2(g_ObOps, 'bOpr', NULL, 0);
g_ObOps = NULL;
}
RtlZeroMemory(&g_ObReg, sizeof(g_ObReg));
}
-346
View File
@@ -1,346 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectRules.h"
#include "ProtectMatch.h"
static __forceinline BOOLEAN USOK(PUNICODE_STRING s)
{
return s && s->Buffer && s->Length;
}
static BOOLEAN WildMatchN(const wchar_t* str, SIZE_T n, const wchar_t* pat)
{
if (*pat == 0)
return n == 0;
if (*pat == L'*') {
if (pat[1] == L'*') {
for (SIZE_T i = 0; i <= n; ++i)
if (WildMatchN(str + i, n - i, pat + 2))
return TRUE;
return FALSE;
}
SIZE_T i = 0;
for (; i < n && str[i] != L'\\'; ++i)
if (WildMatchN(str + i, n - i, pat + 1))
return TRUE;
return WildMatchN(str + i, n - i, pat + 1);
}
if (*pat == L'?')
return n > 0 && str[0] != L'\\' && WildMatchN(str + 1, n - 1, pat + 1);
if (n == 0)
return FALSE;
WCHAR sc = str[0], pc = *pat;
if (sc >= L'A' && sc <= L'Z')
sc += 32;
if (pc >= L'A' && pc <= L'Z')
pc += 32;
return sc == pc && WildMatchN(str + 1, n - 1, pat + 1);
}
static BOOLEAN MatchList(PUNICODE_STRING s, wchar_t** list)
{
if (!USOK(s) || !list)
return FALSE;
SIZE_T s_len = s->Length / sizeof(WCHAR);
for (SIZE_T i = 0; list[i]; ++i) {
wchar_t* pat = list[i];
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
if (WildMatchN(s->Buffer, s_len, pat))
return TRUE;
}
else {
SIZE_T pat_len = wcslen(pat);
if (s_len >= pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0) {
if (s_len == pat_len || s->Buffer[s_len - pat_len - 1] == L'\\') {
return TRUE;
}
}
if (s_len >= pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0) {
return TRUE;
}
}
}
return FALSE;
}
static wchar_t* MatchListGetRule(PUNICODE_STRING s, wchar_t** list)
{
if (!USOK(s) || !list)
return 0;
SIZE_T s_len = s->Length / sizeof(WCHAR);
for (SIZE_T i = 0; list[i]; ++i) {
wchar_t* pat = list[i];
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
if (WildMatchN(s->Buffer, s_len, pat))
return pat;
}
else {
SIZE_T pat_len = wcslen(pat);
if (s_len >= pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0) {
if (s_len == pat_len || s->Buffer[s_len - pat_len - 1] == L'\\') {
return pat;
}
}
if (s_len >= pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0) {
return pat;
}
}
}
return 0;
}
static BOOLEAN StrStrIW(const wchar_t* s, const wchar_t* sub)
{
if (!s || !sub)
return FALSE;
SIZE_T n = wcslen(s), m = wcslen(sub);
if (m == 0 || n < m)
return FALSE;
for (SIZE_T i = 0; i + m <= n; i++) {
if (_wcsnicmp(s + i, sub, m) == 0)
return TRUE;
}
return FALSE;
}
static BOOLEAN EndsWithNameUS(PUNICODE_STRING s, const wchar_t* name)
{
if (!USOK(s) || !name)
return FALSE;
SIZE_T n = s->Length / sizeof(WCHAR);
SIZE_T m = wcslen(name);
return n >= m && _wcsnicmp(s->Buffer + (n - m), name, m) == 0;
}
BOOLEAN IsRegistryBlock(PUNICODE_STRING key, PUNICODE_STRING valueName, PUNICODE_STRING exe)
{
if (USOK(key) && WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\**"))
return FALSE;
if (USOK(exe) && IsWhitelist(exe))
return FALSE;
if (USOK(exe) && USOK(key)) {
if ((EndsWithNameUS(exe, L"services.exe") || EndsWithNameUS(exe, L"svchost.exe") || EndsWithNameUS(exe, L"sc.exe")) &&
WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**"))
return FALSE;
if ((EndsWithNameUS(exe, L"powershell.exe") || EndsWithNameUS(exe, L"pwsh.exe")) &&
(WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\**\\CurrentVersion\\Internet Settings\\ZoneMap\\**") ||
WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\**\\CurrentVersion\\Notifications\\Data\\**")))
return FALSE;
if ((EndsWithNameUS(exe, L"msiexec.exe") || EndsWithNameUS(exe, L"TrustedInstaller.exe")) &&
(WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\**\\CurrentVersion\\Installer\\**") ||
WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\**\\CurrentVersion\\Uninstall\\**") ||
WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**")))
return FALSE;
if (EndsWithNameUS(exe, L"schtasks.exe") && WildMatchN(key->Buffer, key->Length / sizeof(WCHAR), L"\\REGISTRY\\**\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\**"))
return FALSE;
}
if (USOK(key) && MatchBlockReg(key))
return TRUE;
if (USOK(valueName)) {
for (SIZE_T i = 0; g_BlockReg[i]; ++i) {
wchar_t* pat = g_BlockReg[i];
if (!wcschr(pat, L'\\') && !wcschr(pat, L'*') && !wcschr(pat, L'?') && _wcsnicmp(valueName->Buffer, pat, wcslen(pat)) == 0)
return TRUE;
}
}
return FALSE;
}
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath)
{
PEPROCESS process = NULL;
PVOID buf = NULL;
HANDLE h = NULL;
NTSTATUS status;
ULONG len = 0;
status = PsLookupProcessByProcessId(pid, &process);
if (!NT_SUCCESS(status))
return FALSE;
status = ObOpenObjectByPointer(process, OBJ_KERNEL_HANDLE, NULL, PROCESS_QUERY_LIMITED_INFORMATION, *PsProcessType, KernelMode, &h);
if (!NT_SUCCESS(status))
goto cleanup;
status = ZwQueryInformationProcess(h, ProcessImageFileName, NULL, 0, &len);
if (status != STATUS_INFO_LENGTH_MISMATCH || len == 0)
goto cleanup;
buf = ExAllocatePool2(POOL_FLAG_NON_PAGED, len, 'iPgN');
if (!buf)
goto cleanup;
status = ZwQueryInformationProcess(h, ProcessImageFileName, buf, len, &len);
if (NT_SUCCESS(status)) {
PUNICODE_STRING image = (PUNICODE_STRING)buf;
if (image->Buffer && image->Length > 0 && ProcessImagePath->MaximumLength >= image->Length + sizeof(WCHAR)) {
RtlCopyMemory(ProcessImagePath->Buffer, image->Buffer, image->Length);
ProcessImagePath->Length = image->Length;
ProcessImagePath->Buffer[image->Length / sizeof(WCHAR)] = 0;
status = TRUE;
}
else {
status = FALSE;
}
}
else {
status = FALSE;
}
cleanup:
if (buf)
ExFreePool2(buf, 'iPgN', NULL, 0);
if (h)
ZwClose(h);
if (process)
ObDereferenceObject(process);
return NT_SUCCESS(status);
}
BOOLEAN IsWhitelist(PUNICODE_STRING s)
{
if (MatchList(s, g_WhitelistExcept))
return FALSE;
return MatchList(s, g_Whitelist);
}
BOOLEAN MatchBlockReg(PUNICODE_STRING s)
{
return MatchList(s, g_BlockReg);
}
wchar_t* GetMatchedBlockRegRule(PUNICODE_STRING s)
{
return MatchListGetRule(s, g_BlockReg);
}
BOOLEAN MatchBlockFile(PUNICODE_STRING s)
{
return MatchList(s, g_BlockFile);
}
BOOLEAN MatchBlockRansom(PUNICODE_STRING s)
{
return MatchList(s, g_BlockRansom);
}
wchar_t* GetMatchedBlockFileRule(PUNICODE_STRING s)
{
return MatchListGetRule(s, g_BlockFile);
}
BOOLEAN HasBlockedSuffix(PUNICODE_STRING s)
{
if (!USOK(s)) {
return FALSE;
}
for (SIZE_T i = 0; g_Blocksuffix[i]; ++i) {
if (EndsWithNameUS(s, g_Blocksuffix[i])) {
return TRUE;
}
}
return FALSE;
}
BOOLEAN MatchRemoteSuspectBin(PUNICODE_STRING img)
{
if (!USOK(img))
return FALSE;
for (SIZE_T i = 0; g_RemoteSuspectBins[i]; ++i)
if (EndsWithNameUS(img, g_RemoteSuspectBins[i]))
return TRUE;
return FALSE;
}
BOOLEAN MatchRemoteCommand(PUNICODE_STRING cmd, PUNICODE_STRING img)
{
if (!USOK(cmd))
return FALSE;
const wchar_t* s = cmd->Buffer;
for (SIZE_T i = 0; g_RemoteCmdIndicatorsHttp[i]; ++i)
if (StrStrIW(s, g_RemoteCmdIndicatorsHttp[i]))
return TRUE;
for (SIZE_T i = 0; g_RemoteCmdIndicatorsGeneric[i]; ++i)
if (StrStrIW(s, g_RemoteCmdIndicatorsGeneric[i]))
return TRUE;
if (USOK(img) && EndsWithNameUS(img, L"cmd.exe")) {
for (SIZE_T i = 0; g_RemoteCmdFromCmdExe[i]; ++i)
if (StrStrIW(s, g_RemoteCmdFromCmdExe[i]))
return TRUE;
}
if (USOK(img) && EndsWithNameUS(img, L"rundll32.exe")) {
for (SIZE_T i = 0; g_RemoteCmdFromRundll32Exe[i]; ++i)
if (StrStrIW(s, g_RemoteCmdFromRundll32Exe[i]))
return TRUE;
}
if (USOK(img) && EndsWithNameUS(img, L"regsvr32.exe") && StrStrIW(s, L"/i:") && StrStrIW(s, L"http"))
return TRUE;
if (USOK(img) && EndsWithNameUS(img, L"mshta.exe")) {
for (SIZE_T i = 0; g_RemoteCmdFromMshtaExe[i]; ++i)
if (StrStrIW(s, g_RemoteCmdFromMshtaExe[i]))
return TRUE;
}
return FALSE;
}
BOOLEAN MatchScreenCapModule(PUNICODE_STRING mod)
{
if (!USOK(mod))
return FALSE;
for (SIZE_T i = 0; g_ScreenCapModules[i]; ++i)
if (EndsWithNameUS(mod, g_ScreenCapModules[i]))
return TRUE;
return FALSE;
}
BOOLEAN MatchSuspiciousProcPath(PUNICODE_STRING img)
{
if (!USOK(img))
return FALSE;
const wchar_t* s = img->Buffer;
if (StrStrIW(s, L"\\Users\\")) {
for (SIZE_T i = 0; g_ScreenUserSubdirs[i]; ++i)
if (StrStrIW(s, g_ScreenUserSubdirs[i]))
return TRUE;
}
for (SIZE_T i = 0; g_ScreenOtherProcNeedles[i]; ++i)
if (StrStrIW(s, g_ScreenOtherProcNeedles[i]))
return TRUE;
return FALSE;
}
BOOLEAN MatchClrFromNonFramework(PUNICODE_STRING fullImageName)
{
if (!USOK(fullImageName))
return FALSE;
const wchar_t* s = fullImageName->Buffer;
return (StrStrIW(s, L"\\clr.dll") || StrStrIW(s, L"\\mscorwks.dll")) && !StrStrIW(s, L"\\Windows\\Microsoft.NET\\") && !StrStrIW(s, L"\\Framework");
}
BOOLEAN IsWhitelistExcept(PUNICODE_STRING img)
{
if (!USOK(img))
return FALSE;
return MatchList(img, g_WhitelistExcept);
}
-23
View File
@@ -1,23 +0,0 @@
#pragma once
#include <ntifs.h>
wchar_t* GetMatchedBlockRegRule(PUNICODE_STRING s);
wchar_t* GetMatchedBlockFileRule(PUNICODE_STRING s);
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath);
BOOLEAN IsWhitelist(PUNICODE_STRING s);
BOOLEAN IsWhitelistExcept(PUNICODE_STRING img);
BOOLEAN MatchBlockReg(PUNICODE_STRING s);
BOOLEAN IsRegistryBlock(PUNICODE_STRING key, PUNICODE_STRING valueName, PUNICODE_STRING exe);
BOOLEAN MatchBlockFile(PUNICODE_STRING s);
BOOLEAN MatchBlockRansom(PUNICODE_STRING s);
BOOLEAN HasBlockedSuffix(PUNICODE_STRING s);
BOOLEAN MatchRemoteSuspectBin(PUNICODE_STRING img);
BOOLEAN MatchRemoteCommand(PUNICODE_STRING cmd, PUNICODE_STRING img);
BOOLEAN MatchScreenCapModule(PUNICODE_STRING mod);
BOOLEAN MatchSuspiciousProcPath(PUNICODE_STRING img);
BOOLEAN MatchClrFromNonFramework(PUNICODE_STRING fullImageName);
-125
View File
@@ -1,125 +0,0 @@
#include <ntifs.h>
#include <ntstrsafe.h>
#include "DriverEntry.h"
typedef union _PS_PROTECTION {
UCHAR Level;
struct {
UCHAR Type : 3;
UCHAR Audit : 1;
UCHAR Signer : 4;
} Flags;
} PS_PROTECTION, * PPS_PROTECTION;
static PVOID g_PsSetProcessProtection = NULL;
static HANDLE g_ProtectedPid = NULL;
static PVOID g_ObCookie = NULL;
static NTSTATUS SetPPL31(_In_ PEPROCESS proc)
{
if (!proc || !g_PsSetProcessProtection)
return STATUS_PROCEDURE_NOT_FOUND;
PS_PROTECTION p = { 0 };
p.Level = 0x31;
((VOID(NTAPI*)(PEPROCESS, PS_PROTECTION))g_PsSetProcessProtection)(proc, p);
return STATUS_SUCCESS;
}
static OB_PREOP_CALLBACK_STATUS ObPreOperation(
_In_ PVOID RegistrationContext,
_Inout_ POB_PRE_OPERATION_INFORMATION info
)
{
UNREFERENCED_PARAMETER(RegistrationContext);
if (!info || info->KernelHandle)
return OB_PREOP_SUCCESS;
if (info->ObjectType == *PsProcessType) {
PEPROCESS proc = (PEPROCESS)info->Object;
HANDLE pid = PsGetProcessId(proc);
if (g_ProtectedPid && pid == g_ProtectedPid && PsGetCurrentProcessId() != g_ProtectedPid) {
ACCESS_MASK* mask = (info->Operation == OB_OPERATION_HANDLE_CREATE)
? &info->Parameters->CreateHandleInformation.DesiredAccess
: &info->Parameters->DuplicateHandleInformation.DesiredAccess;
if (*mask & PROCESS_TERMINATE) {
LogAnsi3("KILL_ATTEMPT",
(ULONG)(ULONG_PTR)PsGetCurrentProcessId(),
NULL, NULL);
*mask &= ~(PROCESS_TERMINATE | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD);
}
}
}
return OB_PREOP_SUCCESS;
}
static VOID ProcessNotify(
_In_opt_ PEPROCESS Process,
_In_ HANDLE Pid,
_In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo
)
{
UNICODE_STRING target = RTL_CONSTANT_STRING(L"\\??\\C:\\PYAS.exe");
if (CreateInfo) {
if (Process && CreateInfo->ImageFileName &&
RtlEqualUnicodeString(CreateInfo->ImageFileName, &target, TRUE)) {
NTSTATUS st = SetPPL31(Process);
UNREFERENCED_PARAMETER(st);
InterlockedExchangePointer((PVOID*)&g_ProtectedPid, Pid);
LogAnsi3("PROC_PPL", (ULONG)(ULONG_PTR)Pid, (PUNICODE_STRING)CreateInfo->ImageFileName, NULL);
}
}
else {
if (g_ProtectedPid && Pid == g_ProtectedPid) {
InterlockedExchangePointer((PVOID*)&g_ProtectedPid, NULL);
}
}
}
NTSTATUS InitProcessProtect(VOID)
{
UNICODE_STRING n = RTL_CONSTANT_STRING(L"PsSetProcessProtection");
g_PsSetProcessProtection = MmGetSystemRoutineAddress(&n);
static OB_OPERATION_REGISTRATION ops[1];
RtlZeroMemory(ops, sizeof(ops));
ops[0].ObjectType = PsProcessType;
ops[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
ops[0].PreOperation = ObPreOperation;
ops[0].PostOperation = NULL;
UNICODE_STRING alt = RTL_CONSTANT_STRING(L"321000");
OB_CALLBACK_REGISTRATION reg;
RtlZeroMemory(&reg, sizeof(reg));
reg.Version = OB_FLT_REGISTRATION_VERSION;
reg.OperationRegistrationCount = 1;
reg.OperationRegistration = ops;
reg.RegistrationContext = NULL;
reg.Altitude = alt;
NTSTATUS s = ObRegisterCallbacks(&reg, &g_ObCookie);
if (!NT_SUCCESS(s)) {
g_ObCookie = NULL;
return s;
}
s = PsSetCreateProcessNotifyRoutineEx(ProcessNotify, FALSE);
if (!NT_SUCCESS(s)) {
ObUnRegisterCallbacks(g_ObCookie);
g_ObCookie = NULL;
return s;
}
return STATUS_SUCCESS;
}
VOID UninitProcessProtect(VOID)
{
if (g_ObCookie) {
ObUnRegisterCallbacks(g_ObCookie);
g_ObCookie = NULL;
}
PsSetCreateProcessNotifyRoutineEx(ProcessNotify, TRUE);
}
+137
View File
@@ -0,0 +1,137 @@
#include "DriverCommon.h"
PVOID ObRegistrationHandle = NULL;
OB_CALLBACK_REGISTRATION ObRegistration;
OB_OPERATION_REGISTRATION ObCallbacks[1];
static BOOLEAN IsSystemImage(PUNICODE_STRING FullImageName) {
if (!FullImageName || !FullImageName->Buffer) return FALSE;
if (WildcardMatch(L"*\\Windows\\System32\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Windows\\SysWOW64\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Windows\\WinSxS\\*", FullImageName->Buffer, FullImageName->Length)) {
return TRUE;
}
return FALSE;
}
VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) {
UNREFERENCED_PARAMETER(ImageInfo);
if (KeGetCurrentIrql() > APC_LEVEL) return;
if (!FullImageName || !FullImageName->Buffer) return;
if (ProcessId == (HANDLE)0) return;
if (IsSystemImage(FullImageName)) return;
if (IsTargetProtected(ProcessId)) {
if (CheckFileExtensionRule(FullImageName)) {
SendMessageToUser(6001, (ULONG)(ULONG_PTR)ProcessId, FullImageName->Buffer, FullImageName->Length);
}
}
}
static BOOLEAN IsBlacklistedAdminTool(HANDLE ProcessId) {
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
NTSTATUS status;
BOOLEAN isBlacklisted = FALSE;
PEPROCESS Process = NULL;
PUNICODE_STRING imageFileName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return FALSE;
status = SeLocateProcessImageName(Process, &imageFileName);
if (NT_SUCCESS(status) && imageFileName) {
if (imageFileName->Buffer) {
if (WildcardMatch(L"*Taskmgr.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*taskkill.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*ProcessHacker.exe", imageFileName->Buffer, imageFileName->Length) ||
WildcardMatch(L"*procmon.exe", imageFileName->Buffer, imageFileName->Length)) {
isBlacklisted = TRUE;
}
}
ExFreePool(imageFileName);
}
ObDereferenceObject(Process);
return isBlacklisted;
}
static OB_PREOP_CALLBACK_STATUS PreOpenProcess(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) {
UNREFERENCED_PARAMETER(RegistrationContext);
if (OperationInformation->KernelHandle) return OB_PREOP_SUCCESS;
PEPROCESS TargetProcess = (PEPROCESS)OperationInformation->Object;
if (!TargetProcess) return OB_PREOP_SUCCESS;
HANDLE TargetPid = PsGetProcessId(TargetProcess);
HANDLE SourcePid = PsGetCurrentProcessId();
if (SourcePid == TargetPid) return OB_PREOP_SUCCESS;
if ((ULONG)(ULONG_PTR)SourcePid == GlobalData.PyasPid) return OB_PREOP_SUCCESS;
if (SourcePid == (HANDLE)4) return OB_PREOP_SUCCESS;
BOOLEAN bProtected = IsTargetProtected(TargetPid);
if (bProtected) {
BOOLEAN bIsInstaller = IsInstallerProcess(SourcePid);
if (bIsInstaller) {
if (IsBlacklistedAdminTool(SourcePid)) {
bIsInstaller = FALSE;
}
}
if (bIsInstaller) return OB_PREOP_SUCCESS;
ACCESS_MASK DenyMask = PROCESS_TERMINATE |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_CREATE_THREAD |
PROCESS_VM_READ |
PROCESS_DUP_HANDLE |
PROCESS_SUSPEND_RESUME |
PROCESS_SET_INFORMATION |
PROCESS_SET_QUOTA;
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~DenyMask;
OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess &= ~DenyMask;
if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) {
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~DenyMask;
OperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess &= ~DenyMask;
}
}
return OB_PREOP_SUCCESS;
}
NTSTATUS InitializeProcessProtection() {
static UNICODE_STRING Altitude = { 0 };
RtlInitUnicodeString(&Altitude, L"320000");
ObCallbacks[0].ObjectType = PsProcessType;
ObCallbacks[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
ObCallbacks[0].PreOperation = PreOpenProcess;
ObCallbacks[0].PostOperation = NULL;
ObRegistration.Version = OB_FLT_REGISTRATION_VERSION;
ObRegistration.OperationRegistrationCount = 1;
ObRegistration.Altitude = Altitude;
ObRegistration.RegistrationContext = NULL;
ObRegistration.OperationRegistration = ObCallbacks;
return ObRegisterCallbacks(&ObRegistration, &ObRegistrationHandle);
}
VOID UninitializeProcessProtection() {
if (ObRegistrationHandle) {
ObUnRegisterCallbacks(ObRegistrationHandle);
ObRegistrationHandle = NULL;
}
}
-118
View File
@@ -1,118 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static BOOLEAN QueryRegPathFromObject(PVOID KeyObject, PUNICODE_STRING OutPath, POBJECT_NAME_INFORMATION* OutInfo)
{
ULONG len = 0;
NTSTATUS s = ObQueryNameString(KeyObject, NULL, 0, &len);
if (s != STATUS_INFO_LENGTH_MISMATCH)
return FALSE;
POBJECT_NAME_INFORMATION p = (POBJECT_NAME_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, len, 'rgeR');
if (!p)
return FALSE;
s = ObQueryNameString(KeyObject, p, len, &len);
if (!NT_SUCCESS(s) || !p->Name.Buffer || p->Name.Length == 0) {
ExFreePool2(p, 'rgeR', NULL, 0);
return FALSE;
}
*OutInfo = p;
OutPath->Buffer = p->Name.Buffer;
OutPath->Length = p->Name.Length;
OutPath->MaximumLength = p->Name.Length;
return TRUE;
}
NTSTATUS RegistryProtectCallback(PVOID ctx, PVOID arg1, PVOID arg2)
{
UNREFERENCED_PARAMETER(ctx);
if (g_Unloading)
return STATUS_SUCCESS;
if (!ExAcquireRundownProtection(&g_Rundown))
return STATUS_SUCCESS;
REG_NOTIFY_CLASS type = (REG_NOTIFY_CLASS)(ULONG_PTR)arg1;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING checkReg = { 0 };
POBJECT_NAME_INFORMATION nameInfo = NULL;
UNICODE_STRING exe = { 0 };
WCHAR exeBuf[260] = { 0 };
exe.Buffer = exeBuf;
exe.MaximumLength = sizeof(exeBuf);
exe.Length = 0;
HANDLE pid = PsGetCurrentProcessId();
if (pid == (HANDLE)0 || pid == (HANDLE)4) {
ExReleaseRundownProtection(&g_Rundown);
return STATUS_SUCCESS;
}
PUNICODE_STRING valueName = NULL;
BOOLEAN need_log = FALSE;
BOOLEAN canQuery = (KeGetCurrentIrql() == PASSIVE_LEVEL);
if (type == RegNtPreSetValueKey) {
PREG_SET_VALUE_KEY_INFORMATION s = (PREG_SET_VALUE_KEY_INFORMATION)arg2;
valueName = s->ValueName;
if (canQuery)
QueryRegPathFromObject(s->Object, &checkReg, &nameInfo);
}
else if (type == RegNtPreDeleteValueKey) {
PREG_DELETE_VALUE_KEY_INFORMATION d = (PREG_DELETE_VALUE_KEY_INFORMATION)arg2;
valueName = d->ValueName;
if (canQuery)
QueryRegPathFromObject(d->Object, &checkReg, &nameInfo);
}
else if (type == RegNtPreDeleteKey) {
PREG_DELETE_KEY_INFORMATION d = (PREG_DELETE_KEY_INFORMATION)arg2;
if (canQuery)
QueryRegPathFromObject(d->Object, &checkReg, &nameInfo);
}
else if (type == RegNtPreRenameKey) {
PREG_RENAME_KEY_INFORMATION r = (PREG_RENAME_KEY_INFORMATION)arg2;
if (canQuery)
QueryRegPathFromObject(r->Object, &checkReg, &nameInfo);
}
else if (type == RegNtPreCreateKeyEx) {
PREG_CREATE_KEY_INFORMATION c = (PREG_CREATE_KEY_INFORMATION)arg2;
if (c->CompleteName)
checkReg = *c->CompleteName;
}
else if (type == RegNtPreReplaceKey) {
PREG_REPLACE_KEY_INFORMATION rk = (PREG_REPLACE_KEY_INFORMATION)arg2;
if (canQuery)
QueryRegPathFromObject(rk->Object, &checkReg, &nameInfo);
}
else if (type == RegNtPreSaveKey) {
PREG_SAVE_KEY_INFORMATION sk = (PREG_SAVE_KEY_INFORMATION)arg2;
if (canQuery)
QueryRegPathFromObject(sk->Object, &checkReg, &nameInfo);
}
else if (type == RegNtPreRestoreKey) {
PREG_RESTORE_KEY_INFORMATION res = (PREG_RESTORE_KEY_INFORMATION)arg2;
if (canQuery)
QueryRegPathFromObject(res->Object, &checkReg, &nameInfo);
}
else if (type == RegNtPreLoadKey) {
PREG_LOAD_KEY_INFORMATION lk = (PREG_LOAD_KEY_INFORMATION)arg2;
if (lk->KeyName)
checkReg = *lk->KeyName;
}
if (checkReg.Buffer || (valueName && valueName->Buffer)) {
if (canQuery)
GetProcessImagePathByPid(pid, &exe);
if (IsRegistryBlock(&checkReg, valueName, &exe)) {
need_log = TRUE;
status = STATUS_ACCESS_DENIED;
}
}
if (nameInfo)
ExFreePool2(nameInfo, 'rgeR', NULL, 0);
if (need_log)
LogAnsi3("REG_BLOCK", (ULONG)(ULONG_PTR)pid, &exe, &checkReg);
ExReleaseRundownProtection(&g_Rundown);
return status;
}
+51
View File
@@ -0,0 +1,51 @@
#include "DriverCommon.h"
LARGE_INTEGER Cookie;
static NTSTATUS RegistryCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2) {
UNREFERENCED_PARAMETER(CallbackContext);
if (KeGetCurrentIrql() > APC_LEVEL) return STATUS_SUCCESS;
REG_NOTIFY_CLASS Class = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
if (Class == RegNtPreSetValueKey || Class == RegNtPreDeleteKey || Class == RegNtPreCreateKey) {
REG_SET_VALUE_KEY_INFORMATION* Info = (REG_SET_VALUE_KEY_INFORMATION*)Argument2;
PCUNICODE_STRING KeyName = NULL;
if (!NT_SUCCESS(CmCallbackGetKeyObjectIDEx(&Cookie, Info->Object, NULL, &KeyName, 0))) {
return STATUS_SUCCESS;
}
if (KeyName && KeyName->Buffer) {
if (CheckRegistryRule(KeyName)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
if (!IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, KeyName->Buffer, KeyName->Length);
CmCallbackReleaseKeyObjectIDEx(KeyName);
return STATUS_ACCESS_DENIED;
}
}
}
}
if (KeyName) {
CmCallbackReleaseKeyObjectIDEx(KeyName);
}
}
return STATUS_SUCCESS;
}
NTSTATUS InitializeRegistryProtection(PDRIVER_OBJECT DriverObject) {
UNICODE_STRING Altitude;
RtlInitUnicodeString(&Altitude, L"320000");
return CmRegisterCallbackEx(RegistryCallback, &Altitude, DriverObject, NULL, &Cookie, NULL);
}
VOID UninitializeRegistryProtection() {
if (Cookie.QuadPart != 0) {
CmUnRegisterCallback(Cookie);
Cookie.QuadPart = 0;
}
}
-83
View File
@@ -1,83 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static BOOLEAN g_RemoteNotifyEnabled = FALSE;
static VOID ProcessNotifyEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)
{
UNREFERENCED_PARAMETER(Process);
UNREFERENCED_PARAMETER(ProcessId);
if (!CreateInfo)
return;
if (g_Unloading)
return;
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
return;
if (!ExAcquireRundownProtection(&g_Rundown))
return;
HANDLE ppid = CreateInfo->CreatingThreadId.UniqueProcess;
if (ppid == (HANDLE)0 || ppid == (HANDLE)4) {
ExReleaseRundownProtection(&g_Rundown);
return;
}
UNICODE_STRING parent = { 0 };
WCHAR pbuf[512] = { 0 };
parent.Buffer = pbuf;
parent.MaximumLength = sizeof(pbuf);
if (!GetProcessImagePathByPid(ppid, &parent)) {
PEPROCESS eproc = PsGetCurrentProcess();
PCSTR n = PsGetProcessImageFileName(eproc);
size_t l = n ? strlen(n) : 0;
for (size_t i = 0; i < l && i < RTL_NUMBER_OF(pbuf) - 1; i++)
pbuf[i] = (WCHAR)n[i];
pbuf[l] = 0;
parent.Length = (USHORT)(l * sizeof(WCHAR));
}
if (IsWhitelist(&parent)) {
ExReleaseRundownProtection(&g_Rundown);
return;
}
UNICODE_STRING img = { 0 };
if (CreateInfo->ImageFileName)
img = *CreateInfo->ImageFileName;
UNICODE_STRING cmd = { 0 };
if (CreateInfo->CommandLine)
cmd = *CreateInfo->CommandLine;
BOOLEAN suspect = FALSE;
if (MatchRemoteSuspectBin(&img) && MatchRemoteCommand(&cmd, &img))
suspect = TRUE;
if (suspect) {
CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
if (cmd.Buffer && cmd.Length)
LogAnsi3("REMOTE_BLOCK", (ULONG)(ULONG_PTR)ppid, &parent, &cmd);
else if (img.Buffer && img.Length)
LogAnsi3("REMOTE_BLOCK", (ULONG)(ULONG_PTR)ppid, &parent, &img);
else {
UNICODE_STRING none = RTL_CONSTANT_STRING(L"None");
LogAnsi3("REMOTE_BLOCK", (ULONG)(ULONG_PTR)ppid, &parent, &none);
}
}
ExReleaseRundownProtection(&g_Rundown);
}
NTSTATUS InitRemoteProtect(VOID)
{
NTSTATUS s = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyEx, FALSE);
if (NT_SUCCESS(s))
g_RemoteNotifyEnabled = TRUE;
return s;
}
VOID UninitRemoteProtect(VOID)
{
if (g_RemoteNotifyEnabled) {
PsSetCreateProcessNotifyRoutineEx(ProcessNotifyEx, TRUE);
g_RemoteNotifyEnabled = FALSE;
}
}
-296
View File
@@ -1,296 +0,0 @@
#include <ntifs.h>
#include "ProtectRules.h"
wchar_t* g_Whitelist[] = {
L"\\Device\\HarddiskVolume*\\Windows\\**",
L"\\Device\\HarddiskVolume*\\Program*\\**",
L"\\Device\\HarddiskVolume*\\Users\\*\\AppData\\**",
L"**\\PYAS*.exe",
L"Registry",
L"vmmem*",
NULL
};
wchar_t* g_WhitelistExcept[] = {
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\vds.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\bcdedit.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\reg.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\cmd.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\mshta.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\wscript.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\cscript.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\schtasks.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\diskpart.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\format.com",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\mountvol.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\ntoskrnl.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\wbadmin.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\bcdboot.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\dism.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\bootsect.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\cipher.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\net.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\net1.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\msiexec.exe",
L"\\Device\\HarddiskVolume*\\Windows\\Sys*\\WindowsPowerShell\\*\\powershell.exe",
L"\\Device\\HarddiskVolume*\\Program*\\PowerShell\\*\\pwsh.exe",
NULL
};
wchar_t* g_AttachDisk[] = {
L"\\FileSystem\\Ntfs",
L"\\FileSystem\\Refs",
L"\\FileSystem\\Fastfat",
L"\\FileSystem\\exfat",
L"\\FileSystem\\Udfs",
NULL
};
wchar_t* g_BlockFile[] = {
L"\\Device\\Harddisk*\\DR*",
L"\\Device\\Harddisk*\\Partition\\**",
L"\\Device\\HarddiskVolume*\\Boot\\**",
L"\\Device\\HarddiskVolume*\\EFI\\**",
L"\\Device\\HarddiskVolume*\\bootmgr",
L"\\Device\\HarddiskVolume*\\Recovery\\**",
L"\\Device\\HarddiskVolume*\\System Volume Information\\**",
L"\\Device\\HarddiskVolume*\\Windows\\**",
L"\\Device\\HarddiskVolume*\\$*\\**",
L"\\Device\\HarddiskVolume*\\ProgramData\\PYAS\\**",
L"**\\PYAS.exe",
L"**\\CON**",
L"**\\PRN**",
L"**\\AUX**",
L"**\\NUL**",
L"**\\COM*\\**",
L"**\\LPT*\\**",
L"**\\evil*.exe",
L"**\\OSDATA**",
NULL
};
wchar_t* g_BlockRansom[] = {
L"\\Device\\HarddiskVolume*\\Users\\*\\Desktop\\**",
L"\\Device\\HarddiskVolume*\\Users\\*\\Downloads\\**",
L"\\Device\\HarddiskVolume*\\Users\\*\\Documents\\**",
L"\\Device\\HarddiskVolume*\\Users\\*\\Music\\**",
L"\\Device\\HarddiskVolume*\\Users\\*\\Pictures\\**",
L"\\Device\\HarddiskVolume*\\Users\\*\\Videos\\**",
NULL
};
wchar_t* g_Blocksuffix[] = {
L".exe", L".dll", L".sys", L".com", L".scr",
L".zip", L".7z", L".rar", L".tar", L".gz",
L".js", L".bat", L".cmd", L".ps1", L".vbs",
L".ppt", L".pptx", L".wps", L".txt", L".rtf",
L".pdf", L".xls", L".xlsx", L".doc", L".docx",
L".jpg", L".jpeg", L".png", L".webp", L".gif",
L".mp3", L".wav", L".aac", L".ogg", L".flac",
L".mp4", L".avi", L".mov", L".wmv", L".mkv",
L".aux", L".cur", L".mui", L".ttf", L".efi",
NULL
};
wchar_t* g_BlockReg[] = {
L"\\REGISTRY\\MACHINE\\BCD00000000\\**",
L"\\REGISTRY\\MACHINE\\SAM\\**",
L"\\REGISTRY\\MACHINE\\SECURITY\\**",
L"\\REGISTRY\\MACHINE\\SYSTEM\\*ControlSet*\\Control\\**",
L"\\REGISTRY\\MACHINE\\SYSTEM\\*ControlSet*\\Enum\\**",
L"\\REGISTRY\\MACHINE\\SYSTEM\\*ControlSet*\\Services\\**",
L"\\REGISTRY\\MACHINE\\SYSTEM\\MountedDevices\\**",
L"\\REGISTRY\\MACHINE\\SYSTEM\\Setup\\**",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\**",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Policies\\Microsoft\\MMC\\**",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Policies\\Microsoft\\Windows\\System\\**",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Wow6432Node\\**",
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid",
L"\\REGISTRY\\MACHINE\\**\\Microsoft\\Windows Defender\\**",
L"\\REGISTRY\\**\\SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\*\\StubPath",
L"\\REGISTRY\\**\\SOFTWARE\\Microsoft\\Windows*\\CurrentVersion\\**",
L"\\REGISTRY\\**\\SOFTWARE\\Microsoft\\Windows Script Host\\Settings\\**",
L"\\REGISTRY\\USER\\*_Classes\\*\\shell\\open\\command\\**",
L"\\REGISTRY\\USER\\*_Classes\\CLSID\\{fdb00e52-a214-4aa1-8fba-4357bb0072ec}\\**",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\NetWire\\**",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\Remcos*\\**",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\DC3_FEXEC\\**",
L"DisableAntiSpyware",
L"DisableWindowsUpdateAccess",
L"EnableLUA",
L"ConsentPromptBehaviorAdmin",
L"NoControlPanel",
L"NoDrives",
L"NoFileMenu",
L"NoFind",
L"NoStartMenuPinnedList",
L"NoSetFolders",
L"NoSetFolderOptions",
L"NoViewOnDrive",
L"NoClose",
L"NoDesktop",
L"NoLogoff",
L"NoFolderOptions",
L"RestrictRun",
L"NoViewContextMenu",
L"HideClock",
L"NoStartMenuMyGames",
L"NoStartMenuMyMusic",
L"DisableCMD",
L"NoAddingComponents",
L"NoWinKeys",
L"NoStartMenuLogOff",
L"NoSimpleNetIDList",
L"NoLowDiskSpaceChecks",
L"DisableLockWorkstation",
L"Restrict_Run",
L"DisableTaskMgr",
L"DisableRegistryTools",
L"DisableChangePassword",
L"Wallpaper",
L"NoComponents",
L"NoStartMenuMorePrograms",
L"NoActiveDesktop",
L"NoSetActiveDesktop",
L"NoRecentDocsMenu",
L"NoWindowsUpdate",
L"NoChangeStartMenu",
L"NoFavoritesMenu",
L"NoRecentDocsHistory",
L"NoSetTaskbar",
L"NoSMHelp",
L"NoTrayContextMenu",
L"NoManageMyComputerVerb",
L"NoRealMode",
L"NoRun",
L"ClearRecentDocsOnExit",
L"NoActiveDesktopChanges",
L"NoStartMenuNetworkPlaces",
L"NoLockScreen",
L"HideFastUserSwitching",
L"ConsentPromptBehaviorUser",
L"EnableSecureUIAPaths",
L"NoSRM",
L"NoInteractiveServices",
L"ShutdownWithoutLogon",
L"AutoAdminLogon",
L"ImagePath",
L"BootExecute",
L"SubSystems",
L"FirmwareBootDevice",
L"BootDriverFlags",
L"SystemStartOptions",
L"CrashDumpEnabled",
L"DisableAutomaticRestartOnFailure",
L"SystemBiosVersion",
L"NoTheme",
L"PendingFileRenameOperations",
L"SystemSetupInProgress",
L"CmdLine",
L"SetupType",
L"AutoReboot",
L"Shell",
L"Userinit",
L"UIHost",
L"Debugger",
L"DefaultUserName",
L"DefaultPassword",
L"AltDefaultUserName",
L"AltDefaultPassword",
L"DisableCAD",
L"LegalNoticeCaption",
L"LegalNoticeText",
NULL
};
wchar_t* g_RemoteSuspectBins[] = {
L"powershell.exe",
L"pwsh.exe",
L"wscript.exe",
L"cscript.exe",
L"mshta.exe",
L"rundll32.exe",
L"regsvr32.exe",
L"cmd.exe",
L"bitsadmin.exe",
L"msbuild.exe",
L"installutil.exe",
L"wmic.exe",
NULL
};
wchar_t* g_RemoteCmdIndicatorsHttp[] = {
L"http://",
L"https://",
NULL
};
wchar_t* g_RemoteCmdIndicatorsGeneric[] = {
L"-enc",
L"-e",
L"-encodedcommand",
L"frombase64string(",
L"iex(",
L"downloadstring(",
NULL
};
wchar_t* g_RemoteCmdFromCmdExe[] = {
L"powershell",
L"pwsh",
L"mshta",
L"rundll32",
L"wscript",
L"cscript",
NULL
};
wchar_t* g_RemoteCmdFromRundll32Exe[] = {
L".dll,",
L"javascript:",
L"http",
NULL
};
wchar_t* g_RemoteCmdRegsvr32Need[] = {
L"/i:",
NULL
};
wchar_t* g_RemoteCmdFromMshtaExe[] = {
L"http://",
L"https://",
NULL
};
wchar_t* g_ScreenCapModules[] = {
L"windows.graphics.capture.dll",
L"dxgi.dll",
L"d3d11.dll",
L"dwmapi.dll",
L"dcomp.dll",
L"mfreadwrite.dll",
L"mfplat.dll",
L"opengl32.dll",
L"gdi32full.dll",
L"win32u.dll",
NULL
};
wchar_t* g_ScreenUserSubdirs[] = {
L"\\AppData\\",
L"\\Temp\\",
L"\\Downloads\\",
NULL
};
wchar_t* g_ScreenOtherProcNeedles[] = {
L"\\ProgramData\\",
NULL
};
+487
View File
@@ -0,0 +1,487 @@
#include "DriverCommon.h"
constexpr auto MAX_TRACKERS = 64;
constexpr auto RANSOM_TIME_WINDOW_MS = 3000;
constexpr auto RANSOM_COUNT_THRESHOLD = 5;
constexpr auto HIGH_ENTROPY_THRESHOLD = 15;
typedef struct _RANSOM_TRACKER {
HANDLE ProcessId;
ULONG ActivityCount;
LARGE_INTEGER LastActivityTime;
} RANSOM_TRACKER, * PRANSOM_TRACKER;
RANSOM_TRACKER RansomTrackers[MAX_TRACKERS];
static BOOLEAN HasSuffix(PCUNICODE_STRING String, PCWSTR Suffix) {
if (!String || !String->Buffer || !Suffix) return FALSE;
SIZE_T SuffixLenBytes = 0;
while (Suffix[SuffixLenBytes / sizeof(WCHAR)] != L'\0') {
SuffixLenBytes += sizeof(WCHAR);
}
if (String->Length < SuffixLenBytes) return FALSE;
UNICODE_STRING SuffixPart{};
SuffixPart.Buffer = (PWCH)((PUCHAR)String->Buffer + String->Length - SuffixLenBytes);
SuffixPart.Length = (USHORT)SuffixLenBytes;
SuffixPart.MaximumLength = (USHORT)SuffixLenBytes;
UNICODE_STRING TargetSuffix;
RtlInitUnicodeString(&TargetSuffix, Suffix);
return RtlEqualUnicodeString(&SuffixPart, &TargetSuffix, TRUE);
}
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes) {
if (!Pattern || !String) return FALSE;
PCWSTR mp = NULL;
PCWSTR cp = NULL;
PCWSTR StringEnd = (PCWSTR)((PUCHAR)String + StringLengthBytes);
while ((PUCHAR)String < (PUCHAR)StringEnd) {
WCHAR pChar = *Pattern;
WCHAR sChar = *String;
if (pChar == L'*') {
if (!*++Pattern) return TRUE;
mp = Pattern;
cp = String + 1;
}
else if ((RtlDowncaseUnicodeChar(pChar) == RtlDowncaseUnicodeChar(sChar)) || pChar == L'?') {
Pattern++;
String++;
}
else if (mp) {
Pattern = mp;
String = cp++;
}
else {
return FALSE;
}
}
while (*Pattern == L'*') Pattern++;
return !*Pattern && ((PUCHAR)String >= (PUCHAR)StringEnd);
}
const PCWSTR RegistryBlockList[] = {
L"\\REGISTRY\\MACHINE\\BCD00000000\\*",
L"\\REGISTRY\\MACHINE\\SAM\\*",
L"\\REGISTRY\\MACHINE\\SECURITY\\*",
L"\\REGISTRY\\USER\\*_Classes\\*\\shell\\open\\command\\*",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\NetWire\\*",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\Remcos*\\*",
L"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\DC3_FEXEC\\*",
L"*\\DisableAntiSpyware",
L"*\\DisableWindowsUpdateAccess",
L"*\\EnableLUA",
L"*\\ConsentPromptBehaviorAdmin",
L"*\\NoControlPanel",
L"*\\NoDrives",
L"*\\NoFileMenu",
L"*\\NoFind",
L"*\\NoStartMenuPinnedList",
L"*\\NoSetFolders",
L"*\\NoSetFolderOptions",
L"*\\NoViewOnDrive",
L"*\\NoClose",
L"*\\NoDesktop",
L"*\\NoLogoff",
L"*\\NoFolderOptions",
L"*\\RestrictRun",
L"*\\NoViewContextMenu",
L"*\\HideClock",
L"*\\NoStartMenuMyGames",
L"*\\NoStartMenuMyMusic",
L"*\\DisableCMD",
L"*\\NoAddingComponents",
L"*\\NoWinKeys",
L"*\\NoStartMenuLogOff",
L"*\\NoSimpleNetIDList",
L"*\\NoLowDiskSpaceChecks",
L"*\\DisableLockWorkstation",
L"*\\Restrict_Run",
L"*\\DisableTaskMgr",
L"*\\DisableRegistryTools",
L"*\\DisableChangePassword",
L"*\\Wallpaper",
L"*\\NoComponents",
L"*\\NoStartMenuMorePrograms",
L"*\\NoActiveDesktop",
L"*\\NoSetActiveDesktop",
L"*\\NoRecentDocsMenu",
L"*\\NoWindowsUpdate",
L"*\\NoChangeStartMenu",
L"*\\NoFavoritesMenu",
L"*\\NoRecentDocsHistory",
L"*\\NoSetTaskbar",
L"*\\NoSMHelp",
L"*\\NoTrayContextMenu",
L"*\\NoManageMyComputerVerb",
L"*\\NoRealMode",
L"*\\NoRun",
L"*\\ClearRecentDocsOnExit",
L"*\\NoActiveDesktopChanges",
L"*\\NoStartMenuNetworkPlaces",
L"*\\NoLockScreen",
L"*\\HideFastUserSwitching",
L"*\\ConsentPromptBehaviorUser",
L"*\\EnableSecureUIAPaths",
L"*\\NoSRM",
L"*\\NoInteractiveServices",
L"*\\ShutdownWithoutLogon",
L"*\\AutoAdminLogon",
L"*\\ImagePath",
L"*\\BootExecute",
L"*\\SubSystems",
L"*\\FirmwareBootDevice",
L"*\\BootDriverFlags",
L"*\\SystemStartOptions",
L"*\\CrashDumpEnabled",
L"*\\DisableAutomaticRestartOnFailure",
L"*\\SystemBiosVersion",
L"*\\NoTheme",
L"*\\PendingFileRenameOperations",
L"*\\SystemSetupInProgress",
L"*\\CmdLine",
L"*\\SetupType",
L"*\\AutoReboot",
L"*\\Userinit",
L"*\\UIHost",
L"*\\Debugger",
L"*\\DefaultUserName",
L"*\\DefaultPassword",
L"*\\AltDefaultUserName",
L"*\\AltDefaultPassword",
L"*\\DisableCAD",
L"*\\LegalNoticeCaption",
L"*\\LegalNoticeText",
L"*\\Run",
L"*\\RunOnce",
L"*\\Image File Execution Options\\*"
};
const PCWSTR DangerousExtensions[] = {
L".exe", L".dll", L".sys", L".com", L".scr",
L".zip", L".7z", L".rar", L".tar", L".gz",
L".js", L".bat", L".cmd", L".ps1", L".vbs",
L".ppt", L".pptx", L".wps", L".txt", L".rtf",
L".pdf", L".xls", L".xlsx", L".doc", L".docx",
L".jpg", L".jpeg", L".png", L".webp", L".gif",
L".mp3", L".wav", L".aac", L".ogg", L".flac",
L".mp4", L".avi", L".mov", L".wmv", L".mkv",
L".aux", L".cur", L".mui", L".ttf", L".efi"
};
const PCWSTR NaturallyCompressedExtensions[] = {
L".zip", L".7z", L".rar", L".tar", L".gz",
L".jpg", L".jpeg", L".png", L".webp", L".gif",
L".mp3", L".wav", L".aac", L".ogg", L".flac",
L".mp4", L".avi", L".mov", L".wmv", L".mkv",
L".exe", L".dll", L".sys", L".mui",
L".docx", L".xlsx", L".pptx", L".odt", L".ods"
};
const PCWSTR ProtectedPaths[] = {
L"*\\System32\\drivers\\etc\\hosts",
L"*\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
L"\\Device\\HarddiskVolume*\\Windows\\System32\\*.exe",
L"\\Device\\HarddiskVolume*\\Windows\\System32\\*.dll",
L"\\Device\\HarddiskVolume*\\Windows\\SysWOW64\\*.exe",
L"\\Device\\HarddiskVolume*\\Windows\\SysWOW64\\*.dll",
L"\\Device\\HarddiskVolume*\\bootmgr",
L"\\Device\\HarddiskVolume*\\EFI\\*",
L"*\\PYAS.exe",
L"*\\PYAS_Driver.sys"
};
const PCWSTR TrustedInstallerPatterns[] = {
L"*setup*",
L"*install*",
L"*update*",
L"*unins*",
L"*patch*",
L"*msiexec*",
L"*tiworker*",
L"*trustedinstaller*",
L"*dism*",
L"*pkgmgr*",
L"*wuauclt*",
L"*svchost*",
L"*taskhost*",
L"*googleupdate*",
L"*steam*",
L"*origin*",
L"*battle.net*",
L"*avast*",
L"*avg*"
};
BOOLEAN IsProcessTrusted(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
if (ProcessId == (HANDLE)4) return TRUE;
return FALSE;
}
BOOLEAN IsTargetProtected(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
return FALSE;
}
BOOLEAN IsInstallerProcess(HANDLE ProcessId) {
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
NTSTATUS status;
BOOLEAN isTrusted = FALSE;
PEPROCESS Process = NULL;
PUNICODE_STRING imageFileName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return FALSE;
status = SeLocateProcessImageName(Process, &imageFileName);
if (NT_SUCCESS(status) && imageFileName) {
if (imageFileName->Buffer) {
for (int i = 0; i < sizeof(TrustedInstallerPatterns) / sizeof(TrustedInstallerPatterns[0]); i++) {
if (WildcardMatch(TrustedInstallerPatterns[i], imageFileName->Buffer, imageFileName->Length)) {
isTrusted = TRUE;
break;
}
}
}
ExFreePool(imageFileName);
}
ObDereferenceObject(Process);
return isTrusted;
}
BOOLEAN CheckRegistryRule(PCUNICODE_STRING KeyName) {
if (!KeyName || !KeyName->Buffer) return FALSE;
for (int i = 0; i < sizeof(RegistryBlockList) / sizeof(RegistryBlockList[0]); i++) {
if (WildcardMatch(RegistryBlockList[i], KeyName->Buffer, KeyName->Length)) return TRUE;
}
return FALSE;
}
BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
for (int i = 0; i < sizeof(DangerousExtensions) / sizeof(DangerousExtensions[0]); i++) {
if (HasSuffix(FileName, DangerousExtensions[i])) {
return TRUE;
}
}
return FALSE;
}
BOOLEAN CheckProtectedPathRule(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
for (int i = 0; i < sizeof(ProtectedPaths) / sizeof(ProtectedPaths[0]); i++) {
if (WildcardMatch(ProtectedPaths[i], FileName->Buffer, FileName->Length)) return TRUE;
}
return FALSE;
}
static BOOLEAN IsHighEntropy(PVOID Buffer, ULONG Length) {
if (!Buffer || Length < 256) return FALSE;
ULONG Histogram[256] = { 0 };
PUCHAR Ptr = (PUCHAR)Buffer;
ULONG ScanLen = (Length > 1024) ? 1024 : Length;
__try {
for (ULONG i = 0; i < ScanLen; i++) {
Histogram[Ptr[i]]++;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
ULONG MaxFreq = 0;
for (int i = 0; i < 256; i++) {
if (Histogram[i] > MaxFreq) MaxFreq = Histogram[i];
}
ULONG ExpectedAvg = ScanLen / 256;
if (MaxFreq < (ExpectedAvg + HIGH_ENTROPY_THRESHOLD)) {
return TRUE;
}
return FALSE;
}
static BOOLEAN IsNaturallyCompressed(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
for (int i = 0; i < sizeof(NaturallyCompressedExtensions) / sizeof(NaturallyCompressedExtensions[0]); i++) {
if (HasSuffix(FileName, NaturallyCompressedExtensions[i])) {
return TRUE;
}
}
return FALSE;
}
static BOOLEAN IsNoisyRansomPath(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
if (WildcardMatch(L"*\\Windows\\Temp\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\AppData\\Local\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Windows\\SystemTemp\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Program Files*\\*\\Temp\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*$Recycle.Bin*", FileName->Buffer, FileName->Length)) {
return TRUE;
}
return FALSE;
}
static BOOLEAN IsExplorerProcess(HANDLE ProcessId) {
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
NTSTATUS status;
BOOLEAN isExplorer = FALSE;
PEPROCESS Process = NULL;
PUNICODE_STRING imageFileName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return FALSE;
status = SeLocateProcessImageName(Process, &imageFileName);
if (NT_SUCCESS(status) && imageFileName) {
if (imageFileName->Buffer) {
if (HasSuffix(imageFileName, L"explorer.exe")) {
isExplorer = TRUE;
}
}
ExFreePool(imageFileName);
}
ObDereferenceObject(Process);
return isExplorer;
}
BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Buffer, ULONG Length, BOOLEAN IsWrite) {
if (IsNoisyRansomPath(FileName)) return FALSE;
if (!IsWrite) {
if (IsExplorerProcess(ProcessId)) {
return FALSE;
}
}
LARGE_INTEGER Now = { 0 };
KeQuerySystemTime(&Now);
BOOLEAN Result = FALSE;
BOOLEAN SuspiciousWrite = FALSE;
if (IsWrite && Buffer && Length > 0) {
if (!IsNaturallyCompressed(FileName) && IsHighEntropy(Buffer, Length)) {
SuspiciousWrite = TRUE;
}
}
ExAcquireFastMutex(&GlobalData.TrackerMutex);
if (IsWrite && !SuspiciousWrite) {
ExReleaseFastMutex(&GlobalData.TrackerMutex);
return FALSE;
}
PRANSOM_TRACKER Tracker = NULL;
PRANSOM_TRACKER EmptySlot = NULL;
for (int i = 0; i < MAX_TRACKERS; i++) {
if (RansomTrackers[i].ProcessId == ProcessId) {
Tracker = &RansomTrackers[i];
break;
}
if (RansomTrackers[i].ProcessId == NULL && !EmptySlot) {
EmptySlot = &RansomTrackers[i];
}
}
if (!Tracker) {
if (EmptySlot) {
Tracker = EmptySlot;
Tracker->ProcessId = ProcessId;
Tracker->ActivityCount = 0;
Tracker->LastActivityTime = Now;
}
else {
ExReleaseFastMutex(&GlobalData.TrackerMutex);
return FALSE;
}
}
LARGE_INTEGER Diff = { 0 };
Diff.QuadPart = Now.QuadPart - Tracker->LastActivityTime.QuadPart;
if (Diff.QuadPart > (RANSOM_TIME_WINDOW_MS * 10000LL)) {
Tracker->ActivityCount = 0;
Tracker->LastActivityTime = Now;
}
ULONG Weight = 1;
if (IsWrite) {
Weight = SuspiciousWrite ? 2 : 1;
}
Tracker->ActivityCount += Weight;
if (Tracker->ActivityCount >= RANSOM_COUNT_THRESHOLD) {
Result = TRUE;
}
ExReleaseFastMutex(&GlobalData.TrackerMutex);
return Result;
}
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path, USHORT PathSize) {
if (KeGetCurrentIrql() > APC_LEVEL) return STATUS_UNSUCCESSFUL;
PYAS_MESSAGE msg;
RtlZeroMemory(&msg, sizeof(msg));
msg.MessageCode = Code;
msg.ProcessId = Pid;
if (Path && PathSize > 0) {
size_t MaxSize = sizeof(msg.Path) - sizeof(WCHAR);
size_t BytesToCopy = PathSize;
if (BytesToCopy > MaxSize) {
BytesToCopy = MaxSize;
}
__try {
RtlCopyMemory(msg.Path, Path, BytesToCopy);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return STATUS_ACCESS_VIOLATION;
}
msg.Path[BytesToCopy / sizeof(WCHAR)] = L'\0';
}
if (!ExAcquireRundownProtection(&GlobalData.PortRundown)) {
return STATUS_PORT_DISCONNECTED;
}
NTSTATUS status = STATUS_SUCCESS;
if (GlobalData.ClientPort) {
LARGE_INTEGER timeout{};
timeout.QuadPart = -(5 * 10000);
PFLT_PORT Port = GlobalData.ClientPort;
status = FltSendMessage(GlobalData.FilterHandle, &Port, &msg, sizeof(msg), NULL, NULL, &timeout);
}
else {
status = STATUS_PORT_DISCONNECTED;
}
ExReleaseRundownProtection(&GlobalData.PortRundown);
return status;
}
-25
View File
@@ -1,25 +0,0 @@
#pragma once
#include <ntifs.h>
extern wchar_t* g_Whitelist[];
extern wchar_t* g_WhitelistExcept[];
extern wchar_t* g_AttachDisk[];
extern wchar_t* g_BlockFile[];
extern wchar_t* g_BlockRansom[];
extern wchar_t* g_Blocksuffix[];
extern wchar_t* g_BlockReg[];
extern wchar_t* g_RemoteSuspectBins[];
extern wchar_t* g_RemoteCmdIndicatorsHttp[];
extern wchar_t* g_RemoteCmdIndicatorsGeneric[];
extern wchar_t* g_RemoteCmdFromCmdExe[];
extern wchar_t* g_RemoteCmdFromRundll32Exe[];
extern wchar_t* g_RemoteCmdRegsvr32Need[];
extern wchar_t* g_RemoteCmdFromMshtaExe[];
extern wchar_t* g_ScreenCapModules[];
extern wchar_t* g_ScreenUserSubdirs[];
extern wchar_t* g_ScreenOtherProcNeedles[];
-67
View File
@@ -1,67 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static BOOLEAN g_ScreenImgCb = FALSE;
static VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo)
{
UNREFERENCED_PARAMETER(ImageInfo);
if (g_Unloading)
return;
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
return;
if (!ExAcquireRundownProtection(&g_Rundown))
return;
if (!FullImageName || !FullImageName->Buffer || FullImageName->Length == 0) {
ExReleaseRundownProtection(&g_Rundown);
return;
}
UNICODE_STRING proc = { 0 };
WCHAR pbuf[512] = { 0 };
proc.Buffer = pbuf;
proc.MaximumLength = sizeof(pbuf);
if (!GetProcessImagePathByPid(ProcessId, &proc)) {
PEPROCESS eproc = NULL;
if (NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &eproc))) {
PCSTR n = PsGetProcessImageFileName(eproc);
SIZE_T l = n ? strlen(n) : 0;
for (SIZE_T i = 0; i < l && i < RTL_NUMBER_OF(pbuf) - 1; i++)
pbuf[i] = (WCHAR)n[i];
pbuf[l] = 0;
proc.Length = (USHORT)(l * sizeof(WCHAR));
ObDereferenceObject(eproc);
}
}
if (proc.Length == 0) {
ExReleaseRundownProtection(&g_Rundown);
return;
}
if (IsWhitelist(&proc)) {
ExReleaseRundownProtection(&g_Rundown);
return;
}
BOOLEAN suspicious = MatchSuspiciousProcPath(&proc);
if (suspicious && MatchScreenCapModule(FullImageName))
LogAnsi3("SCREEN_BLOCK", (ULONG)(ULONG_PTR)ProcessId, &proc, FullImageName);
ExReleaseRundownProtection(&g_Rundown);
}
NTSTATUS InitScreenProtect(VOID)
{
NTSTATUS s = PsSetLoadImageNotifyRoutine(ImageLoadNotify);
if (NT_SUCCESS(s)) g_ScreenImgCb = TRUE;
return s;
}
VOID UninitScreenProtect(VOID)
{
if (g_ScreenImgCb) {
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
g_ScreenImgCb = FALSE;
}
}
+130 -21
View File
@@ -1,6 +1,6 @@
# PYAS
Antivirus software written in Python and C that blocks threats through deep learning and behavioral monitoring!
Antivirus software written in Python and C++ that blocks threats through deep learning and behavioral monitoring!
<img width="2245" height="1477" alt="PYAS_UI" src="https://github.com/user-attachments/assets/87d40261-7655-49ad-a19c-1ffcca60584f" />
@@ -28,23 +28,22 @@ PYAS/
├── Engine/
│ ├── Models/
│ │ ├── convert.py # Convert executable files or other files to images
│ │ └── train.py # TensorFlow CNN model training complete code
│ │ ├── train.py # TensorFlow CNN model training complete code
│ │ └── ... # Other models folders and files
│ │
│ └── Rules/
│ ├── rules.yar # Yara virus signature rule matching
│ └── rules.ips # IP network address rule matching
│ ├── rules.ips # IP network address rule matching
│ └── ... # Other rules folders and files
│
├── Plugins/
│ └── Filter/
│ ├── DriverEntry.c # Main driver entry and initialization logic
│ ├── DriverEntry.h # Global driver definitions, constants, and functions
│ ├── DriverPipe.c # Kernel to user pipe logging implementation
│ ├── ProtectBoot.c # Disk boot sector write protection
│ ├── ProtectImage.c # Image load monitoring and shellcode detection
│ ├── ProtectInject.c # Process thread handle access control to prevent injection
│ ├── ProtectReg.c # Registry modification protection
│ ├── ProtectRules.c # White, block list, and matching logic for files registry
│ └── ProtectRules.h # Protection rule declarations
│ ├── DriverEntry.cpp # Main driver entry and initialization logic
│ ├── DriverCommon.h # Global driver definitions, constants, and functions
│ ├── ProtectBoot.cpp # Disk boot sector write protection
│ ├── ProtectRegistry.cpp # Registry modification protection
│ ├── ProtectRules.cpp # White, block list, and matching logic for files registry
│ └── ... # Other driver folders and files
│
├── PYAS.py # Main application entry point and UI to engine interface
├── PYAS_Config.py # Configuration loading, saving, and global parameters
@@ -55,15 +54,115 @@ PYAS/
└── ... # Other supplementary folders and files
```
## Program Architecture
## Architecture diagram
PYAS antivirus software complete program flow architecture diagram.
PYAS Security antivirus software general architecture diagram.
<img width="23000" height="6000" alt="PYAS_Architecture" src="https://github.com/user-attachments/assets/3a7ce637-c2b3-4719-9658-07f286cfa879" />
```mermaid
graph TD
%% Global Styles
classDef ui fill:#e1f5fe,stroke:#01579b,stroke-width:2px;
classDef logic fill:#fff9c4,stroke:#fbc02d,stroke-width:2px;
classDef engine fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
classDef thread fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px;
classDef kernel fill:#ffebee,stroke:#c62828,stroke-width:2px;
classDef data fill:#eceff1,stroke:#455a64,stroke-width:2px,stroke-dasharray: 5 5;
## Packaged Releases
User((User))
Packaged Releases Download: https://github.com/87owo/PYAS/releases
subgraph Presentation_Layer ["Presentation Layer (View)"]
direction TB
UI_Static["PYAS_Interface.py<br/>(Ui_main_window Class)"]:::ui
UI_Controller["PYAS.py<br/>(MainWindow_Controller Class)"]:::ui
TrayIcon["System Tray Icon"]:::ui
User <--> UI_Controller
UI_Static --- UI_Controller
UI_Controller --- TrayIcon
end
subgraph Core_Logic_Layer ["Core Logic & Controller"]
direction TB
Init_Env["Initialization<br/>(init_environ, init_variable,<br/>init_windll)"]:::logic
Config_Mgr["Configuration Manager<br/>(load_config, save_config)"]:::logic
subgraph System_Tools ["System Tools"]
Sys_Repair["System Repair<br/>(repair_system_mbr,<br/>repair_system_image, etc.)"]:::logic
Sys_Clean["System Cleaner<br/>(clean_button, traverse_temp)"]:::logic
Proc_Mgr["Process Manager<br/>(list_process, kill_process)"]:::logic
List_Mgr["List Manager<br/>(manage_named_list:<br/>Whitelist/Quarantine)"]:::logic
end
UI_Controller --> Init_Env
Init_Env --> Config_Mgr
UI_Controller --> System_Tools
end
subgraph Protection_Layer ["Real-time Protection Threads (Daemons)"]
direction TB
Thread_Proc["Process Guard Thread<br/>(protect_proc_thread)<br/>[WMI/Snapshot]"]:::thread
Thread_File["File Guard Thread<br/>(protect_file_thread)<br/>[ReadDirectoryChangesW]"]:::thread
Thread_Net["Network Guard Thread<br/>(protect_net_thread)<br/>[GetExtendedTcpTable]"]:::thread
Thread_Sys["System Guard Thread<br/>(protect_system_thread)<br/>[Reg/MBR Check]"]:::thread
Thread_Popup["Popup Blocker Thread<br/>(popup_intercept_thread)<br/>[EnumWindows]"]:::thread
Thread_Pipe["Driver IPC Thread<br/>(pipe_server_thread)<br/>[NamedPipe Server]"]:::thread
Init_Env --> Thread_Proc
Init_Env --> Thread_File
Init_Env --> Thread_Net
Init_Env --> Thread_Sys
Init_Env --> Thread_Popup
Init_Env --> Thread_Pipe
end
subgraph Engine_Layer ["Detection Engine (PYAS_Engine.py)"]
direction TB
Scan_Worker["Scan Worker<br/>(scan_worker / scan_engine)"]:::engine
subgraph Scanners
Sign_Check["Signature Scanner<br/>(sign_scanner)<br/>[WinVerifyTrust]"]:::engine
AI_Model["AI Model Scanner<br/>(model_scanner)<br/>[ONNX/ResNet]"]:::engine
Yara_Rules["Rule Scanner<br/>(rule_scanner)<br/>[Yara/IP Lists]"]:::engine
end
Thread_Proc --> Scan_Worker
Thread_File --> Scan_Worker
Thread_Net --> Scan_Worker
UI_Controller -->|Manual Scan| Scan_Worker
Scan_Worker --> Sign_Check
Scan_Worker --> AI_Model
Scan_Worker --> Yara_Rules
end
subgraph Kernel_OS_Layer ["Windows Kernel & Driver"]
direction TB
WinAPI["Windows API (ctypes)<br/>(kernel32, user32, ntdll,<br/>advapi32, iphlpapi, psapi)"]:::kernel
Driver_Sys["Kernel Driver<br/>(PYAS_Driver.sys)"]:::kernel
OS_FS["File System (NTFS)"]:::kernel
OS_Net["Network Stack"]:::kernel
Init_Env -- Load DLLs --> WinAPI
Thread_File -- Monitor --> OS_FS
Thread_Net -- Monitor --> OS_Net
Thread_Proc -- Suspend/Kill --> WinAPI
Thread_Pipe <==>|"Named Pipe IPC<br/>(\\.\pipe\PYAS_Output_Pipe)"| Driver_Sys
Driver_Sys -- Callback/Block --> WinAPI
end
subgraph Data_Persistence ["Data & Resources"]
Config_File[("Config.json")]:::data
Model_Files[("Model Files<br/>(.onnx)")]:::data
Rule_Files[("Rule Files<br/>(.yar)")]:::data
Quarantine_Dir[("/Quarantine/")]:::data
Config_Mgr <--> Config_File
AI_Model <--> Model_Files
Yara_Rules <--> Rule_Files
List_Mgr <--> Quarantine_Dir
end
```
## Support System
@@ -72,14 +171,24 @@ Packaged Releases Download: https://github.com/87owo/PYAS/releases
| Minimum | Administrator | >= Windows 10 (20H1) | 1 GHz | 200MB | 100MB |
| Recommend | Administrator | >= Windows 10 (21H2) | 3 GHz | 500MB | 200MB |
## Packaged Releases
Download the installer. If it is incompatible with your system, you can repackage it yourself.
Packaged Download: https://github.com/87owo/PYAS/releases
## Official Website
Official Website : https://pyantivirus.wixsite.com/pyas
If you are interested in this project, you can visit the website to see other related content.
Open Source Website : https://github.com/87owo/PYAS
Source Available : https://github.com/87owo/PYAS
Official Website : https://pyas-security.com/antivirus
## Project License
Please read the Project License. If you would like to apply, please submit your application to Github issues.
For any questions, needs, or bug feedback, please contact us through the following website.
https://github.com/87owo/PYAS/blob/main/LICENSE.txt
Source Issues : https://github.com/87owo/PYAS/issues
Official Email : mailto:service.pyas@gmail.com