Compare commits

...
161 Commits
Author SHA1 Message Date
87owo ac4f960352 Add files via upload 2026-02-10 17:45:23 +08:00
87owo e4b3e4e438 Add files via upload 2026-02-10 17:44:48 +08:00
87owo d6ee476296 Add files via upload 2026-02-10 17:44:15 +08:00
87owo c23741ba9a Add files via upload 2026-02-10 17:43:47 +08:00
87owo 7bac5b4740 Add files via upload 2026-02-10 17:43:04 +08:00
87owo 1fe440168e Add files via upload 2026-02-04 23:11:56 +08:00
87owo 26ad57138b Add files via upload 2026-02-04 23:11:14 +08:00
87owo 92e1fdaf0f Add files via upload 2026-02-04 23:09:59 +08:00
87owo 357540d0ad Update README.md 2026-01-24 01:19:33 +08:00
87owo 405622a91e Update README.md 2026-01-24 01:14:02 +08:00
87owo 5686c73c56 Update README.md 2026-01-24 01:11:38 +08:00
87owo 76e2f787ac Update README.md 2026-01-24 01:10:28 +08:00
87owo 02b67f4e6a Update README.md 2026-01-24 01:06:59 +08:00
87owo a2ab527761 Update README.md 2026-01-24 01:05:17 +08:00
87owo f1142ae742 Add files via upload 2026-01-23 14:48:01 +08:00
87owo decb222dac Add files via upload 2026-01-23 14:25:34 +08:00
87owo 00c598e6f7 Add files via upload 2026-01-23 14:25:11 +08:00
87owo e9843dd3a5 Add files via upload 2026-01-23 14:24:27 +08:00
87owo 37f390742b Add files via upload 2026-01-23 14:23:14 +08:00
87owo 533e7dfd15 Add files via upload 2026-01-23 13:49:06 +08:00
87owo ddcbe1cd51 Delete Engine directory 2026-01-23 13:46:15 +08:00
87owo 4eabd04bc6 Add files via upload 2026-01-23 13:44:24 +08:00
87owo c8f2da6ac9 Add files via upload 2026-01-23 13:43:17 +08:00
87owo 8820ac4bf3 Add files via upload 2026-01-23 13:42:37 +08:00
87owo 236b200f39 Add files via upload 2026-01-12 14:28:24 +08:00
87owo 6789e32674 Add files via upload 2026-01-12 14:27:37 +08:00
87owo 9eb55deedf Add files via upload 2026-01-12 13:29:30 +08:00
87owo 6e76b5b8eb Add files via upload 2026-01-12 13:28:04 +08:00
87owo 491b0da83d Add files via upload 2026-01-10 22:48:17 +08:00
87owo 5d2c17e940 Add files via upload 2026-01-10 22:47:35 +08:00
87owo 0497c4a9e7 Add files via upload 2026-01-10 20:05:44 +08:00
87owo 6d0765848b Add files via upload 2026-01-10 20:03:39 +08:00
87owo 40c4ae71bd Merge pull request #35 from secretlay3r/main
refactor: replace ifs with dicts/sets + simplify exception handling
2026-01-10 19:37:25 +08:00
secretlay3r 8edba10dff Update PYAS.py
backup_mbr():
- Shorten except blocks logic into one
- Add len(mbr) == 512 check  
- Add MBR_SIGNATURE instead of just b"\x55\xAA"

pipe_server_thread():
- Replace whole ifs chain with RULES dict
- Replace [4001, 5001] with KILL_CODES set (for readability)

get_window_info()  and  get_process_name():
- Extract process name logic into private _get_process_name()
2026-01-10 14:17:27 +03:00
87owo 85aa7bc652 Add files via upload 2026-01-09 14:05:47 +08:00
87owo 854ad1db07 Add files via upload 2026-01-09 00:11:30 +08:00
87owo 955600a1e1 Add files via upload 2026-01-07 22:19:13 +08:00
87owo b739134d85 Add files via upload 2026-01-07 22:18:36 +08:00
87owo 723152566d Add files via upload 2026-01-07 21:10:34 +08:00
87owo 678b045e0e Update README.md 2026-01-07 17:47:13 +08:00
87owo 681f4df49a Add files via upload 2026-01-07 17:44:23 +08:00
87owo b19f7d7098 Add files via upload 2026-01-06 15:11:42 +08:00
87owo daaae3ec10 Add files via upload 2026-01-06 14:43:06 +08:00
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
87owo e538b837d5 Add files via upload 2025-10-07 21:53:12 +08:00
87owo 7b995e1223 Add files via upload 2025-09-16 20:12:31 +08:00
87owo c7826b58a3 Add files via upload 2025-09-16 20:04:32 +08:00
87owo 5786dbdb75 Add files via upload 2025-09-16 20:03:15 +08:00
87owo 0f42c19ec7 Delete README_zh_TW.md 2025-09-10 13:43:50 +08:00
87owo 87d44a64f3 Delete README_zh_CN.md 2025-09-10 13:43:40 +08:00
87owo 77dd4ace33 Update README.md 2025-09-10 13:43:14 +08:00
87owo 0907d71957 Update README.md 2025-09-10 13:36:40 +08:00
87owo e7a30646e3 Update README.md 2025-09-10 13:35:25 +08:00
87owo 98d21b3391 Update LICENSE.txt 2025-09-09 09:45:56 +08:00
87owo 35d9203b9c Update LICENSE.txt 2025-09-09 09:32:39 +08:00
87owo e6e384a7f7 Rename LICENSE.md to LICENSE.txt 2025-09-09 08:45:38 +08:00
87owo 7d954c14ae Rename LICENSE.txt to LICENSE.md 2025-09-09 08:45:19 +08:00
PYDT 41388962e2 Add files via upload 2025-08-29 17:59:44 +08:00
PYDT 6d51f6b6a9 Add files via upload 2025-08-29 16:42:14 +08:00
PYDT c7af9a3702 Add files via upload 2025-08-29 16:41:38 +08:00
PYDT da7c61202c Add files via upload 2025-08-28 13:36:16 +08:00
PYDT c24e872a33 Add files via upload 2025-08-28 10:28:15 +08:00
PYDT d0809ec313 Add files via upload 2025-08-28 08:58:42 +08:00
PYDT c1a796da38 Add files via upload 2025-08-27 17:53:10 +08:00
PYDT 98c27800e0 Add files via upload 2025-08-26 10:11:36 +08:00
PYDT 7a18eadd13 Add files via upload 2025-08-25 23:50:38 +08:00
PYDT b07adb7b30 Add files via upload 2025-08-25 23:23:42 +08:00
PYDT 4d7c3cce4d Add files via upload 2025-08-25 20:28:36 +08:00
PYDT 4ff0ab9cd8 Add files via upload 2025-08-25 09:42:51 +08:00
44 changed files with 4597 additions and 272677 deletions

No files matched your search

File renamed without changes.
-73
View File
@@ -1,73 +0,0 @@
from PIL import Image
import numpy, pefile, os
def file_to_images(file_data, output_dir, file_name, target_size=(224, 224)):#
wah = int(numpy.ceil(numpy.sqrt(len(file_data))))
file_data = numpy.frombuffer(file_data, dtype=numpy.uint8)
image_array = numpy.zeros((wah * wah,), dtype=numpy.uint8)
image_array[:len(file_data)] = file_data
image = Image.fromarray(image_array.reshape((wah, wah)), 'L')
image = image.resize(target_size, Image.Resampling.NEAREST)
image.save(os.path.join(output_dir, f"{file_name}.png"))
def check_file_type(file_path):
try:
shell_section = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"cry", "tvm", "dec", "enc", "vmp", "upx", "aes", "lzma", "press",
"pack", "enigma", "protect", "secur"]
unknown_section = ["asmstub", "base", "bss", "clr_uef", "cursors",
"engine", "fio", "fothk", "h~;", "icapsec", "malloc_h", "miniex",
"mssmixer", "ndr64", "nsys_wr", "obr", "wow", "wow64svc", "wpp_sf",
"pad", "pgae", "poolmi", "proxy", "qihoo", "res", "retpol", "uedbg",
"rwexec", "rygs", "s:@", "sanontcp", "segm", "test", "tracesup",
"transit", "trs_age", "wisevec"]
unimportant_section = ["viahwaes", "orpc", "nep", "ace", "extjmp",
"no_bbt", "data", "page", "hexpthk"]
shells = shell_section + unimportant_section + unknown_section
ftype = str(f".{file_path.split('.')[-1]}").lower()
if ftype in [".bat", ".cmd", ".ps1", ".vbs", ".wsf", ".js", ".html"]:
with open(file_path, 'rb') as f:
return [f.read()]
match_data = []
if ftype in [".com", ".exe", ".dll", ".sys", ".scr"]:
with pefile.PE(file_path, fast_load=True) as pe:
for section in pe.sections:
section_name = section.Name.rstrip(b'\x00').decode('latin1')
#if (section.Characteristics & 0x00000020 and not
#any(shell in section_name.lower() for shell in shells)):
if section.Characteristics & 0x00000020:
match_data.append(section.get_data())
return match_data
return False
except Exception as e:
print(e)
return False
def batch_file_to_images(input_dir, output_dir):
for root, dirs, files in os.walk(input_dir):
for file in files:
try:
file_path = os.path.join(root, file)
file_data = check_file_type(file_path)
if file_data:
for i, data in enumerate(file_data, 1):
print(i, 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)
file_to_images(data, output_path_dir, f"{i}_{file}")
except Exception as e:
print(e)
pass
input_directory = input('Enter the folder path: ')
output_directory = "./Image_File"
batch_file_to_images(input_directory, output_directory)
input('Conversion Complete')
-112
View File
@@ -1,112 +0,0 @@
import tensorflow as tf
import os, tf2onnx, numpy, random
from PIL import Image
from tensorflow.keras import *
Image.MAX_IMAGE_PIXELS = None
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 load_dataset(train_dir, val_dir, val_split=0.01, batch_size=128, color_mode="grayscale"):
channels = 1 if color_mode == "grayscale" else 3
if train_dir == val_dir:
file_paths, labels, class_indices = get_file_list(train_dir)
combined = list(zip(file_paths, labels))
random.shuffle(combined)
file_paths[:], labels[:] = zip(*combined)
num_val = int(val_split * len(file_paths))
train_files = file_paths[num_val:]
train_labels = labels[num_val:]
val_files = file_paths[:num_val]
val_labels = labels[:num_val]
else:
train_files, train_labels, class_indices = get_file_list(train_dir)
val_files, val_labels, _ = get_file_list(val_dir)
num_classes = len(class_indices)
def parse_fn(filename, label):
img = tf.io.read_file(filename)
img = tf.image.decode_image(img, channels=channels, expand_animations=False)
img = tf.cast(img, tf.float32) / 255.0
label = tf.one_hot(label, depth=num_classes)
return img, label
train_ds = tf.data.Dataset.from_tensor_slices((train_files, train_labels))
train_ds = train_ds.map(parse_fn, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)
val_ds = tf.data.Dataset.from_tensor_slices((val_files, val_labels))
val_ds = val_ds.map(parse_fn, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)
train_ds.class_indices = class_indices
return train_ds, val_ds
def gated_conv(x, strides):
c = layers.DepthwiseConv2D(3, strides=strides, padding='same', activation='gelu')(x)
g = layers.DepthwiseConv2D(3, strides=strides, padding='same', activation='sigmoid')(x)
return layers.Multiply()([c, g])
def multi_conv(x, strides):
convs = [layers.DepthwiseConv2D(kernel_size=k, strides=strides, padding='same')(x) for k in [1, 3, 5, 7]]
x = layers.Concatenate()(convs)
x = layers.BatchNormalization()(x)
return layers.Activation('gelu')(x)
def se_block(x, reduction):
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])
def build_model(input_shape, num_classes):
i = layers.Input(shape=input_shape)
x = multi_conv(i, strides=1)
x = multi_conv(x, strides=2)
x = gated_conv(x, strides=2)
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 = layers.GlobalAveragePooling2D()(x)
o = layers.Dense(num_classes, activation='softmax', dtype='float32')(x)
return models.Model(i, o)
def lr_scheduler(epoch, lr):
return 1e-3 * (0.7 ** epoch)
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)
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', r'./Image_File')
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'])
model.fit(train_ds, epochs=30, callbacks=[CustomModelCheckpoint(), callbacks.LearningRateScheduler(lr_scheduler)], validation_data=val_ds)
input("Training complete.")
+55
View File
@@ -0,0 +1,55 @@
from PIL import Image
import numpy, os
####################################################################################################
def preprocess_image(file_data, size, channels=1):
width, height = size
wah = int(numpy.ceil(numpy.sqrt(len(file_data) / channels)))
arr = numpy.frombuffer(file_data, dtype=numpy.uint8)
img = numpy.zeros(wah*wah*channels, dtype=numpy.uint8)
img[:len(file_data)] = arr
image = Image.fromarray(img.reshape((wah, wah)), 'L')
return image.resize((width, height), Image.Resampling.NEAREST)
####################################################################################################
def get_type(file_path):
suffix = {".com", ".dll", ".drv", ".exe", ".ocx", ".scr", ".sys", ".mui", ".cpl"}
try:
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()
except:
pass
return file_content
####################################################################################################
def file_to_images(input_dir, output_dir):
for root, dirs, files in os.walk(input_dir):
for file in files:
try:
file_path = os.path.join(root, file)
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(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_Output"
file_to_images(input_directory, output_directory)
input('Conversion Complete')
@@ -1,5 +1,7 @@
import os, hashlib
####################################################################################################
def calc_sha256(path):
with open(path, "rb") as f:
return hashlib.sha256(f.read()).digest()
@@ -25,5 +27,8 @@ def dedup_realtime(root):
seen.add(h)
print(f"deleted {deleted}")
####################################################################################################
if __name__ == "__main__":
dedup_realtime(r".\Image_File")
dedup_realtime(input("Input file path: "))
input('Deduplicate Complete')
+165
View File
@@ -0,0 +1,165 @@
import tensorflow as tf
import os, tf2onnx, numpy, random
from PIL import Image
from tensorflow.keras import *
from collections import Counter
####################################################################################################
Image.MAX_IMAGE_PIXELS = None
tf.keras.mixed_precision.set_global_policy('mixed_float16')
####################################################################################################
def load_dataset(data_dir, image_size=(224, 224), val_split=0.0001, 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)
num_val = int(val_split * len(file_paths))
train_files = file_paths[num_val:]
train_labels = labels[num_val:]
val_files = file_paths[:num_val]
val_labels = labels[:num_val]
train_ds = tf.data.Dataset.from_tensor_slices((train_files, train_labels))
train_ds = train_ds.map(lambda f, l: parse_fn(f, l, image_size, channels), num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)
val_ds = tf.data.Dataset.from_tensor_slices((val_files, val_labels))
val_ds = val_ds.map(lambda f, l: parse_fn(f, l, image_size, channels), num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)
train_ds.class_indices = class_indices
return train_ds, val_ds
####################################################################################################
def parse_fn(filename, label, image_size, channels):
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.cast(label, tf.float32)
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, 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)
def gated_conv(x, strides):
c = layers.DepthwiseConv2D(3, strides=strides, padding='same', activation='gelu')(x)
g = layers.DepthwiseConv2D(3, strides=strides, padding='same', activation='sigmoid')(x)
return layers.Multiply()([c, g])
def coordinate_attention(x, reduction):
input_shape = tf.shape(x)
h, w = input_shape[1], input_shape[2]
filters = x.shape[-1]
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):
i = layers.Input(shape=input_shape)
x = multi_conv(i, strides=1)
x = gated_conv(x, strides=2)
x = multi_conv(x, strides=2)
x = multi_conv(x, strides=2)
x = multi_conv(x, strides=2)
x = multi_conv(x, strides=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(1, activation='sigmoid', dtype='float32')(x)
return models.Model(i, o)
####################################################################################################
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 binary_focal_loss(gamma=2.0, alpha=0.25):
def focal_loss(y_true, y_pred):
y_true = tf.cast(y_true, tf.float32)
y_pred = tf.clip_by_value(y_pred, tf.keras.backend.epsilon(), 1.0 - tf.keras.backend.epsilon())
p_t = tf.where(tf.equal(y_true, 1), y_pred, 1 - y_pred)
alpha_t = tf.where(tf.equal(y_true, 1), alpha, 1 - alpha)
loss = -alpha_t * tf.math.pow(1.0 - p_t, gamma) * tf.math.log(p_t)
return tf.reduce_mean(loss)
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,) + self.model.input.shape[1:], tf.float32),)
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_Full_Pefile')
for imgs, _ in train_ds.take(1):
train_ds.image_shape = imgs.shape[1:]
break
try:
model = models.load_model('PYAS_Model_Epoch_0.h5', compile=False)
print("Load model from disk")
except:
print("Creating a new model")
model = build_model(train_ds.image_shape)
print(f"Total parameters: {model.count_params()}")
model.compile(optimizer='adam', loss=binary_focal_loss(gamma=2.0, alpha=0.25),
metrics=[metrics.BinaryAccuracy(name='accuracy'), metrics.AUC(name='auc'),
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, class_weight={0: 10.0, 1: 1.0})
input('Training Complete')
+513
View File
@@ -0,0 +1,513 @@
import os, sys, time, ctypes, sqlite3, datetime, pefile, math
import numpy as np
import ctypes.wintypes
####################################################################################################
DB_PATH = "pe_features.db"
BATCH_SIZE = 100
MAX_FILE_SIZE = 256 * 1024 * 1024
TARGET_EXTENSIONS = {
'.exe', '.dll', '.sys', '.ocx', '.scr', '.efi', '.acm', '.ax', '.cpl', '.drv', '.com'
}
####################################################################################################
class Features:
SCHEMA = [
"FileEntropy", "IsExe", "IsDll", "IsDriver", "Is64Bit", "Machine", "Magic",
"TimeDateStamp", "CheckSum", "ImageBase", "SizeOfImage", "SizeOfHeaders",
"Characteristics", "DllCharacteristics", "Subsystem", "LoaderFlags",
"MajorLinkerVersion", "MinorLinkerVersion", "SizeOfCode",
"SizeOfInitializedData", "SizeOfUninitializedData", "AddressOfEntryPoint",
"BaseOfCode", "SectionAlignment", "FileAlignment",
"MajorOperatingSystemVersion", "MinorOperatingSystemVersion",
"MajorImageVersion", "MinorImageVersion",
"MajorSubsystemVersion", "MinorSubsystemVersion",
"SizeOfStackReserve", "SizeOfStackCommit", "SizeOfHeapReserve", "SizeOfHeapCommit",
"NumberOfSections", "NumberOfRvaAndSizes", "PointerToSymbolTable", "NumberOfSymbols",
"SizeOfOptionalHeader",
"TextSection", "TextSizeRatio", "DataSection", "DataSizeRatio",
"RsrcSection", "RsrcSizeRatio", "SectionCount", "ExecutableSections",
"WritableSections", "ReadableSections", "SectionException",
"IconCount", "ApiCount", "ExportCount", "DebugCount", "ExceptionCount",
"FileDescriptionLength", "FileVersionLength", "ProductNameLength",
"ProductVersionLength", "CompanyNameLength", "LegalCopyrightLength",
"CommentsLength", "InternalNameLength", "LegalTrademarksLength",
"SpecialBuildLength", "PrivateBuildLength",
"TrustSigned", "IsDebug", "IsPatched", "IsPrivateBuild", "IsPreRelease",
"IsSpecialBuild", "IsAdmin", "IsInstall", "HasTlsCallbacks",
"HasInvalidTimestamp", "HasRelocationDirectory", "HasPacked", "FileTimeException",
"_CorExeMain", "_CorDllMain",
"GetDC", "CreateDCW", "CreateDCA", "BitBlt", "StretchBlt", "CreateCompatibleDC",
"CreateCompatibleBitmap", "SelectObject", "DeleteDC", "DeleteObject", "GetDeviceCaps",
"GetSystemMetrics",
"SetWindowsHookExA", "SetWindowsHookExW", "UnhookWindowsHookEx",
"GetAsyncKeyState", "GetKeyState", "GetKeyboardState",
"MapVirtualKeyA", "MapVirtualKeyW", "MapVirtualKeyExA", "MapVirtualKeyExW",
"ToAscii", "ToAsciiEx", "ToUnicode", "ToUnicodeEx", "KeybdEvent", "SendInput",
"GetCursorPos", "SetCursorPos", "MouseEvent", "GetDoubleClickTime",
"GetCapture", "SetCapture",
"WaveInOpen", "WaveInClose", "WaveInStart", "WaveInStop",
"CapCreateCaptureWindowA", "CapCreateCaptureWindowW",
"OpenClipboard", "CloseClipboard", "GetClipboardData", "SetClipboardData",
"GetDesktopWindow", "GetForegroundWindow", "GetWindowDC", "GetWindowRect",
"GetClientRect", "PrintWindow", "SetWindowDisplayAffinity", "FindWindowA", "FindWindowW",
"EnumWindows", "EnumChildWindows",
"Direct3DCreate9", "D3D11CreateDevice", "GdipSaveImageToFile",
"CreateProcessA", "CreateProcessW", "CreateThread", "ResumeThread", "SuspendThread",
"OpenProcess", "TerminateProcess", "GetCurrentProcess", "GetCurrentProcessId",
"ExitProcess", "WinExec", "ShellExecuteA", "ShellExecuteW",
"CreateRemoteThread", "QueueUserAPC", "VirtualAlloc", "VirtualAllocEx",
"VirtualProtect", "VirtualProtectEx", "WriteProcessMemory", "ReadProcessMemory",
"NtUnmapViewOfSection", "SetThreadContext", "GetThreadContext", "Wow64SetThreadContext",
"ZwUnmapViewOfSection", "CreateFileMappingA", "CreateFileMappingW", "MapViewOfFile",
"UnmapViewOfSection",
"LoadLibraryA", "LoadLibraryW", "LoadLibraryExA", "LoadLibraryExW",
"GetProcAddress", "GetModuleHandleA", "GetModuleHandleW", "FreeLibrary",
"CreateFileA", "CreateFileW", "WriteFile", "ReadFile", "DeleteFileA", "DeleteFileW",
"CopyFileA", "CopyFileW", "MoveFileA", "MoveFileW", "FindFirstFileA", "FindNextFileA",
"GetTempPathA", "GetTempPathW", "GetTempFileNameA", "GetTempFileNameW",
"SetFileAttributesA", "SetFileAttributesW", "DeviceIoControl", "SetFileTime",
"RegOpenKeyExA", "RegOpenKeyExW", "RegSetValueExA", "RegSetValueExW",
"RegCreateKeyExA", "RegCreateKeyExW", "RegDeleteKeyA", "RegDeleteKeyW",
"RegEnumValueA", "RegEnumValueW", "RegQueryValueExA", "RegQueryValueExW",
"RegDeleteValueA", "RegDeleteValueW",
"OpenSCManagerA", "OpenSCManagerW", "CreateServiceA", "CreateServiceW",
"StartServiceA", "StartServiceW", "ControlService", "DeleteService",
"AdjustTokenPrivileges", "LookupPrivilegeValueA", "LookupPrivilegeValueW",
"OpenProcessToken", "NetUserAdd", "NetLocalGroupAddMembers",
"Socket", "Connect", "Send", "Recv", "WSAStartup", "gethostbyname", "getaddrinfo",
"WSAIoctl", "WSASocketA", "WSASocketW",
"URLDownloadToFileA", "URLDownloadToFileW",
"InternetOpenA", "InternetOpenW", "InternetConnectA", "InternetConnectW",
"InternetOpenUrlA", "InternetOpenUrlW",
"HttpOpenRequestA", "HttpOpenRequestW", "HttpSendRequestA", "HttpSendRequestW",
"InternetReadFile", "DnsQuery_A", "DnsQuery_W",
"IsDebuggerPresent", "CheckRemoteDebuggerPresent", "OutputDebugStringA", "OutputDebugStringW",
"GetTickCount", "QueryPerformanceCounter", "Sleep", "GetSystemTimeAsFileTime",
"GetLocalTime", "GlobalMemoryStatus", "GetVersionExA", "GetVersionExW",
"GetComputerNameA", "GetComputerNameW", "GetUserNameA", "GetUserNameW",
"CryptAcquireContextA", "CryptAcquireContextW", "CryptCreateHash", "CryptHashData",
"CryptDeriveKey", "CryptEncrypt", "CryptDecrypt", "CryptDestroyKey", "CryptDestroyHash",
"CryptReleaseContext", "CryptGenKey", "CryptImportKey", "CryptExportKey",
"RtlDecompressBuffer", "ConnectNamedPipe", "PeekNamedPipe"
]
SCHEMA_SET = set(SCHEMA)
PACKERS = {
'upx', 'aspack', 'asprotect', 'pecompact', 'upack', 'fsg', 'mew',
'mpress', 'ezip', 'pklt', 'shrink', 'petite', 'telock',
'themida', 'winlicense', 'tmd', 'vmp', 'enigma', 'obsidium',
'pelock', 'exestealth', 'yoda', 'armadillo', 'zprotect',
'sforce', 'starforce', 'qihoo', 'wisevec', 'megastop',
}
INSTALLER_SIGS = [b"Nullsoft.NSIS", b"Inno Setup", b"7-Zip.7zip", b"InstallShield"]
####################################################################################################
def verify_signature(file_path):
if os.name != 'nt':
return 0
try:
wintrust = ctypes.windll.wintrust
WINTRUST_ACTION_GENERIC_VERIFY_V2 = ctypes.c_char_p(b'\x6b\xc5\xaa\x00\x44\xcd\xd0\x11\x8c\xc2\x00\xc0\x4f\xc2\x95\xee')
class WINTRUST_FILE_INFO(ctypes.Structure):
_fields_ = [
("cbStruct", ctypes.wintypes.DWORD),
("pcwszFilePath", ctypes.wintypes.LPCWSTR),
("hFile", ctypes.wintypes.HANDLE),
("pgKnownSubject", ctypes.wintypes.LPVOID)
]
class WINTRUST_DATA(ctypes.Structure):
_fields_ = [
("cbStruct", ctypes.wintypes.DWORD),
("pPolicyCallbackData", ctypes.wintypes.LPVOID),
("pSIPClientData", ctypes.wintypes.LPVOID),
("dwUIChoice", ctypes.wintypes.DWORD),
("fdwRevocationChecks", ctypes.wintypes.DWORD),
("dwUnionChoice", ctypes.wintypes.DWORD),
("pFile", ctypes.POINTER(WINTRUST_FILE_INFO)),
("dwStateAction", ctypes.wintypes.DWORD),
("hWVTStateData", ctypes.wintypes.HANDLE),
("pwszURLReference", ctypes.wintypes.LPCWSTR),
("dwProvFlags", ctypes.wintypes.DWORD),
("dwUIContext", ctypes.wintypes.DWORD),
("pSignatureSettings", ctypes.wintypes.LPVOID)
]
fi = WINTRUST_FILE_INFO(ctypes.sizeof(WINTRUST_FILE_INFO), file_path, None, None)
td = WINTRUST_DATA(ctypes.sizeof(WINTRUST_DATA), None, None, 2, 1, 1, ctypes.pointer(fi), 0, None, None, 0x00000080, 0, None)
action = ctypes.wintypes.GUID.from_buffer_copy(WINTRUST_ACTION_GENERIC_VERIFY_V2)
return 1 if wintrust.WinVerifyTrust(None, ctypes.byref(action), ctypes.byref(td)) == 0 else 0
except:
return 0
####################################################################################################
def safe_float(val):
try:
f = float(val)
if math.isinf(f) or math.isnan(f):
return 0.0
return f
except:
return 0.0
def process_single_file(file_path):
def _calc_entropy(data):
if not data:
return 0.0
arr = np.frombuffer(data, dtype=np.uint8)
counts = np.bincount(arr, minlength=256)
probs = counts[counts > 0] / len(arr)
return float(-np.sum(probs * np.log2(probs)))
def _safe_div(n, d):
return n / d if d > 0 else 0.0
try:
fsize = os.path.getsize(file_path)
if fsize == 0 or fsize > MAX_FILE_SIZE:
return None
except:
return None
fts = {k: 0 for k in Features.SCHEMA}
pe = None
try:
pe = pefile.PE(file_path, fast_load=True)
fts['TrustSigned'] = verify_signature(file_path)
fh = pe.FILE_HEADER
fts['Machine'] = fh.Machine
fts['NumberOfSections'] = fh.NumberOfSections
fts['TimeDateStamp'] = fh.TimeDateStamp
fts['PointerToSymbolTable'] = fh.PointerToSymbolTable
fts['NumberOfSymbols'] = fh.NumberOfSymbols
fts['SizeOfOptionalHeader'] = fh.SizeOfOptionalHeader
fts['Characteristics'] = fh.Characteristics
curr_ts = datetime.datetime.utcnow().timestamp()
fts['HasInvalidTimestamp'] = 1 if (fh.TimeDateStamp < 631152000 or fh.TimeDateStamp > curr_ts + 2592000) else 0
if hasattr(pe, 'OPTIONAL_HEADER'):
op = pe.OPTIONAL_HEADER
fts['Magic'] = op.Magic
fts['MajorLinkerVersion'] = op.MajorLinkerVersion
fts['MinorLinkerVersion'] = op.MinorLinkerVersion
fts['SizeOfCode'] = op.SizeOfCode
fts['SizeOfInitializedData'] = op.SizeOfInitializedData
fts['SizeOfUninitializedData'] = op.SizeOfUninitializedData
fts['AddressOfEntryPoint'] = op.AddressOfEntryPoint
fts['BaseOfCode'] = op.BaseOfCode
fts['ImageBase'] = op.ImageBase
fts['SectionAlignment'] = op.SectionAlignment
fts['FileAlignment'] = op.FileAlignment
fts['MajorOperatingSystemVersion'] = op.MajorOperatingSystemVersion
fts['MinorOperatingSystemVersion'] = op.MinorOperatingSystemVersion
fts['MajorImageVersion'] = op.MajorImageVersion
fts['MinorImageVersion'] = op.MinorImageVersion
fts['MajorSubsystemVersion'] = op.MajorSubsystemVersion
fts['MinorSubsystemVersion'] = op.MinorSubsystemVersion
fts['SizeOfImage'] = op.SizeOfImage
fts['SizeOfHeaders'] = op.SizeOfHeaders
fts['CheckSum'] = op.CheckSum
fts['Subsystem'] = op.Subsystem
fts['DllCharacteristics'] = op.DllCharacteristics
fts['SizeOfStackReserve'] = op.SizeOfStackReserve
fts['SizeOfStackCommit'] = op.SizeOfStackCommit
fts['SizeOfHeapReserve'] = op.SizeOfHeapReserve
fts['SizeOfHeapCommit'] = op.SizeOfHeapCommit
fts['LoaderFlags'] = op.LoaderFlags
fts['NumberOfRvaAndSizes'] = op.NumberOfRvaAndSizes
fts['Is64Bit'] = 1 if fh.Machine == 0x8664 else 0
fts['IsExe'] = 1 if pe.is_exe() else 0
fts['IsDll'] = 1 if pe.is_dll() else 0
fts['IsDriver'] = 1 if pe.is_driver() else 0
if len(op.DATA_DIRECTORY) > 9 and op.DATA_DIRECTORY[9].VirtualAddress > 0:
fts['HasTlsCallbacks'] = 1
if len(op.DATA_DIRECTORY) > 5 and op.DATA_DIRECTORY[5].Size > 0:
fts['HasRelocationDirectory'] = 1
pe.parse_sections(pe.FILE_HEADER.NumberOfSections)
file_data = pe.get_memory_mapped_image()
fts['FileEntropy'] = _calc_entropy(file_data)
fts['SectionCount'] = len(pe.sections)
for section in pe.sections:
try:
name = section.Name.decode('ascii', 'ignore').strip('\x00')
except:
name = ""
s_data = section.get_data()
s_entropy = _calc_entropy(s_data)
if any(p in name.lower() for p in Features.PACKERS):
fts['HasPacked'] = 1
if section.Characteristics & 0x20000000:
fts['ExecutableSections'] += 1
if section.Characteristics & 0x80000000:
fts['WritableSections'] += 1
if section.Characteristics & 0x40000000:
fts['ReadableSections'] += 1
if section.SizeOfRawData + section.PointerToRawData > fsize:
fts['SectionException'] = 1
ratio = _safe_div(section.SizeOfRawData, fsize)
if name.startswith('.text'):
fts['TextSection'] = s_entropy
fts['TextSizeRatio'] = ratio
elif name.startswith('.data'):
fts['DataSection'] = s_entropy
fts['DataSizeRatio'] = ratio
elif name.startswith('.rsrc'):
fts['RsrcSection'] = s_entropy
fts['RsrcSizeRatio'] = ratio
if b"requireAdministrator" in s_data:
fts['IsAdmin'] = 1
for sig in Features.INSTALLER_SIGS:
if sig in s_data:
fts['IsInstall'] = 1
break
pe.parse_data_directories(directories=[
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT'],
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXPORT'],
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_RESOURCE'],
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_DEBUG']
])
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
fts['ApiCount'] += 1
if not imp or not hasattr(imp, 'name') or not imp.name:
continue
try:
name = imp.name.decode('ascii', 'ignore')
if name in Features.SCHEMA_SET:
fts[name] = 1
except:
pass
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
fts['ExportCount'] = len(pe.DIRECTORY_ENTRY_EXPORT.symbols)
if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:
if entry.id == 3 and hasattr(entry, 'directory'):
fts['IconCount'] = len(entry.directory.entries)
break
if hasattr(pe, 'DIRECTORY_ENTRY_DEBUG'):
fts['DebugCount'] = len(pe.DIRECTORY_ENTRY_DEBUG)
for k in fts:
fts[k] = safe_float(fts[k])
return fts
except Exception:
return None
finally:
if pe:
pe.close()
####################################################################################################
def init_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("PRAGMA synchronous = OFF")
conn.execute("PRAGMA journal_mode = WAL")
conn.execute("PRAGMA cache_size = 10000")
cols = ", ".join([f"{c} REAL" for c in Features.SCHEMA])
conn.execute(f"CREATE TABLE IF NOT EXISTS PeData ({cols}, Label INTEGER)")
conn.commit()
return conn
def prune_db_duplicates(conn):
try:
print("\n[*] Post-processing: Checking for and removing duplicate entries...")
all_cols = ", ".join(Features.SCHEMA + ["Label"])
sql_count_before = "SELECT COUNT(*) FROM PeData"
before = conn.execute(sql_count_before).fetchone()[0]
sql_dedup = f"""
DELETE FROM PeData
WHERE rowid NOT IN (
SELECT MIN(rowid)
FROM PeData
GROUP BY {all_cols}
)
"""
conn.execute(sql_dedup)
conn.commit()
after = conn.execute(sql_count_before).fetchone()[0]
removed = before - after
if removed > 0:
print(f"[+] Deduplication complete. Removed {removed} duplicate rows.")
print(" (Duplicates occur if the same file is scanned multiple times)")
else:
print("[+] Deduplication complete. No duplicates found.")
except Exception as e:
print(f"[-] Deduplication Warning: {e}")
####################################################################################################
def scan_and_save(conn, path, label):
print(f"\n[*] Scanning: {path} (Label={label})")
print(f"[*] Config: Max File Size = {MAX_FILE_SIZE/1024/1024:.0f} MB")
files = []
print("[*] Walking directory tree...")
if os.path.isfile(path):
files.append(path)
else:
for r, _, fs in os.walk(path):
for f in fs:
if os.path.splitext(f)[1].lower() in TARGET_EXTENSIONS:
files.append(os.path.join(r, f))
total = len(files)
if total == 0:
print("[-] No valid PE files found in this path.")
return
print(f"[*] Found {total} files. Processing...")
batch = []
count = 0
errors = 0
start_time = time.time()
placeholders = ",".join(["?"] * (len(Features.SCHEMA) + 1))
sql = f"INSERT INTO PeData VALUES ({placeholders})"
try:
for i, file_path in enumerate(files):
res = process_single_file(file_path)
if res:
vals = [res.get(c, 0.0) for c in Features.SCHEMA]
vals.append(float(label))
batch.append(tuple(vals))
count += 1
else:
errors += 1
if len(batch) >= BATCH_SIZE:
try:
conn.executemany(sql, batch)
conn.commit()
batch = []
except Exception as batch_err:
print(f"\n[-] Batch Error: {batch_err}. Retrying strictly...")
for row in batch:
try:
conn.execute(sql, row)
except Exception:
errors += 1
count -= 1
conn.commit()
batch = []
elapsed = time.time() - start_time
rate = (i + 1) / elapsed if elapsed > 0 else 0
sys.stdout.write(f"\r[{i+1}/{total}] OK: {count} | Skip/Err: {errors} | {rate:.1f} files/s")
sys.stdout.flush()
except KeyboardInterrupt:
print("\n\n[-] Interrupted by user.")
except Exception as e:
print(f"\n[-] Unexpected Error: {e}")
finally:
if batch:
print(f"\n[*] Saving remaining {len(batch)} items...")
try:
conn.executemany(sql, batch)
conn.commit()
except Exception as final_err:
print(f"[-] Final Batch Error: {final_err}. Retrying strictly...")
for row in batch:
try:
conn.execute(sql, row)
except Exception:
pass
conn.commit()
print(f"\n[+] Scan finished/stopped. Total added: {count}")
prune_db_duplicates(conn)
####################################################################################################
if __name__ == "__main__":
print("\n---------------- PE Dataset Builder v2.6 ----------------\n")
print("Type 'exit' or 'q' at any prompt to quit.")
if os.path.exists(DB_PATH):
print(f"[-] Note: If SCHEMA changed, please delete {DB_PATH} before running.")
conn = init_db()
try:
while True:
print("\n---------------------------------------------------------\n")
raw_path = input("[*] Enter Path (File or Folder): ").strip()
target_path = raw_path.strip('"').strip("'")
if target_path.lower() in ['exit', 'q']:
break
if not target_path or not os.path.exists(target_path):
print("[-] Invalid path. Please try again.")
continue
while True:
label_input = input("[*] Enter Label (0=Safe, 1=Malware): ").strip()
if label_input.lower() in ['exit', 'q']:
conn.close()
sys.exit()
if label_input in ['0', '1']:
label = int(label_input)
break
else:
print("[-] Please enter 0 or 1.")
scan_and_save(conn, target_path, label)
except KeyboardInterrupt:
print("\n\n[-] Interrupted.")
finally:
conn.close()
print(f"\n[+] Database saved to: {os.path.abspath(DB_PATH)}")
+195
View File
@@ -0,0 +1,195 @@
import os, sys, time, sqlite3, re, json
import pandas as pd
import numpy as np
import lightgbm as lgb
import onnxmltools
from onnxmltools.convert.common.data_types import FloatTensorType
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score, roc_auc_score
####################################################################################################
DB_PATH = "pe_features.db"
MODEL_FILE = "pe_malware_lgbm.txt"
ONNX_FILE = "pe_malware.onnx"
FEATURE_FILE = "features.json"
TEST_SIZE = 0.0001
RANDOM_SEED = 42
LGBM_PARAMS = {
'objective': 'binary',
'metric': ['binary_logloss', 'auc'],
'boosting_type': 'gbdt',
'num_leaves': 63,
'learning_rate': 0.05,
'feature_fraction': 0.8,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'verbose': -1,
'seed': RANDOM_SEED,
'n_jobs': -1,
'max_depth': -1,
'min_data_in_leaf': 20,
'lambda_l1': 0.1,
'lambda_l2': 0.1
}
####################################################################################################
def get_raw_schema(db_path):
if not os.path.exists(db_path):
return None
conn = sqlite3.connect(db_path)
try:
cursor = conn.cursor()
cursor.execute("PRAGMA table_info(PeData)")
columns = [row[1] for row in cursor.fetchall()]
exclude_lower = {'label', 'id', 'filename', 'filelength', 'rowid', 'probability', 'predictedlabel', 'score'}
return [c for c in columns if c.lower().strip() not in exclude_lower]
except:
return None
finally:
conn.close()
def load_and_clean_data(db_path, raw_cols):
print(f"[*] Connecting to database: {db_path}")
conn = sqlite3.connect(db_path)
req_cols = list(set(raw_cols + ['Label']))
sql = f"SELECT {', '.join(req_cols)} FROM PeData"
try:
df = pd.read_sql_query(sql, conn)
if df.empty: return None, None, None
label_col = next((c for c in df.columns if c.lower().strip() == 'label'), None)
if not label_col:
print("[-] Critical Error: Label column not found.")
return None, None, None
y = df[label_col].astype(int)
X = df.drop(columns=[label_col], errors='ignore')
valid_features = [c for c in raw_cols if c in X.columns]
X = X[valid_features].copy()
X = X.rename(columns=lambda x: re.sub('[^A-Za-z0-9_]+', '', x))
if X.isnull().values.any():
X = X.fillna(X.median(numeric_only=True))
final_features = X.columns.tolist()
return X, y, final_features
finally:
conn.close()
####################################################################################################
def train_process(X, y):
print(f"[*] Dataset shape: {X.shape}")
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=TEST_SIZE, random_state=RANDOM_SEED, stratify=y
)
n_pos = (y_train == 1).sum()
n_neg = (y_train == 0).sum()
base_weight = n_neg / n_pos if n_pos > 0 else 1.0
weight_ratio_base = 1.0
weight_ratio_target = 0.1
final_pos_weight = base_weight * (weight_ratio_target / weight_ratio_base)
print(f"[*] Balance Report: Safe={n_neg}, Malware={n_pos}")
print(f"[*] Weight Config: Base Balanced={base_weight:.4f}, Final Adjusted (Favor Safe)={final_pos_weight:.4f}")
train_data = lgb.Dataset(X_train, label=y_train)
valid_data = lgb.Dataset(X_test, label=y_test, reference=train_data)
params = LGBM_PARAMS.copy()
params['scale_pos_weight'] = final_pos_weight
print("\n[*] Starting LightGBM training (Full Force, No Early Stopping)...")
start_time = time.time()
model = lgb.train(
params,
train_data,
valid_sets=[valid_data],
num_boost_round=1000,
callbacks=[
lgb.log_evaluation(period=100)
]
)
elapsed = time.time() - start_time
print(f"\n[+] Training finished in {elapsed:.2f}s")
return model, X_test, y_test
def export_onnx_model(model, feature_names):
print(f"[*] Exporting ONNX model to {ONNX_FILE}...")
try:
initial_type = [('float_input', FloatTensorType([None, len(feature_names)]))]
onnx_model = onnxmltools.convert_lightgbm(model, initial_types=initial_type)
onnxmltools.utils.save_model(onnx_model, ONNX_FILE)
with open(FEATURE_FILE, 'w') as f:
json.dump(feature_names, f)
print(f"[+] ONNX export success. Features synced to {FEATURE_FILE}")
except Exception as e:
print(f"[-] ONNX export failed: {e}")
def evaluate_and_save(model, X_test, y_test):
print("\n------------------- Evaluation Report -------------------\n")
y_prob = model.predict(X_test, num_iteration=model.best_iteration)
y_pred = (y_prob > 0.5).astype(int)
acc = accuracy_score(y_test, y_pred)
auc = roc_auc_score(y_test, y_prob)
print(f"Accuracy : {acc:.4f}")
print(f"ROC AUC : {auc:.4f}")
print("\n" + classification_report(y_test, y_pred, zero_division=0))
print("---------------------------------------------------------\n")
print("[*] Top 20 Features (Importance by Gain):")
feature_names = model.feature_name()
importance = model.feature_importance(importance_type='gain')
feature_imp = pd.DataFrame(sorted(zip(importance, feature_names), reverse=True), columns=['Value', 'Feature'])
print(feature_imp.head(20).to_string(index=False))
print("\n---------------------------------------------------------\n")
model.save_model(MODEL_FILE)
print(f"[+] Native model saved to: {os.path.abspath(MODEL_FILE)}")
export_onnx_model(model, feature_names)
####################################################################################################
if __name__ == "__main__":
print("\n---------------- PE Malware Trainer v3.0 ----------------\n")
if not os.path.exists(DB_PATH):
print(f"[-] Error: Database {DB_PATH} not found.")
sys.exit(1)
raw_schema = get_raw_schema(DB_PATH)
if not raw_schema:
print("[-] Error: Could not read schema.")
sys.exit(1)
X, y, _ = load_and_clean_data(DB_PATH, raw_schema)
if X is None:
sys.exit(1)
try:
model, X_test, y_test = train_process(X, y)
evaluate_and_save(model, X_test, y_test)
except KeyboardInterrupt:
print("\n\n[-] Training interrupted.")
except Exception as e:
print(f"\n[-] Critical Error: {e}")
File diff suppressed because it is too large. Load diff
+25 -21
View File
@@ -1,27 +1,31 @@
PYAS Security Software Development License Agreement
Last updated: 2025-08-15
87owo Publicly Available Source Code License Agreement
Last updated: 2025-12-19
1. License & Ownership
– A single device key may be required to activate the software or source code.
– Non exclusive, non transferable, and for personal, internal use only.
– 87owo reserves all rights. Intellectual property rights are not transferred.
1. License and Ownership
- 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 & Prohibitions
– Private redistribution, sublicensing, or rental is prohibited.
– Private reverse engineering or removal of notices is prohibited.
– Any of the above requires prior authorization from the original author.
– Only personal internal use or modification of the source code is permitted.
– Use of the software or source code for any illegal purpose is prohibited.
2. Use and Prohibitions
- 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. License Components
– All project script archives and executable files are proprietary.
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. Updates & Terms
– Updates to new versions may include patches, enhancements, or modifications.
– Continued use constitutes your acceptance of these features or terms.
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.
5. Warranty & Liability
– This software is provided "as is," without warranty of any kind.
– In no event shall there be any liability for consequential damages.
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–2025 87owo (PYAS Security). All rights reserved.
© 2020-2026 87owo (PYAS Security). All rights reserved.
+586 -246
View File
File diff suppressed because it is too large. Load diff
+9 -9
View File
@@ -24,10 +24,10 @@ 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 ",
"啟用":"Enable ","禁用":"Disable ","正在初始化中":"Initializing ","初始化":"initialize ",
"正在掃描":"Scanning ","正在刪除":"Deleting ","正在追蹤":"Tracking ",
"最小化到":"Minimize To ","靈敏度":"Sensitivity ","正在檢查":"Checking ",
"確定要":"Sure Want To ","引擎靈敏度":"Sensitivity ","更新":"Update ",
@@ -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"
}
+552 -117
View File
@@ -1,6 +1,8 @@
import os, yara, numpy, onnxruntime
import ctypes, ctypes.wintypes, pefile
import os, yara, time, numpy, base64, requests, pefile, math
import ctypes, ctypes.wintypes, hashlib, onnxruntime
from PIL import Image
from io import BytesIO
####################################################################################################
@@ -44,167 +46,600 @@ 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, 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])
label = rule_name.split("_")[0]
level = rule_name.split("_")[-1]
return f"{label}:WinPE/Unknown.A!rb", level
return False, False
except Exception:
return False, False
####################################################################################################
class model_scanner:
class cnn_scanner:
def __init__(self):
self.models = {}
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 = {
"Pefile/General", "Script/General"}
self.models = []
self.labels = ["White:WinPE/Unknown", "General:WinPE/Unknown"]
self.detect_set = {"General:WinPE/Unknown"}
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.models[file] = onnxruntime.InferenceSession(file)
session = onnxruntime.InferenceSession(file, providers=['CPUExecutionProvider'])
self.models.append(session)
except Exception:
return False
def model_scan(self, file_path):
####################################################################################################
def model_scan(self, file_path, full_output=False):
if not self.models:
return (False, False) if not full_output else ([], str(file_path), None)
data = self.get_data(file_path)
if not data:
return (False, False) if not full_output else ([], str(file_path), None)
image = self.preprocess_image(data, self.resize)
if not image:
return (False, False) if not full_output else ([], str(file_path), None)
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 = []
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_prob = float(probs[0][0]) if hasattr(probs[0], '__len__') else float(probs[0])
except Exception:
continue
is_malicious = pred_prob > 0.5
idx = 1 if is_malicious else 0
label = self.labels[idx]
conf = pred_prob if is_malicious else (1.0 - pred_prob)
conf = round(conf * 100, 2)
if full_output:
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 = (f"{label}.{int(conf)}!dl", 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)
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()
img.save(buf, format='PNG')
return base64.b64encode(buf.getvalue()).decode()
def preprocess_image(self, data, size, channels=1):
width, height = size
wah = int(numpy.ceil(numpy.sqrt(len(data) / channels)))
arr = numpy.frombuffer(data, dtype=numpy.uint8)
imgbuf = numpy.zeros(wah * wah * channels, dtype=numpy.uint8)
imgbuf[:len(arr)] = arr
image = Image.fromarray(imgbuf.reshape((wah, wah)), 'L')
return image.resize((width, height), Image.Resampling.NEAREST)
def get_data(self, file_path):
try:
model = next(iter(self.models.values()))
shape = model.get_inputs()[0].shape
channels = shape[-1] if shape[-1] in (1, 3) else (shape[1] if shape[1] in (1, 3) else 1)
with open(file_path, 'rb') as f:
return f.read()
except Exception:
return None
file_sections = self.get_type(file_path)
if not file_sections:
return False, False
####################################################################################################
batch_images = [self.preprocess_image(data, self.resize, channels) for data in file_sections.values()]
arr = numpy.stack([numpy.asarray(img).astype('float32') / 255.0 for img in batch_images])
if arr.ndim == 3:
arr = arr[..., None]
if shape[-1] in (1, 3):
model_input = arr
elif shape[1] in (1, 3):
model_input = arr.transpose(0, 3, 1, 2)
else:
return False, False
class pe_scanner:
def __init__(self):
self.model = None
self.input_name = None
self.signer = sign_scanner()
self.signer.init_windll(["wintrust"])
self.SCHEMA = [
"FileEntropy", "IsExe", "IsDll", "IsDriver", "Is64Bit", "Machine", "Magic",
"TimeDateStamp", "CheckSum", "ImageBase", "SizeOfImage", "SizeOfHeaders",
"Characteristics", "DllCharacteristics", "Subsystem", "LoaderFlags",
"MajorLinkerVersion", "MinorLinkerVersion", "SizeOfCode",
"SizeOfInitializedData", "SizeOfUninitializedData", "AddressOfEntryPoint",
"BaseOfCode", "SectionAlignment", "FileAlignment",
"MajorOperatingSystemVersion", "MinorOperatingSystemVersion",
"MajorImageVersion", "MinorImageVersion",
"MajorSubsystemVersion", "MinorSubsystemVersion",
"SizeOfStackReserve", "SizeOfStackCommit", "SizeOfHeapReserve", "SizeOfHeapCommit",
"NumberOfSections", "NumberOfRvaAndSizes", "PointerToSymbolTable", "NumberOfSymbols",
"SizeOfOptionalHeader",
"TextSection", "TextSizeRatio", "DataSection", "DataSizeRatio",
"RsrcSection", "RsrcSizeRatio", "SectionCount", "ExecutableSections",
"WritableSections", "ReadableSections", "SectionException",
"IconCount", "ApiCount", "ExportCount", "DebugCount", "ExceptionCount",
"FileDescriptionLength", "FileVersionLength", "ProductNameLength",
"ProductVersionLength", "CompanyNameLength", "LegalCopyrightLength",
"CommentsLength", "InternalNameLength", "LegalTrademarksLength",
"SpecialBuildLength", "PrivateBuildLength",
"TrustSigned", "IsDebug", "IsPatched", "IsPrivateBuild", "IsPreRelease",
"IsSpecialBuild", "IsAdmin", "IsInstall", "HasTlsCallbacks",
"HasInvalidTimestamp", "HasRelocationDirectory", "HasPacked", "FileTimeException",
"_CorExeMain", "_CorDllMain",
"GetDC", "CreateDCW", "CreateDCA", "BitBlt", "StretchBlt", "CreateCompatibleDC",
"CreateCompatibleBitmap", "SelectObject", "DeleteDC", "DeleteObject", "GetDeviceCaps",
"GetSystemMetrics",
"SetWindowsHookExA", "SetWindowsHookExW", "UnhookWindowsHookEx",
"GetAsyncKeyState", "GetKeyState", "GetKeyboardState",
"MapVirtualKeyA", "MapVirtualKeyW", "MapVirtualKeyExA", "MapVirtualKeyExW",
"ToAscii", "ToAsciiEx", "ToUnicode", "ToUnicodeEx", "KeybdEvent", "SendInput",
"GetCursorPos", "SetCursorPos", "MouseEvent", "GetDoubleClickTime",
"GetCapture", "SetCapture",
"WaveInOpen", "WaveInClose", "WaveInStart", "WaveInStop",
"CapCreateCaptureWindowA", "CapCreateCaptureWindowW",
"OpenClipboard", "CloseClipboard", "GetClipboardData", "SetClipboardData",
"GetDesktopWindow", "GetForegroundWindow", "GetWindowDC", "GetWindowRect",
"GetClientRect", "PrintWindow", "SetWindowDisplayAffinity", "FindWindowA", "FindWindowW",
"EnumWindows", "EnumChildWindows",
"Direct3DCreate9", "D3D11CreateDevice", "GdipSaveImageToFile",
"CreateProcessA", "CreateProcessW", "CreateThread", "ResumeThread", "SuspendThread",
"OpenProcess", "TerminateProcess", "GetCurrentProcess", "GetCurrentProcessId",
"ExitProcess", "WinExec", "ShellExecuteA", "ShellExecuteW",
"CreateRemoteThread", "QueueUserAPC", "VirtualAlloc", "VirtualAllocEx",
"VirtualProtect", "VirtualProtectEx", "WriteProcessMemory", "ReadProcessMemory",
"NtUnmapViewOfSection", "SetThreadContext", "GetThreadContext", "Wow64SetThreadContext",
"ZwUnmapViewOfSection", "CreateFileMappingA", "CreateFileMappingW", "MapViewOfFile",
"UnmapViewOfSection",
"LoadLibraryA", "LoadLibraryW", "LoadLibraryExA", "LoadLibraryExW",
"GetProcAddress", "GetModuleHandleA", "GetModuleHandleW", "FreeLibrary",
"CreateFileA", "CreateFileW", "WriteFile", "ReadFile", "DeleteFileA", "DeleteFileW",
"CopyFileA", "CopyFileW", "MoveFileA", "MoveFileW", "FindFirstFileA", "FindNextFileA",
"GetTempPathA", "GetTempPathW", "GetTempFileNameA", "GetTempFileNameW",
"SetFileAttributesA", "SetFileAttributesW", "DeviceIoControl", "SetFileTime",
"RegOpenKeyExA", "RegOpenKeyExW", "RegSetValueExA", "RegSetValueExW",
"RegCreateKeyExA", "RegCreateKeyExW", "RegDeleteKeyA", "RegDeleteKeyW",
"RegEnumValueA", "RegEnumValueW", "RegQueryValueExA", "RegQueryValueExW",
"RegDeleteValueA", "RegDeleteValueW",
"OpenSCManagerA", "OpenSCManagerW", "CreateServiceA", "CreateServiceW",
"StartServiceA", "StartServiceW", "ControlService", "DeleteService",
"AdjustTokenPrivileges", "LookupPrivilegeValueA", "LookupPrivilegeValueW",
"OpenProcessToken", "NetUserAdd", "NetLocalGroupAddMembers",
"Socket", "Connect", "Send", "Recv", "WSAStartup", "gethostbyname", "getaddrinfo",
"WSAIoctl", "WSASocketA", "WSASocketW",
"URLDownloadToFileA", "URLDownloadToFileW",
"InternetOpenA", "InternetOpenW", "InternetConnectA", "InternetConnectW",
"InternetOpenUrlA", "InternetOpenUrlW",
"HttpOpenRequestA", "HttpOpenRequestW", "HttpSendRequestA", "HttpSendRequestW",
"InternetReadFile", "DnsQuery_A", "DnsQuery_W",
"IsDebuggerPresent", "CheckRemoteDebuggerPresent", "OutputDebugStringA", "OutputDebugStringW",
"GetTickCount", "QueryPerformanceCounter", "Sleep", "GetSystemTimeAsFileTime",
"GetLocalTime", "GlobalMemoryStatus", "GetVersionExA", "GetVersionExW",
"GetComputerNameA", "GetComputerNameW", "GetUserNameA", "GetUserNameW",
"CryptAcquireContextA", "CryptAcquireContextW", "CryptCreateHash", "CryptHashData",
"CryptDeriveKey", "CryptEncrypt", "CryptDecrypt", "CryptDestroyKey", "CryptDestroyHash",
"CryptReleaseContext", "CryptGenKey", "CryptImportKey", "CryptExportKey",
"RtlDecompressBuffer", "ConnectNamedPipe", "PeekNamedPipe"
]
self.PACKERS = {
'upx', 'aspack', 'asprotect', 'pecompact', 'upack', 'fsg', 'mew',
'mpress', 'ezip', 'pklt', 'shrink', 'petite', 'telock',
'themida', 'winlicense', 'tmd', 'vmp', 'enigma', 'obsidium',
'pelock', 'exestealth', 'yoda', 'armadillo', 'zprotect',
'sforce', 'starforce', 'qihoo', 'wisevec', 'megastop',
}
self.INSTALLER_SIGS = [b"Nullsoft.NSIS", b"Inno Setup", b"7-Zip.7zip", b"InstallShield"]
self.SCHEMA_SET = set(self.SCHEMA)
input_name = model.get_inputs()[0].name
predictions = model.run(None, {input_name: model_input})[0]
####################################################################################################
label_scores = {label: [] for label in self.labels}
for pre_answers in predictions:
for k, score in enumerate(pre_answers):
label_scores[self.labels[k]].append(score)
label_percentage = {label: (sum(scores)/len(scores))*100 for label, scores in label_scores.items() if scores}
if not label_percentage:
return False, False
best_label, best_conf = max(label_percentage.items(), key=lambda x: x[1])
if best_label in self.detect:
return best_label, int(best_conf)
def load_path(self, path, callback=None):
for root, _, files in os.walk(path):
for file in files:
full_path = os.path.join(root, file)
if callback:
callback(full_path)
self.load_model(full_path)
def load_model(self, model_path):
if not os.path.exists(model_path) or not model_path.endswith('.onnx'):
return
try:
self.model = onnxruntime.InferenceSession(model_path, providers=['CPUExecutionProvider'])
self.input_name = self.model.get_inputs()[0].name
except Exception:
pass
####################################################################################################
def _safe_float(self, val):
try:
f = float(val)
if math.isinf(f) or math.isnan(f): return 0.0
return f
except:
return 0.0
def _calc_entropy(self, data):
if not data: return 0.0
arr = numpy.frombuffer(data, dtype=numpy.uint8)
counts = numpy.bincount(arr, minlength=256)
probs = counts[counts > 0] / len(arr)
return float(-numpy.sum(probs * numpy.log2(probs)))
####################################################################################################
def extract_features(self, file_path):
fts = {k: 0 for k in self.SCHEMA}
pe = None
try:
fsize = os.path.getsize(file_path)
if fsize == 0: return None
pe = pefile.PE(file_path, fast_load=True)
fts['TrustSigned'] = 1 if self.signer.sign_verify(file_path) else 0
fh = pe.FILE_HEADER
fts['Machine'] = fh.Machine
fts['NumberOfSections'] = fh.NumberOfSections
fts['TimeDateStamp'] = fh.TimeDateStamp
fts['PointerToSymbolTable'] = fh.PointerToSymbolTable
fts['NumberOfSymbols'] = fh.NumberOfSymbols
fts['SizeOfOptionalHeader'] = fh.SizeOfOptionalHeader
fts['Characteristics'] = fh.Characteristics
curr_ts = time.time()
fts['HasInvalidTimestamp'] = 1 if (fh.TimeDateStamp < 631152000 or fh.TimeDateStamp > curr_ts + 2592000) else 0
if hasattr(pe, 'OPTIONAL_HEADER'):
op = pe.OPTIONAL_HEADER
fts['Magic'] = op.Magic
fts['MajorLinkerVersion'] = op.MajorLinkerVersion
fts['MinorLinkerVersion'] = op.MinorLinkerVersion
fts['SizeOfCode'] = op.SizeOfCode
fts['SizeOfInitializedData'] = op.SizeOfInitializedData
fts['SizeOfUninitializedData'] = op.SizeOfUninitializedData
fts['AddressOfEntryPoint'] = op.AddressOfEntryPoint
fts['BaseOfCode'] = op.BaseOfCode
fts['ImageBase'] = op.ImageBase
fts['SectionAlignment'] = op.SectionAlignment
fts['FileAlignment'] = op.FileAlignment
fts['MajorOperatingSystemVersion'] = op.MajorOperatingSystemVersion
fts['MinorOperatingSystemVersion'] = op.MinorOperatingSystemVersion
fts['MajorImageVersion'] = op.MajorImageVersion
fts['MinorImageVersion'] = op.MinorImageVersion
fts['MajorSubsystemVersion'] = op.MajorSubsystemVersion
fts['MinorSubsystemVersion'] = op.MinorSubsystemVersion
fts['SizeOfImage'] = op.SizeOfImage
fts['SizeOfHeaders'] = op.SizeOfHeaders
fts['CheckSum'] = op.CheckSum
fts['Subsystem'] = op.Subsystem
fts['DllCharacteristics'] = op.DllCharacteristics
fts['SizeOfStackReserve'] = op.SizeOfStackReserve
fts['SizeOfStackCommit'] = op.SizeOfStackCommit
fts['SizeOfHeapReserve'] = op.SizeOfHeapReserve
fts['SizeOfHeapCommit'] = op.SizeOfHeapCommit
fts['LoaderFlags'] = op.LoaderFlags
fts['NumberOfRvaAndSizes'] = op.NumberOfRvaAndSizes
fts['Is64Bit'] = 1 if fh.Machine == 0x8664 else 0
fts['IsExe'] = 1 if pe.is_exe() else 0
fts['IsDll'] = 1 if pe.is_dll() else 0
fts['IsDriver'] = 1 if pe.is_driver() else 0
if len(op.DATA_DIRECTORY) > 9 and op.DATA_DIRECTORY[9].VirtualAddress > 0:
fts['HasTlsCallbacks'] = 1
if len(op.DATA_DIRECTORY) > 5 and op.DATA_DIRECTORY[5].Size > 0:
fts['HasRelocationDirectory'] = 1
pe.parse_sections(pe.FILE_HEADER.NumberOfSections)
file_data = pe.get_memory_mapped_image()
fts['FileEntropy'] = self._calc_entropy(file_data)
fts['SectionCount'] = len(pe.sections)
for section in pe.sections:
try:
name = section.Name.decode('ascii', 'ignore').strip('\x00')
except:
name = ""
s_data = section.get_data()
s_entropy = self._calc_entropy(s_data)
if any(p in name.lower() for p in self.PACKERS):
fts['HasPacked'] = 1
if section.Characteristics & 0x20000000:
fts['ExecutableSections'] += 1
if section.Characteristics & 0x80000000:
fts['WritableSections'] += 1
if section.Characteristics & 0x40000000:
fts['ReadableSections'] += 1
if section.SizeOfRawData + section.PointerToRawData > fsize:
fts['SectionException'] = 1
ratio = section.SizeOfRawData / fsize if fsize > 0 else 0
if name.startswith('.text'):
fts['TextSection'] = s_entropy
fts['TextSizeRatio'] = ratio
elif name.startswith('.data'):
fts['DataSection'] = s_entropy
fts['DataSizeRatio'] = ratio
elif name.startswith('.rsrc'):
fts['RsrcSection'] = s_entropy
fts['RsrcSizeRatio'] = ratio
if b"requireAdministrator" in s_data:
fts['IsAdmin'] = 1
for sig in self.INSTALLER_SIGS:
if sig in s_data:
fts['IsInstall'] = 1
break
pe.parse_data_directories(directories=[
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT'],
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXPORT'],
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_RESOURCE'],
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_DEBUG']
])
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
fts['ApiCount'] += 1
if not imp or not hasattr(imp, 'name') or not imp.name:
continue
try:
name = imp.name.decode('ascii', 'ignore')
if name in self.SCHEMA_SET:
fts[name] = 1
except:
pass
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
fts['ExportCount'] = len(pe.DIRECTORY_ENTRY_EXPORT.symbols)
if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):
for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:
if entry.id == 3 and hasattr(entry, 'directory'):
fts['IconCount'] = len(entry.directory.entries)
break
if hasattr(pe, 'DIRECTORY_ENTRY_DEBUG'):
fts['DebugCount'] = len(pe.DIRECTORY_ENTRY_DEBUG)
return {k: self._safe_float(v) for k, v in fts.items()}
except Exception:
return None
finally:
if pe: pe.close()
####################################################################################################
def pe_scan(self, file_path):
if not self.model:
return False, False
try:
data = self.extract_features(file_path)
if not data:
return False, False
vec = numpy.array(
[data.get(feat, 0.0) for feat in self.SCHEMA],
dtype=numpy.float32
).reshape(1, -1)
outputs = self.model.run(None, {self.input_name: vec})
result = outputs[1]
prob = 0.0
if isinstance(result, list):
prob = float(result[0].get(1, 0.0))
score = int(prob * 100)
if prob > 0.5:
return f"General:WinPE/Unknown.{score}!ml", score
return False, False
except Exception:
return False, False
def preprocess_image(self, file_data, size, channels=1):
width, height = size
wah = int(numpy.ceil(numpy.sqrt(len(file_data) / channels)))
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')
return image.resize((width, height), Image.Resampling.NEAREST)
class cloud_scanner:
def __init__(self):
pass
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 get_type(self, file_path):
match_data = {}
if not os.path.splitext(file_path)[-1].lower() in self.suffix:
return match_data
def calc_hash(self, file_path, block_size=65536):
try:
with pefile.PE(file_path, fast_load=True) as pe:
sec = pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_SECURITY']]
if bool(sec.VirtualAddress and sec.Size):
return {}
for section in pe.sections:
name = section.Name.rstrip(b'\x00').decode('latin1').lower()
if section.Characteristics & 0x00000020:
match_data[name] = section.get_data()
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 ""
except pefile.PEFormatError:
with open(file_path, 'rb') as f:
file_content = f.read()
if self.is_text_file(file_content):
match_data[os.path.splitext(file_path)[-1].lower()] = file_content
return match_data
####################################################################################################
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 f"General:WinPE/Unknown.{score}!cl"
except Exception:
pass
return False
+49 -43
View File
@@ -363,6 +363,7 @@ class Ui_main_window(object):
self.english_switch.setLayoutDirection(Qt.LeftToRight)
self.english_switch.setStyleSheet(u"QRadioButton { background-color: transparent; color: rgb(0, 0, 0); }\n"
"")
self.english_switch.setChecked(True)
self.extension_widget = QWidget(self.setting_window)
self.extension_widget.setObjectName(u"extension_widget")
self.extension_widget.setGeometry(QRect(30, 100, 750, 80))
@@ -463,6 +464,7 @@ class Ui_main_window(object):
self.white_switch.setLayoutDirection(Qt.LeftToRight)
self.white_switch.setStyleSheet(u"QRadioButton { background-color: transparent; color: rgb(0, 0, 0); }\n"
"")
self.white_switch.setChecked(True)
self.cloud_widget = QWidget(self.setting_window)
self.cloud_widget.setObjectName(u"cloud_widget")
self.cloud_widget.setGeometry(QRect(30, 180, 750, 80))
@@ -488,18 +490,19 @@ class Ui_main_window(object):
self.cloud_text.setScaledContents(False)
self.cloud_text.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter)
self.cloud_text.setWordWrap(False)
self.cloud_button = QPushButton(self.cloud_widget)
self.cloud_button.setObjectName(u"cloud_button")
self.cloud_button.setGeometry(QRect(660, 20, 80, 30))
sizePolicy1.setHeightForWidth(self.cloud_button.sizePolicy().hasHeightForWidth())
self.cloud_button.setSizePolicy(sizePolicy1)
self.cloud_button.setFont(font)
self.cloud_button.setFocusPolicy(Qt.StrongFocus)
self.cloud_button.setLayoutDirection(Qt.LeftToRight)
self.cloud_button.setStyleSheet(u"QPushButton { background-color: rgb(235, 235, 235); color: rgb(0, 0, 0); border-radius: 10px; } QPushButton:hover { background-color: rgb(240, 240, 240); }\n"
self.cloud_switch = QPushButton(self.cloud_widget)
self.cloud_switch.setObjectName(u"cloud_switch")
self.cloud_switch.setGeometry(QRect(660, 20, 80, 30))
sizePolicy1.setHeightForWidth(self.cloud_switch.sizePolicy().hasHeightForWidth())
self.cloud_switch.setSizePolicy(sizePolicy1)
self.cloud_switch.setFont(font)
self.cloud_switch.setFocusPolicy(Qt.StrongFocus)
self.cloud_switch.setLayoutDirection(Qt.LeftToRight)
self.cloud_switch.setStyleSheet(u"QPushButton { background-color: rgb(235, 235, 235); color: rgb(0, 0, 0); border-radius: 10px; } QPushButton:hover { background-color: rgb(240, 240, 240); } QPushButton:checked { background-color: rgb(210, 255, 210); } QPushButton:checked:hover { background-color: rgb(220, 255, 220); }\n"
"")
self.cloud_button.setIconSize(QSize(16, 16))
self.cloud_button.setCheckable(False)
self.cloud_switch.setIconSize(QSize(16, 16))
self.cloud_switch.setCheckable(True)
self.cloud_switch.setChecked(True)
self.reset_widget = QWidget(self.setting_window)
self.reset_widget.setObjectName(u"reset_widget")
self.reset_widget.setGeometry(QRect(30, 260, 750, 80))
@@ -1413,10 +1416,10 @@ class Ui_main_window(object):
self.blank_window.raise_()
self.tool_window.raise_()
self.taskmgr_window.raise_()
self.setting_window.raise_()
self.home_window.raise_()
self.navigate_window.raise_()
self.options_window.raise_()
self.setting_window.raise_()
self.retranslateUi(main_window)
@@ -1437,8 +1440,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))
@@ -1460,7 +1463,7 @@ class Ui_main_window(object):
self.white_switch.setText(QCoreApplication.translate("main_window", u"\u767d\u8272\u4e3b\u984c", None))
self.cloud_title.setText(QCoreApplication.translate("main_window", u"\u96f2\u7aef\u670d\u52d9", None))
self.cloud_text.setText(QCoreApplication.translate("main_window", u"\u6b64\u9078\u9805\u53ef\u4ee5\u4e0a\u5831\u96f2\u7aef\u5f15\u64ce", None))
self.cloud_button.setText(QCoreApplication.translate("main_window", u"\u9078\u64c7", None))
self.cloud_switch.setText(QCoreApplication.translate("main_window", u"\u958b\u555f", None))
self.reset_title.setText(QCoreApplication.translate("main_window", u"\u91cd\u7f6e\u9078\u9805", None))
self.reset_text.setText(QCoreApplication.translate("main_window", u"\u6b64\u9078\u9805\u53ef\u4ee5\u91cd\u7f6e\u6240\u6709\u8a2d\u5b9a", None))
self.reset_button.setText(QCoreApplication.translate("main_window", u"\u9078\u64c7", None))
@@ -1477,39 +1480,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.5',
version='3.4.0',
company_name="PYAS Security",
file_description="Python Antivirus Software",
internal_name="PYAS",
+165
View File
@@ -0,0 +1,165 @@
#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;
typedef struct _RULE_NODE {
struct _RULE_NODE* Next;
UNICODE_STRING Pattern;
} RULE_NODE, * PRULE_NODE;
extern DRIVER_DATA GlobalData;
//
// Rule Lists Externs (Added for Exception Path support)
//
extern PRULE_NODE g_RegistryBlockList;
extern PRULE_NODE g_RegistryTrustedList;
extern PRULE_NODE g_ProcessTrustedPaths;
extern PRULE_NODE g_ProcessExploitable;
extern PRULE_NODE g_FileProtectedPaths;
extern PRULE_NODE g_FileExceptionPaths; // [Added] Exception List
extern PRULE_NODE g_FileRansomExts;
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 ProtectFile_SetSecurity(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();
NTSTATUS LoadRulesFromDisk(PUNICODE_STRING RegistryPath);
VOID UnloadRules();
VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo);
NTSTATUS GetProcessImageName(HANDLE ProcessId, PUNICODE_STRING* ImageName);
BOOLEAN IsProcessTrusted(HANDLE ProcessId);
BOOLEAN IsCriticalSystemProcess(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 WriteBuffer, ULONG WriteLength, 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);
}
-310
View File
@@ -1,310 +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 FileProtectDispatch(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();
{
NTSTATUS ps = InitProcessProtect();
if (!NT_SUCCESS(ps)) {
CHAR b[64] = { 0 };
RtlStringCchPrintfA(b, RTL_NUMBER_OF(b), "PROC_INIT | 0x%08X", ps);
SendPipeLog(b, strlen(b));
}
else {
static CHAR ok[] = "PROC_INIT | 0x00000000";
SendPipeLog(ok, sizeof(ok) - 1);
}
}
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;
}
}
+155
View File
@@ -0,0 +1,155 @@
#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) {
if (!(Flags & FLTFL_FILTER_UNLOAD_MANDATORY)) {
ExAcquireFastMutex(&GlobalData.PortMutex);
BOOLEAN IsConnected = (GlobalData.ClientPort != NULL);
ExReleaseFastMutex(&GlobalData.PortMutex);
if (IsConnected) {
return STATUS_FLT_DO_NOT_DETACH;
}
}
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
UninitializeRegistryProtection();
UninitializeProcessProtection();
UnloadRules(); // Release JSON rules memory
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_SET_SECURITY, 0, ProtectFile_SetSecurity, 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) {
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 = LoadRulesFromDisk(RegistryPath);
if (!NT_SUCCESS(status)) {
// Optional: Fail load if rules missing, or continue with empty rules
// return status;
}
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);
}
-178
View File
@@ -1,178 +0,0 @@
#pragma once
#include <ntifs.h>
#include <ntstrsafe.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#define PIPE_NAME L"\\??\\pipe\\PYAS_Output_Pipe"
#define MAX_MBR_TARGETS 256
#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
extern POBJECT_TYPE* PsJobType;
extern volatile LONG g_LogWorkCount;
extern BOOLEAN g_Unloading;
extern KEVENT g_LogDrainEvent;
extern PDEVICE_OBJECT g_MbrFilterTargets[MAX_MBR_TARGETS];
extern ULONG g_MbrFilterCount;
extern KSPIN_LOCK g_ProtectLock;
extern LARGE_INTEGER g_CmRegHandle;
extern POBJECT_TYPE* IoDriverObjectType;
extern POBJECT_TYPE* IoFileObjectType;
extern FAST_MUTEX HookMutex;
extern PDRIVER_OBJECT DiskDrvObj;
extern PCSTR PsGetProcessImageFileName(PEPROCESS Process);
extern EX_RUNDOWN_REF g_Rundown;
extern PDEVICE_OBJECT g_GuardDevice;
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);
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 FileProtectDispatch(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);
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath);
-62
View File
@@ -1,62 +0,0 @@
#include <ntifs.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);
}
+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>
+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;
}
-323
View File
@@ -1,323 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static BOOLEAN GetFilePathFromFileObject(PFILE_OBJECT fo, PUNICODE_STRING out)
{
if (!fo || !out || !out->Buffer || out->MaximumLength == 0)
return FALSE;
out->Length = 0;
if (fo->DeviceObject && fo->FileName.Buffer && fo->FileName.Length) {
ULONG need = 0;
NTSTATUS s = ObQueryNameString(fo->DeviceObject, NULL, 0, &need);
if (s == STATUS_INFO_LENGTH_MISMATCH && need > 0) {
POBJECT_NAME_INFORMATION oni = (POBJECT_NAME_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, need, 'nOmD');
if (oni) {
if (NT_SUCCESS(ObQueryNameString(fo->DeviceObject, oni, need, &need)) && oni->Name.Buffer && oni->Name.Length) {
ULONG total = oni->Name.Length + fo->FileName.Length;
if (total + sizeof(WCHAR) <= out->MaximumLength) {
RtlCopyMemory(out->Buffer, oni->Name.Buffer, oni->Name.Length);
RtlCopyMemory((PUCHAR)out->Buffer + oni->Name.Length, fo->FileName.Buffer, fo->FileName.Length);
out->Length = (USHORT)total;
out->Buffer[total / sizeof(WCHAR)] = 0;
ExFreePool2(oni, 'nOmD', NULL, 0);
return TRUE;
}
}
ExFreePool2(oni, 'nOmD', NULL, 0);
}
}
}
HANDLE hFile = NULL;
OBJECT_ATTRIBUTES oa = { 0 };
IO_STATUS_BLOCK iosb;
InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
if (!NT_SUCCESS(ObOpenObjectByPointer(fo, OBJ_KERNEL_HANDLE, NULL, FILE_READ_ATTRIBUTES, *IoFileObjectType, KernelMode, &hFile)))
return FALSE;
ULONG buflen = sizeof(FILE_NAME_INFORMATION) + 2048 * sizeof(WCHAR);
PFILE_NAME_INFORMATION pfi = (PFILE_NAME_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, buflen, 'nIIF');
if (!pfi) {
ZwClose(hFile);
return FALSE;
}
RtlZeroMemory(pfi, buflen);
NTSTATUS st = ZwQueryInformationFile(hFile, &iosb, pfi, buflen, FileNormalizedNameInformation);
if (NT_SUCCESS(st) && pfi->FileNameLength > 0 && pfi->FileNameLength + sizeof(WCHAR) <= out->MaximumLength) {
RtlCopyMemory(out->Buffer, pfi->FileName, pfi->FileNameLength);
out->Length = (USHORT)pfi->FileNameLength;
out->Buffer[out->Length / sizeof(WCHAR)] = 0;
ExFreePool2(pfi, 'nIIF', NULL, 0);
ZwClose(hFile);
return TRUE;
}
ExFreePool2(pfi, 'nIIF', NULL, 0);
ZwClose(hFile);
return FALSE;
}
static BOOLEAN WantDelete(PIRP Irp, PIO_STACK_LOCATION s)
{
if (s->MajorFunction != IRP_MJ_SET_INFORMATION)
return FALSE;
FILE_INFORMATION_CLASS c = s->Parameters.SetFile.FileInformationClass;
if (c == FileDispositionInformation) {
PFILE_DISPOSITION_INFORMATION di = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
return di && di->DeleteFile;
}
if (c == FileDispositionInformationEx) {
PFILE_DISPOSITION_INFORMATION_EX dx = (PFILE_DISPOSITION_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
return dx && (dx->Flags & FILE_DISPOSITION_DELETE);
}
return FALSE;
}
static BOOLEAN WantRename(PIRP Irp, PIO_STACK_LOCATION s)
{
if (s->MajorFunction != IRP_MJ_SET_INFORMATION)
return FALSE;
FILE_INFORMATION_CLASS c = s->Parameters.SetFile.FileInformationClass;
if (c == FileRenameInformation || c == FileRenameInformationEx)
return Irp->AssociatedIrp.SystemBuffer != NULL;
return FALSE;
}
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 VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
{
ANSI_STRING a1 = { 0 }, a2 = { 0 };
CHAR buf[1024] = { 0 };
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);
}
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 FileProtectDispatch(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;
BOOLEAN isWrite = (s->MajorFunction == IRP_MJ_WRITE);
BOOLEAN isDeleteReq = WantDelete(Irp, s);
BOOLEAN isRenameReq = WantRename(Irp, s);
BOOLEAN canQuery = (KeGetCurrentIrql() == PASSIVE_LEVEL);
WCHAR eb[512] = { 0 };
UNICODE_STRING exe = { 0 };
exe.Buffer = eb;
exe.MaximumLength = sizeof(eb);
if (canQuery) {
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 (canQuery && QueryDevName(lower, &dev)) {
if (MatchBlockFile(&dev))
hit = TRUE;
}
else {
hit = TRUE;
}
if (!hit && s->FileObject && canQuery) {
WCHAR nb[512] = { 0 };
UNICODE_STRING n2 = { 0 };
n2.Buffer = nb;
n2.MaximumLength = sizeof(nb);
if (QueryDevName(s->FileObject->DeviceObject, &n2)) {
if (MatchBlockFile(&n2))
hit = TRUE;
}
}
if (!hit && s->MajorFunction == IRP_MJ_WRITE && s->FileObject && IsDASDRoot(s->FileObject))
hit = TRUE;
if (hit) {
blocked = TRUE;
if (canQuery) {
if (dev.Length == 0)
QueryDevName(lower, &dev);
LogAnsi3("BOOT_BLOCK", upid, &exe, dev.Length ? &dev : &exe);
}
}
}
}
if (!blocked && (isWrite || isDeleteReq || isRenameReq) && s->FileObject && canQuery) {
WCHAR pb[1024] = { 0 };
UNICODE_STRING path = { 0 };
path.Buffer = pb;
path.MaximumLength = sizeof(pb);
if (GetFilePathFromFileObject(s->FileObject, &path)) {
BOOLEAN hitFile = MatchBlockFile(&path);
BOOLEAN hitRansom = MatchBlockRansom(&path) && HasBlockedSuffix(&path);
if (hitFile || hitRansom) {
blocked = TRUE;
LogAnsi3(hitFile && !hitRansom ? "FILE_BLOCK" : "RANSOM_BLOCK", upid, &exe, &path);
}
}
else {
ULONG need = 0;
POBJECT_NAME_INFORMATION dev = NULL;
NTSTATUS qs2 = ObQueryNameString(s->FileObject->DeviceObject, NULL, 0, &need);
if (qs2 == STATUS_INFO_LENGTH_MISMATCH && need > 0) {
dev = (POBJECT_NAME_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, need, 'dOnF');
if (dev && NT_SUCCESS(ObQueryNameString(s->FileObject->DeviceObject, dev, need, &need)) && dev->Name.Buffer && dev->Name.Length) {
if (MatchBlockFile(&dev->Name)) {
blocked = TRUE;
UNICODE_STRING rule = { 0 };
rule.Buffer = GetMatchedBlockFileRule(&dev->Name);
rule.Length = rule.Buffer ? (USHORT)(wcslen(rule.Buffer) * sizeof(WCHAR)) : 0;
rule.MaximumLength = rule.Length;
LogAnsi3("FILE_BLOCK", upid, &exe, rule.Buffer ? &rule : &dev->Name);
}
}
if (dev)
ExFreePool2(dev, 'dOnF', NULL, 0);
}
}
}
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;
}
+288
View File
@@ -0,0 +1,288 @@
#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);
ULONG CreateDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;
BOOLEAN IsCreateAction = (CreateDisposition == FILE_CREATE ||
CreateDisposition == FILE_SUPERSEDE ||
CreateDisposition == FILE_OVERWRITE ||
CreateDisposition == FILE_OVERWRITE_IF ||
CreateDisposition == FILE_OPEN_IF);
if (IsHoneyToken(&FileName)) {
if (!Trusted) {
if ((Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE)) || IsCreateAction) {
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 | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | DELETE | WRITE_DAC | GENERIC_WRITE)) || IsCreateAction) {
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 (CheckProtectedPathRule(&nameInfo->Name)) {
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
if (CheckFileExtensionRule(&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_SetSecurity(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;
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;
}
SECURITY_INFORMATION SecurityInfo = Data->Iopb->Parameters.SetSecurity.SecurityInformation;
if (SecurityInfo & (OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) {
if (CheckProtectedPathRule(&nameInfo->Name)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
}
}
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(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;
}
-136
View File
@@ -1,136 +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 LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
{
ANSI_STRING a1 = { 0 }, a2 = { 0 };
CHAR buf[1024] = { 0 };
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);
}
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;
}
}
-190
View File
@@ -1,190 +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 VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
{
ANSI_STRING a1 = { 0 }, a2 = { 0 };
CHAR buf[1024] = { 0 };
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);
}
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));
}
-372
View File
@@ -1,372 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectRules.h"
#include "ProtectMatch.h"
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 (!s || !s->Buffer || s->Length == 0)
return FALSE;
size_t s_len = s->Length / sizeof(WCHAR);
for (SIZE_T i = 0; list[i]; ++i) {
wchar_t* pat = list[i];
size_t pat_len = wcslen(pat);
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
if (WildMatchN(s->Buffer, s_len, pat))
return TRUE;
}
else {
if (s_len == pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
return TRUE;
if (s_len > pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0)
return TRUE;
if (s_len > pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
return TRUE;
}
}
return FALSE;
}
static wchar_t* MatchListGetRule(PUNICODE_STRING s, wchar_t** list)
{
if (!s || !s->Buffer || s->Length == 0)
return 0;
size_t s_len = s->Length / sizeof(WCHAR);
for (SIZE_T i = 0; list[i]; ++i) {
wchar_t* pat = list[i];
size_t pat_len = wcslen(pat);
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
if (WildMatchN(s->Buffer, s_len, pat))
return pat;
}
else {
if (s_len == pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
return pat;
if (s_len > pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0)
return pat;
if (s_len > pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
return pat;
}
}
return 0;
}
static __forceinline BOOLEAN USOK(PUNICODE_STRING s)
{
return s && s->Buffer && s->Length;
}
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++) {
SIZE_T j = 0;
for (; j < m; j++) {
WCHAR a = s[i + j], b = sub[j];
if (a >= L'A' && a <= L'Z') a += 32;
if (b >= L'A' && b <= L'Z') b += 32;
if (a != b) break;
}
if (j == m)
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);
if (n < m)
return FALSE;
return _wcsnicmp(s->Buffer + (n - m), name, m) == 0;
}
BOOLEAN IsRegistryBlock(PUNICODE_STRING key, PUNICODE_STRING valueName, PUNICODE_STRING exe)
{
if (USOK(key)) {
size_t klen0 = key->Length / sizeof(WCHAR);
if (WildMatchN(key->Buffer, klen0, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\**"))
return FALSE;
}
if (USOK(exe)) {
if (IsWhitelist(exe))
return FALSE;
}
if (USOK(exe) && USOK(key)) {
size_t elen = exe->Length / sizeof(WCHAR);
size_t klen = key->Length / sizeof(WCHAR);
if (((elen >= 12 && _wcsnicmp(exe->Buffer + elen - 12, L"services.exe", 12) == 0) ||
(elen >= 11 && _wcsnicmp(exe->Buffer + elen - 11, L"svchost.exe", 11) == 0) ||
(elen >= 6 && _wcsnicmp(exe->Buffer + elen - 6, L"sc.exe", 6) == 0))) {
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**"))
return FALSE;
}
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)) {
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Internet Settings\\ZoneMap") ||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Internet Settings\\ZoneMap\\**") ||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Notifications\\Data") ||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Notifications\\Data\\**"))
return FALSE;
}
if ((elen >= 11 && _wcsnicmp(exe->Buffer + elen - 11, L"msiexec.exe", 11) == 0) ||
(elen >= 20 && _wcsnicmp(exe->Buffer + elen - 20, L"TrustedInstaller.exe", 20) == 0)) {
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Installer\\**") ||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Uninstall\\**") ||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**"))
return FALSE;
}
if (elen >= 12 && _wcsnicmp(exe->Buffer + elen - 12, L"schtasks.exe", 12) == 0) {
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\**"))
return FALSE;
}
}
if (USOK(key)) {
if (MatchBlockReg(key))
return TRUE;
}
if (USOK(valueName)) {
SIZE_T n = valueName->Length / sizeof(WCHAR);
for (SIZE_T i = 0; i < (SIZE_T)-1 && g_BlockReg[i]; ++i) {
wchar_t* pat = g_BlockReg[i];
if (wcschr(pat, L'\\') || wcschr(pat, L'*') || wcschr(pat, L'?'))
continue;
size_t m = wcslen(pat);
if (n == m && _wcsnicmp(valueName->Buffer, pat, m) == 0)
return TRUE;
}
}
return FALSE;
}
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath)
{
PEPROCESS process = NULL;
NTSTATUS status = PsLookupProcessByProcessId(pid, &process);
if (!NT_SUCCESS(status))
return FALSE;
HANDLE h = NULL;
status = ObOpenObjectByPointer(process, OBJ_KERNEL_HANDLE, NULL, PROCESS_QUERY_LIMITED_INFORMATION, *PsProcessType, KernelMode, &h);
if (!NT_SUCCESS(status)) {
ObDereferenceObject(process);
return FALSE;
}
ULONG len = 0;
status = ZwQueryInformationProcess(h, ProcessImageFileName, NULL, 0, &len);
if (status != STATUS_INFO_LENGTH_MISMATCH || len == 0) {
ZwClose(h);
ObDereferenceObject(process);
return FALSE;
}
PVOID buf = ExAllocatePool2(POOL_FLAG_NON_PAGED, len, 'iPgN');
if (!buf) {
ZwClose(h);
ObDereferenceObject(process);
return FALSE;
}
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;
ExFreePool2(buf, 'iPgN', NULL, 0);
ZwClose(h);
ObDereferenceObject(process);
return TRUE;
}
}
ExFreePool2(buf, 'iPgN', NULL, 0);
ZwClose(h);
ObDereferenceObject(process);
return FALSE;
}
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;
SIZE_T n = s->Length / sizeof(WCHAR);
for (SIZE_T i = 0; g_Blocksuffix[i]; ++i) {
wchar_t* ext = g_Blocksuffix[i];
SIZE_T m = wcslen(ext);
if (n >= m && _wcsnicmp(s->Buffer + (n - m), ext, m) == 0)
return TRUE;
}
return FALSE;
}
BOOLEAN MatchRemoteSuspectBin(PUNICODE_STRING img)
{
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")) {
BOOLEAN need = FALSE, http = FALSE;
for (SIZE_T i = 0; g_RemoteCmdRegsvr32Need[i]; ++i)
if (StrStrIW(s, g_RemoteCmdRegsvr32Need[i])) {
need = TRUE;
break;
}
for (SIZE_T i = 0; g_RemoteCmdIndicatorsHttp[i]; ++i)
if (StrStrIW(s, g_RemoteCmdIndicatorsHttp[i])) {
http = TRUE;
break;
}
if (need && 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)
{
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;
BOOLEAN isClr = StrStrIW(s, L"\\clr.dll") || StrStrIW(s, L"\\mscorwks.dll");
if (!isClr)
return FALSE;
if (!StrStrIW(s, L"\\Windows\\Microsoft.NET\\"))
return TRUE;
if (!StrStrIW(s, L"\\Framework\\") && !StrStrIW(s, L"\\Framework64\\"))
return TRUE;
return FALSE;
}
-22
View File
@@ -1,22 +0,0 @@
#pragma once
#include <ntifs.h>
wchar_t* GetMatchedBlockRegRule(PUNICODE_STRING s);
wchar_t* GetMatchedBlockFileRule(PUNICODE_STRING s);
BOOLEAN IsWhitelist(PUNICODE_STRING s);
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath);
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);
-224
View File
@@ -1,224 +0,0 @@
#include <ntifs.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;
typedef struct _OBCTX {
POBJECT_TYPE ProcessType;
POBJECT_TYPE ThreadType;
}OBCTX, * POBCTX;
static PVOID g_PsSetProcessProtection = NULL;
static BOOLEAN g_ProcNotifyEnabled = FALSE;
static PVOID g_ObCookie = NULL;
static OBCTX g_ObCtx = { 0 };
static HANDLE g_ProtectedPid = NULL;
static PWCH g_ObAltitudeBuf = NULL;
static BOOLEAN IsProcNameEq(PEPROCESS p, PCSTR name)
{
PCSTR img = PsGetProcessImageFileName(p);
if (!img || !name)
return FALSE;
ANSI_STRING a = { 0 }, b = { 0 };
RtlInitAnsiString(&a, img);
RtlInitAnsiString(&b, name);
return RtlEqualString(&a, &b, TRUE) ? TRUE : FALSE;
}
static NTSTATUS SetPPL31(PEPROCESS p)
{
if (!g_PsSetProcessProtection)
return STATUS_PROCEDURE_NOT_FOUND;
PS_PROTECTION pr = { 0 };
pr.Level = 0x31;
((VOID(NTAPI*)(PEPROCESS, PS_PROTECTION))g_PsSetProcessProtection)(p, pr);
return STATUS_SUCCESS;
}
static VOID LogSet(HANDLE pid, NTSTATUS st)
{
CHAR b[128] = { 0 };
RtlStringCchPrintfA(b, RTL_NUMBER_OF(b), "PROC_PPL_SET | %u | 0x31 | 0x%08X", (ULONG)(ULONG_PTR)pid, st);
SendPipeLog(b, strlen(b));
}
static VOID UpdateProtectedPid(HANDLE pid)
{
InterlockedExchangePointer((PVOID*)&g_ProtectedPid, pid);
}
static VOID BootstrapExisting(VOID)
{
typedef PEPROCESS(NTAPI* PFN_PsGetNextProcess)(PEPROCESS);
UNICODE_STRING n = RTL_CONSTANT_STRING(L"PsGetNextProcess");
PFN_PsGetNextProcess fp = (PFN_PsGetNextProcess)MmGetSystemRoutineAddress(&n);
if (!fp)
return;
PEPROCESS p = fp(NULL);
while (p) {
if (IsProcNameEq(p, "PYAS.exe")) {
HANDLE pid = PsGetProcessId(p);
NTSTATUS s = SetPPL31(p);
UpdateProtectedPid(pid);
LogSet(pid, s);
}
PEPROCESS nx = fp(p);
ObDereferenceObject(p);
p = nx;
}
}
static VOID StripProcessAccess(POB_PRE_OPERATION_INFORMATION Info)
{
ACCESS_MASK d = PROCESS_TERMINATE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_SET_INFORMATION | PROCESS_SET_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME | PROCESS_DUP_HANDLE;
if (Info->Operation == OB_OPERATION_HANDLE_CREATE) {
Info->Parameters->CreateHandleInformation.DesiredAccess &= ~d;
}
else {
Info->Parameters->DuplicateHandleInformation.DesiredAccess &= ~d;
}
}
static VOID StripThreadAccess(POB_PRE_OPERATION_INFORMATION Info)
{
ACCESS_MASK d = THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_SET_CONTEXT | THREAD_IMPERSONATE | THREAD_DIRECT_IMPERSONATION;
if (Info->Operation == OB_OPERATION_HANDLE_CREATE) {
Info->Parameters->CreateHandleInformation.DesiredAccess &= ~d;
}
else {
Info->Parameters->DuplicateHandleInformation.DesiredAccess &= ~d;
}
}
static OB_PREOP_CALLBACK_STATUS ObPreOperation(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 (!ExAcquireRundownProtection(&g_Rundown))
return OB_PREOP_SUCCESS;
if (Info->ObjectType == g_ObCtx.ProcessType) {
PEPROCESS pe = (PEPROCESS)Info->Object;
HANDLE tpid = PsGetProcessId(pe);
if (g_ProtectedPid && tpid == g_ProtectedPid) {
if (PsGetCurrentProcessId() != g_ProtectedPid) StripProcessAccess(Info);
}
}
else if (Info->ObjectType == g_ObCtx.ThreadType) {
PETHREAD th = (PETHREAD)Info->Object;
HANDLE owner = PsGetThreadProcessId(th);
if (g_ProtectedPid && owner == g_ProtectedPid) {
if (PsGetCurrentProcessId() != g_ProtectedPid) StripThreadAccess(Info);
}
}
ExReleaseRundownProtection(&g_Rundown);
return OB_PREOP_SUCCESS;
}
static NTSTATUS InitObCallbacks(VOID)
{
g_ObCtx.ProcessType = *PsProcessType;
g_ObCtx.ThreadType = *PsThreadType;
static OB_OPERATION_REGISTRATION ops[2];
RtlZeroMemory(ops, sizeof(ops));
ops[0].ObjectType = PsProcessType;
ops[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
ops[0].PreOperation = ObPreOperation;
ops[1].ObjectType = PsThreadType;
ops[1].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
ops[1].PreOperation = ObPreOperation;
const WCHAR* altStatic = L"321000";
USHORT alen = (USHORT)(wcslen(altStatic) * sizeof(WCHAR));
g_ObAltitudeBuf = (PWCH)ExAllocatePool2(POOL_FLAG_NON_PAGED, alen + sizeof(WCHAR), 'tlaO');
if (!g_ObAltitudeBuf)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(g_ObAltitudeBuf, altStatic, alen);
g_ObAltitudeBuf[alen / sizeof(WCHAR)] = 0;
UNICODE_STRING alt = { 0 };
alt.Buffer = g_ObAltitudeBuf;
alt.Length = alen;
alt.MaximumLength = alen;
OB_CALLBACK_REGISTRATION reg = { 0 };
reg.Version = OB_FLT_REGISTRATION_VERSION;
reg.OperationRegistrationCount = 2;
reg.RegistrationContext = g_ObAltitudeBuf;
reg.Altitude = alt;
reg.OperationRegistration = ops;
NTSTATUS s = ObRegisterCallbacks(&reg, &g_ObCookie);
if (!NT_SUCCESS(s)) {
ExFreePool2(g_ObAltitudeBuf, 'tlaO', NULL, 0);
g_ObAltitudeBuf = NULL;
}
return s;
}
static VOID ProcessNotifyEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)
{
if (g_Unloading)
return;
if (!ExAcquireRundownProtection(&g_Rundown))
return;
if (CreateInfo) {
if (IsProcNameEq(Process, "PYAS.exe")) {
NTSTATUS s = SetPPL31(Process);
UpdateProtectedPid(ProcessId);
LogSet(ProcessId, s);
}
}
else {
if (g_ProtectedPid && ProcessId == g_ProtectedPid) UpdateProtectedPid(NULL);
}
ExReleaseRundownProtection(&g_Rundown);
}
NTSTATUS InitProcessProtect(VOID)
{
UNICODE_STRING n = RTL_CONSTANT_STRING(L"PsSetProcessProtection");
g_PsSetProcessProtection = MmGetSystemRoutineAddress(&n);
NTSTATUS s = InitObCallbacks();
if (!NT_SUCCESS(s))
return s;
s = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyEx, FALSE);
if (NT_SUCCESS(s))
g_ProcNotifyEnabled = TRUE;
BootstrapExisting();
return STATUS_SUCCESS;
}
VOID UninitProcessProtect(VOID)
{
if (g_ProcNotifyEnabled) {
PsSetCreateProcessNotifyRoutineEx(ProcessNotifyEx, TRUE);
g_ProcNotifyEnabled = FALSE;
}
if (g_ObCookie) {
ObUnRegisterCallbacks(g_ObCookie);
g_ObCookie = NULL;
}
if (g_ObAltitudeBuf) {
ExFreePool2(g_ObAltitudeBuf, 'tlaO', NULL, 0);
g_ObAltitudeBuf = NULL;
}
}
+140
View File
@@ -0,0 +1,140 @@
#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) ||
WildcardMatch(L"*\\Windows\\Microsoft.NET\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Common Files\\Microsoft Shared\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Program Files*\\*", 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;
}
}
-131
View File
@@ -1,131 +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;
}
static VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
{
ANSI_STRING a1 = { 0 }, a2 = { 0 };
CHAR buf[1024] = { 0 };
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);
}
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;
}
+253
View File
@@ -0,0 +1,253 @@
#include "DriverCommon.h"
LARGE_INTEGER Cookie;
static BOOLEAN IsBamRegistryPath(PCUNICODE_STRING KeyName) {
if (!KeyName || !KeyName->Buffer) return FALSE;
if (WildcardMatch(L"*\\Services\\bam\\*", KeyName->Buffer, KeyName->Length)) {
return TRUE;
}
return FALSE;
}
static BOOLEAN IsWriteAccess(ACCESS_MASK Access) {
if (Access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK |
DELETE | WRITE_DAC | WRITE_OWNER | GENERIC_WRITE)) {
return TRUE;
}
return FALSE;
}
static PWCHAR GetFullPath(PVOID RootObject, PUNICODE_STRING CompleteName, PULONG OutLength) {
PWCHAR Buffer = NULL;
ULONG TotalSize = 0;
PCUNICODE_STRING RootName = NULL;
BOOLEAN NeedFreeRootName = FALSE;
if (RootObject) {
NTSTATUS status = CmCallbackGetKeyObjectIDEx(&Cookie, RootObject, NULL, &RootName, 0);
if (NT_SUCCESS(status) && RootName) {
NeedFreeRootName = TRUE;
}
}
ULONG RootLen = (RootName && RootName->Buffer) ? RootName->Length : 0;
ULONG RelLen = (CompleteName && CompleteName->Buffer) ? CompleteName->Length : 0;
TotalSize = RootLen + sizeof(WCHAR) + RelLen + sizeof(WCHAR);
Buffer = (PWCHAR)PyasAllocate(TotalSize);
if (!Buffer) {
if (NeedFreeRootName) CmCallbackReleaseKeyObjectIDEx(RootName);
return NULL;
}
RtlZeroMemory(Buffer, TotalSize);
PWCHAR Current = Buffer;
if (RootLen > 0) {
RtlCopyMemory(Current, RootName->Buffer, RootLen);
Current += (RootLen / sizeof(WCHAR));
if (Current > Buffer && *(Current - 1) != L'\\') {
*Current = L'\\';
Current++;
}
}
if (RelLen > 0) {
if (RootLen > 0 && CompleteName->Buffer[0] == L'\\') {
RtlCopyMemory(Current, CompleteName->Buffer + 1, RelLen - sizeof(WCHAR));
}
else {
RtlCopyMemory(Current, CompleteName->Buffer, RelLen);
}
}
if (NeedFreeRootName) CmCallbackReleaseKeyObjectIDEx(RootName);
if (OutLength) *OutLength = (ULONG)wcslen(Buffer) * sizeof(WCHAR);
return Buffer;
}
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;
NTSTATUS status = STATUS_SUCCESS;
if (Class == RegNtPreCreateKey || Class == RegNtPreOpenKey || Class == RegNtPreOpenKeyEx) {
PVOID RootObject = NULL;
PUNICODE_STRING CompleteName = NULL;
ACCESS_MASK DesiredAccess = 0;
if (Class == RegNtPreCreateKey) {
REG_CREATE_KEY_INFORMATION* Info = (REG_CREATE_KEY_INFORMATION*)Argument2;
RootObject = Info->RootObject;
CompleteName = Info->CompleteName;
DesiredAccess = Info->DesiredAccess;
}
else {
REG_OPEN_KEY_INFORMATION* Info = (REG_OPEN_KEY_INFORMATION*)Argument2;
RootObject = Info->RootObject;
CompleteName = Info->CompleteName;
DesiredAccess = Info->DesiredAccess;
}
if (!IsWriteAccess(DesiredAccess)) {
return STATUS_SUCCESS;
}
ULONG PathLen = 0;
PWCHAR FullPathBuffer = GetFullPath(RootObject, CompleteName, &PathLen);
if (FullPathBuffer) {
UNICODE_STRING FullPath;
RtlInitUnicodeString(&FullPath, FullPathBuffer);
if (CheckRegistryRule(&FullPath)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, FullPath.Buffer, FullPath.Length);
status = STATUS_ACCESS_DENIED;
}
}
PyasFree(FullPathBuffer);
}
return status;
}
if (Class == RegNtPreDeleteKey) {
REG_DELETE_KEY_INFORMATION* Info = (REG_DELETE_KEY_INFORMATION*)Argument2;
PCUNICODE_STRING KeyName = NULL;
if (NT_SUCCESS(CmCallbackGetKeyObjectIDEx(&Cookie, Info->Object, NULL, &KeyName, 0))) {
if (KeyName) {
if (CheckRegistryRule(KeyName)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, KeyName->Buffer, KeyName->Length);
status = STATUS_ACCESS_DENIED;
}
}
CmCallbackReleaseKeyObjectIDEx(KeyName);
}
}
return status;
}
if (Class == RegNtPreSetValueKey) {
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))) {
if (KeyName && KeyName->Buffer) {
if (!IsBamRegistryPath(KeyName)) {
ULONG FullSize = KeyName->Length + sizeof(WCHAR) +
(Info->ValueName ? Info->ValueName->Length : 0) +
sizeof(WCHAR);
PWCHAR Buffer = (PWCHAR)PyasAllocate(FullSize);
if (Buffer) {
UNICODE_STRING FullPath;
FullPath.Buffer = Buffer;
FullPath.Length = 0;
FullPath.MaximumLength = (USHORT)FullSize;
RtlCopyUnicodeString(&FullPath, KeyName);
if (Info->ValueName && Info->ValueName->Length > 0) {
if (FullPath.Length > 0 && FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] != L'\\') {
RtlAppendUnicodeToString(&FullPath, L"\\");
}
RtlAppendUnicodeStringToString(&FullPath, Info->ValueName);
}
if (CheckRegistryRule(&FullPath)) {
HANDLE Pid = PsGetCurrentProcessId();
BOOLEAN IsCriticalReg = FALSE;
if (WildcardMatch(L"*\\MACHINE\\SAM*", FullPath.Buffer, FullPath.Length) ||
WildcardMatch(L"*\\MACHINE\\SECURITY*", FullPath.Buffer, FullPath.Length) ||
WildcardMatch(L"*\\MACHINE\\SYSTEM*", FullPath.Buffer, FullPath.Length) ||
WildcardMatch(L"*\\MACHINE\\BCD00000000*", FullPath.Buffer, FullPath.Length)) {
if (IsCriticalSystemProcess(Pid)) {
IsCriticalReg = TRUE;
}
}
if (!IsCriticalReg) {
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, FullPath.Buffer, FullPath.Length);
status = STATUS_ACCESS_DENIED;
}
}
}
PyasFree(Buffer);
}
}
CmCallbackReleaseKeyObjectIDEx(KeyName);
}
}
return status;
}
if (Class == RegNtPreDeleteValueKey) {
REG_DELETE_VALUE_KEY_INFORMATION* Info = (REG_DELETE_VALUE_KEY_INFORMATION*)Argument2;
PCUNICODE_STRING KeyName = NULL;
if (NT_SUCCESS(CmCallbackGetKeyObjectIDEx(&Cookie, Info->Object, NULL, &KeyName, 0))) {
if (KeyName && KeyName->Buffer) {
if (!IsBamRegistryPath(KeyName)) {
ULONG FullSize = KeyName->Length + sizeof(WCHAR) +
(Info->ValueName ? Info->ValueName->Length : 0) +
sizeof(WCHAR);
PWCHAR Buffer = (PWCHAR)PyasAllocate(FullSize);
if (Buffer) {
UNICODE_STRING FullPath;
FullPath.Buffer = Buffer;
FullPath.Length = 0;
FullPath.MaximumLength = (USHORT)FullSize;
RtlCopyUnicodeString(&FullPath, KeyName);
if (Info->ValueName && Info->ValueName->Length > 0) {
if (FullPath.Length > 0 && FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] != L'\\') {
RtlAppendUnicodeToString(&FullPath, L"\\");
}
RtlAppendUnicodeStringToString(&FullPath, Info->ValueName);
}
if (CheckRegistryRule(&FullPath)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, FullPath.Buffer, FullPath.Length);
status = STATUS_ACCESS_DENIED;
}
}
PyasFree(Buffer);
}
}
CmCallbackReleaseKeyObjectIDEx(KeyName);
}
}
return status;
}
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;
}
}
-96
View File
@@ -1,96 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static BOOLEAN g_RemoteNotifyEnabled = FALSE;
static VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
{
ANSI_STRING a1 = { 0 }, a2 = { 0 };
CHAR buf[1024] = { 0 };
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);
}
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;
}
}
-295
View File
@@ -1,295 +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*\\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
};
+791
View File
@@ -0,0 +1,791 @@
#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 = 10;
constexpr auto TRUST_CACHE_SIZE = 128;
constexpr auto TRUST_CACHE_TTL_SEC = 300;
typedef struct _RANSOM_TRACKER {
HANDLE ProcessId;
ULONG ActivityCount;
LARGE_INTEGER LastActivityTime;
} RANSOM_TRACKER, * PRANSOM_TRACKER;
typedef struct _TRUST_CACHE_ENTRY {
HANDLE ProcessId;
BOOLEAN IsTrusted;
LARGE_INTEGER CacheTime;
} TRUST_CACHE_ENTRY, * PTRUST_CACHE_ENTRY;
RANSOM_TRACKER RansomTrackers[MAX_TRACKERS];
TRUST_CACHE_ENTRY TrustCache[TRUST_CACHE_SIZE];
FAST_MUTEX TrustCacheLock;
static BOOLEAN g_CacheInitialized = FALSE;
ERESOURCE RuleLock;
PRULE_NODE g_RegistryBlockList = NULL;
PRULE_NODE g_RegistryTrustedList = NULL;
PRULE_NODE g_ProcessTrustedPaths = NULL;
PRULE_NODE g_ProcessExploitable = NULL;
PRULE_NODE g_FileProtectedPaths = NULL;
PRULE_NODE g_FileExceptionPaths = NULL;
PRULE_NODE g_FileRansomExts = NULL;
const PCWSTR Helper_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".docx", L".xlsx", L".pptx", L".pdf", L".wps",
L".apk", L".jar", L".class", L".db", L".sqlite"
};
static VOID FreeList(PRULE_NODE* Head) {
PRULE_NODE Current = *Head;
while (Current) {
PRULE_NODE Next = Current->Next;
if (Current->Pattern.Buffer) PyasFree(Current->Pattern.Buffer);
PyasFree(Current);
Current = Next;
}
*Head = NULL;
}
static VOID AddRule(PRULE_NODE* Head, PUNICODE_STRING RuleStr) {
if (!RuleStr || !RuleStr->Buffer) return;
PRULE_NODE Node = (PRULE_NODE)PyasAllocate(sizeof(RULE_NODE));
if (!Node) return;
SIZE_T Size = RuleStr->Length + sizeof(WCHAR);
Node->Pattern.Buffer = (PWCHAR)PyasAllocate(Size);
if (!Node->Pattern.Buffer) {
PyasFree(Node);
return;
}
RtlCopyMemory(Node->Pattern.Buffer, RuleStr->Buffer, RuleStr->Length);
Node->Pattern.Buffer[RuleStr->Length / sizeof(WCHAR)] = L'\0';
Node->Pattern.Length = RuleStr->Length;
Node->Pattern.MaximumLength = (USHORT)Size;
Node->Next = *Head;
*Head = Node;
}
static BOOLEAN HasSuffix(PCUNICODE_STRING String, PCWSTR Suffix) {
if (!String || !String->Buffer || !Suffix) return FALSE;
SIZE_T StringLenChars = String->Length / sizeof(WCHAR);
SIZE_T SuffixLenChars = 0;
while (Suffix[SuffixLenChars] != L'\0') {
SuffixLenChars++;
}
if (StringLenChars < SuffixLenChars) return FALSE;
PCWSTR Ptr = String->Buffer + (StringLenChars - SuffixLenChars);
for (SIZE_T i = 0; i < SuffixLenChars; i++) {
if (RtlDowncaseUnicodeChar(Ptr[i]) != RtlDowncaseUnicodeChar(Suffix[i])) {
return FALSE;
}
}
return 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 (String < StringEnd) {
if (*Pattern == L'*') {
mp = ++Pattern;
cp = String + 1;
}
else if (*Pattern == L'?' || (RtlDowncaseUnicodeChar(*Pattern) == RtlDowncaseUnicodeChar(*String))) {
Pattern++;
String++;
}
else if (mp) {
Pattern = mp;
String = cp++;
}
else {
return FALSE;
}
}
while (*Pattern == L'*') {
Pattern++;
}
return !*Pattern;
}
static ULONG ProcessJsonUnescape(PWCHAR Buffer, ULONG LengthChars) {
if (!Buffer || LengthChars == 0) return 0;
ULONG WriteIdx = 0;
ULONG ReadIdx = 0;
while (ReadIdx < LengthChars) {
if (Buffer[ReadIdx] == L'\\' && (ReadIdx + 1 < LengthChars)) {
WCHAR NextChar = Buffer[ReadIdx + 1];
if (NextChar == L'\\' || NextChar == L'"' || NextChar == L'/') {
Buffer[WriteIdx++] = NextChar;
ReadIdx += 2;
}
else if (NextChar == L'n') { Buffer[WriteIdx++] = L'\n'; ReadIdx += 2; }
else if (NextChar == L'r') { Buffer[WriteIdx++] = L'\r'; ReadIdx += 2; }
else if (NextChar == L't') { Buffer[WriteIdx++] = L'\t'; ReadIdx += 2; }
else {
Buffer[WriteIdx++] = Buffer[ReadIdx++];
}
}
else {
Buffer[WriteIdx++] = Buffer[ReadIdx++];
}
}
Buffer[WriteIdx] = L'\0';
return WriteIdx * sizeof(WCHAR);
}
static VOID SkipWhitespace(PCHAR* Ptr, PCHAR End) {
while (*Ptr < End) {
char c = **Ptr;
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
(*Ptr)++;
}
else {
break;
}
}
}
static VOID ParseAndLoadRules(PCHAR JsonContent, ULONG ContentLength, PCSTR KeyName, PRULE_NODE* ListHead) {
if (!JsonContent || !KeyName || !ListHead) return;
PCHAR Ptr = JsonContent;
PCHAR End = JsonContent + ContentLength;
SIZE_T KeyLen = 0;
while (KeyName[KeyLen] != '\0') KeyLen++;
while (Ptr < End) {
if (*Ptr == '"') {
if ((SIZE_T)(End - Ptr) > KeyLen && RtlCompareMemory(Ptr + 1, KeyName, KeyLen) == KeyLen) {
if (*(Ptr + 1 + KeyLen) == '"') {
Ptr += 1 + KeyLen + 1;
SkipWhitespace(&Ptr, End);
if (Ptr >= End || *Ptr != ':') continue;
Ptr++;
SkipWhitespace(&Ptr, End);
if (Ptr >= End || *Ptr != '[') continue;
Ptr++;
while (Ptr < End) {
SkipWhitespace(&Ptr, End);
if (Ptr >= End) break;
if (*Ptr == ']') {
Ptr++;
return;
}
if (*Ptr == '"') {
PCHAR StartQuote = ++Ptr;
while (Ptr < End) {
if (*Ptr == '"' && *(Ptr - 1) != '\\') break;
Ptr++;
}
if (Ptr < End && *Ptr == '"') {
ULONG UTF8Len = (ULONG)(Ptr - StartQuote);
if (UTF8Len > 0) {
ULONG WideSize = 0;
RtlUTF8ToUnicodeN(NULL, 0, &WideSize, StartQuote, UTF8Len);
if (WideSize > 0) {
PWCHAR WideBuffer = (PWCHAR)PyasAllocate(WideSize + sizeof(WCHAR));
if (WideBuffer) {
ULONG ResultSize = 0;
RtlUTF8ToUnicodeN(WideBuffer, WideSize, &ResultSize, StartQuote, UTF8Len);
ULONG FinalSize = ProcessJsonUnescape(WideBuffer, ResultSize / sizeof(WCHAR));
UNICODE_STRING Us;
Us.Buffer = WideBuffer;
Us.Length = (USHORT)FinalSize;
Us.MaximumLength = (USHORT)(WideSize + sizeof(WCHAR));
AddRule(ListHead, &Us);
PyasFree(WideBuffer);
}
}
}
Ptr++;
}
}
else if (*Ptr == ',') {
Ptr++;
}
else {
Ptr++;
}
}
return;
}
}
}
Ptr++;
}
}
NTSTATUS LoadRulesFromDisk(PUNICODE_STRING RegistryPath) {
NTSTATUS status = STATUS_SUCCESS;
HANDLE FileHandle = NULL;
IO_STATUS_BLOCK IoStatus = { 0 };
OBJECT_ATTRIBUTES oa = { 0 };
UNICODE_STRING ImagePathName;
OBJECT_ATTRIBUTES RegOa = { 0 };
HANDLE RegHandle = NULL;
PKEY_VALUE_PARTIAL_INFORMATION Info = NULL;
ULONG ResultLength = 0;
PWCHAR PathBuffer = NULL;
SIZE_T PathBufferSize = 0;
UNICODE_STRING FinalPath = { 0 };
RtlInitUnicodeString(&ImagePathName, L"ImagePath");
ExInitializeResourceLite(&RuleLock);
InitializeObjectAttributes(&RegOa, RegistryPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwOpenKey(&RegHandle, KEY_READ, &RegOa);
if (!NT_SUCCESS(status)) return status;
status = ZwQueryValueKey(RegHandle, &ImagePathName, KeyValuePartialInformation, NULL, 0, &ResultLength);
if (status != STATUS_BUFFER_TOO_SMALL) {
ZwClose(RegHandle);
return status;
}
Info = (PKEY_VALUE_PARTIAL_INFORMATION)PyasAllocate(ResultLength);
if (!Info) {
ZwClose(RegHandle);
return STATUS_INSUFFICIENT_RESOURCES;
}
status = ZwQueryValueKey(RegHandle, &ImagePathName, KeyValuePartialInformation, Info, ResultLength, &ResultLength);
ZwClose(RegHandle);
if (!NT_SUCCESS(status)) {
PyasFree(Info);
return status;
}
if (Info->Type == REG_EXPAND_SZ || Info->Type == REG_SZ) {
PathBufferSize = ResultLength + 1024;
PathBuffer = (PWCHAR)PyasAllocate(PathBufferSize);
if (PathBuffer) {
RtlZeroMemory(PathBuffer, PathBufferSize);
PWCHAR Src = (PWCHAR)Info->Data;
if (NT_SUCCESS(RtlStringCbCopyW(PathBuffer, PathBufferSize, Src))) {
PWCHAR LastSlash = NULL;
PWCHAR Current = PathBuffer;
while (*Current) {
if (*Current == L'\\') LastSlash = Current;
Current++;
}
if (LastSlash) {
*LastSlash = L'\0';
SIZE_T CurrentPathLen = wcslen(PathBuffer);
const WCHAR FilterSuffix[] = L"\\Filter";
SIZE_T FilterLen = (sizeof(FilterSuffix) / sizeof(WCHAR)) - 1;
if (CurrentPathLen >= FilterLen) {
PWCHAR SuffixStart = PathBuffer + CurrentPathLen - FilterLen;
BOOLEAN Match = TRUE;
for (SIZE_T i = 0; i < FilterLen; i++) {
if (RtlDowncaseUnicodeChar(SuffixStart[i]) != RtlDowncaseUnicodeChar(FilterSuffix[i])) {
Match = FALSE;
break;
}
}
if (Match) {
*SuffixStart = L'\0';
}
}
RtlStringCbCatW(PathBuffer, PathBufferSize, L"\\Rules\\Rules_Driver_P1.json");
if (wcsncmp(PathBuffer, L"\\??\\", 4) != 0 &&
wcsncmp(PathBuffer, L"\\SystemRoot", 11) != 0 &&
wcsncmp(PathBuffer, L"\\DosDevices\\", 12) != 0) {
PWCHAR TmpBuffer = (PWCHAR)PyasAllocate(PathBufferSize + 16);
if (TmpBuffer) {
RtlStringCbCopyW(TmpBuffer, PathBufferSize + 16, L"\\??\\");
RtlStringCbCatW(TmpBuffer, PathBufferSize + 16, PathBuffer);
PyasFree(PathBuffer);
PathBuffer = TmpBuffer;
}
}
RtlInitUnicodeString(&FinalPath, PathBuffer);
}
}
}
}
PyasFree(Info);
if (!FinalPath.Buffer) {
if (PathBuffer) PyasFree(PathBuffer);
return STATUS_UNSUCCESSFUL;
}
InitializeObjectAttributes(&oa, &FinalPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwCreateFile(&FileHandle, GENERIC_READ | SYNCHRONIZE, &oa, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (NT_SUCCESS(status)) {
FILE_STANDARD_INFORMATION FileInfo = { 0 };
status = ZwQueryInformationFile(FileHandle, &IoStatus, &FileInfo, sizeof(FileInfo), FileStandardInformation);
if (NT_SUCCESS(status) && FileInfo.EndOfFile.LowPart > 0) {
PVOID FileBuffer = PyasAllocate(FileInfo.EndOfFile.LowPart + 1);
if (FileBuffer) {
status = ZwReadFile(FileHandle, NULL, NULL, NULL, &IoStatus, FileBuffer, FileInfo.EndOfFile.LowPart, NULL, NULL);
if (NT_SUCCESS(status)) {
((PCHAR)FileBuffer)[FileInfo.EndOfFile.LowPart] = '\0';
ExAcquireResourceExclusiveLite(&RuleLock, TRUE);
ParseAndLoadRules((PCHAR)FileBuffer, FileInfo.EndOfFile.LowPart, "Rule_Registry_BlockList", &g_RegistryBlockList);
ParseAndLoadRules((PCHAR)FileBuffer, FileInfo.EndOfFile.LowPart, "Rule_Registry_TrustedList", &g_RegistryTrustedList);
ParseAndLoadRules((PCHAR)FileBuffer, FileInfo.EndOfFile.LowPart, "Rule_Process_TrustedPaths", &g_ProcessTrustedPaths);
ParseAndLoadRules((PCHAR)FileBuffer, FileInfo.EndOfFile.LowPart, "Rule_Process_ExploitableBlacklist", &g_ProcessExploitable);
ParseAndLoadRules((PCHAR)FileBuffer, FileInfo.EndOfFile.LowPart, "Rule_File_ProtectedPaths", &g_FileProtectedPaths);
ParseAndLoadRules((PCHAR)FileBuffer, FileInfo.EndOfFile.LowPart, "Rule_File_ExceptionPaths", &g_FileExceptionPaths);
ParseAndLoadRules((PCHAR)FileBuffer, FileInfo.EndOfFile.LowPart, "Rule_File_RansomwareExtensions", &g_FileRansomExts);
ExReleaseResourceLite(&RuleLock);
}
PyasFree(FileBuffer);
}
}
ZwClose(FileHandle);
}
if (PathBuffer) PyasFree(PathBuffer);
return status;
}
VOID UnloadRules() {
ExAcquireResourceExclusiveLite(&RuleLock, TRUE);
FreeList(&g_RegistryBlockList);
FreeList(&g_RegistryTrustedList);
FreeList(&g_ProcessTrustedPaths);
FreeList(&g_ProcessExploitable);
FreeList(&g_FileProtectedPaths);
FreeList(&g_FileExceptionPaths);
FreeList(&g_FileRansomExts);
ExReleaseResourceLite(&RuleLock);
ExDeleteResourceLite(&RuleLock);
}
NTSTATUS GetProcessImageName(HANDLE ProcessId, PUNICODE_STRING* ImageName) {
NTSTATUS status;
PEPROCESS Process = NULL;
*ImageName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return status;
status = SeLocateProcessImageName(Process, ImageName);
ObDereferenceObject(Process);
return status;
}
static VOID InitTrustCache() {
if (g_CacheInitialized) return;
ExInitializeFastMutex(&TrustCacheLock);
RtlZeroMemory(TrustCache, sizeof(TrustCache));
g_CacheInitialized = TRUE;
}
static BOOLEAN IsWindowsSystemApp(PCWSTR Buffer, USHORT Length) {
if (WildcardMatch(L"*\\Windows\\SystemApps\\*", Buffer, Length)) return TRUE;
if (WildcardMatch(L"*\\Windows\\ImmersiveControlPanel\\*", Buffer, Length)) return TRUE;
if (WildcardMatch(L"*\\explorer.exe", Buffer, Length)) return TRUE;
return FALSE;
}
BOOLEAN IsProcessTrusted(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
if (ProcessId == (HANDLE)4) return TRUE;
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
if (g_CacheInitialized) {
ExAcquireFastMutex(&TrustCacheLock);
ULONG Hash = ((ULONG)(ULONG_PTR)ProcessId) & (TRUST_CACHE_SIZE - 1);
if (TrustCache[Hash].ProcessId == ProcessId) {
BOOLEAN cachedResult = TrustCache[Hash].IsTrusted;
ExReleaseFastMutex(&TrustCacheLock);
return cachedResult;
}
ExReleaseFastMutex(&TrustCacheLock);
}
else {
InitTrustCache();
}
PUNICODE_STRING imageFileName = NULL;
NTSTATUS status = GetProcessImageName(ProcessId, &imageFileName);
BOOLEAN isTrusted = FALSE;
if (NT_SUCCESS(status) && imageFileName && imageFileName->Buffer) {
ExAcquireResourceSharedLite(&RuleLock, TRUE);
PRULE_NODE Node = g_ProcessExploitable;
while (Node) {
if (WildcardMatch(Node->Pattern.Buffer, imageFileName->Buffer, imageFileName->Length)) {
ExReleaseResourceLite(&RuleLock);
goto cleanup;
}
Node = Node->Next;
}
if (IsWindowsSystemApp(imageFileName->Buffer, imageFileName->Length)) {
isTrusted = TRUE;
ExReleaseResourceLite(&RuleLock);
goto cleanup;
}
Node = g_ProcessTrustedPaths;
while (Node) {
if (WildcardMatch(Node->Pattern.Buffer, imageFileName->Buffer, imageFileName->Length)) {
isTrusted = TRUE;
ExReleaseResourceLite(&RuleLock);
goto cleanup;
}
Node = Node->Next;
}
ExReleaseResourceLite(&RuleLock);
}
cleanup:
if (g_CacheInitialized) {
ExAcquireFastMutex(&TrustCacheLock);
ULONG Hash = ((ULONG)(ULONG_PTR)ProcessId) & (TRUST_CACHE_SIZE - 1);
TrustCache[Hash].ProcessId = ProcessId;
TrustCache[Hash].IsTrusted = isTrusted;
KeQuerySystemTime(&TrustCache[Hash].CacheTime);
ExReleaseFastMutex(&TrustCacheLock);
}
if (imageFileName) ExFreePool(imageFileName);
return isTrusted;
}
BOOLEAN IsCriticalSystemProcess(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
if (ProcessId == (HANDLE)4) return TRUE;
return IsProcessTrusted(ProcessId);
}
BOOLEAN IsInstallerProcess(HANDLE ProcessId) {
return IsProcessTrusted(ProcessId);
}
BOOLEAN IsTargetProtected(HANDLE ProcessId) {
if ((ULONG)(ULONG_PTR)ProcessId == GlobalData.PyasPid) return TRUE;
return FALSE;
}
BOOLEAN CheckRegistryRule(PCUNICODE_STRING KeyName) {
if (!KeyName || !KeyName->Buffer) return FALSE;
if (KeyName->Length < 4 * sizeof(WCHAR)) return FALSE;
if (WildcardMatch(L"*{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon", KeyName->Buffer, KeyName->Length)) {
return FALSE;
}
ExAcquireResourceSharedLite(&RuleLock, TRUE);
PRULE_NODE AllowNode = g_RegistryTrustedList;
while (AllowNode) {
if (WildcardMatch(AllowNode->Pattern.Buffer, KeyName->Buffer, KeyName->Length)) {
ExReleaseResourceLite(&RuleLock);
return FALSE;
}
AllowNode = AllowNode->Next;
}
PRULE_NODE Node = g_RegistryBlockList;
BOOLEAN Match = FALSE;
while (Node) {
if (WildcardMatch(Node->Pattern.Buffer, KeyName->Buffer, KeyName->Length)) {
Match = TRUE;
break;
}
Node = Node->Next;
}
ExReleaseResourceLite(&RuleLock);
return Match;
}
BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
ExAcquireResourceSharedLite(&RuleLock, TRUE);
PRULE_NODE ExNode = g_FileExceptionPaths;
while (ExNode) {
if (WildcardMatch(ExNode->Pattern.Buffer, FileName->Buffer, FileName->Length)) {
ExReleaseResourceLite(&RuleLock);
return FALSE;
}
ExNode = ExNode->Next;
}
PRULE_NODE Node = g_FileRansomExts;
BOOLEAN Match = FALSE;
while (Node) {
if (HasSuffix(FileName, Node->Pattern.Buffer)) {
Match = TRUE;
break;
}
Node = Node->Next;
}
ExReleaseResourceLite(&RuleLock);
return Match;
}
BOOLEAN CheckProtectedPathRule(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
if (WildcardMatch(L"*\\Windows\\System32\\config\\systemprofile*", FileName->Buffer, FileName->Length)) {
return FALSE;
}
ExAcquireResourceSharedLite(&RuleLock, TRUE);
PRULE_NODE ExNode = g_FileExceptionPaths;
while (ExNode) {
if (WildcardMatch(ExNode->Pattern.Buffer, FileName->Buffer, FileName->Length)) {
ExReleaseResourceLite(&RuleLock);
return FALSE;
}
ExNode = ExNode->Next;
}
PRULE_NODE Node = g_FileProtectedPaths;
BOOLEAN Match = FALSE;
while (Node) {
if (WildcardMatch(Node->Pattern.Buffer, FileName->Buffer, FileName->Length)) {
Match = TRUE;
break;
}
Node = Node->Next;
}
ExReleaseResourceLite(&RuleLock);
return Match;
}
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;
return (MaxFreq < (ExpectedAvg + HIGH_ENTROPY_THRESHOLD));
}
static BOOLEAN IsNaturallyCompressed(PCUNICODE_STRING FileName) {
if (!FileName || !FileName->Buffer) return FALSE;
for (int i = 0; i < sizeof(Helper_NaturallyCompressedExtensions) / sizeof(Helper_NaturallyCompressedExtensions[0]); i++) {
if (HasSuffix(FileName, Helper_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"*\\Windows\\SystemTemp\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Windows\\Prefetch\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Windows\\Logs\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Profiles\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\Program*\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\AppData\\Local\\*", FileName->Buffer, FileName->Length) ||
WildcardMatch(L"*\\User Data\\*", 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;
PUNICODE_STRING imageFileName = NULL;
NTSTATUS status = GetProcessImageName(ProcessId, &imageFileName);
BOOLEAN isExplorer = FALSE;
if (NT_SUCCESS(status) && imageFileName && imageFileName->Buffer) {
if (HasSuffix(imageFileName, L"\\explorer.exe")) isExplorer = TRUE;
ExFreePool(imageFileName);
}
return isExplorer;
}
BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID WriteBuffer, ULONG WriteLength, BOOLEAN IsWrite) {
if (IsNoisyRansomPath(FileName)) {
return FALSE;
}
if (!IsWrite) {
if (IsExplorerProcess(ProcessId)) return FALSE;
}
BOOLEAN SuspiciousWrite = FALSE;
if (IsWrite && WriteBuffer && WriteLength > 0) {
if (!IsNaturallyCompressed(FileName) && IsHighEntropy(WriteBuffer, WriteLength)) {
SuspiciousWrite = TRUE;
}
}
if (IsWrite && !SuspiciousWrite) {
return FALSE;
}
LARGE_INTEGER Now = { 0 };
KeQuerySystemTime(&Now);
BOOLEAN Result = FALSE;
ExAcquireFastMutex(&GlobalData.TrackerMutex);
PRANSOM_TRACKER Tracker = NULL;
PRANSOM_TRACKER CandidateSlot = NULL;
PRANSOM_TRACKER LruSlot = &RansomTrackers[0];
for (int i = 0; i < MAX_TRACKERS; i++) {
PRANSOM_TRACKER Current = &RansomTrackers[i];
if (Current->LastActivityTime.QuadPart < LruSlot->LastActivityTime.QuadPart) {
LruSlot = Current;
}
if (Current->ProcessId == ProcessId) {
Tracker = Current;
break;
}
BOOLEAN IsExpired = FALSE;
if (Current->ProcessId != NULL) {
LARGE_INTEGER Diff;
Diff.QuadPart = Now.QuadPart - Current->LastActivityTime.QuadPart;
if (Diff.QuadPart > (RANSOM_TIME_WINDOW_MS * 10000LL)) {
IsExpired = TRUE;
}
}
if ((Current->ProcessId == NULL || IsExpired) && !CandidateSlot) {
CandidateSlot = Current;
}
}
if (!Tracker) {
if (CandidateSlot) {
Tracker = CandidateSlot;
}
else {
Tracker = LruSlot;
}
Tracker->ProcessId = ProcessId;
Tracker->ActivityCount = 0;
Tracker->LastActivityTime = Now;
}
else {
LARGE_INTEGER Diff;
Diff.QuadPart = Now.QuadPart - Tracker->LastActivityTime.QuadPart;
if (Diff.QuadPart > (RANSOM_TIME_WINDOW_MS * 10000LL)) {
Tracker->ActivityCount = 0;
}
Tracker->LastActivityTime = Now;
}
ULONG Weight = 2;
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);
msg.Path[BytesToCopy / sizeof(WCHAR)] = L'\0';
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return STATUS_ACCESS_VIOLATION;
}
}
if (!ExAcquireRundownProtection(&GlobalData.PortRundown)) {
return STATUS_PORT_DISCONNECTED;
}
NTSTATUS status = STATUS_PORT_DISCONNECTED;
if (GlobalData.ClientPort) {
LARGE_INTEGER timeout;
timeout.QuadPart = -(5 * 10000);
status = FltSendMessage(GlobalData.FilterHandle, &GlobalData.ClientPort, &msg, sizeof(msg), NULL, NULL, &timeout);
}
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[];
-80
View File
@@ -1,80 +0,0 @@
#include <ntifs.h>
#include "DriverEntry.h"
#include "ProtectMatch.h"
static BOOLEAN g_ScreenImgCb = FALSE;
static VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
{
ANSI_STRING a1 = { 0 }, a2 = { 0 };
CHAR buf[1024] = { 0 };
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);
}
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;
}
}
+217
View File
@@ -0,0 +1,217 @@
{
"Rule_Registry_BlockList": [
"\\REGISTRY\\MACHINE\\BCD00000000",
"\\REGISTRY\\MACHINE\\BCD00000000\\*",
"*\\Image File Execution Options\\*",
"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\NetWire\\*",
"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\Remcos*\\*",
"\\REGISTRY\\USER\\S-1-*\\SOFTWARE\\DC3_FEXEC\\*",
"*\\Classes\\.exe",
"*\\Classes\\.bat",
"*\\Classes\\.cmd",
"*\\Classes\\.com",
"*\\Classes\\exefile\\*",
"*\\Classes\\batfile\\*",
"*\\Classes\\cmdfile\\*",
"*\\Classes\\comfile\\*",
"*\\DefaultIcon",
"*\\DisableAntiSpyware",
"*\\DisableWindowsUpdateAccess",
"*\\EnableLUA",
"*\\ConsentPromptBehaviorAdmin",
"*\\NoControlPanel",
"*\\NoDrives",
"*\\NoFileMenu",
"*\\NoFind",
"*\\NoStartMenuPinnedList",
"*\\NoSetFolders",
"*\\NoSetFolderOptions",
"*\\NoViewOnDrive",
"*\\NoClose",
"*\\NoDesktop",
"*\\NoLogoff",
"*\\NoFolderOptions",
"*\\RestrictRun",
"*\\NoViewContextMenu",
"*\\HideClock",
"*\\NoStartMenuMyGames",
"*\\NoStartMenuMyMusic",
"*\\DisableCMD",
"*\\NoAddingComponents",
"*\\NoWinKeys",
"*\\NoStartMenuLogOff",
"*\\NoSimpleNetIDList",
"*\\NoLowDiskSpaceChecks",
"*\\DisableLockWorkstation",
"*\\Restrict_Run",
"*\\DisableTaskMgr",
"*\\DisableRegistryTools",
"*\\DisableChangePassword",
"*\\Wallpaper",
"*\\NoComponents",
"*\\NoStartMenuMorePrograms",
"*\\NoActiveDesktop",
"*\\NoSetActiveDesktop",
"*\\NoRecentDocsMenu",
"*\\NoWindowsUpdate",
"*\\NoChangeStartMenu",
"*\\NoFavoritesMenu",
"*\\NoRecentDocsHistory",
"*\\NoSetTaskbar",
"*\\NoSMHelp",
"*\\NoTrayContextMenu",
"*\\NoManageMyComputerVerb",
"*\\NoRealMode",
"*\\NoRun",
"*\\ClearRecentDocsOnExit",
"*\\NoActiveDesktopChanges",
"*\\NoStartMenuNetworkPlaces",
"*\\NoLockScreen",
"*\\HideFastUserSwitching",
"*\\ConsentPromptBehaviorUser",
"*\\EnableSecureUIAPaths",
"*\\NoSRM",
"*\\NoInteractiveServices",
"*\\ShutdownWithoutLogon",
"*\\AutoAdminLogon",
"*\\ImagePath",
"*\\BootExecute",
"*\\SubSystems",
"*\\FirmwareBootDevice",
"*\\BootDriverFlags",
"*\\SystemStartOptions",
"*\\CrashDumpEnabled",
"*\\DisableAutomaticRestartOnFailure",
"*\\SystemBiosVersion",
"*\\NoTheme",
"*\\PendingFileRenameOperations",
"*\\SystemSetupInProgress",
"*\\CmdLine",
"*\\SetupType",
"*\\AutoReboot",
"*\\Userinit",
"*\\UIHost",
"*\\Debugger",
"*\\DefaultUserName",
"*\\DefaultPassword",
"*\\AltDefaultUserName",
"*\\AltDefaultPassword",
"*\\DisableCAD",
"*\\LegalNoticeCaption",
"*\\LegalNoticeText",
],
"Rule_Registry_TrustedList": [
],
"Rule_Process_TrustedPaths": [
"*\\Windows\\*",
"*\\Windows Defender\\*",
"*\\Windows Defender Advanced Threat Protection\\*",
"*\\Program Files\\*",
"*\\Program Files (x86)\\*",
"*\\Google\\Chrome\\Application\\chrome.exe",
"*\\Microsoft\\Edge\\Application\\msedge.exe",
"*\\Mozilla Firefox\\firefox.exe",
"*\\Steam\\steam.exe",
"*\\Battle.net\\*\\Battle.net.exe",
"*\\Epic Games\\Launcher\\Portal\\Binaries\\*\\EpicGamesLauncher.exe"
],
"Rule_Process_ExploitableBlacklist": [
"*\\cmd.exe",
"*\\powershell.exe",
"*\\pwsh.exe",
"*\\wscript.exe",
"*\\cscript.exe",
"*\\mshta.exe",
"*\\regsvr32.exe",
"*\\certutil.exe",
"*\\bitsadmin.exe",
"*\\wmic.exe",
"*\\hh.exe",
"*\\cmstp.exe",
"*\\installutil.exe",
"*\\regasm.exe",
"*\\regsvcs.exe",
"*\\msbuild.exe",
"*\\csc.exe",
"*\\vbc.exe",
"*\\jsc.exe",
"*\\bash.exe",
"*\\scrcons.exe",
"*\\schtasks.exe",
"*\\at.exe",
"*\\reg.exe",
"*\\sc.exe",
"*\\net.exe",
"*\\net1.exe",
"*\\whoami.exe",
"*\\ipconfig.exe",
"*\\taskkill.exe",
"*\\ProcessHacker.exe",
"*\\procmon.exe",
"*\\procexp.exe"
],
"Rule_File_ProtectedPaths": [
"*\\PYAS.exe",
"*\\PYAS_Driver.sys",
"*\\ProgramData\\PYAS\\*.json",
"*\\bootmgr",
"*\\boot.ini",
"*\\BOOTNXT",
"*\\BCD",
"*\\EFI\\*",
"*\\Boot\\*",
"*\\Recovery\\*",
"*\\Windows\\*.exe",
"*\\Windows\\*.dll",
"*\\Windows\\*.sys",
"*\\Windows\\System32\\*.exe",
"*\\Windows\\System32\\*.dll",
"*\\Windows\\System32\\*.sys",
"*\\Windows\\SysWOW64\\*.exe",
"*\\Windows\\SysWOW64\\*.dll",
"*\\Windows\\SysWOW64\\*.sys",
"*\\System Volume Information\\*",
"*\\CON",
"*\\CON\\*",
"*\\PRN",
"*\\PRN\\*",
"*\\AUX",
"*\\AUX\\*",
"*\\NUL",
"*\\NUL\\*",
"*\\COM?",
"*\\COM?\\*",
"*\\LPT?",
"*\\LPT?\\*",
"*\\LPT?",
"*\\LPT?\\*",
"*\\OSDATA",
"*\\OSDATA\\*",
"*\\*<*",
"*\\*>*",
"*\\*:*",
],
"Rule_File_ExceptionPaths": [
"*\\AppData\\*"
],
"Rule_File_RansomwareExtensions": [
".exe", ".dll", ".sys", ".com", ".scr",
".zip", ".7z", ".rar", ".tar", ".gz",
".js", ".bat", ".cmd", ".ps1", ".vbs",
".ppt", ".pptx", ".wps", ".txt", ".rtf",
".pdf", ".xls", ".xlsx", ".doc", ".docx",
".jpg", ".jpeg", ".png", ".webp", ".gif",
".mp3", ".wav", ".aac", ".ogg", ".flac",
".mp4", ".avi", ".mov", ".wmv", ".mkv",
".aux", ".cur", ".mui", ".ttf", ".efi",
".cpp", ".h", ".c", ".hpp", ".cs", ".java", ".py", ".go", ".rs",
".php", ".html", ".css", ".json", ".xml", ".sql", ".db"
]
}
+144 -38
View File
@@ -1,30 +1,23 @@
# 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" />
## Readme Language
English : https://github.com/87owo/PYAS/blob/main/README.md
繁體中文 : https://github.com/87owo/PYAS/blob/main/README_zh_TW.md
简体中文 : https://github.com/87owo/PYAS/blob/main/README_zh_CN.md
## Requirements
Python 3.10 is recommended. Other Python versions may require different pip commands.
```
pip install numpy==1.26.4
pip install onnxruntime==1.18.1
pip install pefile==2023.2.7
pip install Pillow==11.0.0
pip install pyperclip==1.9.0
pip install PySide6==6.9.1
pip install requests==2.32.4
pip install PySide6==6.9.1
pip install yara-python==4.5.4
pip install Pillow==11.0.0
pip install numpy==1.26.4
pip install tensorflow==2.10.0
pip install tf2onnx==1.13.0
pip install lightgbm==4.6.0
pip install onnxruntime==1.18.1
```
## File Information
@@ -34,26 +27,25 @@ The following lists the storage locations of all relevant code and other related
```
PYAS/
├── Engine/
│ ├── Models/
│ ├── Pattern/
│ │ ├── 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
│ ├── Heuristic/
│ │ ├── rules.yar # Yara virus signature rule matching
│ │ └── ... # Other rules folders and files
│ └── ... # Other engine 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
│ │ └── ... # Other driver folders and files
│ │
│ └── Rules/
│ └── rules.json # White, block list, and matching logic for files registry
|
├── PYAS.py # Main application entry point and UI to engine interface
├── PYAS_Config.py # Configuration loading, saving, and global parameters
├── PYAS_Engine.py # Core scanning engine: YARA, IP, ONNX model execution
@@ -63,15 +55,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 userMode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef kernelMode fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#e65100
classDef storage fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c
classDef interaction fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,stroke-dasharray: 5 5,color:#1b5e20
## Packaged Releases
subgraph UserSpace [User Mode Application - PYAS.exe]
direction TB
GUI[MainWindow_Controller / UI]:::userMode
ConfigMgr[Configuration & Rule Manager]:::userMode
subgraph DetectionEngine [Analysis Engine - PYAS_Engine.py]
direction TB
SignScanner[Digital Signature Scanner]:::userMode
PEScanner[PE Feature & Entropy Analysis]:::userMode
YaraScanner[Heuristic / YARA Scanner]:::userMode
CNNScanner[AI / CNN Model Scanner]:::userMode
CloudScanner[Cloud API / Hash Check]:::userMode
end
Packaged Releases Download: https://github.com/87owo/PYAS/releases
subgraph UserMonitors [User-Mode Protection Threads]
direction TB
ProcMon[Process Monitor - CreateToolhelp32Snapshot]:::userMode
FileMon[File Monitor - ReadDirectoryChangesW]:::userMode
NetMon[Network Monitor - GetExtendedTcpTable]:::userMode
SysRep[System Repair - MBR/Reg/Wallpaper]:::userMode
PopupBlock[Popup Blocker - EnumWindows]:::userMode
PipeClient[IPC Client Thread]:::userMode
end
GUI --> ConfigMgr
GUI --> DetectionEngine
GUI --> UserMonitors
UserMonitors --> DetectionEngine
end
subgraph StorageLayer [File System / Configuration]
direction LR
JSONRules[JSON Rules Files]:::storage
ConfigJSON[Config.json]:::storage
Quarantine[Quarantine Folder]:::storage
end
subgraph KernelSpace [Kernel Mode Driver - PYAS_Driver.sys]
direction TB
DriverEntry[DriverEntry / Initialization]:::kernelMode
GlobalData[Global Data & State]:::kernelMode
CommServer[Communication Port Server]:::kernelMode
subgraph KernelLogic [Core Protection Logic]
RuleLoader[Rule Loader & Parser]:::kernelMode
TrustCache[Trust Cache & Ransom Tracker]:::kernelMode
subgraph MiniFilter [File System MiniFilter]
PreCreate[PreCreate: HoneyToken / Access Control]:::kernelMode
PreWrite[PreWrite: Ransomware / Entropy Check]:::kernelMode
PreSetInfo[PreSetInfo: Anti-Rename / Extension]:::kernelMode
PreDevCtrl[PreDeviceControl: Boot / Disk Wipe Protect]:::kernelMode
end
subgraph ObjectCallbacks [Object Manager Callbacks]
ProcProtect[ObRegisterCallbacks: Handle Stripping]:::kernelMode
ImageLoad[PsSetLoadImageNotifyRoutine: Image Blocking]:::kernelMode
end
subgraph RegistryCallbacks [Configuration Manager Callbacks]
RegFilter[CmRegisterCallbackEx: Registry Guard]:::kernelMode
end
end
DriverEntry --> GlobalData
DriverEntry --> CommServer
DriverEntry --> MiniFilter
DriverEntry --> ProcProtect
DriverEntry --> ImageLoad
DriverEntry --> RegFilter
MiniFilter --> RuleLoader
ProcProtect --> RuleLoader
RegFilter --> RuleLoader
PreWrite --> TrustCache
PreCreate --> TrustCache
end
%% Cross-Boundary Interactions
ConfigMgr -- Writes --> JSONRules
ConfigMgr -- Writes --> ConfigJSON
RuleLoader -- Reads --> JSONRules
GUI -- Service Control (SCM) --> DriverEntry
PipeClient -- FltSendMessage (IPC) --> CommServer
CommServer -- Notifications --> PipeClient
FileMon -- Moves Malicious Files --> Quarantine
%% Logic Flow Details
ProcProtect -- Protects --> UserSpace
RegFilter -- Protects --> StorageLayer
PreDevCtrl -- Protects --> StorageLayer
```
## Support System
@@ -80,12 +172,26 @@ 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
Online Analyze : https://pyas-security.com/analyze
## Project License
https://github.com/87owo/PYAS/blob/main/LICENSE.txt
For any questions, needs, or bug feedback, please contact us through the following website.
Source Issues : https://github.com/87owo/PYAS/issues
Official Email : mailto:service.pyas@gmail.com
-91
View File
@@ -1,91 +0,0 @@
# PYAS
使用 Python 和 C 编写的杀毒软件,并通过深度学习和行为监控阻止威胁!
<img width="2245" height="1477" alt="PYAS_UI" src="https://github.com/user-attachments/assets/87d40261-7655-49ad-a19c-1ffcca60584f" />
## 说明语言
English : https://github.com/87owo/PYAS/blob/main/README.md
繁體中文 : https://github.com/87owo/PYAS/blob/main/README_zh_TW.md
简体中文 : https://github.com/87owo/PYAS/blob/main/README_zh_CN.md
## 安装需求
建议使用 Python 3.10。其他版本的 Python 可能需要不同的 pip 指令。
```
pip install numpy==1.26.4
pip install onnxruntime==1.18.1
pip install pefile==2023.2.7
pip install Pillow==11.0.0
pip install pyperclip==1.9.0
pip install PySide6==6.9.1
pip install requests==2.32.4
pip install yara-python==4.5.4
```
## 文件讯息
以下列出所有相关代码与文件的存放位置。
```
PYAS/
├── Engine/
│ ├── Models/
│ │ ├── convert.py # 将可执行文件或其他文件转换为图片
│ │ └── train.py # TensorFlow CNN 模型训练完整代码
│ │
│ └── Rules/
│ ├── rules.yar # YARA 病毒特征码规则匹配
│ └── rules.ips # IP 网络地址规则匹配
│
├── Plugins/
│ └── Filter/
│ ├── DriverEntry.c # 驱动主入口与初始化逻辑
│ ├── DriverEntry.h # 全局驱动定义、常量与函数
│ ├── DriverPipe.c # 内核与用户层的管道日志传输实现
│ ├── ProtectBoot.c # 磁盘引导区写入保护
│ ├── ProtectImage.c # 映像加载监控与 shellcode 检测
│ ├── ProtectInject.c # 进程与线程控制,防止注入
│ ├── ProtectReg.c # 注册表修改保护
│ ├── ProtectRules.c # 白名单、阻止名单与文件/注册表匹配逻辑
│ └── ProtectRules.h # 保护规则声明
│
├── PYAS.py # 主应用程序入口点与 UI 到引擎的接口
├── PYAS_Config.py # 配置加载、保存与全局参数
├── PYAS_Engine.py # 核心扫描引擎:YARA、IP、ONNX 模型执行
├── PYAS_Interface.py # 用户界面组件与事件处理
├── PYAS_Resource.py # 静态图片与图标资源管理
├── PYAS_Version.py # 版本元数据,用于打包与更新
└── ... # 其他补充文件夹与文件
```
## 代码架构
PYAS 杀毒软件完整代码流程架构图。
<img width="23000" height="6000" alt="PYAS_Architecture" src="https://github.com/user-attachments/assets/3a7ce637-c2b3-4719-9658-07f286cfa879" />
## 安装版本
打包发行版下载:https://github.com/87owo/PYAS/releases
## 系统需求
| 配置要求 | 权限 | 系统版本 | 处理器 | 可用内存空间 | 可用存储空间 |
| ------- | ----- | ------ | ----- | ------------ | ---------- |
| 最低配置 | 管理员 | >= Windows 10 (20H1) | 1 GHz | 200MB | 100MB |
| 推荐配置 | 管理员 | >= Windows 10 (21H2) | 3 GHz | 300MB | 200MB |
## 官方网站
官方网站 : https://pyantivirus.wixsite.com/pyas
开源网站 : https://github.com/87owo/PYAS
## 授权条款
https://github.com/87owo/PYAS/blob/main/LICENSE.txt
-91
View File
@@ -1,91 +0,0 @@
# PYAS
使用 Python 和 C 開發的防毒軟體,並透過深度學習和行為監控來阻止威脅!
<img width="2245" height="1477" alt="PYAS_UI" src="https://github.com/user-attachments/assets/87d40261-7655-49ad-a19c-1ffcca60584f" />
## 說明語言
English : https://github.com/87owo/PYAS/blob/main/README.md
繁體中文 : https://github.com/87owo/PYAS/blob/main/README_zh_TW.md
简体中文 : https://github.com/87owo/PYAS/blob/main/README_zh_CN.md
## 安裝需求
建議使用 Python 3.10。其他版本的 Python 可能需要不同的 pip 指令。
```
pip install numpy==1.26.4
pip install onnxruntime==1.18.1
pip install pefile==2023.2.7
pip install Pillow==11.0.0
pip install pyperclip==1.9.0
pip install PySide6==6.9.1
pip install requests==2.32.4
pip install yara-python==4.5.4
```
## 檔案資訊
以下列出所有相關程式碼與文件的存放位置。
```
PYAS/
├── Engine/
│ ├── Models/
│ │ ├── convert.py # 將可執行檔或其他檔案轉換為圖片
│ │ └── train.py # TensorFlow CNN 模型訓練完整程式碼
│ │
│ └── Rules/
│ ├── rules.yar # YARA 病毒特徵碼規則匹配
│ └── rules.ips # IP 網路位址規則匹配
│
├── Plugins/
│ └── Filter/
│ ├── DriverEntry.c # 驅動主入口與初始化邏輯
│ ├── DriverEntry.h # 全域驅動定義、常數與函式
│ ├── DriverPipe.c # 核心層與使用者層的管道日誌傳輸實作
│ ├── ProtectBoot.c # 磁碟開機區寫入保護
│ ├── ProtectImage.c # 映像載入監控與 shellcode 偵測
│ ├── ProtectInject.c # 程序與執行緒控制,防止注入
│ ├── ProtectReg.c # 登錄檔修改保護
│ ├── ProtectRules.c # 白名單、封鎖清單與檔案/登錄匹配邏輯
│ └── ProtectRules.h # 保護規則宣告
│
├── PYAS.py # 主應用程式入口點與 UI 到引擎的介面
├── PYAS_Config.py # 組態載入、儲存與全域參數
├── PYAS_Engine.py # 核心掃描引擎:YARA、IP、ONNX 模型執行
├── PYAS_Interface.py # 使用者介面元件與事件處理
├── PYAS_Resource.py # 靜態圖片與圖示資源管理
├── PYAS_Version.py # 版本中繼資料,用於打包與更新
└── ... # 其他補充資料夾與檔案
```
## 程式架構
PYAS 防毒軟體完整程式流程架構圖。
<img width="23000" height="6000" alt="PYAS_Architecture" src="https://github.com/user-attachments/assets/3a7ce637-c2b3-4719-9658-07f286cfa879" />
## 安裝版本
打包發行版下載 : https://github.com/87owo/PYAS/releases
## 系統需求
| 配置要求 | 權限 | 系統版本 | 處理器 | 可用記憶體空間 | 可用儲存空間 |
| ------- | ---- | ------- | ------ | ------------ | ----------- |
| 最低配置 | 管理員 | >= Windows 10 (20H1) | 1 GHz | 200MB | 100MB |
| 推薦配置 | 管理員 | >= Windows 10 (21H2) | 3 GHz | 300MB | 200MB |
## 官方網站
官方網站 : https://pyantivirus.wixsite.com/pyas
開源網站 : https://github.com/87owo/PYAS
## 授權條款
https://github.com/87owo/PYAS/blob/main/LICENSE.txt